diff --git a/BUILD.gn b/BUILD.gn index 95b5560..b9b09ed 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1458,23 +1458,18 @@ # This target differs from :blink_web_tests in that it uses the same # test harness and a few additional flags but, more importantly, only runs # the web_tests/wpt_internal/webgpu tests, so it doesn't have a data - # dependency on the whole web_test directory. run_webgpu_cts.py is a wrapper - # script around run_web_tests.py which performs additional setup for running - # the WebGPU CTS. + # dependency on the whole web_test directory. script = _common_web_test_script - # Add run_webgpu_cts.py and remove run_web_tests.py from _common_web_test_args - args = [ "@WrappedPath(" + - rebase_path("//third_party/blink/tools/run_webgpu_cts.py", - root_build_dir) + ")" ] + _common_web_test_args - - [ _common_web_test_args[0] ] + args = _common_web_test_args if (is_asan) { args += [ "--timeout-ms=30000" ] } args += [ - "--webgpu-cts-expectations", + "--ignore-default-expectations", + "--additional-expectations", "@WrappedPath(../../third_party/blink/web_tests/WebGPUExpectations)", - "--isolated-script-test-filter=wpt_internal/webgpu/web_platform/reftests", + "--isolated-script-test-filter=wpt_internal/webgpu/web_platform/reftests/*", ] data_deps = [
diff --git a/DEPS b/DEPS index fd570c6..490e7ea9 100644 --- a/DEPS +++ b/DEPS
@@ -275,7 +275,7 @@ # 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': 'd45ffc66de49de91e0be652cf3933940efd410a0', + 'skia_revision': '6a36fc1491fd55ca0bbdea141e28e6d500f2050d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -283,11 +283,11 @@ # 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': 'a65af046953a0a16ceed4ad1dbb91fb377bf245b', + 'angle_revision': '48b928d98fc888b9887de814ad49fb9dc11910a6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '1178eb9eef342d5dfebddc551d0831f5309ebf13', + 'swiftshader_revision': 'f1a62bb45663f127bc75348a6e3d90508469cef3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -318,7 +318,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lss # and whatever else without interference from each other. - 'lss_revision': '92a65a8f5d705d1928874420c8d0d15bde8c89e5', + 'lss_revision': '1d387f43f3702818f7fc04d334539a2f05cafccd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. @@ -354,7 +354,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': 'ac6b02745945218c6e79b2adb8ef987f892fc141', + 'devtools_frontend_revision': 'b870512aaee40281a4f247aaf945646f242d0912', # 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. @@ -390,7 +390,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'bd30d9e594226e96c07ec3cd46dbdc68928aef41', + 'dawn_revision': '5fb759f6e76a827f19ed6665b77aaeaa4cc4bbf2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -418,7 +418,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '6347f80a1196ea15ee18ff6d0fd1917f1cb2b404', + 'nearby_revision': 'd8453565db739ebbfbbeade9ec8f8239057b1e13', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -434,7 +434,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': '11395e54b43a650df15a50b2d6bfb419e9ff312f', + 'libcxxabi_revision': '013bcd820a353ec1d3ff472f2971553fea7232cf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -457,7 +457,7 @@ 'libcxx_revision': 'b1269813eaf5b8ac78e35e45a0f7cc320bd3e7d6', # GN CIPD package version. - 'gn_version': 'git_revision:fd6cae41bd7d5d255dc2fb96004a8bf74ac9d972', + 'gn_version': 'git_revision:2ecd43a10266bd091c98e6dcde507c64f6a0dad3', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -756,7 +756,7 @@ }, 'src/ios/third_party/edo/src': { - 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '4be4a94e0aa64b279a3eaae18414b2a7e7769be3', + 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '07ef2f35406e9f04cf86d11da5cc62d58f36cb15', 'condition': 'checkout_ios', }, @@ -920,7 +920,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'JPzPwtVT1B0wxFtrYWysxKnlZrx9hVhFuT00NvADQ64C', + 'version': 'h_P2inqiGpL43nlN62apySX-dW_9fOY90d7Iuh8ayj8C', }, ], 'condition': 'checkout_android', @@ -1705,10 +1705,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'bb289ce3cb15bbabd42fdcb01439367846d9069d', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'edd275f0ad33c708fba30643cf971adf0f6ba488', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '84183b561b7f44b2eae6a5f268d5085accb0ad7a', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'da0ea972364f23d21893cf58701ce8ccd798c1c4', + Var('webrtc_git') + '/src.git' + '@' + '774b4725a20934c99d94c63ab7ce842c5a4ce9d7', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1781,7 +1781,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ea11a9525684a5ba7962ca95a9a42511bc0697a8', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@62ab10dea1a693fd29ed8c56f5723bcb522ec746', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/aw_web_contents_delegate.cc b/android_webview/browser/aw_web_contents_delegate.cc index c5e1077..c5f852e5 100644 --- a/android_webview/browser/aw_web_contents_delegate.cc +++ b/android_webview/browser/aw_web_contents_delegate.cc
@@ -257,7 +257,7 @@ AwContents* aw_contents = AwContents::FromWebContents(web_contents); if (!aw_contents) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, nullptr); return;
diff --git a/android_webview/browser/permission/media_access_permission_request.cc b/android_webview/browser/permission/media_access_permission_request.cc index 429068e1..c5fd659 100644 --- a/android_webview/browser/permission/media_access_permission_request.cc +++ b/android_webview/browser/permission/media_access_permission_request.cc
@@ -4,6 +4,7 @@ #include "android_webview/browser/permission/media_access_permission_request.h" +#include <algorithm> #include <utility> #include "android_webview/browser/permission/aw_permission_request.h" @@ -48,14 +49,18 @@ void MediaAccessPermissionRequest::NotifyRequestResult(bool allowed) { std::unique_ptr<content::MediaStreamUI> ui; - blink::mojom::StreamDevices devices; if (!allowed) { std::move(callback_).Run( - devices, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + blink::mojom::StreamDevicesSet(), + blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, std::move(ui)); return; } + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; if (request_.audio_type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { const MediaStreamDevices& audio_devices = @@ -79,11 +84,16 @@ if (device) devices.video_device = *device; } + + const bool has_no_hardware = + !devices.audio_device.has_value() && !devices.video_device.has_value(); + if (has_no_hardware) { + stream_devices_set.stream_devices.clear(); + } std::move(callback_).Run( - devices, - (!devices.audio_device.has_value() && !devices.video_device.has_value()) - ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE - : blink::mojom::MediaStreamRequestResult::OK, + stream_devices_set, + has_no_hardware ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE + : blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); }
diff --git a/android_webview/browser/permission/media_access_permission_request_unittest.cc b/android_webview/browser/permission/media_access_permission_request_unittest.cc index 7d46316..02b2a861 100644 --- a/android_webview/browser/permission/media_access_permission_request_unittest.cc +++ b/android_webview/browser/permission/media_access_permission_request_unittest.cc
@@ -80,10 +80,10 @@ blink::mojom::MediaStreamRequestResult result_; private: - void Callback(const blink::mojom::StreamDevices& devices, + void Callback(const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { - devices_ = blink::StreamDevicesToMediaStreamDevicesList(devices); + devices_ = blink::ToMediaStreamDevicesList(stream_devices_set); result_ = result; } };
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index 699ca19..2a290103 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -171,9 +171,6 @@ + "names and house numberse."), Flag.baseFeature(AutofillFeatures.AUTOFILL_FIX_FILLABLE_FIELD_TYPES, "Fix how it is determined if a field type is fillable with Autofill"), - Flag.baseFeature(AutofillFeatures.AUTOFILL_ENABLE_MERCHANT_BOUND_VIRTUAL_CARDS, - "When enabled, merchant bound virtual cards will be offered when users " - + "interact with a payment form."), Flag.baseFeature(AutofillFeatures.AUTOFILL_ENABLE_AUGMENTED_PHONE_COUNTRY_CODE, "Enables support for phone code number fields with additional text."), Flag.baseFeature(AutofillFeatures.AUTOFILL_ENFORCE_DELAYS_IN_STRIKE_DATABASE,
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc index 660aef5..a2bca072 100644 --- a/ash/capture_mode/capture_mode_session.cc +++ b/ash/capture_mode/capture_mode_session.cc
@@ -1352,8 +1352,9 @@ // long as the cursor is not on top of the capture button, since clicking // anywhere outside the bounds of either of them (the menu or the clickable // capture button) will dismiss the menu. Also if the event is on the bar, a - // pointer will also be used. + // pointer will also be used, as long as the bar is visible. const bool is_event_on_capture_bar = + capture_mode_bar_widget_->GetLayer()->GetTargetOpacity() && capture_mode_bar_widget_->GetWindowBoundsInScreen().Contains( location_in_screen); if (capture_mode_settings_widget_ || is_event_on_capture_bar) {
diff --git a/ash/capture_mode/capture_mode_toast_controller.cc b/ash/capture_mode/capture_mode_toast_controller.cc index c50cef8..d5e2b3a 100644 --- a/ash/capture_mode/capture_mode_toast_controller.cc +++ b/ash/capture_mode/capture_mode_toast_controller.cc
@@ -174,6 +174,12 @@ kShellWindowId_MenuContainer), CalculateToastWidgetScreenBounds())); + // We animate the toast widget explicitly in `ShowCaptureToast()` and + // `MaybeDismissCaptureToast()`. Any default visibility animations added by + // the widget's window should be disabled. + capture_toast_widget_->SetVisibilityAnimationTransition( + views::Widget::ANIMATE_NONE); + toast_label_view_ = capture_toast_widget_->SetContentsView( std::make_unique<views::Label>(label)); toast_label_view_->SetMultiLine(true);
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc index 856984f..75b883ee 100644 --- a/ash/capture_mode/capture_mode_unittests.cc +++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -1367,6 +1367,30 @@ controller->Stop(); } +// Regression testing for https://crbug.com/1334824. +TEST_F(CaptureModeTest, CursorShouldNotChangeWhileAdjustingRegion) { + UpdateDisplay("800x600"); + using ui::mojom::CursorType; + + auto* cursor_manager = Shell::Get()->cursor_manager(); + auto* event_generator = GetEventGenerator(); + + EXPECT_FALSE(cursor_manager->IsCursorLocked()); + StartImageRegionCapture(); + event_generator->MoveMouseTo(gfx::Point(200, 200)); + EXPECT_EQ(CursorType::kCell, cursor_manager->GetCursor().type()); + event_generator->PressLeftButton(); + event_generator->MoveMouseTo(gfx::Point(300, 300)); + EXPECT_EQ(CursorType::kSouthEastResize, cursor_manager->GetCursor().type()); + + // Drag the region by moving the cursor to the center point of the capture bar + // and expect that it doesn't change back to a pointer. + const auto capture_bar_center = + GetCaptureModeBarView()->GetBoundsInScreen().CenterPoint(); + event_generator->MoveMouseTo(capture_bar_center); + EXPECT_EQ(CursorType::kSouthEastResize, cursor_manager->GetCursor().type()); +} + TEST_F(CaptureModeTest, FullscreenCursorStates) { using ui::mojom::CursorType;
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 39442923..1ada1b1 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -268,7 +268,7 @@ // Enable or disable calendar view from the system tray. Also enables the system // tray to show date in the shelf when the screen is sufficiently large. const base::Feature kCalendarView{"CalendarView", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Enable or disable debug mode for CalendarModel. const base::Feature kCalendarModelDebugMode{"CalendarModelDebugMode",
diff --git a/ash/shelf/scrollable_shelf_view_unittest.cc b/ash/shelf/scrollable_shelf_view_unittest.cc index 7f0fe2c..bcba93b 100644 --- a/ash/shelf/scrollable_shelf_view_unittest.cc +++ b/ash/shelf/scrollable_shelf_view_unittest.cc
@@ -1424,13 +1424,20 @@ // of [1, (hotseat width) / (shelf button + button spacing) + 1]. // So we can get |kAppCount| in that range manually static constexpr int kAppCount = 10; + + // If calendar view is enabled, the space is a little smaller and can only + // show 9 apps at one time. + static constexpr int kAppCountWithShowingDateTray = 9; }; // Verifies the basic function of app scaling which scales down the hotseat and // its children's sizes if there is insufficient space for shelf buttons to show // without scrolling. TEST_F(ScrollableShelfViewWithAppScalingTest, AppScalingBasics) { - PopulateAppShortcut(kAppCount); + if (features::IsCalendarViewEnabled()) + PopulateAppShortcut(kAppCountWithShowingDateTray); + else + PopulateAppShortcut(kAppCount); HotseatWidget* hotseat_widget = GetPrimaryShelf()->shelf_widget()->hotseat_widget(); EXPECT_EQ(HotseatDensity::kNormal, hotseat_widget->target_hotseat_density()); @@ -1473,7 +1480,10 @@ // Verifies that app scaling works as expected with hotseat state transition. TEST_F(ScrollableShelfViewWithAppScalingTest, VerifyWithHotseatStateTransition) { - PopulateAppShortcut(kAppCount); + if (features::IsCalendarViewEnabled()) + PopulateAppShortcut(kAppCountWithShowingDateTray); + else + PopulateAppShortcut(kAppCount); HotseatWidget* hotseat_widget = GetPrimaryShelf()->shelf_widget()->hotseat_widget(); EXPECT_EQ(HotseatDensity::kNormal, hotseat_widget->target_hotseat_density());
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc index 70efc52..e7370b8 100644 --- a/ash/shelf/shelf.cc +++ b/ash/shelf/shelf.cc
@@ -648,10 +648,6 @@ return shelf_widget_ ? shelf_widget_->status_area_widget() : nullptr; } -TrayBackgroundView* Shelf::GetSystemTrayAnchorView() const { - return GetStatusAreaWidget()->GetSystemTrayAnchor(); -} - gfx::Rect Shelf::GetSystemTrayAnchorRect() const { gfx::Rect work_area = GetWorkAreaInsets()->user_work_area_bounds(); switch (alignment_) {
diff --git a/ash/shelf/shelf.h b/ash/shelf/shelf.h index d07f507e..b3d22dd 100644 --- a/ash/shelf/shelf.h +++ b/ash/shelf/shelf.h
@@ -44,7 +44,6 @@ class ShelfWidget; class StatusAreaWidget; class ShelfObserver; -class TrayBackgroundView; class WorkAreaInsets; class ShelfTooltipManager; @@ -194,10 +193,6 @@ StatusAreaWidget* GetStatusAreaWidget() const; - // Get the tray button that the system tray bubble and the notification center - // bubble will be anchored. See also: StatusAreaWidget::GetSystemTrayAnchor() - TrayBackgroundView* GetSystemTrayAnchorView() const; - // Get the anchor rect that the system tray bubble and the notification center // bubble will be anchored. // x() and y() designates anchor point, but width() and height() are dummy.
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 7479df9..ff31fab 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -4456,8 +4456,10 @@ // Tests that pinned app icons are visible on non-primary displays. TEST_F(ShelfLayoutManagerTest, ShelfShowsPinnedAppsOnOtherDisplays) { - // Create three displays. - UpdateDisplay("600x400,1000x700,800x900"); + // Create three displays. Should use 600+ pixel as the horizontal display + // size, otherwise there's no enough space to show both the date tray and + // unified system tray on the screen. + UpdateDisplay("700x400,1000x700,800x900"); const unsigned int display_count = 3U; aura::Window::Windows root_windows = Shell::GetAllRootWindows(); EXPECT_EQ(display_count, root_windows.size()); @@ -4511,6 +4513,7 @@ .GetViewAt(app_count - 1) ->GetBoundsInScreen() .right_center(); + EXPECT_EQ(left.x() - display.bounds().x(), display.bounds().right() - right.x()) << "Apps on either end should be at the same distance from the "
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 82e7f18..8fe3a1c 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -1366,6 +1366,9 @@ } TEST_P(LtrRtlShelfViewTest, ShouldHideTooltipTest) { + // Set a screen size large enough to have space between the home button and + // app buttons. + UpdateDisplay("2000x600"); ShelfID app_button_id = AddAppShortcut(); ShelfID platform_button_id = AddApp(); // TODO(manucornet): It should not be necessary to call this manually. The @@ -2510,9 +2513,10 @@ EXPECT_EQ(-1, shelf_view_->current_ghost_view_index()); } +// Disabled as likely to cause builder failure, see https://crbug.com/1334936. // Tests that the ghost image is reinserted if the app is dragged within the // bounds of the shelf after a rip off. -TEST_F(GhostImageShelfViewTest, ReinsertGhostImageAfterRipOffDrag) { +TEST_F(GhostImageShelfViewTest, DISABLED_ReinsertGhostImageAfterRipOffDrag) { std::vector<std::pair<ShelfID, views::View*>> id_map; SetupForDragTest(&id_map); ShelfAppButton* first_app = GetButtonByID(id_map[0].first); @@ -3283,7 +3287,7 @@ EXPECT_TRUE(test_api_->GetViewAt(2)->HasFocus()); // This is the last element. Tabbing once more should go into the status - // area. + // area. If calendar view is enabled it is focusing on the date tray. DoTab(); ExpectNotFocused(shelf_view_); ExpectFocused(status_area_); @@ -3298,6 +3302,14 @@ ExpectNotFocused(shelf_view_); ExpectFocused(status_area_); + // If calendar view is enabled, move the focusing ring from the date tray to + // the unified tray. + if (features::IsCalendarViewEnabled()) { + DoTab(); + ExpectNotFocused(shelf_view_); + ExpectFocused(status_area_); + } + // And keep going forward, now we should be cycling back to the first shelf // element. DoTab(); @@ -3321,6 +3333,14 @@ ExpectNotFocused(shelf_view_); ExpectFocused(status_area_); + // If calendar view is enabled, move the focusing ring from the unified tray + // to the date tray. + if (features::IsCalendarViewEnabled()) { + DoShiftTab(); + ExpectNotFocused(shelf_view_); + ExpectFocused(status_area_); + } + // Advance backwards to the last element of the shelf. DoShiftTab(); ExpectNotFocused(status_area_);
diff --git a/ash/system/network/network_list_view_controller_impl.cc b/ash/system/network/network_list_view_controller_impl.cc index b5d113b4..c89377f 100644 --- a/ash/system/network/network_list_view_controller_impl.cc +++ b/ash/system/network/network_list_view_controller_impl.cc
@@ -135,7 +135,7 @@ } void NetworkListViewControllerImpl::GlobalPolicyChanged() { - UpdateMobileSectionHeader(); + UpdateMobileSection(); }; void NetworkListViewControllerImpl::OnPropertiesUpdated( @@ -144,7 +144,7 @@ return; bluetooth_system_state_ = properties->system_state; - UpdateMobileSectionHeader(); + UpdateMobileSection(); } void NetworkListViewControllerImpl::GetNetworkStateList() { @@ -196,7 +196,7 @@ NetworkListViewControllerViewChildId::kMobileSectionHeader)); } - UpdateMobileSectionHeader(); + UpdateMobileSection(); network_detailed_network_view()->network_list()->ReorderChildView( mobile_header_view_, index++); @@ -222,23 +222,17 @@ RemoveAndResetViewIfExists(&wifi_separator_view_); } - if (!wifi_header_view_) { - wifi_header_view_ = network_detailed_network_view()->AddWifiSectionHeader(); - wifi_header_view_->SetID(static_cast<int>( - NetworkListViewControllerViewChildId::kWifiSectionHeader)); - } - - wifi_header_view_->SetJoinWifiButtonState(/*enabled=*/is_wifi_enabled_, - /*visible=*/true); - wifi_header_view_->SetToggleVisibility(/*visible=*/true); - wifi_header_view_->SetToggleState(/*enabled=*/true, - /*is_on=*/is_wifi_enabled_); + UpdateWifiSection(); network_detailed_network_view()->network_list()->ReorderChildView( wifi_header_view_, index++); index = CreateItemViewsIfMissingAndReorder(NetworkType::kWiFi, index, networks, &previous_network_views); + if (wifi_status_message_) { + network_detailed_network_view()->network_list()->ReorderChildView( + wifi_status_message_, index++); + } // Remaining views in |previous_network_views| are no longer needed // and should be deleted. @@ -254,11 +248,14 @@ void NetworkListViewControllerImpl::UpdateNetworkTypeExistence( const std::vector<NetworkStatePropertiesPtr>& networks) { has_mobile_networks_ = false; + has_wifi_networks_ = false; is_vpn_connected_ = false; for (auto& network : networks) { if (NetworkTypeMatchesType(network->type, NetworkType::kMobile)) { has_mobile_networks_ = true; + } else if (NetworkTypeMatchesType(network->type, NetworkType::kWiFi)) { + has_wifi_networks_ = true; } else if (NetworkTypeMatchesType(network->type, NetworkType::kVPN) && StateIsConnected(network->connection_state)) { is_vpn_connected_ = true; @@ -352,7 +349,7 @@ return index; } -void NetworkListViewControllerImpl::UpdateMobileSectionHeader() { +void NetworkListViewControllerImpl::UpdateMobileSection() { if (!mobile_header_view_) return; @@ -375,6 +372,30 @@ UpdateMobileToggleAndSetStatusMessage(); } +void NetworkListViewControllerImpl::UpdateWifiSection() { + if (!wifi_header_view_) { + wifi_header_view_ = network_detailed_network_view()->AddWifiSectionHeader(); + wifi_header_view_->SetID(static_cast<int>( + NetworkListViewControllerViewChildId::kWifiSectionHeader)); + } + + wifi_header_view_->SetJoinWifiButtonState(/*enabled=*/is_wifi_enabled_, + /*visible=*/true); + wifi_header_view_->SetToggleVisibility(/*visible=*/true); + wifi_header_view_->SetToggleState(/*enabled=*/true, + /*is_on=*/is_wifi_enabled_); + + if (!is_wifi_enabled_) { + CreateInfoLabelIfMissingAndUpdate(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED, + &wifi_status_message_); + } else if (!has_wifi_networks_) { + CreateInfoLabelIfMissingAndUpdate(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED, + &wifi_status_message_); + } else { + RemoveAndResetViewIfExists(&wifi_status_message_); + } +} + void NetworkListViewControllerImpl::UpdateMobileToggleAndSetStatusMessage() { if (!mobile_header_view_) return; @@ -387,8 +408,8 @@ const bool is_secondary_user = IsSecondaryUser(); if (cellular_state == DeviceStateType::kUninitialized) { - CreateMobileInfoLabelIfMissingAndUpdate( - IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR); + CreateInfoLabelIfMissingAndUpdate(IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR, + &mobile_status_message_); mobile_header_view_->SetToggleVisibility(/*visible=*/false); return; } @@ -415,8 +436,9 @@ /*is_on=*/cellular_enabled); if (cellular_state == DeviceStateType::kDisabling) { - CreateMobileInfoLabelIfMissingAndUpdate( - IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLING); + CreateInfoLabelIfMissingAndUpdate( + IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLING, + &mobile_status_message_); return; } @@ -426,13 +448,13 @@ return; } - CreateMobileInfoLabelIfMissingAndUpdate( - IDS_ASH_STATUS_TRAY_NO_MOBILE_NETWORKS); + CreateInfoLabelIfMissingAndUpdate(IDS_ASH_STATUS_TRAY_NO_MOBILE_NETWORKS, + &mobile_status_message_); return; } - CreateMobileInfoLabelIfMissingAndUpdate( - IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLED); + CreateInfoLabelIfMissingAndUpdate( + IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLED, &mobile_status_message_); return; } @@ -444,14 +466,15 @@ if (bluetooth_system_state_ == BluetoothSystemState::kEnabling) { mobile_header_view_->SetToggleState(/*toggle_enabled=*/false, /*is_on=*/true); - CreateMobileInfoLabelIfMissingAndUpdate( - IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR); + CreateInfoLabelIfMissingAndUpdate( + IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR, &mobile_status_message_); return; } mobile_header_view_->SetToggleState( /*toggle_enabled=*/!is_secondary_user, /*is_on=*/false); - CreateMobileInfoLabelIfMissingAndUpdate( - IDS_ASH_STATUS_TRAY_ENABLING_MOBILE_ENABLES_BLUETOOTH); + CreateInfoLabelIfMissingAndUpdate( + IDS_ASH_STATUS_TRAY_ENABLING_MOBILE_ENABLES_BLUETOOTH, + &mobile_status_message_); return; } @@ -461,28 +484,41 @@ mobile_header_view_->SetToggleState(/*toggle_enabled=*/!is_secondary_user, /*is_on=*/tether_enabled); if (tether_enabled && !has_mobile_networks_) { - CreateMobileInfoLabelIfMissingAndUpdate( - IDS_ASH_STATUS_TRAY_NO_MOBILE_DEVICES_FOUND); + CreateInfoLabelIfMissingAndUpdate( + IDS_ASH_STATUS_TRAY_NO_MOBILE_DEVICES_FOUND, &mobile_status_message_); return; } RemoveAndResetViewIfExists(&mobile_status_message_); } -void NetworkListViewControllerImpl::CreateMobileInfoLabelIfMissingAndUpdate( - int message_id) { +void NetworkListViewControllerImpl::CreateInfoLabelIfMissingAndUpdate( + int message_id, + TrayInfoLabel** info_label_ptr) { DCHECK(message_id); + DCHECK(info_label_ptr); - if (mobile_status_message_) { - mobile_status_message_->Update(message_id); + TrayInfoLabel* info_label = *info_label_ptr; + + if (info_label) { + info_label->Update(message_id); return; } std::unique_ptr<TrayInfoLabel> info = std::make_unique<TrayInfoLabel>(message_id); - info->SetID(static_cast<int>( - NetworkListViewControllerViewChildId::kMobileStatusMessage)); - mobile_status_message_ = + + if (info_label_ptr == &mobile_status_message_) { + info->SetID(static_cast<int>( + NetworkListViewControllerViewChildId::kMobileStatusMessage)); + } else if (info_label_ptr == &wifi_status_message_) { + info->SetID(static_cast<int>( + NetworkListViewControllerViewChildId::kWifiStatusMessage)); + } else { + NOTREACHED(); + } + + *info_label_ptr = network_detailed_network_view()->network_list()->AddChildView( std::move(info)); }
diff --git a/ash/system/network/network_list_view_controller_impl.h b/ash/system/network/network_list_view_controller_impl.h index 9dcc79e..62ad1a8 100644 --- a/ash/system/network/network_list_view_controller_impl.h +++ b/ash/system/network/network_list_view_controller_impl.h
@@ -62,6 +62,7 @@ kMobileSectionHeader = 15, kWifiSeperator = 16, kWifiSectionHeader = 17, + kWifiStatusMessage = 18, }; // Map of network guids and their corresponding list item views. @@ -84,8 +85,9 @@ std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr> networks); - // Checks |networks| and caches whether mobile network exist in the list - // of |networks|. Also caches if a Mobile networks are enabled. + // Checks |networks| and caches whether Mobile network, WiFi networks and vpn + // networks exist in the list of |networks|. Also caches if a Mobile and + // WiFi networks are enabled. void UpdateNetworkTypeExistence( const std::vector< chromeos::network_config::mojom::NetworkStatePropertiesPtr>& @@ -104,13 +106,22 @@ int CreateSeparatorIfMissingAndReorder(int index, views::Separator** separator_view); - // Updates mobile data section, updates add eSIM button states and + // Updates Mobile data section, updates add eSIM button states and // calls UpdateMobileToggleAndSetStatusMessage(). - void UpdateMobileSectionHeader(); + void UpdateMobileSection(); + + // Updates the WiFi data section. This method creates a new header if one does + // not exist, and will update both the WiFi toggle and "add network" button. + // If there are no WiFi networks or WiFi is disabled, this method will also + // add an info message. + void UpdateWifiSection(); // Updated mobile data toggle states and sets mobile data status message. void UpdateMobileToggleAndSetStatusMessage(); - void CreateMobileInfoLabelIfMissingAndUpdate(int message_id); + + // Creates an info label if missing and updates info label message. + void CreateInfoLabelIfMissingAndUpdate(int message_id, + TrayInfoLabel** info_label_ptr); // Creates a NetworkListNetworkItem if it does not exist else uses the // existing view, also reorders it in NetworkDetailedNetworkView scroll list. @@ -146,8 +157,10 @@ NetworkListWifiHeaderView* wifi_header_view_ = nullptr; views::Separator* wifi_separator_view_ = nullptr; + TrayInfoLabel* wifi_status_message_ = nullptr; bool has_mobile_networks_; + bool has_wifi_networks_; bool is_vpn_connected_; bool is_mobile_network_enabled_; bool is_wifi_enabled_;
diff --git a/ash/system/network/network_list_view_controller_unittest.cc b/ash/system/network/network_list_view_controller_unittest.cc index 7f1a7d4..131161c9 100644 --- a/ash/system/network/network_list_view_controller_unittest.cc +++ b/ash/system/network/network_list_view_controller_unittest.cc
@@ -220,6 +220,12 @@ kMobileStatusMessage); } + TrayInfoLabel* GetWifiStatusMessage() { + return FindViewById<TrayInfoLabel*>( + NetworkListViewControllerImpl::NetworkListViewControllerViewChildId:: + kWifiStatusMessage); + } + TriView* GetConnectionWarning() { return FindViewById<TriView*>( NetworkListViewControllerImpl::NetworkListViewControllerViewChildId:: @@ -302,6 +308,15 @@ EXPECT_STREQ(network_list()->children().at(index++)->GetClassName(), kNetworkListNetworkItemView); } + + if (!wifi_network_count) { + // When no WiFi networks are available, status message is shown. + EXPECT_NE(nullptr, GetWifiStatusMessage()); + index++; + } else { + // Status message is not shown when WiFi networks are available. + EXPECT_EQ(nullptr, GetWifiStatusMessage()); + } } void CheckNetworkListItem(NetworkType type, @@ -701,6 +716,9 @@ TEST_F(NetworkListViewControllerTest, HasCorrectWifiNetworkList) { std::vector<NetworkStatePropertiesPtr> networks; + // Add an enabled wifi device. + AddWifiDevice(); + // Add Wifi network. NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties( kWifiName, NetworkType::kWiFi, ConnectionStateType::kNotConnected); @@ -896,6 +914,40 @@ EXPECT_EQ(nullptr, GetMobileStatusMessage()); } +TEST_F(NetworkListViewControllerTest, HasCorrectWifiStatusMessage) { + EXPECT_EQ(nullptr, GetWifiStatusMessage()); + + // Add an enabled wifi device. + AddWifiDevice(); + + // Wifi is enabled but not networks are added. + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED), + GetWifiStatusMessage()->label()->GetText()); + + // Disable wifi device. + network_state_handler()->SetTechnologyEnabled( + NetworkTypePattern::WiFi(), /*enabled=*/false, base::DoNothing()); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ( + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED), + GetWifiStatusMessage()->label()->GetText()); + + // Enable and add wifi network. + network_state_handler()->SetTechnologyEnabled( + NetworkTypePattern::WiFi(), /*enabled=*/true, base::DoNothing()); + base::RunLoop().RunUntilIdle(); + + std::vector<NetworkStatePropertiesPtr> networks; + networks.push_back(CreateStandaloneNetworkProperties( + kWifiName, NetworkType::kWiFi, ConnectionStateType::kNotConnected)); + UpdateNetworkList(networks); + + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/-1, + /*wifi_network_count=*/1); +} + TEST_F(NetworkListViewControllerTest, HasConnectionWarning) { EXPECT_EQ(nullptr, GetConnectionWarning());
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc index 9b38bbd..c848bec 100644 --- a/ash/system/status_area_widget.cc +++ b/ash/system/status_area_widget.cc
@@ -352,13 +352,8 @@ : 0; // We update visibility of each tray button based on the available width. - const int shelf_width = - shelf_->shelf_widget()->GetClientAreaBoundsInScreen().width(); - const int available_width = - (force_collapsible - ? kStatusAreaForceCollapseAvailableWidth - : shelf_width / 2 - kStatusAreaLeftPaddingForOverflow) - - stop_recording_button_width; + const int available_width = GetCollapseAvailableWidth(force_collapsible) - + stop_recording_button_width; // First, reset all tray button to be hidden. overflow_button_tray_->ResetStateToCollapsed(); @@ -448,11 +443,8 @@ if (state == CollapseState::COLLAPSED) { // We might not need to be collapsed, if there is enough space for all the // buttons. - const int shelf_width = - shelf_->shelf_widget()->GetClientAreaBoundsInScreen().width(); - const int available_width = - force_collapsible ? kStatusAreaForceCollapseAvailableWidth - : shelf_width / 2 - kStatusAreaLeftPaddingForOverflow; + const int available_width = GetCollapseAvailableWidth(force_collapsible); + int used_width = 0; for (TrayBackgroundView* tray : base::Reversed(tray_buttons_)) { // If we reach the final overflow tray button, then all the tray buttons @@ -648,4 +640,21 @@ child_visibility_bitmask, should_animate}; } +int StatusAreaWidget::GetCollapseAvailableWidth(bool force_collapsible) const { + const int shelf_width = + shelf_->shelf_widget()->GetClientAreaBoundsInScreen().width(); + + if (!force_collapsible) + return shelf_width / 2 - kStatusAreaLeftPaddingForOverflow; + + int available_width = kStatusAreaForceCollapseAvailableWidth; + // If calendar view is enabled, add the date tray width to the collapse + // available width. + if (features::IsCalendarViewEnabled()) { + DCHECK(date_tray_); + available_width += date_tray_->tray_container()->GetPreferredSize().width(); + } + return available_width; +} + } // namespace ash
diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h index f80809e9..607f7b7 100644 --- a/ash/system/status_area_widget.h +++ b/ash/system/status_area_widget.h
@@ -234,6 +234,11 @@ // current conditions. CollapseState CalculateCollapseState() const; + // Gets the collapse available width based on if the date tray is shown. + // If `force_collapsible`, returns a fixed width which is not based on the + // shelf width. + int GetCollapseAvailableWidth(bool force_collapsible) const; + StatusAreaWidgetDelegate* const status_area_widget_delegate_; StatusAreaOverflowButtonTray* overflow_button_tray_ = nullptr;
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc index 12f160c..8753871a 100644 --- a/ash/system/status_area_widget_unittest.cc +++ b/ash/system/status_area_widget_unittest.cc
@@ -570,10 +570,11 @@ switches::kAshForceStatusAreaCollapsible); status_area_->UpdateCollapseState(); - // The palette tray button should not visible initially. EXPECT_EQ(StatusAreaWidget::CollapseState::COLLAPSED, collapse_state()); EXPECT_FALSE(ime_menu_->GetVisible()); EXPECT_FALSE(virtual_keyboard_->GetVisible()); + + // The palette tray button should visible initially. EXPECT_TRUE(palette_->GetVisible()); // Hiding it should make the virtual keyboard tray button replace it. @@ -591,7 +592,7 @@ EXPECT_EQ(StatusAreaWidget::CollapseState::COLLAPSED, collapse_state()); // If all tray buttons can fit in the available space, the overflow button is - // now shown. + // not shown. select_to_speak_->SetVisiblePreferred(false); ime_menu_->SetVisiblePreferred(false); dictation_button_->SetVisiblePreferred(false);
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html index c5566c1..41ac52b8 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html
@@ -129,7 +129,7 @@ </div> </template> <template is="dom-if" if="[[!loadingAmbientMode_(ambientModeEnabled_)]]"> - <toggle-row checked="[[ambientModeEnabled_]]" + <toggle-row id="ambientToggleRow" checked="[[ambientModeEnabled_]]" on-click="onClickAmbientModeButton_" on-change="onToggleStateChanged_"> </toggle-row> </template>
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts index fe176a5..7c27844 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts
@@ -17,6 +17,7 @@ import {assert} from 'chrome://resources/js/assert_ts.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {afterNextRender} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {AmbientModeAlbum, AnimationTheme, TemperatureUnit, TopicSource} from '../personalization_app.mojom-webui.js'; import {isAmbientModeAllowed, Paths} from '../personalization_router_element.js'; @@ -76,6 +77,20 @@ private temperatureUnit_: TemperatureUnit|null = null; private topicSource_: TopicSource|null = null; + override ready() { + // Pre-scroll to prevent visual jank when focusing the toggle row. + window.scrollTo(0, 0); + super.ready(); + afterNextRender(this, () => { + const elem = this.shadowRoot!.getElementById('ambientToggleRow'); + if (elem) { + // Focus the toggle row to inform screen reader users of the current + // state. + elem.focus(); + } + }); + } + override connectedCallback() { assert( isAmbientModeAllowed(),
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/toggle_row_element.ts b/ash/webui/personalization_app/resources/trusted/ambient/toggle_row_element.ts index 5968268..d2c828d 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/toggle_row_element.ts +++ b/ash/webui/personalization_app/resources/trusted/ambient/toggle_row_element.ts
@@ -38,6 +38,10 @@ checked: boolean; override ariaLabel: string; + override focus() { + this.$.toggle.focus(); + } + private getAriaLabel_(): string { return this.i18n(this.checked ? 'ambientModeOn' : 'ambientModeOff'); }
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html index 07c81dd..a065b869 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html +++ b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html
@@ -57,14 +57,14 @@ <template is="dom-if" if="[[shouldShowRootPage_(path_)]]"> <personalization-main path="[[path_]]"></personalization-main> </template> - <template is="dom-if" if="[[shouldShowAmbientSubpage_(path_)]]"> + <template is="dom-if" if="[[shouldShowAmbientSubpage_(path_)]]" restamp> <ambient-subpage path="[[path_]]" query-params="[[queryParams_]]"> </ambient-subpage> </template> <template is="dom-if" if="[[shouldShowUserSubpage_(path_)]]" restamp> <user-subpage path="[[path_]]"></user-subpage> </template> - <template is="dom-if" if="[[shouldShowWallpaperSubpage_(path_)]]"> + <template is="dom-if" if="[[shouldShowWallpaperSubpage_(path_)]]" restamp> <wallpaper-subpage path="[[path_]]" query-params="[[queryParams_]]"> </wallpaper-subpage> </template>
diff --git a/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html b/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html index 9ba8279..435dc7d 100644 --- a/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html +++ b/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html
@@ -6,7 +6,7 @@ } div[slot='body'] { - height: 255px; + height: 252px; overflow: hidden; position: relative; } @@ -25,8 +25,10 @@ animation-play-state: paused; animation-timing-function: ease-in-out; background-color: white; + border-radius: 8px; bottom: 0; left: 0; + margin: 0 24px; opacity: 0; position: absolute; right: 0; @@ -39,6 +41,7 @@ #webcamVideo { border-radius: 8px; + height: 100%; /* * Mirror the webcam feed because people are used to seeing themselves in a * mirror. Still has to be mirrored even in RTL layouts.
diff --git a/base/allocator/partition_allocator/partition_alloc_config.h b/base/allocator/partition_allocator/partition_alloc_config.h index 16ed3cc..866c187 100644 --- a/base/allocator/partition_allocator/partition_alloc_config.h +++ b/base/allocator/partition_allocator/partition_alloc_config.h
@@ -78,16 +78,15 @@ // - On Linux, futex(2) // - On Windows, a fast userspace "try" operation which is available // with SRWLock -// - Otherwise, a fast userspace pthread_mutex_trylock(). -// -// On macOS, pthread_mutex_trylock() is fast by default starting with macOS -// 10.14. Chromium targets an earlier version, so it cannot be known at -// compile-time. So we use something different. On other POSIX systems, we -// assume that pthread_mutex_trylock() is suitable. +// - On macOS, pthread_mutex_trylock() is fast by default starting with macOS +// 10.14. Chromium targets an earlier version, so it cannot be known at +// compile-time. So we use something different. +// - Otherwise, on POSIX we assume that a fast userspace pthread_mutex_trylock() +// is available. // // Otherwise, a userspace spinlock implementation is used. #if defined(PA_HAS_LINUX_KERNEL) || BUILDFLAG(IS_WIN) || \ - (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)) || BUILDFLAG(IS_FUCHSIA) + BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #define PA_HAS_FAST_MUTEX #endif
diff --git a/base/allocator/partition_allocator/spinning_mutex.cc b/base/allocator/partition_allocator/spinning_mutex.cc index 9b06852..d1577ce 100644 --- a/base/allocator/partition_allocator/spinning_mutex.cc +++ b/base/allocator/partition_allocator/spinning_mutex.cc
@@ -141,6 +141,12 @@ ::AcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&lock_)); } +#elif BUILDFLAG(IS_APPLE) + +void SpinningMutex::LockSlow() { + return os_unfair_lock_lock(&unfair_lock_); +} + #elif BUILDFLAG(IS_POSIX) void SpinningMutex::LockSlow() {
diff --git a/base/allocator/partition_allocator/spinning_mutex.h b/base/allocator/partition_allocator/spinning_mutex.h index 7719bb05..8412626 100644 --- a/base/allocator/partition_allocator/spinning_mutex.h +++ b/base/allocator/partition_allocator/spinning_mutex.h
@@ -51,19 +51,17 @@ // We don't rely on base::Lock which we could make spin (by calling Try() in a // loop), as performance is below a custom spinlock as seen on high-level // benchmarks. Instead this implements a simple non-recursive mutex on top of -// the futex() syscall on Linux, and SRWLock on Windows. The main difference -// between this and a libc implementation is that it only supports the simplest -// path: private (to a process), non-recursive mutexes with no priority -// inheritance, no timed waits. +// the futex() syscall on Linux, SRWLock on Windows, os_unfair_lock on macOS, +// and pthread_mutex on POSIX. The main difference between this and a libc +// implementation is that it only supports the simplest path: private (to a +// process), non-recursive mutexes with no priority inheritance, no timed waits. // // As an interesting side-effect to be used in the allocator, this code does not // make any allocations, locks are small with a constexpr constructor and no // destructor. // // 2. Otherwise: This is a simple SpinLock, in the sense that it does not have -// any awareness of other threads' behavior. One exception: x86 macOS uses -// os_unfair_lock() if available, which is the case for macOS >= 10.12, that is -// most clients. +// any awareness of other threads' behavior. class PA_LOCKABLE PA_COMPONENT_EXPORT(PARTITION_ALLOC) SpinningMutex { public: inline constexpr SpinningMutex(); @@ -98,6 +96,8 @@ std::atomic<int32_t> state_{kUnlocked}; #elif BUILDFLAG(IS_WIN) PA_CHROME_SRWLOCK lock_ = SRWLOCK_INIT; +#elif BUILDFLAG(IS_APPLE) + os_unfair_lock unfair_lock_ = OS_UNFAIR_LOCK_INIT; #elif BUILDFLAG(IS_POSIX) pthread_mutex_t lock_ = PTHREAD_MUTEX_INITIALIZER; #elif BUILDFLAG(IS_FUCHSIA) @@ -107,17 +107,10 @@ #else // defined(PA_HAS_FAST_MUTEX) std::atomic<bool> lock_{false}; -#if BUILDFLAG(IS_APPLE) - - os_unfair_lock unfair_lock_ = OS_UNFAIR_LOCK_INIT; - -#endif // BUILDFLAG(IS_APPLE) - // Spinlock-like, fallback. PA_ALWAYS_INLINE bool TrySpinLock(); PA_ALWAYS_INLINE void ReleaseSpinLock(); void LockSlowSpinLock(); - #endif // defined(PA_HAS_FAST_MUTEX) }; @@ -183,6 +176,16 @@ ::ReleaseSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&lock_)); } +#elif BUILDFLAG(IS_APPLE) + +PA_ALWAYS_INLINE bool SpinningMutex::Try() { + return os_unfair_lock_trylock(&unfair_lock_); +} + +PA_ALWAYS_INLINE void SpinningMutex::Release() { + return os_unfair_lock_unlock(&unfair_lock_); +} + #elif BUILDFLAG(IS_POSIX) PA_ALWAYS_INLINE bool SpinningMutex::Try() { @@ -210,47 +213,21 @@ #else // defined(PA_HAS_FAST_MUTEX) -PA_ALWAYS_INLINE bool SpinningMutex::TrySpinLock() { +PA_ALWAYS_INLINE bool SpinningMutex::Try() { // Possibly faster than CAS. The theory is that if the cacheline is shared, // then it can stay shared, for the contended case. return !lock_.load(std::memory_order_relaxed) && !lock_.exchange(true, std::memory_order_acquire); } -PA_ALWAYS_INLINE void SpinningMutex::ReleaseSpinLock() { +PA_ALWAYS_INLINE void SpinningMutex::Release() { lock_.store(false, std::memory_order_release); } -#if BUILDFLAG(IS_APPLE) - -PA_ALWAYS_INLINE bool SpinningMutex::Try() { - return os_unfair_lock_trylock(&unfair_lock_); -} - -PA_ALWAYS_INLINE void SpinningMutex::Release() { - return os_unfair_lock_unlock(&unfair_lock_); -} - -PA_ALWAYS_INLINE void SpinningMutex::LockSlow() { - return os_unfair_lock_lock(&unfair_lock_); -} - -#else - -PA_ALWAYS_INLINE bool SpinningMutex::Try() { - return TrySpinLock(); -} - -PA_ALWAYS_INLINE void SpinningMutex::Release() { - return ReleaseSpinLock(); -} - PA_ALWAYS_INLINE void SpinningMutex::LockSlow() { return LockSlowSpinLock(); } -#endif // BUILDFLAG(IS_APPLE) - #endif // defined(PA_HAS_FAST_MUTEX) } // namespace partition_alloc::internal
diff --git a/base/task/sequence_manager/atomic_flag_set.cc b/base/task/sequence_manager/atomic_flag_set.cc index 67a149f..7ff2fe5 100644 --- a/base/task/sequence_manager/atomic_flag_set.cc +++ b/base/task/sequence_manager/atomic_flag_set.cc
@@ -15,7 +15,7 @@ namespace internal { AtomicFlagSet::AtomicFlagSet( - scoped_refptr<AssociatedThreadId> associated_thread) + scoped_refptr<const AssociatedThreadId> associated_thread) : associated_thread_(std::move(associated_thread)) {} AtomicFlagSet::~AtomicFlagSet() {
diff --git a/base/task/sequence_manager/atomic_flag_set.h b/base/task/sequence_manager/atomic_flag_set.h index 3d52d89..2b20459 100644 --- a/base/task/sequence_manager/atomic_flag_set.h +++ b/base/task/sequence_manager/atomic_flag_set.h
@@ -28,7 +28,8 @@ struct Group; public: - explicit AtomicFlagSet(scoped_refptr<AssociatedThreadId> associated_thread); + explicit AtomicFlagSet( + scoped_refptr<const AssociatedThreadId> associated_thread); AtomicFlagSet(const AtomicFlagSet&) = delete; AtomicFlagSet& operator=(const AtomicFlagSet&) = delete; // AtomicFlags need to be released (or deleted) before this can be deleted. @@ -129,7 +130,7 @@ // This does not delete |element|. void RemoveFromPartiallyFreeList(Group* element); - scoped_refptr<AssociatedThreadId> associated_thread_; + const scoped_refptr<const AssociatedThreadId> associated_thread_; std::unique_ptr<Group> alloc_list_head_; raw_ptr<Group> partially_free_list_head_ = nullptr; };
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h index d3180ba8..b7c530b 100644 --- a/base/task/sequence_manager/sequence_manager_impl.h +++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -195,7 +195,7 @@ void ShutdownTaskQueueGracefully( std::unique_ptr<internal::TaskQueueImpl> task_queue); - const scoped_refptr<AssociatedThreadId>& associated_thread() const { + scoped_refptr<const AssociatedThreadId> associated_thread() const { return associated_thread_; } @@ -446,7 +446,7 @@ TaskQueue::TaskTiming InitializeTaskTiming( internal::TaskQueueImpl* task_queue); - scoped_refptr<AssociatedThreadId> associated_thread_; + const scoped_refptr<AssociatedThreadId> associated_thread_; EnqueueOrderGenerator enqueue_order_generator_;
diff --git a/base/task/sequence_manager/task_queue.h b/base/task/sequence_manager/task_queue.h index 53c8881..2f0528d3 100644 --- a/base/task/sequence_manager/task_queue.h +++ b/base/task/sequence_manager/task_queue.h
@@ -469,8 +469,8 @@ const WeakPtr<internal::SequenceManagerImpl> sequence_manager_; - scoped_refptr<internal::AssociatedThreadId> associated_thread_; - scoped_refptr<SingleThreadTaskRunner> default_task_runner_; + const scoped_refptr<const internal::AssociatedThreadId> associated_thread_; + const scoped_refptr<SingleThreadTaskRunner> default_task_runner_; int enabled_voter_count_ = 0; int voter_count_ = 0;
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc index 8163162..f79eaf2 100644 --- a/base/task/sequence_manager/task_queue_impl.cc +++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -128,7 +128,7 @@ TaskQueueImpl::TaskRunner::TaskRunner( scoped_refptr<GuardedTaskPoster> task_poster, - scoped_refptr<AssociatedThreadId> associated_thread, + scoped_refptr<const AssociatedThreadId> associated_thread, TaskType task_type) : task_poster_(std::move(task_poster)), associated_thread_(std::move(associated_thread)), @@ -1626,7 +1626,7 @@ TaskQueueImpl::OnTaskPostedCallbackHandleImpl::OnTaskPostedCallbackHandleImpl( TaskQueueImpl* task_queue_impl, - scoped_refptr<AssociatedThreadId> associated_thread) + scoped_refptr<const AssociatedThreadId> associated_thread) : task_queue_impl_(task_queue_impl), associated_thread_(std::move(associated_thread)) { DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h index 30bb789..0a7ad55 100644 --- a/base/task/sequence_manager/task_queue_impl.h +++ b/base/task/sequence_manager/task_queue_impl.h
@@ -335,9 +335,10 @@ class TaskRunner final : public SingleThreadTaskRunner { public: - explicit TaskRunner(scoped_refptr<GuardedTaskPoster> task_poster, - scoped_refptr<AssociatedThreadId> associated_thread, - TaskType task_type); + explicit TaskRunner( + scoped_refptr<GuardedTaskPoster> task_poster, + scoped_refptr<const AssociatedThreadId> associated_thread, + TaskType task_type); bool PostDelayedTask(const Location& location, OnceClosure callback, @@ -366,7 +367,7 @@ ~TaskRunner() final; const scoped_refptr<GuardedTaskPoster> task_poster_; - const scoped_refptr<AssociatedThreadId> associated_thread_; + const scoped_refptr<const AssociatedThreadId> associated_thread_; const TaskType task_type_; }; @@ -375,7 +376,7 @@ public: OnTaskPostedCallbackHandleImpl( TaskQueueImpl* task_queue_impl, - scoped_refptr<AssociatedThreadId> associated_thread_); + scoped_refptr<const AssociatedThreadId> associated_thread_); ~OnTaskPostedCallbackHandleImpl() override; // Callback handles can outlive the associated TaskQueueImpl, so the @@ -384,7 +385,7 @@ private: raw_ptr<TaskQueueImpl> task_queue_impl_; - scoped_refptr<AssociatedThreadId> associated_thread_; + const scoped_refptr<const AssociatedThreadId> associated_thread_; }; // A queue for holding delayed tasks before their delay has expired. @@ -557,7 +558,7 @@ const char* name_; const raw_ptr<SequenceManagerImpl> sequence_manager_; - scoped_refptr<AssociatedThreadId> associated_thread_; + const scoped_refptr<const AssociatedThreadId> associated_thread_; const scoped_refptr<GuardedTaskPoster> task_poster_;
diff --git a/base/task/sequence_manager/task_queue_selector.cc b/base/task/sequence_manager/task_queue_selector.cc index adba952..a527d24 100644 --- a/base/task/sequence_manager/task_queue_selector.cc +++ b/base/task/sequence_manager/task_queue_selector.cc
@@ -20,7 +20,7 @@ namespace internal { TaskQueueSelector::TaskQueueSelector( - scoped_refptr<AssociatedThreadId> associated_thread, + scoped_refptr<const AssociatedThreadId> associated_thread, const SequenceManager::Settings& settings) : associated_thread_(std::move(associated_thread)), delayed_work_queue_sets_("delayed", this, settings),
diff --git a/base/task/sequence_manager/task_queue_selector.h b/base/task/sequence_manager/task_queue_selector.h index 13ee8b0..418f312 100644 --- a/base/task/sequence_manager/task_queue_selector.h +++ b/base/task/sequence_manager/task_queue_selector.h
@@ -33,7 +33,7 @@ public: using SelectTaskOption = SequencedTaskSource::SelectTaskOption; - TaskQueueSelector(scoped_refptr<AssociatedThreadId> associated_thread, + TaskQueueSelector(scoped_refptr<const AssociatedThreadId> associated_thread, const SequenceManager::Settings& settings); TaskQueueSelector(const TaskQueueSelector&) = delete; @@ -221,7 +221,7 @@ // Returns true if there are pending tasks with priority |priority|. bool HasTasksWithPriority(TaskQueue::QueuePriority priority) const; - scoped_refptr<AssociatedThreadId> associated_thread_; + const scoped_refptr<const AssociatedThreadId> associated_thread_; // Count of the number of sets (delayed or immediate) for each priority. // Should only contain 0, 1 or 2.
diff --git a/base/task/sequence_manager/thread_controller.cc b/base/task/sequence_manager/thread_controller.cc index 6f181dca..4492b2a 100644 --- a/base/task/sequence_manager/thread_controller.cc +++ b/base/task/sequence_manager/thread_controller.cc
@@ -11,17 +11,29 @@ namespace sequence_manager { namespace internal { -ThreadController::RunLevelTracker::RunLevelTracker() = default; +ThreadController::ThreadController() + : associated_thread_(AssociatedThreadId::CreateUnbound()) {} + +ThreadController::~ThreadController() = default; + +ThreadController::RunLevelTracker::RunLevelTracker( + const ThreadController& outer) + : outer_(outer) {} ThreadController::RunLevelTracker::~RunLevelTracker() { + DCHECK_CALLED_ON_VALID_THREAD(outer_.associated_thread_->thread_checker); + // There shouldn't be any remaining |run_levels_| by the time this unwinds. DCHECK_EQ(run_levels_.size(), 0u); } void ThreadController::RunLevelTracker::OnRunLoopStarted(State initial_state) { + DCHECK_CALLED_ON_VALID_THREAD(outer_.associated_thread_->thread_checker); run_levels_.emplace(initial_state, !run_levels_.empty()); } void ThreadController::RunLevelTracker::OnRunLoopEnded() { + DCHECK_CALLED_ON_VALID_THREAD(outer_.associated_thread_->thread_checker); + // Normally this will occur while kIdle or kSelectingNextTask but it can also // occur while kRunningTask in rare situations where the owning // ThreadController is deleted from within a task. Ref. @@ -33,6 +45,7 @@ } void ThreadController::RunLevelTracker::OnTaskStarted() { + DCHECK_CALLED_ON_VALID_THREAD(outer_.associated_thread_->thread_checker); // Ignore tasks outside the main run loop. // The only practical case where this would happen is if a native loop is spun // outside the main runloop (e.g. system dialog during startup). We cannot @@ -53,6 +66,7 @@ } void ThreadController::RunLevelTracker::OnTaskEnded() { + DCHECK_CALLED_ON_VALID_THREAD(outer_.associated_thread_->thread_checker); if (run_levels_.empty()) return; @@ -67,6 +81,7 @@ } void ThreadController::RunLevelTracker::OnIdle() { + DCHECK_CALLED_ON_VALID_THREAD(outer_.associated_thread_->thread_checker); if (run_levels_.empty()) return;
diff --git a/base/task/sequence_manager/thread_controller.h b/base/task/sequence_manager/thread_controller.h index b96c7e8..ad14d96 100644 --- a/base/task/sequence_manager/thread_controller.h +++ b/base/task/sequence_manager/thread_controller.h
@@ -9,12 +9,15 @@ #include <vector> #include "base/base_export.h" +#include "base/memory/scoped_refptr.h" #include "base/message_loop/message_pump.h" #include "base/profiler/sample_metadata.h" #include "base/run_loop.h" +#include "base/task/sequence_manager/associated_thread_id.h" #include "base/task/sequence_manager/lazy_now.h" #include "base/task/sequence_manager/tasks.h" #include "base/task/single_thread_task_runner.h" +#include "base/thread_annotations.h" #include "base/time/time.h" #include "build/build_config.h" @@ -27,7 +30,6 @@ namespace sequence_manager { namespace internal { -class AssociatedThreadId; class SequencedTaskSource; // Implementation of this interface is used by SequenceManager to schedule @@ -35,7 +37,8 @@ // interface will become more concise. class ThreadController { public: - virtual ~ThreadController() = default; + ThreadController(); + virtual ~ThreadController(); // Sets the number of tasks executed in a single invocation of DoWork. // Increasing the batch size can reduce the overhead of yielding back to the @@ -132,10 +135,14 @@ virtual void RestoreDefaultTaskRunner() = 0; virtual void AddNestingObserver(RunLoop::NestingObserver* observer) = 0; virtual void RemoveNestingObserver(RunLoop::NestingObserver* observer) = 0; - virtual const scoped_refptr<AssociatedThreadId>& GetAssociatedThread() - const = 0; + + const scoped_refptr<AssociatedThreadId>& GetAssociatedThread() const { + return associated_thread_; + } protected: + const scoped_refptr<AssociatedThreadId> associated_thread_; + // Tracks the state of each run-level (main and nested ones) in its associated // ThreadController. It does so using two high-level principles: // 1) #task-in-task-implies-nested : @@ -191,7 +198,7 @@ kRunningTask, }; - RunLevelTracker(); + explicit RunLevelTracker(const ThreadController& outer); ~RunLevelTracker(); void OnRunLoopStarted(State initial_state); @@ -200,7 +207,10 @@ void OnTaskEnded(); void OnIdle(); - size_t num_run_levels() const { return run_levels_.size(); } + size_t num_run_levels() const { + DCHECK_CALLED_ON_VALID_THREAD(outer_.associated_thread_->thread_checker); + return run_levels_.size(); + } // Observers changes of state sent as trace-events so they can be tested. class TraceObserverForTesting { @@ -237,10 +247,13 @@ size_t thread_controller_active_id_ = 0; }; - std::stack<RunLevel, std::vector<RunLevel>> run_levels_; + [[maybe_unused]] const ThreadController& outer_; + + std::stack<RunLevel, std::vector<RunLevel>> run_levels_ + GUARDED_BY_CONTEXT(outer_.associated_thread_->thread_checker); static TraceObserverForTesting* trace_observer_for_testing_; - }; + } run_level_tracker_{*this}; }; } // namespace internal
diff --git a/base/task/sequence_manager/thread_controller_impl.cc b/base/task/sequence_manager/thread_controller_impl.cc index 91d72498..2e30022 100644 --- a/base/task/sequence_manager/thread_controller_impl.cc +++ b/base/task/sequence_manager/thread_controller_impl.cc
@@ -29,7 +29,6 @@ const TickClock* time_source) : funneled_sequence_manager_(funneled_sequence_manager), task_runner_(task_runner), - associated_thread_(AssociatedThreadId::CreateUnbound()), message_loop_task_runner_(funneled_sequence_manager ? funneled_sequence_manager->GetTaskRunner() : nullptr), @@ -47,14 +46,13 @@ // Unlike ThreadControllerWithMessagePumpImpl, ThreadControllerImpl isn't // explicitly Run(). Rather, DoWork() will be invoked at some point in the // future when the associated thread begins pumping messages. - main_sequence_only().run_level_tracker.OnRunLoopStarted( - RunLevelTracker::kIdle); + run_level_tracker_.OnRunLoopStarted(RunLevelTracker::kIdle); } ThreadControllerImpl::~ThreadControllerImpl() { // Balances OnRunLoopStarted() in the constructor to satisfy the exit criteria // of ~RunLevelTracker(). - main_sequence_only().run_level_tracker.OnRunLoopEnded(); + run_level_tracker_.OnRunLoopEnded(); } ThreadControllerImpl::MainSequenceOnly::MainSequenceOnly() = default; @@ -193,8 +191,8 @@ // [OnTaskStarted(), OnTaskEnded()] must outscope all other tracing calls // so that the "ThreadController active" trace event lives on top of all // "run task" events. - DCHECK_GT(main_sequence_only().run_level_tracker.num_run_levels(), 0U); - main_sequence_only().run_level_tracker.OnTaskStarted(); + DCHECK_GT(run_level_tracker_.num_run_levels(), 0U); + run_level_tracker_.OnTaskStarted(); { // Trace-parsing tools (DevTools, Lighthouse, etc) consume this event // to determine long tasks. @@ -228,7 +226,7 @@ recent_time.reset(); } } - main_sequence_only().run_level_tracker.OnTaskEnded(); + run_level_tracker_.OnTaskEnded(); // NOTE: https://crbug.com/828835. // When we're running inside a nested RunLoop it may quit anytime, so any @@ -241,7 +239,7 @@ // to disable this batching optimization while nested. // Implementing MessagePump::Delegate ourselves will help to resolve this // issue. - if (main_sequence_only().run_level_tracker.num_run_levels() > 1) + if (run_level_tracker_.num_run_levels() > 1) break; } @@ -274,7 +272,7 @@ } // No more immediate work. - main_sequence_only().run_level_tracker.OnIdle(); + run_level_tracker_.OnIdle(); // Any future work? if (!next_wake_up) { @@ -313,14 +311,8 @@ RunLoop::RemoveNestingObserverOnCurrentThread(this); } -const scoped_refptr<AssociatedThreadId>& -ThreadControllerImpl::GetAssociatedThread() const { - return associated_thread_; -} - void ThreadControllerImpl::OnBeginNestedRunLoop() { - main_sequence_only().run_level_tracker.OnRunLoopStarted( - RunLevelTracker::kSelectingNextTask); + run_level_tracker_.OnRunLoopStarted(RunLevelTracker::kSelectingNextTask); // Just assume we have a pending task and post a DoWork to make sure we don't // grind to a halt while nested. @@ -334,7 +326,7 @@ void ThreadControllerImpl::OnExitNestedRunLoop() { if (nesting_observer_) nesting_observer_->OnExitNestedRunLoop(); - main_sequence_only().run_level_tracker.OnRunLoopEnded(); + run_level_tracker_.OnRunLoopEnded(); } void ThreadControllerImpl::SetWorkBatchSize(int work_batch_size) {
diff --git a/base/task/sequence_manager/thread_controller_impl.h b/base/task/sequence_manager/thread_controller_impl.h index b188010..0413bdb 100644 --- a/base/task/sequence_manager/thread_controller_impl.h +++ b/base/task/sequence_manager/thread_controller_impl.h
@@ -15,7 +15,6 @@ #include "base/run_loop.h" #include "base/sequence_checker.h" #include "base/task/common/task_annotator.h" -#include "base/task/sequence_manager/associated_thread_id.h" #include "base/task/sequence_manager/thread_controller.h" #include "base/task/sequence_manager/work_deduplicator.h" #include "base/task/single_thread_task_runner.h" @@ -61,7 +60,6 @@ void RestoreDefaultTaskRunner() override; void AddNestingObserver(RunLoop::NestingObserver* observer) override; void RemoveNestingObserver(RunLoop::NestingObserver* observer) override; - const scoped_refptr<AssociatedThreadId>& GetAssociatedThread() const override; void SetTaskExecutionAllowed(bool allowed) override; bool IsTaskExecutionAllowed() const override; MessagePump* GetBoundMessagePump() const override; @@ -104,13 +102,8 @@ int work_batch_size_ = 1; TimeTicks next_delayed_do_work = TimeTicks::Max(); - - // Tracks the number and state of each run-level managed by this instance. - RunLevelTracker run_level_tracker; }; - scoped_refptr<AssociatedThreadId> associated_thread_; - MainSequenceOnly main_sequence_only_; MainSequenceOnly& main_sequence_only() { DCHECK_CALLED_ON_VALID_SEQUENCE(associated_thread_->sequence_checker);
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc index 86e99b3..eed2159f 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -80,9 +80,7 @@ ThreadControllerWithMessagePumpImpl::ThreadControllerWithMessagePumpImpl( const SequenceManager::Settings& settings) - : associated_thread_(AssociatedThreadId::CreateUnbound()), - work_deduplicator_(associated_thread_), - time_source_(settings.clock) {} + : work_deduplicator_(associated_thread_), time_source_(settings.clock) {} ThreadControllerWithMessagePumpImpl::ThreadControllerWithMessagePumpImpl( std::unique_ptr<MessagePump> message_pump, @@ -266,29 +264,24 @@ RunLoop::RemoveNestingObserverOnCurrentThread(this); } -const scoped_refptr<AssociatedThreadId>& -ThreadControllerWithMessagePumpImpl::GetAssociatedThread() const { - return associated_thread_; -} - void ThreadControllerWithMessagePumpImpl::OnBeginWorkItem() { MaybeStartWatchHangsInScope(); work_id_provider_->IncrementWorkId(); - main_thread_only().run_level_tracker.OnTaskStarted(); + run_level_tracker_.OnTaskStarted(); } void ThreadControllerWithMessagePumpImpl::OnEndWorkItem() { // Work completed, stop hang watching this specific work item. hang_watch_scope_.reset(); work_id_provider_->IncrementWorkId(); - main_thread_only().run_level_tracker.OnTaskEnded(); + run_level_tracker_.OnTaskEnded(); } void ThreadControllerWithMessagePumpImpl::BeforeWait() { work_id_provider_->IncrementWorkId(); // The loop is going to sleep, stop watching for hangs. hang_watch_scope_.reset(); - main_thread_only().run_level_tracker.OnIdle(); + run_level_tracker_.OnIdle(); } MessagePump::Delegate::NextWorkInfo @@ -497,7 +490,7 @@ } } - main_thread_only().run_level_tracker.OnIdle(); + run_level_tracker_.OnIdle(); // Check if any runloop timeout has expired. if (main_thread_only().quit_runloop_after != TimeTicks::Max() && @@ -525,8 +518,7 @@ (timeout == TimeDelta::Max()) ? TimeTicks::Max() : time_source_->NowTicks() + timeout); - main_thread_only().run_level_tracker.OnRunLoopStarted( - RunLevelTracker::kSelectingNextTask); + run_level_tracker_.OnRunLoopStarted(RunLevelTracker::kSelectingNextTask); // Quit may have been called outside of a Run(), so |quit_pending| might be // true here. We can't use InTopLevelDoWork() in Quit() as this call may be @@ -542,7 +534,7 @@ pump_->Run(this); } - main_thread_only().run_level_tracker.OnRunLoopEnded(); + run_level_tracker_.OnRunLoopEnded(); main_thread_only().quit_pending = false; // All work items should be over when exiting the loop so hang watching should @@ -624,7 +616,7 @@ #endif bool ThreadControllerWithMessagePumpImpl::ShouldQuitRunLoopWhenIdle() { - if (main_thread_only().run_level_tracker.num_run_levels() == 0) + if (run_level_tracker_.num_run_levels() == 0) return false; // It's only safe to call ShouldQuitWhenIdle() when in a RunLoop. return ShouldQuitWhenIdle();
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.h b/base/task/sequence_manager/thread_controller_with_message_pump_impl.h index a79de81..09e56be 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.h +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.h
@@ -14,7 +14,6 @@ #include "base/run_loop.h" #include "base/task/common/checked_lock.h" #include "base/task/common/task_annotator.h" -#include "base/task/sequence_manager/associated_thread_id.h" #include "base/task/sequence_manager/sequence_manager_impl.h" #include "base/task/sequence_manager/sequenced_task_source.h" #include "base/task/sequence_manager/thread_controller.h" @@ -74,7 +73,6 @@ void RestoreDefaultTaskRunner() override; void AddNestingObserver(RunLoop::NestingObserver* observer) override; void RemoveNestingObserver(RunLoop::NestingObserver* observer) override; - const scoped_refptr<AssociatedThreadId>& GetAssociatedThread() const override; void SetTaskExecutionAllowed(bool allowed) override; bool IsTaskExecutionAllowed() const override; MessagePump* GetBoundMessagePump() const override; @@ -129,9 +127,6 @@ // yield to the MessagePump after |work_batch_size| work items. base::TimeTicks yield_to_native_after_batch = base::TimeTicks(); - // Tracks the number and state of each run-level managed by this instance. - RunLevelTracker run_level_tracker; - // When the next scheduled delayed work should run, if any. TimeTicks next_delayed_do_work = TimeTicks::Max(); @@ -175,8 +170,6 @@ // watching is activated via finch. void MaybeStartWatchHangsInScope(); - // TODO(altimin): Merge with the one in SequenceManager. - scoped_refptr<AssociatedThreadId> associated_thread_; MainThreadOnly main_thread_only_; mutable base::internal::CheckedLock task_runner_lock_;
diff --git a/base/task/sequence_manager/wake_up_queue.cc b/base/task/sequence_manager/wake_up_queue.cc index 5ecac60..635d2ecf 100644 --- a/base/task/sequence_manager/wake_up_queue.cc +++ b/base/task/sequence_manager/wake_up_queue.cc
@@ -15,7 +15,7 @@ namespace internal { WakeUpQueue::WakeUpQueue( - scoped_refptr<internal::AssociatedThreadId> associated_thread) + scoped_refptr<const internal::AssociatedThreadId> associated_thread) : associated_thread_(std::move(associated_thread)) {} WakeUpQueue::~WakeUpQueue() {
diff --git a/base/task/sequence_manager/wake_up_queue.h b/base/task/sequence_manager/wake_up_queue.h index 0d46349..b017ff53 100644 --- a/base/task/sequence_manager/wake_up_queue.h +++ b/base/task/sequence_manager/wake_up_queue.h
@@ -72,7 +72,7 @@ protected: explicit WakeUpQueue( - scoped_refptr<internal::AssociatedThreadId> associated_thread); + scoped_refptr<const internal::AssociatedThreadId> associated_thread); // Called every time the next `next_wake_up` changes. absl::nullopt is used to // cancel the next wake-up. Subclasses may use this to tell SequenceManager to @@ -109,7 +109,7 @@ IntrusiveHeap<ScheduledWakeUp, std::greater<>> wake_up_queue_; int pending_high_res_wake_up_count_ = 0; - scoped_refptr<internal::AssociatedThreadId> associated_thread_; + const scoped_refptr<const internal::AssociatedThreadId> associated_thread_; }; // Default WakeUpQueue implementation that forwards wake-ups to
diff --git a/base/task/sequence_manager/work_deduplicator.cc b/base/task/sequence_manager/work_deduplicator.cc index f72eb7c7..6b029e6 100644 --- a/base/task/sequence_manager/work_deduplicator.cc +++ b/base/task/sequence_manager/work_deduplicator.cc
@@ -12,7 +12,7 @@ namespace internal { WorkDeduplicator::WorkDeduplicator( - scoped_refptr<AssociatedThreadId> associated_thread) + scoped_refptr<const AssociatedThreadId> associated_thread) : associated_thread_(std::move(associated_thread)) {} WorkDeduplicator::~WorkDeduplicator() = default;
diff --git a/base/task/sequence_manager/work_deduplicator.h b/base/task/sequence_manager/work_deduplicator.h index 5a21f3a..4c0731fd 100644 --- a/base/task/sequence_manager/work_deduplicator.h +++ b/base/task/sequence_manager/work_deduplicator.h
@@ -35,7 +35,7 @@ // Creates an unbound WorkDeduplicator. BindToCurrentThread must be called // before work can be scheduled. explicit WorkDeduplicator( - scoped_refptr<AssociatedThreadId> associated_thread); + scoped_refptr<const AssociatedThreadId> associated_thread); ~WorkDeduplicator(); @@ -135,7 +135,7 @@ std::atomic<int> state_{State::kUnbound}; - scoped_refptr<AssociatedThreadId> associated_thread_; + const scoped_refptr<const AssociatedThreadId> associated_thread_; }; } // namespace internal
diff --git a/build/config/coverage/OWNERS b/build/config/coverage/OWNERS index dd8d822..7b0fe27 100644 --- a/build/config/coverage/OWNERS +++ b/build/config/coverage/OWNERS
@@ -1,3 +1 @@ -inferno@chromium.org -ochang@chromium.org pasthana@google.com
diff --git a/build/config/sanitizers/OWNERS b/build/config/sanitizers/OWNERS index f6a122b5..331e8bc 100644 --- a/build/config/sanitizers/OWNERS +++ b/build/config/sanitizers/OWNERS
@@ -1,3 +1 @@ -inferno@chromium.org metzman@chromium.org -ochang@chromium.org
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 739e28d4..626f505 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -8.20220608.1.1 +8.20220609.0.1
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh index dc92d11..2c305f5e 100755 --- a/build/install-build-deps.sh +++ b/build/install-build-deps.sh
@@ -288,9 +288,15 @@ if package_exists libgl1; then lib_list="${lib_list} libgl1" fi +if package_exists libegl1; then + lib_list="${lib_list} libegl1" +fi if package_exists libgl1:i386; then lib_list="${lib_list} libgl1:i386" fi +if package_exists libegl1:i386; then + lib_list="${lib_list} libegl1:i386" +fi # 32-bit libraries needed e.g. to compile V8 snapshot for Android or armhf lib32_list="linux-libc-dev:i386 libpci3:i386"
diff --git a/build/sanitizers/OWNERS b/build/sanitizers/OWNERS index b893bc8..09f2efa9 100644 --- a/build/sanitizers/OWNERS +++ b/build/sanitizers/OWNERS
@@ -1,7 +1,5 @@ -ochang@chromium.org eugenis@chromium.org glider@chromium.org -inferno@chromium.org metzman@chromium.org rnk@chromium.org per-file tsan_suppressions.cc=*
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn index e67f09f..102e712 100644 --- a/build/toolchain/linux/BUILD.gn +++ b/build/toolchain/linux/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/dcheck_always_on.gni") import("//build/config/ozone.gni") import("//build/config/sysroot.gni") import("//build/config/ui.gni") @@ -208,7 +209,7 @@ chromeos_is_browser_only = true use_clang_coverage = false dcheck_always_on = false - symbol_level=1 + symbol_level = 1 } }
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc index cfc0d60..1892656 100644 --- a/cc/animation/animation_host.cc +++ b/cc/animation/animation_host.cc
@@ -154,6 +154,15 @@ has_smil_animation_.Write(*this) = has_smil_animation; } +bool AnimationHost::HasSharedElementTransition() const { + return has_shared_element_transition_.Read(*this); +} + +void AnimationHost::SetHasSharedElementTransition( + bool has_shared_element_transition) { + has_shared_element_transition_.Write(*this) = has_shared_element_transition; +} + void AnimationHost::SetCurrentFrameHadRaf(bool current_frame_had_raf) { current_frame_had_raf_.Write(*this) = current_frame_had_raf; } @@ -328,6 +337,7 @@ host_impl->SetHasCanvasInvalidation(HasCanvasInvalidation()); host_impl->SetHasInlineStyleMutation(HasJSAnimation()); host_impl->SetHasSmilAnimation(HasSmilAnimation()); + host_impl->SetHasSharedElementTransition(HasSharedElementTransition()); if (needs_push_properties()) { needs_push_properties_.Write(*this) = false;
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h index 3ec13443..402c54f 100644 --- a/cc/animation/animation_host.h +++ b/cc/animation/animation_host.h
@@ -211,6 +211,7 @@ bool HasCanvasInvalidation() const override; bool HasJSAnimation() const override; bool HasSmilAnimation() const override; + bool HasSharedElementTransition() const override; // Starts/stops throughput tracking represented by |sequence_id|. void StartThroughputTracking(TrackedAnimationSequenceId sequence_id); @@ -220,6 +221,7 @@ void SetHasCanvasInvalidation(bool has_canvas_invalidation); void SetHasInlineStyleMutation(bool has_inline_style_mutation); void SetHasSmilAnimation(bool has_svg_smil_animation); + void SetHasSharedElementTransition(bool hash_shared_element_transition); void SetCurrentFrameHadRaf(bool current_frame_had_raf); void SetNextFrameHasPendingRaf(bool next_frame_has_pending_raf); @@ -284,6 +286,7 @@ ProtectedSequenceReadable<bool> has_canvas_invalidation_{false}; ProtectedSequenceReadable<bool> has_inline_style_mutation_{false}; ProtectedSequenceReadable<bool> has_smil_animation_{false}; + ProtectedSequenceReadable<bool> has_shared_element_transition_{false}; ProtectedSequenceWritable<PendingThroughputTrackerInfos> pending_throughput_tracker_infos_;
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc index 96290db..c1b76e54 100644 --- a/cc/metrics/compositor_frame_reporter.cc +++ b/cc/metrics/compositor_frame_reporter.cc
@@ -347,6 +347,16 @@ DCHECK(smooth_thread_ == SmoothThread::kSmoothMain || smooth_thread_ == SmoothThread::kSmoothBoth); } + // If we have a SET version of the animation, then we should also have a + // non-SET version of the same animation. + DCHECK(!active_trackers_.test(static_cast<size_t>( + FrameSequenceTrackerType::kSETCompositorAnimation)) || + active_trackers_.test(static_cast<size_t>( + FrameSequenceTrackerType::kCompositorAnimation))); + DCHECK(!active_trackers_.test(static_cast<size_t>( + FrameSequenceTrackerType::kSETMainThreadAnimation)) || + active_trackers_.test(static_cast<size_t>( + FrameSequenceTrackerType::kMainThreadAnimation))); } // static @@ -777,6 +787,14 @@ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.JSAnimation", report_type); break; + case FrameSequenceTrackerType::kSETCompositorAnimation: + UMA_HISTOGRAM_ENUMERATION( + "CompositorLatency.Type.SETCompositorAnimation", report_type); + break; + case FrameSequenceTrackerType::kSETMainThreadAnimation: + UMA_HISTOGRAM_ENUMERATION( + "CompositorLatency.Type.SETMainThreadAnimation", report_type); + break; case FrameSequenceTrackerType::kCustom: case FrameSequenceTrackerType::kMaxType: NOTREACHED();
diff --git a/cc/metrics/frame_sequence_metrics.cc b/cc/metrics/frame_sequence_metrics.cc index df79838..5d39381 100644 --- a/cc/metrics/frame_sequence_metrics.cc +++ b/cc/metrics/frame_sequence_metrics.cc
@@ -25,6 +25,10 @@ bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type, SmoothEffectDrivingThread thread_type) { + // kSETMainThreadAnimation and kSETCompositorAnimation sequences are a subset + // of kMainThreadAnimation and kCompositorAnimation sequences. So these are + // excluded from the AllAnimation metric to avoid double counting. + if (sequence_type == FrameSequenceTrackerType::kCompositorAnimation) return thread_type == SmoothEffectDrivingThread::kCompositor; @@ -156,11 +160,13 @@ SmoothEffectDrivingThread FrameSequenceMetrics::GetEffectiveThread() const { switch (type_) { case FrameSequenceTrackerType::kCompositorAnimation: + case FrameSequenceTrackerType::kSETCompositorAnimation: case FrameSequenceTrackerType::kPinchZoom: case FrameSequenceTrackerType::kVideo: return SmoothEffectDrivingThread::kCompositor; case FrameSequenceTrackerType::kMainThreadAnimation: + case FrameSequenceTrackerType::kSETMainThreadAnimation: case FrameSequenceTrackerType::kRAF: case FrameSequenceTrackerType::kCanvasAnimation: case FrameSequenceTrackerType::kJSAnimation: @@ -311,7 +317,6 @@ base::LinearHistogram::FactoryGet( GetThroughputV2HistogramName(type(), thread_name), 1, 100, 101, base::HistogramBase::kUmaTargetedHistogramFlag)); - v2_ = {}; } @@ -513,14 +518,16 @@ const auto sequence_type = metrics->type(); DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType); - // All video frames are compositor thread only. - if (sequence_type == FrameSequenceTrackerType::kVideo && + // All video frames and SET compositor animations are compositor thread only. + if ((sequence_type == FrameSequenceTrackerType::kVideo || + sequence_type == FrameSequenceTrackerType::kSETCompositorAnimation) && thread_type == SmoothEffectDrivingThread::kMain) return false; - // RAF and CanvasAnimation are main thread only. + // RAF, CanvasAnimation and SET main thread animations are main thread only. if ((sequence_type == FrameSequenceTrackerType::kRAF || - sequence_type == FrameSequenceTrackerType::kCanvasAnimation) && + sequence_type == FrameSequenceTrackerType::kCanvasAnimation || + sequence_type == FrameSequenceTrackerType::kSETMainThreadAnimation) && thread_type == SmoothEffectDrivingThread::kCompositor) return false; @@ -533,7 +540,9 @@ return is_animation || IsInteractionType(sequence_type) || sequence_type == FrameSequenceTrackerType::kVideo || sequence_type == FrameSequenceTrackerType::kRAF || - sequence_type == FrameSequenceTrackerType::kCanvasAnimation; + sequence_type == FrameSequenceTrackerType::kCanvasAnimation || + sequence_type == FrameSequenceTrackerType::kSETMainThreadAnimation || + sequence_type == FrameSequenceTrackerType::kSETCompositorAnimation; } int FrameSequenceMetrics::ThroughputData::ReportDroppedFramePercentHistogram(
diff --git a/cc/metrics/frame_sequence_metrics.h b/cc/metrics/frame_sequence_metrics.h index ba9fb74e..33fa2b8 100644 --- a/cc/metrics/frame_sequence_metrics.h +++ b/cc/metrics/frame_sequence_metrics.h
@@ -40,6 +40,8 @@ // and instead are dispatched back to the LayerTreeHostClient. kCanvasAnimation = 10, kJSAnimation = 11, + kSETMainThreadAnimation = 12, + kSETCompositorAnimation = 13, kMaxType };
diff --git a/cc/metrics/frame_sequence_metrics_unittest.cc b/cc/metrics/frame_sequence_metrics_unittest.cc index cbef003..c5729bd 100644 --- a/cc/metrics/frame_sequence_metrics_unittest.cc +++ b/cc/metrics/frame_sequence_metrics_unittest.cc
@@ -233,4 +233,50 @@ } } +TEST(FrameSequenceMetricsTest, CompositorSharedElementTransitionReported) { + base::HistogramTester histograms; + + auto metrics = std::make_unique<FrameSequenceMetrics>( + FrameSequenceTrackerType::kSETCompositorAnimation, nullptr); + metrics->impl_throughput().frames_expected = 100; + metrics->impl_throughput().frames_produced = 80; + metrics->impl_throughput().frames_ontime = 70; + metrics->main_throughput().frames_expected = 100; + metrics->main_throughput().frames_produced = 60; + metrics->main_throughput().frames_ontime = 50; + EXPECT_TRUE(metrics->HasEnoughDataForReporting()); + metrics->ReportMetrics(); + histograms.ExpectTotalCount( + "Graphics.Smoothness.PercentDroppedFrames.CompositorThread." + "SETCompositorAnimation", + 1u); + histograms.ExpectTotalCount( + "Graphics.Smoothness.PercentDroppedFrames.MainThread." + "SETCompositorAnimation", + 0u); +} + +TEST(FrameSequenceMetricsTest, MainThreadSharedElementTransitionReported) { + base::HistogramTester histograms; + + auto metrics = std::make_unique<FrameSequenceMetrics>( + FrameSequenceTrackerType::kSETMainThreadAnimation, nullptr); + metrics->impl_throughput().frames_expected = 100; + metrics->impl_throughput().frames_produced = 80; + metrics->impl_throughput().frames_ontime = 70; + metrics->main_throughput().frames_expected = 100; + metrics->main_throughput().frames_produced = 60; + metrics->main_throughput().frames_ontime = 50; + EXPECT_TRUE(metrics->HasEnoughDataForReporting()); + metrics->ReportMetrics(); + histograms.ExpectTotalCount( + "Graphics.Smoothness.PercentDroppedFrames.CompositorThread." + "SETMainThreadAnimation", + 0u); + histograms.ExpectTotalCount( + "Graphics.Smoothness.PercentDroppedFrames.MainThread." + "SETMainThreadAnimation", + 1u); +} + } // namespace cc
diff --git a/cc/metrics/frame_sequence_tracker.cc b/cc/metrics/frame_sequence_tracker.cc index baf282b8..8db6973 100644 --- a/cc/metrics/frame_sequence_tracker.cc +++ b/cc/metrics/frame_sequence_tracker.cc
@@ -74,6 +74,10 @@ return "CanvasAnimation"; case FrameSequenceTrackerType::kJSAnimation: return "JSAnimation"; + case FrameSequenceTrackerType::kSETMainThreadAnimation: + return "SETMainThreadAnimation"; + case FrameSequenceTrackerType::kSETCompositorAnimation: + return "SETCompositorAnimation"; case FrameSequenceTrackerType::kMaxType: return ""; }
diff --git a/cc/test/mock_mutator_host.h b/cc/test/mock_mutator_host.h index 9c294d8..81378dda 100644 --- a/cc/test/mock_mutator_host.h +++ b/cc/test/mock_mutator_host.h
@@ -89,6 +89,7 @@ MOCK_CONST_METHOD0(HasNativePropertyAnimation, bool()); MOCK_CONST_METHOD0(CurrentFrameHadRAF, bool()); MOCK_CONST_METHOD0(HasSmilAnimation, bool()); + MOCK_CONST_METHOD0(HasSharedElementTransition, bool()); MOCK_CONST_METHOD0(NextFrameHasPendingRAF, bool()); MOCK_METHOD0(TakePendingThroughputTrackerInfos, PendingThroughputTrackerInfos());
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index cde4cfa..269b0c2 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -722,6 +722,10 @@ mutator_host_->HasSmilAnimation()) { frame_trackers_.StartSequence( FrameSequenceTrackerType::kMainThreadAnimation); + if (mutator_host_->HasSharedElementTransition()) { + frame_trackers_.StartSequence( + FrameSequenceTrackerType::kSETMainThreadAnimation); + } } for (const auto& info : mutator_host_->TakePendingThroughputTrackerInfos()) { @@ -2513,6 +2517,11 @@ !mutator_host_->HasSmilAnimation()) { frame_trackers_.StopSequence( FrameSequenceTrackerType::kMainThreadAnimation); + frame_trackers_.StopSequence( + FrameSequenceTrackerType::kSETMainThreadAnimation); + } else if (!mutator_host_->HasSharedElementTransition()) { + frame_trackers_.StopSequence( + FrameSequenceTrackerType::kSETMainThreadAnimation); } if (lcd_text_metrics_reporter_) { @@ -4239,6 +4248,14 @@ FrameSequenceTrackerType::kCompositorAnimation); } + if (animated && mutator_host_->HasSharedElementTransition()) { + frame_trackers_.StartSequence( + FrameSequenceTrackerType::kSETCompositorAnimation); + } else { + frame_trackers_.StopSequence( + FrameSequenceTrackerType::kSETCompositorAnimation); + } + // TODO(crbug.com/551138): We could return true only if the animations are on // the active tree. There's no need to cause a draw to take place from // animations starting/ticking on the pending tree.
diff --git a/cc/trees/mutator_host.h b/cc/trees/mutator_host.h index 142ab6f..819856c 100644 --- a/cc/trees/mutator_host.h +++ b/cc/trees/mutator_host.h
@@ -141,6 +141,7 @@ virtual bool HasCanvasInvalidation() const = 0; virtual bool HasJSAnimation() const = 0; virtual bool HasSmilAnimation() const = 0; + virtual bool HasSharedElementTransition() const = 0; // Iterates through all animations and returns the minimum tick interval. // Returns 0 if there is a continuous animation which should be ticked
diff --git a/cc/trees/ukm_manager.cc b/cc/trees/ukm_manager.cc index e0b88d5..6d8e854 100644 --- a/cc/trees/ukm_manager.cc +++ b/cc/trees/ukm_manager.cc
@@ -51,7 +51,11 @@ CASE_FOR_MAIN_THREAD_TRACKER(CanvasAnimation); CASE_FOR_MAIN_THREAD_TRACKER(JSAnimation); #undef CASE_FOR_MAIN_THREAD_TRACKER - default: + case FrameSequenceTrackerType::kSETCompositorAnimation: + case FrameSequenceTrackerType::kSETMainThreadAnimation: + break; + case FrameSequenceTrackerType::kCustom: + case FrameSequenceTrackerType::kMaxType: NOTREACHED(); break; } @@ -74,7 +78,13 @@ CASE_FOR_COMPOSITOR_THREAD_TRACKER(Video); CASE_FOR_COMPOSITOR_THREAD_TRACKER(WheelScroll); #undef CASE_FOR_COMPOSITOR_THREAD_TRACKER - default: + case FrameSequenceTrackerType::kCanvasAnimation: + case FrameSequenceTrackerType::kJSAnimation: + case FrameSequenceTrackerType::kSETCompositorAnimation: + case FrameSequenceTrackerType::kSETMainThreadAnimation: + break; + case FrameSequenceTrackerType::kCustom: + case FrameSequenceTrackerType::kMaxType: NOTREACHED(); break; } @@ -138,7 +148,7 @@ CASE_FOR_STAGE(SubmitCompositorFrameToPresentationCompositorFrame); CASE_FOR_STAGE(TotalLatency); #undef CASE_FOR_STAGE - default: + case StageType::kStageTypeCount: NOTREACHED(); break; } @@ -165,7 +175,7 @@ CASE_FOR_BLINK_BREAKDOWN(UpdateLayers); CASE_FOR_BLINK_BREAKDOWN(BeginMainSentToStarted); #undef CASE_FOR_BLINK_BREAKDOWN - default: + case CompositorFrameReporter::BlinkBreakdown::kBreakdownCount: NOTREACHED(); break; } @@ -190,7 +200,7 @@ CASE_FOR_VIZ_BREAKDOWN(BufferReadyToLatch); CASE_FOR_VIZ_BREAKDOWN(LatchToSwapEnd); #undef CASE_FOR_VIZ_BREAKDOWN - default: + case CompositorFrameReporter::VizBreakdown::kBreakdownCount: NOTREACHED(); break; } @@ -218,7 +228,11 @@ CASE_FOR_TRACKER(CanvasAnimation); CASE_FOR_TRACKER(JSAnimation); #undef CASE_FOR_TRACKER - default: + case FrameSequenceTrackerType::kSETCompositorAnimation: + case FrameSequenceTrackerType::kSETMainThreadAnimation: + break; + case FrameSequenceTrackerType::kCustom: + case FrameSequenceTrackerType::kMaxType: NOTREACHED(); break; } @@ -355,7 +369,8 @@ CASE_FOR_STAGE(SubmitCompositorFrameToPresentationCompositorFrame, SubmitCompositorFrame); #undef CASE_FOR_STAGE - default: + case StageType::kTotalLatency: + case StageType::kStageTypeCount: NOTREACHED(); break; } @@ -376,7 +391,8 @@ CASE_FOR_STAGE(SubmitCompositorFrameToPresentationCompositorFrame, SubmitCompositorFrame); #undef CASE_FOR_STAGE - default: + case StageType::kTotalLatency: + case StageType::kStageTypeCount: NOTREACHED(); break; } @@ -385,7 +401,6 @@ NOTREACHED(); break; } - for (; stage_it != stage_history.end(); ++stage_it) { // Total latency is calculated since the event timestamp. const base::TimeTicks start_time = @@ -407,7 +422,7 @@ CASE_FOR_STAGE(SubmitCompositorFrameToPresentationCompositorFrame); CASE_FOR_STAGE(TotalLatency); #undef CASE_FOR_STAGE - default: + case StageType::kStageTypeCount: NOTREACHED(); break; } @@ -434,7 +449,7 @@ CASE_FOR_BLINK_BREAKDOWN(UpdateLayers); CASE_FOR_BLINK_BREAKDOWN(BeginMainSentToStarted); #undef CASE_FOR_BLINK_BREAKDOWN - default: + case CompositorFrameReporter::BlinkBreakdown::kBreakdownCount: NOTREACHED(); break; } @@ -459,7 +474,7 @@ CASE_FOR_VIZ_BREAKDOWN(BufferReadyToLatch); CASE_FOR_VIZ_BREAKDOWN(LatchToSwapEnd); #undef CASE_FOR_VIZ_BREAKDOWN - default: + case CompositorFrameReporter::VizBreakdown::kBreakdownCount: NOTREACHED(); break; }
diff --git a/chrome/VERSION b/chrome/VERSION index d320449..9ec5897 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=104 MINOR=0 -BUILD=5110 +BUILD=5111 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 973bffa..53ade5c 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2828,7 +2828,13 @@ deps = [] if (_is_bundle) { - deps += [ "//chrome/android:chrome_base_module_resources" ] + deps += [ + "//chrome/android:chrome_base_module_resources", + + # deps in delegate_public_impl_java are put into the Chrome module, but the language deps + # are needed by the base module. + "//components/language/android:ulp_delegate_public_java", + ] } else { deps += [ ":delegate_public_impl_java" ] }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java index 443911d..ca7757f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java
@@ -37,6 +37,7 @@ import org.chromium.chrome.browser.crash.FirebaseConfig; import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.language.AppLocaleUtils; import org.chromium.chrome.browser.language.GlobalAppLocaleController; import org.chromium.chrome.browser.metrics.UmaUtils; import org.chromium.components.crash.PureJavaExceptionHandler; @@ -199,6 +200,10 @@ // Disable MemoryPressureMonitor polling when Chrome goes to the background. ApplicationStatus.registerApplicationStateListener( SplitCompatApplication::updateMemoryPressurePolling); + + if (AppLocaleUtils.shouldUseSystemManagedLocale()) { + AppLocaleUtils.maybeMigrateOverrideLanguage(); + } } BuildInfo.setFirebaseAppId(FirebaseConfig.getFirebaseAppId());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java index 7f36027..e240b92 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java
@@ -12,6 +12,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.tab.Tab; @@ -83,6 +84,7 @@ pref.writeLong(ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP, timestamp); pref.writeBoolean( ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION, hadInteraction); + RecordHistogram.recordBooleanHistogram("CustomTabs.HadInteractionOnClose", hadInteraction); } @NativeMethods
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java index 188b0596..77519ef00 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -457,6 +457,8 @@ ContextUtils.getApplicationContext())); deferredStartupHandler.addDeferredTask( () -> GlobalAppLocaleController.getInstance().recordOverrideLanguageMetrics()); + deferredStartupHandler.addDeferredTask( + () -> GlobalAppLocaleController.getInstance().maybeSetupLocaleManager()); deferredStartupHandler.addDeferredTask(() -> { // OptimizationTypes which we give a guarantee will be registered when we pass the // onDeferredStartup() signal to OptimizationGuide.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java index ec1e041..d8668e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java
@@ -87,6 +87,9 @@ // If present, this is the video's aspect ratio. private Rational mAspectRatio; + // Maximum pip width, in pixels, to prevent resizes that are too big. + private int mMaxWidth; + private BroadcastReceiver mMediaSessionReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -186,6 +189,11 @@ public void finishNativeInitialization() { super.finishNativeInitialization(); + // Compute a somewhat arbitrary cut-off of 90% of the window's display width. The PiP + // window can't be anywhere near this big, so the exact value doesn't matter. We'll ignore + // resizes messages that are above it, since they're spurious. + mMaxWidth = (int) ((getWindowAndroid().getDisplay().getDisplayWidth()) * 0.9); + mCompositorView = CompositorViewFactory.create( this, getWindowAndroid(), new ThinWebViewConstraints()); addContentView(mCompositorView.getView(), @@ -200,8 +208,13 @@ // We sometimes get an initial update of zero before getting something reasonable. if (top == bottom || left == right) return; + // On close, sometimes we get a size update that's almost the entire display width. + // Pip window's can't be that big, so ignore it. + final int width = right - left; + if (width > mMaxWidth) return; + PictureInPictureActivityJni.get().onViewSizeChanged( - sNativeOverlayWindowAndroid, right - left, bottom - top); + sNativeOverlayWindowAndroid, width, bottom - top); } }); @@ -450,6 +463,11 @@ return original; } + @VisibleForTesting + /* package */ View getViewForTesting() { + return mCompositorView.getView(); + } + @NativeMethods public interface Natives { void onActivityStart(long nativeOverlayWindowAndroid, PictureInPictureActivity self,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 60dbd9e..aba87c53 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -1371,6 +1371,10 @@ ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION) && SharedPreferencesManager.getInstance().contains( ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP)); + + Assert.assertEquals(1, + RecordHistogram.getHistogramTotalCountForTesting( + "CustomTabs.HadInteractionOnClose")); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java index e4f173d..2e8b0dd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.media; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -16,6 +17,7 @@ import android.os.Bundle; import android.support.test.InstrumentationRegistry; import android.util.Rational; +import android.view.View; import androidx.annotation.RequiresApi; import androidx.test.filters.MediumTest; @@ -140,6 +142,24 @@ Assert.assertTrue(mBounds == null); } + @Test + @MediumTest + @MinAndroidSdkLevel(Build.VERSION_CODES.O) + public void testResize() throws Throwable { + PictureInPictureActivity activity = startPictureInPictureActivity(); + // Resize to some reasonable size, and verify that native is told about it. + final int reasonableSize = 10; + View view = activity.getViewForTesting(); + view.layout(0, 0, reasonableSize, reasonableSize); + verify(mNativeMock, times(1)) + .onViewSizeChanged(NATIVE_OVERLAY, reasonableSize, reasonableSize); + + // An unreasonably large size should not generate a resize event. + final int unreasonableSize = activity.getWindowAndroid().getDisplay().getDisplayWidth(); + view.layout(0, 0, unreasonableSize, unreasonableSize); + verify(mNativeMock, times(0)).onViewSizeChanged(anyInt(), anyInt(), anyInt()); + } + private WebContents getWebContents() { return mActivityTestRule.getActivity().getCurrentWebContents(); }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1dcd8f8b..5af60f8 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -7854,13 +7854,6 @@ FEATURE_VALUE_TYPE(ui::kEnableInputEventLogging)}, #endif - {"autofill-enable-merchant-bound-virtual-cards", - flag_descriptions::kAutofillEnableMerchantBoundVirtualCardsName, - flag_descriptions::kAutofillEnableMerchantBoundVirtualCardsDescription, - kOsDesktop | kOsAndroid, - FEATURE_VALUE_TYPE( - autofill::features::kAutofillEnableMerchantBoundVirtualCards)}, - {"autofill-enable-sticky-manual-fallback-for-cards", flag_descriptions::kAutofillEnableStickyManualFallbackForCardsName, flag_descriptions::kAutofillEnableStickyManualFallbackForCardsDescription,
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h index 01cd02d..2e666b3 100644 --- a/chrome/browser/app_controller_mac.h +++ b/chrome/browser/app_controller_mac.h
@@ -20,7 +20,6 @@ #include "components/prefs/pref_change_registrar.h" class AppControllerProfileObserver; -class AppControllerNativeThemeObserver; @class AppShimMenuController; class BookmarkMenuBridge; class CommandUpdater; @@ -36,7 +35,7 @@ class TabMenuBridge; namespace ui { -class ColorProvider; +class ThemeProvider; } // namespace ui // The application controller object, created by loading the MainMenu nib. @@ -60,10 +59,6 @@ std::unique_ptr<AppControllerProfileObserver> _profileAttributesStorageObserver; - // The NativeThemeObserver observes system-wide theme related settings - // change. - std::unique_ptr<AppControllerNativeThemeObserver> _nativeThemeObserver; - // Management of the bookmark menu which spans across all windows // (and Browser*s). |profileBookmarkMenuBridgeMap_| is a cache that owns one // pointer to a BookmarkMenuBridge for each profile. |bookmarkMenuBridge_| is @@ -120,8 +115,6 @@ // Request to keep the browser alive during that object's lifetime. std::unique_ptr<ScopedKeepAlive> _keep_alive; - - const ui::ColorProvider* _lastActiveColorProvider; } @property(readonly, nonatomic) BOOL startupComplete; @@ -203,11 +196,9 @@ // the original or the incognito profile. - (void)setLastProfile:(Profile*)profile; -// Returns the last active ColorProvider. -- (const ui::ColorProvider&)lastActiveColorProvider; - -// This is called when the system wide light or dark mode changes. -- (void)nativeThemeDidChange; +// Returns the last active ThemeProvider. It is only valid to call this with a +// last available profile. +- (const ui::ThemeProvider&)lastActiveThemeProvider; // Certain NSMenuItems [Close Tab and Close Window] have different // keyEquivalents depending on context. This must be invoked in two locations:
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 78a2ae8..9163dc8 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -57,6 +57,7 @@ #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" +#include "chrome/browser/themes/theme_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_commands.h" @@ -111,8 +112,6 @@ #include "net/base/mac/url_conversions.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" -#include "ui/native_theme/native_theme_mac.h" -#include "ui/native_theme/native_theme_observer.h" #include "url/gurl.h" namespace { @@ -513,25 +512,6 @@ AppController* const app_controller_; // Weak; owns us. }; -class AppControllerNativeThemeObserver : public ui::NativeThemeObserver { - public: - AppControllerNativeThemeObserver(AppController* app_controller) - : app_controller_(app_controller) { - native_theme_observation_.Observe( - ui::NativeThemeMac::GetInstanceForNativeUi()); - } - - // NativeThemeObserver: - void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override { - [app_controller_ nativeThemeDidChange]; - } - - private: - base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver> - native_theme_observation_{this}; - AppController* const app_controller_; // Weak; owns us. -}; - @implementation AppController @synthesize startupComplete = _startupComplete; @@ -781,7 +761,6 @@ profile = profile->GetOriginalProfile(); } [self setLastProfile:profile]; - _lastActiveColorProvider = browser->window()->GetColorProvider(); } - (void)activeSpaceDidChange:(NSNotification*)notify { @@ -903,10 +882,6 @@ std::make_unique<AppControllerProfileObserver>( g_browser_process->profile_manager(), self); - // Observe native theme change (e.g. light and dark mode). - _nativeThemeObserver = - std::make_unique<AppControllerNativeThemeObserver>(self); - // Record the path to the (browser) app bundle; this is used by the app mode // shim. if (base::mac::AmIBundled()) { @@ -927,11 +902,8 @@ Browser* browser = chrome::FindLastActive(); content::WebContents* activeWebContents = nullptr; - _lastActiveColorProvider = nullptr; - if (browser) { + if (browser) activeWebContents = browser->tab_strip_model()->GetActiveWebContents(); - _lastActiveColorProvider = browser->window()->GetColorProvider(); - } [self updateHandoffManager:activeWebContents]; [self openStartupUrls]; @@ -1754,14 +1726,14 @@ _menuState.get(), _lastProfile)); } -- (const ui::ColorProvider&)lastActiveColorProvider { - DCHECK(_lastActiveColorProvider); - return *_lastActiveColorProvider; -} +- (const ui::ThemeProvider&)lastActiveThemeProvider { + // Themes are only available while a profile is available. + DCHECK(_lastProfile); -- (void)nativeThemeDidChange { - Browser* browser = chrome::FindBrowserWithProfile(_lastProfile); - _lastActiveColorProvider = browser->window()->GetColorProvider(); + // AppController is conceptually a root for Chromium Mac. As a result, it is + // allowed to refer to the profile to get a theme provider. Non-root UI + // concepts should rely on well known roots to obtain a ThemeProvider. + return ThemeService::GetThemeProviderForProfile(_lastProfile); } - (BOOL)windowHasBrowserTabs:(NSWindow*)window { @@ -1927,8 +1899,6 @@ - (void)setLastProfileForTesting:(Profile*)profile { _lastProfile = profile; - Browser* browser = chrome::FindLastActiveWithProfile(profile); - _lastActiveColorProvider = browser->window()->GetColorProvider(); } @end // @implementation AppController
diff --git a/chrome/browser/apps/app_service/intent_util.cc b/chrome/browser/apps/app_service/intent_util.cc index 728a15f2..ed6cc9c 100644 --- a/chrome/browser/apps/app_service/intent_util.cc +++ b/chrome/browser/apps/app_service/intent_util.cc
@@ -242,14 +242,6 @@ return filters; } -apps::mojom::IntentFilterPtr CreateNoteTakingIntentFilter() { - auto intent_filter = apps::mojom::IntentFilter::New(); - AddSingleValueCondition(apps::mojom::ConditionType::kAction, - kIntentActionCreateNote, - apps::mojom::PatternMatchType::kNone, intent_filter); - return intent_filter; -} - #if BUILDFLAG(IS_CHROMEOS_ASH) constexpr char kIntentExtraText[] = "S.android.intent.extra.TEXT"; constexpr char kIntentExtraSubject[] = "S.android.intent.extra.SUBJECT"; @@ -425,7 +417,6 @@ apps::IntentFilters CreateIntentFiltersForWebApp( const web_app::AppId& app_id, - bool is_note_taking_web_app, const GURL& app_scope, const apps::ShareTarget* app_share_target, const apps::FileHandlers* enabled_file_handlers) { @@ -446,11 +437,6 @@ CreateIntentFiltersFromFileHandlers(*enabled_file_handlers)); } - if (is_note_taking_web_app) { - filters.push_back(apps::ConvertMojomIntentFilterToIntentFilter( - CreateNoteTakingIntentFilter())); - } - #if BUILDFLAG(IS_CHROMEOS_ASH) if (ash::features::IsProjectorEnabled() && app_id == ash::kChromeUITrustedProjectorSwaAppId) { @@ -465,7 +451,6 @@ std::vector<apps::mojom::IntentFilterPtr> CreateWebAppIntentFilters( const web_app::AppId& app_id, - bool is_note_taking_web_app, const GURL& app_scope, const apps::ShareTarget* app_share_target, const apps::FileHandlers* enabled_file_handlers) { @@ -484,10 +469,6 @@ CreateWebAppFileHandlerIntentFilters(*enabled_file_handlers)); } - if (is_note_taking_web_app) { - filters.push_back(CreateNoteTakingIntentFilter()); - } - #if BUILDFLAG(IS_CHROMEOS_ASH) if (ash::features::IsProjectorEnabled() && app_id == ash::kChromeUITrustedProjectorSwaAppId) { @@ -612,6 +593,18 @@ #endif // BUILDFLAG(IS_CHROMEOS) } +apps::IntentFilterPtr CreateNoteTakingFilter() { + auto intent_filter = std::make_unique<apps::IntentFilter>(); + intent_filter->AddSingleValueCondition(apps::ConditionType::kAction, + kIntentActionCreateNote, + apps::PatternMatchType::kNone); + return intent_filter; +} + +apps::mojom::IntentFilterPtr CreateNoteTakingFilterMojom() { + return apps::ConvertIntentFilterToMojomIntentFilter(CreateNoteTakingFilter()); +} + #if BUILDFLAG(IS_CHROMEOS_ASH) // TODO(crbug.com/1253219): Use FilePaths in intents to avoid dependency on // File Manager.
diff --git a/chrome/browser/apps/app_service/intent_util.h b/chrome/browser/apps/app_service/intent_util.h index 25f746f2..9388d7a 100644 --- a/chrome/browser/apps/app_service/intent_util.h +++ b/chrome/browser/apps/app_service/intent_util.h
@@ -73,7 +73,6 @@ // shortcuts. apps::IntentFilters CreateIntentFiltersForWebApp( const web_app::AppId& app_id, - bool is_note_taking_web_app, const GURL& app_scope, const apps::ShareTarget* app_share_target, const apps::FileHandlers* enabled_file_handlers); @@ -84,7 +83,6 @@ // TODO(crbug.com/1253250): Remove after migrating to non-mojo AppService. std::vector<apps::mojom::IntentFilterPtr> CreateWebAppIntentFilters( const web_app::AppId& app_id, - bool is_note_taking_web_app, const GURL& app_scope, const apps::ShareTarget* app_share_target, const apps::FileHandlers* enabled_file_handlers); @@ -111,6 +109,13 @@ std::vector<apps::mojom::IntentFilterPtr> CreateExtensionIntentFilters( const extensions::Extension* extension); +// Create an intent filter for a note-taking app. +apps::IntentFilterPtr CreateNoteTakingFilter(); + +// Create a mojom intent filter for a note-taking app. +// TODO(crbug.com/1253250): Remove after migrating to non-mojo AppService. +apps::mojom::IntentFilterPtr CreateNoteTakingFilterMojom(); + #if BUILDFLAG(IS_CHROMEOS_ASH) // Create an intent struct with filesystem:// type URLs from the file paths and // mime types of a list of files. This util has to live under chrome/ because it
diff --git a/chrome/browser/apps/app_service/intent_util_browsertest.cc b/chrome/browser/apps/app_service/intent_util_browsertest.cc index 1413f5d5..8a41e32 100644 --- a/chrome/browser/apps/app_service/intent_util_browsertest.cc +++ b/chrome/browser/apps/app_service/intent_util_browsertest.cc
@@ -142,8 +142,7 @@ const web_app::AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url); filters = CreateWebAppIntentFilters( - app_id, /*is_note_taking_web_app*/ false, - provider.registrar().GetAppScope(app_id), + app_id, provider.registrar().GetAppScope(app_id), provider.registrar().GetAppShareTarget(app_id), provider.os_integration_manager().GetEnabledFileHandlers(app_id)); } @@ -176,8 +175,7 @@ const web_app::AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url); filters = CreateWebAppIntentFilters( - app_id, /*is_note_taking_web_app*/ false, - provider.registrar().GetAppScope(app_id), + app_id, provider.registrar().GetAppScope(app_id), provider.registrar().GetAppShareTarget(app_id), provider.os_integration_manager().GetEnabledFileHandlers(app_id)); } @@ -207,8 +205,7 @@ const web_app::AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url); filters = CreateWebAppIntentFilters( - app_id, /*is_note_taking_web_app*/ false, - provider.registrar().GetAppScope(app_id), + app_id, provider.registrar().GetAppScope(app_id), provider.registrar().GetAppShareTarget(app_id), provider.os_integration_manager().GetEnabledFileHandlers(app_id)); }
diff --git a/chrome/browser/apps/app_service/intent_util_unittest.cc b/chrome/browser/apps/app_service/intent_util_unittest.cc index 5dc2f0f33..c31bb1ff 100644 --- a/chrome/browser/apps/app_service/intent_util_unittest.cc +++ b/chrome/browser/apps/app_service/intent_util_unittest.cc
@@ -186,7 +186,7 @@ web_app->SetScope(scope); IntentFilters filters = apps_util::CreateIntentFiltersForWebApp( - web_app->app_id(), /*is_note_taking_web_app*/ false, scope, + web_app->app_id(), scope, /*app_share_target*/ nullptr, /*enabled_file_handlers*/ nullptr); ASSERT_EQ(filters.size(), 1u); @@ -241,9 +241,9 @@ web_app->SetScope(scope); std::vector<apps::mojom::IntentFilterPtr> filters = - apps_util::CreateWebAppIntentFilters( - web_app->app_id(), /*is_note_taking_web_app*/ false, scope, - /*app_share_target*/ nullptr, /*enabled_file_handlers*/ nullptr); + apps_util::CreateWebAppIntentFilters(web_app->app_id(), scope, + /*app_share_target*/ nullptr, + /*enabled_file_handlers*/ nullptr); ASSERT_EQ(filters.size(), 1u); apps::mojom::IntentFilterPtr& filter = filters[0]; @@ -312,7 +312,7 @@ web_app->SetFileHandlers(file_handlers); IntentFilters filters = apps_util::CreateIntentFiltersForWebApp( - web_app->app_id(), /*is_note_taking_web_app*/ false, scope, + web_app->app_id(), scope, /*app_share_target*/ nullptr, &file_handlers); ASSERT_EQ(filters.size(), 2u); @@ -356,9 +356,9 @@ web_app->SetFileHandlers(file_handlers); std::vector<apps::mojom::IntentFilterPtr> filters = - apps_util::CreateWebAppIntentFilters( - web_app->app_id(), /*is_note_taking_web_app*/ false, scope, - /*app_share_target*/ nullptr, &file_handlers); + apps_util::CreateWebAppIntentFilters(web_app->app_id(), scope, + /*app_share_target*/ nullptr, + &file_handlers); ASSERT_EQ(filters.size(), 2u); // 1st filter is URL filter. @@ -383,58 +383,35 @@ EXPECT_EQ(file_cond.condition_values[1]->value, ".txt"); } -TEST_F(IntentUtilsTest, CreateIntentFiltersForWebApp_NoteTakingApp) { - auto web_app = web_app::test::CreateWebApp(); - DCHECK(web_app->start_url().is_valid()); - GURL scope = web_app->start_url().GetWithoutFilename(); - web_app->SetScope(scope); - GURL new_note_url = scope.Resolve("/new_note.html"); - web_app->SetNoteTakingNewNoteUrl(new_note_url); +TEST_F(IntentUtilsTest, CreateNoteTakingFilter) { + IntentFilterPtr filter = apps_util::CreateNoteTakingFilter(); - IntentFilters filters = apps_util::CreateIntentFiltersForWebApp( - web_app->app_id(), /*is_note_taking_web_app*/ true, scope, - /*app_share_target*/ nullptr, /*enabled_file_handlers*/ nullptr); - - ASSERT_EQ(filters.size(), 2u); - - // 2nd filter is note-taking filter. - ASSERT_EQ(filters[1]->conditions.size(), 1u); - const Condition& condition = *filters[1]->conditions[0]; + ASSERT_EQ(filter->conditions.size(), 1u); + const Condition& condition = *filter->conditions[0]; EXPECT_EQ(condition.condition_type, ConditionType::kAction); ASSERT_EQ(condition.condition_values.size(), 1u); EXPECT_EQ(condition.condition_values[0]->value, apps_util::kIntentActionCreateNote); + + apps::IntentPtr intent = + apps::ConvertMojomIntentToIntent(apps_util::CreateCreateNoteIntent()); + EXPECT_TRUE(intent->MatchFilter(filter)); } // TODO(crbug.com/1253250): Remove after migrating to non-mojo AppService. -TEST_F(IntentUtilsTest, CreateWebAppIntentFilters_NoteTakingApp) { - auto web_app = web_app::test::CreateWebApp(); - DCHECK(web_app->start_url().is_valid()); - GURL scope = web_app->start_url().GetWithoutFilename(); - web_app->SetScope(scope); - GURL new_note_url = scope.Resolve("/new_note.html"); - web_app->SetNoteTakingNewNoteUrl(new_note_url); +TEST_F(IntentUtilsTest, CreateNoteTakingFilterMojom) { + apps::mojom::IntentFilterPtr filter = + apps_util::CreateNoteTakingFilterMojom(); - std::vector<apps::mojom::IntentFilterPtr> filters = - apps_util::CreateWebAppIntentFilters( - web_app->app_id(), /*is_note_taking_web_app*/ true, scope, - /*app_share_target*/ nullptr, /*enabled_file_handlers*/ nullptr); - - ASSERT_EQ(filters.size(), 2u); - - // 1st filter is URL filter. - EXPECT_TRUE(apps_util::IntentMatchesFilter( - apps_util::CreateIntentFromUrl(scope), filters[0])); - - // 2nd filter is note-taking filter. - ASSERT_EQ(filters[1]->conditions.size(), 1u); - const apps::mojom::Condition& condition = *filters[1]->conditions[0]; + ASSERT_EQ(filter->conditions.size(), 1u); + const apps::mojom::Condition& condition = *filter->conditions[0]; EXPECT_EQ(condition.condition_type, apps::mojom::ConditionType::kAction); ASSERT_EQ(condition.condition_values.size(), 1u); EXPECT_EQ(condition.condition_values[0]->value, apps_util::kIntentActionCreateNote); + EXPECT_TRUE(apps_util::IntentMatchesFilter( - apps_util::CreateCreateNoteIntent(), filters[1])); + apps_util::CreateCreateNoteIntent(), filter)); } TEST_F(IntentUtilsTest, CreateIntentFiltersForChromeApp_FileHandlers) {
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc index dcefdfac..3ceed49 100644 --- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc +++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc
@@ -63,7 +63,7 @@ profile_, app_registry_cache, instance_registry); app_platform_input_metrics_ = std::make_unique<apps::AppPlatformInputMetrics>( profile_, instance_registry); - website_metrics_ = std::make_unique<apps::WebsiteMetrics>(); + website_metrics_ = std::make_unique<apps::WebsiteMetrics>(profile_); day_id_ = profile_->GetPrefs()->GetInteger(kAppPlatformMetricsDayId); CheckForNewDay();
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc index f1eb23f..f24c802c 100644 --- a/chrome/browser/apps/app_service/metrics/website_metrics.cc +++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -4,35 +4,65 @@ #include "chrome/browser/apps/app_service/metrics/website_metrics.h" +#include "chrome/browser/history/history_service_factory.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/web_applications/web_app_helpers.h" #include "ui/aura/window.h" namespace { -wm::ActivationClient* GetActivationClientWithTabStripModel( - TabStripModel* tab_strip_model) { +// Checks if a given browser is running a windowed app. It will return true for +// web apps, hosted apps, and packaged V1 apps. +bool IsAppBrowser(const Browser* browser) { + return (browser->is_type_app() || browser->is_type_app_popup()) && + !web_app::GetAppIdFromApplicationName(browser->app_name()).empty(); +} + +aura::Window* GetWindowWithBrowser(Browser* browser) { + if (!browser) { + return nullptr; + } + BrowserWindow* browser_window = browser->window(); + // In some test cases, browser window might be skipped. + return browser_window ? browser_window->GetNativeWindow() : nullptr; +} + +aura::Window* GetWindowWithTabStripModel(TabStripModel* tab_strip_model) { for (auto* browser : *BrowserList::GetInstance()) { if (browser->tab_strip_model() == tab_strip_model) { - BrowserWindow* browser_window = browser->window(); - DCHECK(browser_window); - aura::Window* window = browser_window->GetNativeWindow(); - DCHECK(window); - auto* root_window = window->GetRootWindow(); - DCHECK(root_window); - return wm::GetActivationClient(root_window); + return GetWindowWithBrowser(browser); } } return nullptr; } +wm::ActivationClient* GetActivationClientWithTabStripModel( + TabStripModel* tab_strip_model) { + auto* window = GetWindowWithTabStripModel(tab_strip_model); + if (!window) { + return nullptr; + } + + auto* root_window = window->GetRootWindow(); + DCHECK(root_window); + return wm::GetActivationClient(root_window); +} + } // namespace namespace apps { -WebsiteMetrics::WebsiteMetrics() : browser_tab_strip_tracker_(this, nullptr) { +WebsiteMetrics::WebsiteMetrics(Profile* profile) + : browser_tab_strip_tracker_(this, nullptr) { BrowserList::GetInstance()->AddObserver(this); browser_tab_strip_tracker_.Init(); + history::HistoryService* history_service = + HistoryServiceFactory::GetForProfileWithoutCreating(profile); + if (history_service) { + history_observation_.Observe(history_service); + } } WebsiteMetrics::~WebsiteMetrics() { @@ -40,11 +70,21 @@ } void WebsiteMetrics::OnBrowserAdded(Browser* browser) { - // TODO(crbug.com/1334173): Save the browser window. + if (IsAppBrowser(browser)) { + return; + } + + auto* window = GetWindowWithBrowser(browser); + if (window) { + window_to_web_contents_[window] = nullptr; + } } void WebsiteMetrics::OnBrowserRemoved(Browser* browser) { - // TODO(crbug.com/1334173): Remove the browser window. + auto* window = GetWindowWithBrowser(browser); + if (window) { + window_to_web_contents_.erase(window); + } } void WebsiteMetrics::OnTabStripModelChanged( @@ -74,6 +114,17 @@ // url. } +void WebsiteMetrics::OnURLsDeleted(history::HistoryService* history_service, + const history::DeletionInfo& deletion_info) { + // TODO(crbug.com/1334173): Remove local records for urls in `deletion_info`. +} + +void WebsiteMetrics::HistoryServiceBeingDeleted( + history::HistoryService* history_service) { + DCHECK(history_observation_.IsObservingSource(history_service)); + history_observation_.Reset(); +} + void WebsiteMetrics::OnTabStripModelChangeInsert( TabStripModel* tab_strip_model, const TabStripModelChange::Insert& insert, @@ -88,8 +139,9 @@ // tracked browser matching it). auto* activation_client = GetActivationClientWithTabStripModel(tab_strip_model); - if (!activation_client_observations_.IsObservingSource(activation_client)) + if (!activation_client_observations_.IsObservingSource(activation_client)) { activation_client_observations_.AddObservation(activation_client); + } } } @@ -103,8 +155,9 @@ // window if the last browser using it was just removed. auto* activation_client = GetActivationClientWithTabStripModel(tab_strip_model); - if (activation_client_observations_.IsObservingSource(activation_client)) + if (activation_client_observations_.IsObservingSource(activation_client)) { activation_client_observations_.RemoveObservation(activation_client); + } } }
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.h b/chrome/browser/apps/app_service/metrics/website_metrics.h index f61c4fa0..bb6d803 100644 --- a/chrome/browser/apps/app_service/metrics/website_metrics.h +++ b/chrome/browser/apps/app_service/metrics/website_metrics.h
@@ -5,14 +5,19 @@ #ifndef CHROME_BROWSER_APPS_APP_SERVICE_METRICS_WEBSITE_METRICS_H_ #define CHROME_BROWSER_APPS_APP_SERVICE_METRICS_WEBSITE_METRICS_H_ +#include "base/containers/flat_map.h" #include "base/scoped_multi_source_observation.h" +#include "base/scoped_observation.h" #include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/browser_tab_strip_tracker.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" +#include "components/history/core/browser/history_service.h" +#include "components/history/core/browser/history_service_observer.h" #include "ui/wm/public/activation_change_observer.h" #include "ui/wm/public/activation_client.h" class Browser; +class Profile; namespace apps { @@ -20,9 +25,10 @@ // TabStripModel to record the website usage time metrics. class WebsiteMetrics : public BrowserListObserver, public TabStripModelObserver, - public wm::ActivationChangeObserver { + public wm::ActivationChangeObserver, + public history::HistoryServiceObserver { public: - WebsiteMetrics(); + explicit WebsiteMetrics(Profile* profile); WebsiteMetrics(const WebsiteMetrics&) = delete; WebsiteMetrics& operator=(const WebsiteMetrics&) = delete; @@ -44,6 +50,12 @@ aura::Window* gained_active, aura::Window* lost_active) override; + // history::HistoryServiceObserver: + void OnURLsDeleted(history::HistoryService* history_service, + const history::DeletionInfo& deletion_info) override; + void HistoryServiceBeingDeleted( + history::HistoryService* history_service) override; + private: void OnTabStripModelChangeInsert(TabStripModel* tab_strip_model, const TabStripModelChange::Insert& insert, @@ -54,10 +66,17 @@ BrowserTabStripTracker browser_tab_strip_tracker_; + // The map from the window to the active tab contents. + base::flat_map<aura::Window*, content::WebContents*> window_to_web_contents_; + // A set of observed activation clients for all browser's windows. base::ScopedMultiSourceObservation<wm::ActivationClient, wm::ActivationChangeObserver> activation_client_observations_{this}; + + base::ScopedObservation<history::HistoryService, + history::HistoryServiceObserver> + history_observation_{this}; }; } // namespace apps
diff --git a/chrome/browser/apps/app_service/notifications_browsertest.cc b/chrome/browser/apps/app_service/notifications_browsertest.cc index 3cdee4e2..9ace9c23 100644 --- a/chrome/browser/apps/app_service/notifications_browsertest.cc +++ b/chrome/browser/apps/app_service/notifications_browsertest.cc
@@ -536,8 +536,20 @@ ASSERT_FALSE(HasBadge(profile(), app_id3).value()); } -IN_PROC_BROWSER_TEST_F(AppNotificationsWebNotificationTest, - NonPersistentNotificationWhenInstallAndUninstallApp) { +// TODO(crbug.com/1334910): Disable AppNotificationsWebNotificationTest. +// NonPersistentNotificationWhenInstallAndUninstallApp on chromeos, +// because it is failing on linux-chromeos-chrome and linux-chromeos-rel. +#if BUILDFLAG(IS_CHROMEOS) +#define MAYBE_NonPersistentNotificationWhenInstallAndUninstallApp \ + DISABLED_NonPersistentNotificationWhenInstallAndUninstallApp +#else +#define MAYBE_NonPersistentNotificationWhenInstallAndUninstallApp \ + NonPersistentNotificationWhenInstallAndUninstallApp +#endif + +IN_PROC_BROWSER_TEST_F( + AppNotificationsWebNotificationTest, + MAYBE_NonPersistentNotificationWhenInstallAndUninstallApp) { base::HistogramTester histogram_tester; // Send the notification 1 before installing apps.
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc index e67c603..158f35a 100644 --- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc +++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -1009,7 +1009,8 @@ switches::kLoginProfile); if (BrowserDataMigratorImpl::MaybeForceResumeMoveMigration( - g_browser_process->local_state(), account_id, user_id_hash)) { + g_browser_process->local_state(), account_id, user_id_hash, + crosapi::browser_util::PolicyInitState::kBeforeInit)) { LOG(WARNING) << "Restarting chrome to resume move migration."; return; }
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator.cc b/chrome/browser/ash/crosapi/browser_data_migrator.cc index 1bd8d5e..da323bf0 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator.cc
@@ -80,12 +80,14 @@ bool BrowserDataMigratorImpl::MaybeForceResumeMoveMigration( PrefService* local_state, const AccountId& account_id, - const std::string& user_id_hash) { + const std::string& user_id_hash, + crosapi::browser_util::PolicyInitState policy_init_state) { LOG(WARNING) << "MaybeForceResumeMoveMigration() is called."; if (!MoveMigrator::ResumeRequired(local_state, user_id_hash)) return false; - return RestartToMigrate(account_id, user_id_hash, local_state); + return RestartToMigrate(account_id, user_id_hash, local_state, + policy_init_state); } // static @@ -108,7 +110,8 @@ return false; } return RestartToMigrate(account_id, user_id_hash, - user_manager::UserManager::Get()->GetLocalState()); + user_manager::UserManager::Get()->GetLocalState(), + policy_init_state); } void BrowserDataMigratorImpl::MaybeRestartToMigrateWithDiskCheck( @@ -154,7 +157,8 @@ bool result = RestartToMigrate(account_id, user_id_hash, - user_manager::UserManager::Get()->GetLocalState()); + user_manager::UserManager::Get()->GetLocalState(), + crosapi::browser_util::PolicyInitState::kAfterInit); std::move(callback).Run(result, absl::nullopt); } @@ -271,8 +275,9 @@ crosapi::browser_util::RecordDataVer(local_state, user_id_hash, version_info::GetVersion()); - crosapi::browser_util::SetProfileMigrationCompletedForUser(local_state, - user_id_hash); + crosapi::browser_util::SetProfileMigrationCompletedForUser( + local_state, user_id_hash, + crosapi::browser_util::GetMigrationMode(user, policy_init_state)); // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, remove // this log message. LOG(WARNING) << "Setting migration as completed since it is a new user."; @@ -291,7 +296,7 @@ return false; } - if (crosapi::browser_util::IsDataWipeRequired(user_id_hash)) { + if (crosapi::browser_util::IsDataWipeRequired(local_state, user_id_hash)) { // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, remove // this log message. LOG(WARNING) @@ -301,21 +306,36 @@ return true; } - if (crosapi::browser_util::IsProfileMigrationCompletedForUser(local_state, - user_id_hash)) { + crosapi::browser_util::MigrationMode mode = + crosapi::browser_util::GetMigrationMode(user, policy_init_state); + + if (crosapi::browser_util::IsProfileMigrationCompletedForUser( + local_state, user_id_hash, mode)) { // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, // remove this log message. LOG(WARNING) << "Profile migration has been completed already."; return false; } + // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, + // remove this log message. + if (mode == crosapi::browser_util::MigrationMode::kMove && + crosapi::browser_util::IsProfileMigrationCompletedForUser( + local_state, user_id_hash, + crosapi::browser_util::MigrationMode::kCopy)) { + LOG(WARNING) << "Only copy migration is marked as completed. Running " + "profile move migraiton."; + } + return true; } // static -bool BrowserDataMigratorImpl::RestartToMigrate(const AccountId& account_id, - const std::string& user_id_hash, - PrefService* local_state) { +bool BrowserDataMigratorImpl::RestartToMigrate( + const AccountId& account_id, + const std::string& user_id_hash, + PrefService* local_state, + crosapi::browser_util::PolicyInitState policy_init_state) { SetMigrationStep(local_state, MigrationStep::kRestartCalled); UpdateMigrationAttemptCountForUser(local_state, user_id_hash); @@ -325,9 +345,15 @@ local_state->CommitPendingWrite(); - const bool is_move = base::FeatureList::IsEnabled( - ash::features::kLacrosMoveProfileMigration) || - MoveMigrator::ResumeRequired(local_state, user_id_hash); + const user_manager::User* user = + user_manager::UserManager::Get()->FindUser(account_id); + // `user` should exist by the time `RestartToMigrate()` is called. + CHECK(user) << "User could not be found for " << account_id.GetUserEmail() + << " but RestartToMigrate() was called."; + const bool is_move = + crosapi::browser_util::GetMigrationMode(user, policy_init_state) == + crosapi::browser_util::MigrationMode::kMove || + MoveMigrator::ResumeRequired(local_state, user_id_hash); // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, remove // this log message. @@ -385,7 +411,7 @@ cancel_flag_, local_state_, base::BindOnce( &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), mode)); break; case crosapi::browser_util::MigrationMode::kCopy: LOG(WARNING) << "Initializing CopyMigrator."; @@ -394,7 +420,7 @@ cancel_flag_, base::BindOnce( &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), mode)); break; } @@ -407,6 +433,7 @@ } void BrowserDataMigratorImpl::MigrateInternalFinishedUIThread( + crosapi::browser_util::MigrationMode mode, MigrationResult result) { DCHECK(local_state_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -428,8 +455,8 @@ } if (result.data_migration_result.kind == ResultKind::kSucceeded) { - crosapi::browser_util::SetProfileMigrationCompletedForUser(local_state_, - user_id_hash_); + crosapi::browser_util::SetProfileMigrationCompletedForUser( + local_state_, user_id_hash_, mode); ClearMigrationAttemptCountForUser(local_state_, user_id_hash_); }
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator.h b/chrome/browser/ash/crosapi/browser_data_migrator.h index 5ed2619..5cbe086e 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator.h +++ b/chrome/browser/ash/crosapi/browser_data_migrator.h
@@ -150,9 +150,11 @@ // `MaybeRestartToMigrate()` it returns true if the D-Bus call to the // session_manager is made and successful. The return value of true means that // `chrome::AttemptRestart()` has been called. - static bool MaybeForceResumeMoveMigration(PrefService* local_state, - const AccountId& account_id, - const std::string& user_id_hash); + static bool MaybeForceResumeMoveMigration( + PrefService* local_state, + const AccountId& account_id, + const std::string& user_id_hash, + crosapi::browser_util::PolicyInitState policy_init_state); // Checks if migration is required for the user identified by `user_id_hash` // and if it is required, calls a D-Bus method to session_manager and @@ -205,6 +207,8 @@ MigrateOutOfDiskForMove); FRIEND_TEST_ALL_PREFIXES(BrowserDataMigratorRestartTest, MaybeRestartToMigrateWithMigrationStep); + FRIEND_TEST_ALL_PREFIXES(BrowserDataMigratorRestartTest, + MaybeRestartToMigrateMoveAfterCopy); // The common implementation of `MaybeRestartToMigrate` and // `MaybeRestartToMigrateWithDiskCheck`. @@ -240,12 +244,16 @@ // Called from `MaybeRestartToMigrate()` to proceed with restarting to start // the migration. It returns true if D-Bus call was successful. - static bool RestartToMigrate(const AccountId& account_id, - const std::string& user_id_hash, - PrefService* local_state); + static bool RestartToMigrate( + const AccountId& account_id, + const std::string& user_id_hash, + PrefService* local_state, + crosapi::browser_util::PolicyInitState policy_init_state); // Called on UI thread once migration is finished. - void MigrateInternalFinishedUIThread(MigrationResult result); + void MigrateInternalFinishedUIThread( + crosapi::browser_util::MigrationMode mode, + MigrationResult result); // Path to the original profile data directory, which is directly under the // user data directory.
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc index 6c40980..6a36a3a 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
@@ -7,10 +7,12 @@ #include <string> #include "ash/components/login/auth/user_context.h" +#include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/browser/ash/crosapi/move_migrator.h" #include "chrome/browser/ash/login/existing_user_controller.h" #include "chrome/browser/ash/login/login_manager_test.h" @@ -19,6 +21,9 @@ #include "chrome/browser/browser_process.h" #include "chromeos/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/dbus/session_manager/session_manager_client.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/policy_types.h" +#include "components/policy/policy_constants.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_launcher.h" @@ -33,15 +38,17 @@ } // namespace -class BrowserDataMigratorResumeOnSignInTest : public ash::LoginManagerTest, - public LocalStateMixin::Delegate { +// Used to test whether migration gets triggered during the signin flow. +// Concretely it tests `MaybeRestartToMigrate()` called from +// `UserSessionManager::DoBrowserLaunchInternal()` and +// `MaybeForceResumeMoveMigration()` called from +// `ExistingUserController::ContinueAuthSuccessAfterResumeAttempt()`. +class BrowserDataMigratorOnSignIn : public ash::LoginManagerTest { public: - BrowserDataMigratorResumeOnSignInTest() = default; - BrowserDataMigratorResumeOnSignInTest( - BrowserDataMigratorResumeOnSignInTest&) = delete; - BrowserDataMigratorResumeOnSignInTest& operator=( - BrowserDataMigratorResumeOnSignInTest&) = delete; - ~BrowserDataMigratorResumeOnSignInTest() override = default; + BrowserDataMigratorOnSignIn() = default; + BrowserDataMigratorOnSignIn(BrowserDataMigratorOnSignIn&) = delete; + BrowserDataMigratorOnSignIn& operator=(BrowserDataMigratorOnSignIn&) = delete; + ~BrowserDataMigratorOnSignIn() override = default; // ash::LoginManagerTest: void SetUp() override { @@ -50,19 +57,6 @@ ash::LoginManagerTest::SetUp(); } - // LocalStateMixin::Delegate: - void SetUpLocalState() override { - const auto& user = login_manager_mixin_.users()[0]; - - const std::string user_id_hash = - user.account_id.GetUserEmail() + kUserIdHashSuffix; - - // Setting this pref triggers a restart to resume move migration. Check - // `BrowserDataMigratorImpl::MaybeForceResumeMoveMigration()`. - MoveMigrator::SetResumeStep(g_browser_process->local_state(), user_id_hash, - MoveMigrator::ResumeStep::kMoveLacrosItems); - } - bool LoginAsRegularUser() { ExistingUserController* controller = ExistingUserController::current_controller(); @@ -83,14 +77,162 @@ chromeos::SessionManagerClient::InitializeFakeInMemory(); } - private: + protected: LoginManagerMixin login_manager_mixin_{&mixin_host_}; - LocalStateMixin local_state_mixin_{&mixin_host_, this}; +}; + +class BrowserDataMigratorCopyMigrateOnSignIn + : public BrowserDataMigratorOnSignIn { + public: + BrowserDataMigratorCopyMigrateOnSignIn() = default; + BrowserDataMigratorCopyMigrateOnSignIn( + BrowserDataMigratorCopyMigrateOnSignIn&) = delete; + BrowserDataMigratorCopyMigrateOnSignIn& operator=( + BrowserDataMigratorCopyMigrateOnSignIn&) = delete; + ~BrowserDataMigratorCopyMigrateOnSignIn() override = default; + + void SetUp() override { + feature_list_.InitWithFeatures( + {ash::features::kLacrosSupport, + ash::features::kLacrosProfileMigrationForAnyUser}, + {}); + + BrowserDataMigratorOnSignIn::SetUp(); + } + + private: base::test::ScopedFeatureList feature_list_; }; -IN_PROC_BROWSER_TEST_F(BrowserDataMigratorResumeOnSignInTest, - ForceResumeOnLogin) { +// Check that migration is triggered from signin flow if Lacros is enabled. +IN_PROC_BROWSER_TEST_F(BrowserDataMigratorCopyMigrateOnSignIn, + MigrateOnSignIn) { + base::RunLoop run_loop; + ScopedRestartAttemptForTesting scoped_restart_attempt( + base::BindLambdaForTesting([&]() { run_loop.Quit(); })); + LoginAsRegularUser(); + run_loop.Run(); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_called()); + // Migration should be triggered in copy mode and not move mode. + EXPECT_FALSE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_for_move_called()); +}; + +class BrowserDataMigratorMoveMigrateOnSignInByPolicy + : public BrowserDataMigratorOnSignIn { + public: + BrowserDataMigratorMoveMigrateOnSignInByPolicy() = default; + BrowserDataMigratorMoveMigrateOnSignInByPolicy( + BrowserDataMigratorMoveMigrateOnSignInByPolicy&) = delete; + BrowserDataMigratorMoveMigrateOnSignInByPolicy& operator=( + BrowserDataMigratorMoveMigrateOnSignInByPolicy&) = delete; + ~BrowserDataMigratorMoveMigrateOnSignInByPolicy() override = default; + + void SetUp() override { + feature_list_.InitWithFeatures( + {ash::features::kLacrosProfileMigrationForAnyUser}, {}); + + BrowserDataMigratorOnSignIn::SetUp(); + } + + void SetLacrosAvailability( + crosapi::browser_util::LacrosAvailability lacros_availability) { + policy::PolicyMap policy; + policy.Set( + policy::key::kLacrosAvailability, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, + base::Value(GetLacrosAvailabilityPolicyName(lacros_availability)), + /*external_data_fetcher=*/nullptr); + crosapi::browser_util::CacheLacrosAvailability(policy); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// Enabling LacrosOnly by policy should trigger move migration during signin. +IN_PROC_BROWSER_TEST_F(BrowserDataMigratorMoveMigrateOnSignInByPolicy, + MigrateOnSignIn) { + base::RunLoop run_loop; + ScopedRestartAttemptForTesting scoped_restart_attempt( + base::BindLambdaForTesting([&]() { run_loop.Quit(); })); + SetLacrosAvailability(crosapi::browser_util::LacrosAvailability::kLacrosOnly); + LoginAsRegularUser(); + run_loop.Run(); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_called()); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_for_move_called()); +}; + +class BrowserDataMigratorMoveMigrateOnSignInByFeature + : public BrowserDataMigratorOnSignIn { + public: + BrowserDataMigratorMoveMigrateOnSignInByFeature() = default; + BrowserDataMigratorMoveMigrateOnSignInByFeature( + BrowserDataMigratorMoveMigrateOnSignInByFeature&) = delete; + BrowserDataMigratorMoveMigrateOnSignInByFeature& operator=( + BrowserDataMigratorMoveMigrateOnSignInByFeature&) = delete; + ~BrowserDataMigratorMoveMigrateOnSignInByFeature() override = default; + + void SetUp() override { + feature_list_.InitWithFeatures( + {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, + ash::features::kLacrosOnly, + ash::features::kLacrosProfileMigrationForAnyUser}, + {}); + + BrowserDataMigratorOnSignIn::SetUp(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// Enabling LacrosOnly with feature flags should trigger move migration during +// signin. +IN_PROC_BROWSER_TEST_F(BrowserDataMigratorMoveMigrateOnSignInByFeature, + MigrateOnSignIn) { + base::RunLoop run_loop; + ScopedRestartAttemptForTesting scoped_restart_attempt( + base::BindLambdaForTesting([&]() { run_loop.Quit(); })); + LoginAsRegularUser(); + run_loop.Run(); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_called()); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_for_move_called()); +}; + +class BrowserDataMigratorResumeOnSignIn : public BrowserDataMigratorOnSignIn, + public LocalStateMixin::Delegate { + public: + BrowserDataMigratorResumeOnSignIn() = default; + BrowserDataMigratorResumeOnSignIn(BrowserDataMigratorResumeOnSignIn&) = + delete; + BrowserDataMigratorResumeOnSignIn& operator=( + BrowserDataMigratorResumeOnSignIn&) = delete; + ~BrowserDataMigratorResumeOnSignIn() override = default; + + // LocalStateMixin::Delegate: + void SetUpLocalState() override { + const auto& user = login_manager_mixin_.users()[0]; + + const std::string user_id_hash = + user.account_id.GetUserEmail() + kUserIdHashSuffix; + + // Setting this pref triggers a restart to resume move migration. Check + // `BrowserDataMigratorImpl::MaybeForceResumeMoveMigration()`. + MoveMigrator::SetResumeStep(g_browser_process->local_state(), user_id_hash, + MoveMigrator::ResumeStep::kMoveLacrosItems); + } + + private: + LocalStateMixin local_state_mixin_{&mixin_host_, this}; +}; + +IN_PROC_BROWSER_TEST_F(BrowserDataMigratorResumeOnSignIn, ForceResumeOnLogin) { // Test `MaybeForceResumeMoveMigration()` in // `ExistingUserController::ContinueAuthSuccessAfterResumeAttempt()`. base::RunLoop run_loop; @@ -100,31 +242,40 @@ run_loop.Run(); EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() ->request_browser_data_migration_called()); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_for_move_called()); } -class BrowserDataMigratorResumeRestartInSession +// Used to test whether migration gets triggered upon restart in session. +// Concretely it tests `MaybeRestartToMigrate()` or +// `MaybeForceResumeMoveMigration()` called from +// `ChromeBrowserMainPartsAsh::PreProfileInit()`. Since `PreProfileInit()` gets +// called before the body of tests are run, all the setups have to happen in +// early setup stages like `SetUp()` or `SetUpCommandLine()`. +class BrowserDataMigratorRestartInSession : public MixinBasedInProcessBrowserTest, public LocalStateMixin::Delegate { public: - BrowserDataMigratorResumeRestartInSession() + BrowserDataMigratorRestartInSession() : scoped_attempt_restart_( std::make_unique<ScopedRestartAttemptForTesting>( base::DoNothing())) {} - - BrowserDataMigratorResumeRestartInSession( - BrowserDataMigratorResumeRestartInSession&) = delete; - BrowserDataMigratorResumeRestartInSession& operator=( - BrowserDataMigratorResumeRestartInSession&) = delete; - ~BrowserDataMigratorResumeRestartInSession() override = default; - - void SetUp() override { MixinBasedInProcessBrowserTest::SetUp(); } + BrowserDataMigratorRestartInSession(BrowserDataMigratorRestartInSession&) = + delete; + BrowserDataMigratorRestartInSession& operator=( + BrowserDataMigratorRestartInSession&) = delete; + ~BrowserDataMigratorRestartInSession() override = default; // LocalStateMixin::Delegate void SetUpLocalState() override { - // Setting this pref triggers a restart to resume move migration. Check - // `BrowserDataMigratorImpl::MaybeForceResumeMoveMigration()`. - MoveMigrator::SetResumeStep(g_browser_process->local_state(), kUserIdHash, - MoveMigrator::ResumeStep::kMoveLacrosItems); + // Add `kUserIdHash`@gmail.com to kRegularUsersPref so that + // `UserManager::FindUser()` is able to find this user in + // `BrowserDataMigrator::MaybeRestartToMigrate()` and + // `BrowserDataMigrator::RestartToMigrate()`. + base::Value::List users; + users.Append(base::Value(std::string(kUserIdHash) + "@gmail.com")); + g_browser_process->local_state()->SetList(user_manager::kRegularUsersPref, + std::move(users)); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -140,21 +291,112 @@ chromeos::SessionManagerClient::InitializeFakeInMemory(); } - private: + protected: + // Since triggering migration means calling `chrome::AttemptRestart()`, it has + // to be substituted. std::unique_ptr<ScopedRestartAttemptForTesting> scoped_attempt_restart_; LocalStateMixin local_state_mixin_{&mixin_host_, this}; + base::test::ScopedFeatureList feature_list_; +}; + +class BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature + : public BrowserDataMigratorRestartInSession { + public: + BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature() = default; + BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature( + BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature&) = delete; + BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature& operator=( + BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature&) = delete; + ~BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature() override = + default; + + void SetUp() override { + feature_list_.InitWithFeatures( + {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, + ash::features::kLacrosOnly, + ash::features::kLacrosProfileMigrationForAnyUser}, + {}); + + BrowserDataMigratorRestartInSession::SetUp(); + } +}; + +// Test that enabling LacrosOnly by feature flags triggers move migration during +// restart. +IN_PROC_BROWSER_TEST_F( + BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature, + RunMoveMigration) { + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_called()); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_for_move_called()); +} + +class BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy + : public BrowserDataMigratorRestartInSession { + public: + BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy() = default; + BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy( + BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy&) = delete; + BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy& operator=( + BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy&) = delete; + ~BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy() override = + default; + + void SetUp() override { + feature_list_.InitAndEnableFeature( + ash::features::kLacrosProfileMigrationForAnyUser); + + BrowserDataMigratorRestartInSession::SetUp(); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII( + crosapi::browser_util::kLacrosAvailabilityPolicySwitch, + crosapi::browser_util::kLacrosAvailabilityPolicyLacrosOnly); + BrowserDataMigratorRestartInSession::SetUpCommandLine(command_line); + } +}; + +// Test that enabling LacrosOnly by policy triggers move migration during +// restart. +IN_PROC_BROWSER_TEST_F(BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy, + RunMoveMigration) { + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_called()); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_for_move_called()); +} + +class BrowserDataMigratorResumeRestartInSession + : public BrowserDataMigratorRestartInSession { + public: + BrowserDataMigratorResumeRestartInSession() = default; + BrowserDataMigratorResumeRestartInSession( + BrowserDataMigratorResumeRestartInSession&) = delete; + BrowserDataMigratorResumeRestartInSession& operator=( + BrowserDataMigratorResumeRestartInSession&) = delete; + ~BrowserDataMigratorResumeRestartInSession() override = default; + + // LocalStateMixin::Delegate + void SetUpLocalState() override { + // Setting this pref triggers a restart to resume move migration. Check + // `BrowserDataMigratorImpl::MaybeForceResumeMoveMigration()`. + MoveMigrator::SetResumeStep(g_browser_process->local_state(), kUserIdHash, + MoveMigrator::ResumeStep::kMoveLacrosItems); + + BrowserDataMigratorRestartInSession::SetUpLocalState(); + } }; IN_PROC_BROWSER_TEST_F(BrowserDataMigratorResumeRestartInSession, ResumeMigration) { // Test `MaybeForceResumeMoveMigration()` in // `ChromeBrowserMainPartsAsh::PreProfileInit()`. - - // Note that by the time the body of the test is called, - // `ChromeBrowserMainPartsAsh::PreProfileInit()` would have been called. Thus - // there is no need for a waiter. EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() ->request_browser_data_migration_called()); + EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get() + ->request_browser_data_migration_for_move_called()); } } // namespace ash
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc index ec816f0..5b41227 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc
@@ -11,6 +11,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" +#include "base/strings/string_piece.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_command_line.h" @@ -21,10 +22,13 @@ #include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/browser/ash/crosapi/fake_migration_progress_tracker.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ash/profiles/profile_helper.h" #include "chromeos/dbus/session_manager/fake_session_manager_client.h" #include "components/prefs/testing_pref_service.h" #include "components/user_manager/fake_user_manager.h" +#include "components/user_manager/scoped_user_manager.h" #include "components/version_info/version_info.h" +#include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -116,7 +120,8 @@ EXPECT_TRUE(base::PathExists(new_user_data_dir.Append(kFirstRun))); // Check that migration is marked as completed for the user. EXPECT_TRUE(crosapi::browser_util::IsProfileMigrationCompletedForUser( - &pref_service_, user_id_hash)); + &pref_service_, user_id_hash, + crosapi::browser_util::MigrationMode::kCopy)); ASSERT_TRUE(result.has_value()); EXPECT_EQ(BrowserDataMigrator::ResultKind::kSucceeded, result->kind); EXPECT_EQ(BrowserDataMigratorImpl::GetMigrationStep(&pref_service_), @@ -162,7 +167,8 @@ new_user_data_dir.Append("Default"); EXPECT_FALSE(base::PathExists(new_user_data_dir.Append(kFirstRun))); EXPECT_FALSE(crosapi::browser_util::IsProfileMigrationCompletedForUser( - &pref_service_, user_id_hash)); + &pref_service_, user_id_hash, + crosapi::browser_util::MigrationMode::kCopy)); ASSERT_TRUE(result.has_value()); EXPECT_EQ(BrowserDataMigrator::ResultKind::kCancelled, result->kind); EXPECT_EQ(BrowserDataMigratorImpl::GetMigrationStep(&pref_service_), @@ -253,26 +259,40 @@ ~BrowserDataMigratorRestartTest() override = default; void SetUp() override { - user_manager_.CreateLocalState(); + fake_user_manager_ = new ash::FakeChromeUserManager; + scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( + base::WrapUnique(fake_user_manager_)); + fake_user_manager_->CreateLocalState(); + auto* local_state_simple = static_cast<TestingPrefServiceSimple*>(local_state()); BrowserDataMigratorImpl::RegisterLocalStatePrefs( local_state_simple->registry()); crosapi::browser_util::RegisterLocalStatePrefs( local_state_simple->registry()); - user_manager_.Initialize(); } - void TearDown() override { user_manager_.Destroy(); } + void AddRegularUser(const std::string& email) { + AccountId account_id = AccountId::FromUserEmail(email); + const user_manager::User* user = fake_user_manager_->AddUser(account_id); + fake_user_manager_->UserLoggedIn(account_id, user->username_hash(), + /*browser_restart=*/false, + /*is_child=*/false); + ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting( + user, &testing_profile_); + } protected: - ash::FakeChromeUserManager* user_manager() { return &user_manager_; } - PrefService* local_state() { return user_manager_.GetLocalState(); } + TestingProfile* testing_profile() { return &testing_profile_; } + ash::FakeChromeUserManager* user_manager() { return fake_user_manager_; } + PrefService* local_state() { return fake_user_manager_->GetLocalState(); } private: - ash::FakeChromeUserManager user_manager_; + content::BrowserTaskEnvironment task_environment_; + TestingProfile testing_profile_; + ash::FakeChromeUserManager* fake_user_manager_ = nullptr; + std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; FakeSessionManagerClient session_manager_; - base::test::TaskEnvironment task_environment; }; TEST_F(BrowserDataMigratorRestartTest, MaybeRestartToMigrateWithMigrationStep) { @@ -305,12 +325,17 @@ ScopedRestartAttemptForTesting scoped_restart_attempt( base::BindLambdaForTesting( [&restart_called]() { restart_called = true; })); + + base::test::ScopedFeatureList feature_list; + AddRegularUser("user@gmail.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(testing_profile()); { base::test::ScopedCommandLine command_line; command_line.GetProcessCommandLine()->AppendSwitchASCII( switches::kForceBrowserDataMigrationForTesting, "force-skip"); EXPECT_FALSE(BrowserDataMigratorImpl::MaybeRestartToMigrate( - AccountId::FromUserEmail("fake@gmail.com"), "abcde", + user->GetAccountId(), user->username_hash(), crosapi::browser_util::PolicyInitState::kAfterInit)); } { @@ -318,7 +343,7 @@ command_line.GetProcessCommandLine()->AppendSwitchASCII( switches::kForceBrowserDataMigrationForTesting, "force-migration"); EXPECT_TRUE(BrowserDataMigratorImpl::MaybeRestartToMigrate( - AccountId::FromUserEmail("fake@gmail.com"), "abcde", + user->GetAccountId(), user->username_hash(), crosapi::browser_util::PolicyInitState::kAfterInit)); } } @@ -329,6 +354,10 @@ base::BindLambdaForTesting( [&restart_called]() { restart_called = true; })); + base::test::ScopedFeatureList feature_list; + AddRegularUser("user@gmail.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(testing_profile()); // If MaybeRestartToMigrate will skip the restarting, WithDiskCheck variation // also skips it. { @@ -338,7 +367,7 @@ switches::kForceBrowserDataMigrationForTesting, "force-skip"); absl::optional<bool> result; BrowserDataMigratorImpl::MaybeRestartToMigrateWithDiskCheck( - AccountId::FromUserEmail("fake@gmail.com"), "abcde", + user->GetAccountId(), user->username_hash(), base::BindLambdaForTesting( [&out_result = result](bool result, const absl::optional<uint64_t>& size) { @@ -364,7 +393,7 @@ absl::optional<uint64_t> out_size; base::RunLoop run_loop; BrowserDataMigratorImpl::MaybeRestartToMigrateWithDiskCheck( - AccountId::FromUserEmail("fake@gmail.com"), "abcde", + user->GetAccountId(), user->username_hash(), base::BindLambdaForTesting( [&out_result = result, &out_size, &run_loop]( bool result, const absl::optional<uint64_t>& size) { @@ -391,7 +420,7 @@ absl::optional<bool> result; base::RunLoop run_loop; BrowserDataMigratorImpl::MaybeRestartToMigrateWithDiskCheck( - AccountId::FromUserEmail("fake@gmail.com"), "abcde", + user->GetAccountId(), user->username_hash(), base::BindLambdaForTesting( [&out_result = result, &run_loop]( bool result, const absl::optional<uint64_t>& size) { @@ -405,4 +434,102 @@ } } +TEST_F(BrowserDataMigratorRestartTest, MaybeRestartToMigrateMoveAfterCopy) { + // Check that `MaybeRestartToMigrateInternal()` returns true after completion + // of copy migration if move migration is enabled. + AddRegularUser("user@gmail.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(testing_profile()); + + crosapi::browser_util::RecordDataVer( + local_state(), user->username_hash(), + base::Version( + base::StringPiece(crosapi::browser_util::kRequiredDataVersion))); + + { + // If Lacros is not enabled, migration should not run. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {ash::features::kLacrosProfileMigrationForAnyUser}, {}); + EXPECT_EQ(crosapi::browser_util::GetMigrationMode( + user, crosapi::browser_util::PolicyInitState::kAfterInit), + crosapi::browser_util::MigrationMode::kCopy); + EXPECT_FALSE(BrowserDataMigratorImpl::MaybeRestartToMigrateInternal( + user->GetAccountId(), user->username_hash(), + crosapi::browser_util::PolicyInitState::kAfterInit)); + } + + { + // If Lacros is enabled, migration should run. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {ash::features::kLacrosSupport, + ash::features::kLacrosProfileMigrationForAnyUser}, + {}); + EXPECT_EQ(crosapi::browser_util::GetMigrationMode( + user, crosapi::browser_util::PolicyInitState::kAfterInit), + crosapi::browser_util::MigrationMode::kCopy); + EXPECT_TRUE(BrowserDataMigratorImpl::MaybeRestartToMigrateInternal( + user->GetAccountId(), user->username_hash(), + crosapi::browser_util::PolicyInitState::kAfterInit)); + } + + // Mark copy migration as completed. + crosapi::browser_util::SetProfileMigrationCompletedForUser( + local_state(), user->username_hash(), + crosapi::browser_util::MigrationMode::kCopy); + { + // If migration is marked as completed, migration should not run. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {ash::features::kLacrosSupport, + ash::features::kLacrosProfileMigrationForAnyUser}, + {}); + EXPECT_EQ(crosapi::browser_util::GetMigrationMode( + user, crosapi::browser_util::PolicyInitState::kAfterInit), + crosapi::browser_util::MigrationMode::kCopy); + EXPECT_FALSE(BrowserDataMigratorImpl::MaybeRestartToMigrateInternal( + user->GetAccountId(), user->username_hash(), + crosapi::browser_util::PolicyInitState::kAfterInit)); + } + + { + // If copy migration is marked as completed but not move then migration + // should run if move migration is enabled. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, + ash::features::kLacrosOnly, + ash::features::kLacrosProfileMigrationForAnyUser}, + {}); + EXPECT_EQ(crosapi::browser_util::GetMigrationMode( + user, crosapi::browser_util::PolicyInitState::kAfterInit), + crosapi::browser_util::MigrationMode::kMove); + EXPECT_TRUE(BrowserDataMigratorImpl::MaybeRestartToMigrateInternal( + user->GetAccountId(), user->username_hash(), + crosapi::browser_util::PolicyInitState::kAfterInit)); + } + + // Mark move migration as completed. + crosapi::browser_util::ClearProfileMigrationCompletedForUser( + local_state(), user->username_hash()); + crosapi::browser_util::SetProfileMigrationCompletedForUser( + local_state(), user->username_hash(), + crosapi::browser_util::MigrationMode::kMove); + { + // If move migration is marked as completed, move migration should not run. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, + ash::features::kLacrosOnly, + ash::features::kLacrosProfileMigrationForAnyUser}, + {}); + EXPECT_EQ(crosapi::browser_util::GetMigrationMode( + user, crosapi::browser_util::PolicyInitState::kAfterInit), + crosapi::browser_util::MigrationMode::kMove); + EXPECT_FALSE(BrowserDataMigratorImpl::MaybeRestartToMigrateInternal( + user->GetAccountId(), user->username_hash(), + crosapi::browser_util::PolicyInitState::kAfterInit)); + } +} } // namespace ash
diff --git a/chrome/browser/ash/crosapi/browser_manager_unittest.cc b/chrome/browser/ash/crosapi/browser_manager_unittest.cc index 95160c4..4972521 100644 --- a/chrome/browser/ash/crosapi/browser_manager_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_manager_unittest.cc
@@ -138,9 +138,11 @@ TEST_F(BrowserManagerTest, LacrosKeepAlive) { AddRegularUser("user@test.com"); browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash()); + local_state_.Get(), + ash::ProfileHelper::Get() + ->GetUserByProfile(&testing_profile_) + ->username_hash(), + browser_util::MigrationMode::kCopy); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); @@ -182,9 +184,11 @@ TEST_F(BrowserManagerTest, LacrosKeepAliveReloadsWhenUpdateAvailable) { AddRegularUser("user@test.com"); browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash()); + local_state_.Get(), + ash::ProfileHelper::Get() + ->GetUserByProfile(&testing_profile_) + ->username_hash(), + browser_util::MigrationMode::kCopy); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); @@ -227,9 +231,11 @@ TEST_F(BrowserManagerTest, NewWindowReloadsWhenUpdateAvailable) { AddRegularUser("user@test.com"); browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash()); + local_state_.Get(), + ash::ProfileHelper::Get() + ->GetUserByProfile(&testing_profile_) + ->username_hash(), + browser_util::MigrationMode::kCopy); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); @@ -264,9 +270,11 @@ TEST_F(BrowserManagerTest, LacrosKeepAliveDoesNotBlockRestart) { AddRegularUser("user@test.com"); browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash()); + local_state_.Get(), + ash::ProfileHelper::Get() + ->GetUserByProfile(&testing_profile_) + ->username_hash(), + browser_util::MigrationMode::kCopy); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch());
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index 6b2b3f1..356817d4 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -295,6 +295,8 @@ const char kRequiredDataVersion[] = "92.0.0.0"; const char kProfileMigrationCompletedForUserPref[] = "lacros.profile_migration_completed_for_user"; +const char kProfileMoveMigrationCompletedForUserPref[] = + "lacros.profile_move_migration_completed_for_user"; // This pref is to record whether the user clicks "Go to files" button // on error page of the data migration. const char kGotoFilesPref[] = "lacros.goto_files"; @@ -309,6 +311,8 @@ registry->RegisterDictionaryPref(kDataVerPref); registry->RegisterDictionaryPref(kProfileMigrationCompletedForUserPref, base::DictionaryValue()); + registry->RegisterDictionaryPref(kProfileMoveMigrationCompletedForUserPref, + base::DictionaryValue()); registry->RegisterListPref(kGotoFilesPref); } @@ -363,10 +367,12 @@ user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId())) { PrefService* local_state = g_browser_process->local_state(); // Note that local_state can be nullptr in tests. - if (local_state && !IsProfileMigrationCompletedForUser( - local_state, user_manager::UserManager::Get() - ->GetPrimaryUser() - ->username_hash())) { + if (local_state && + !IsProfileMigrationCompletedForUser( + local_state, + user_manager::UserManager::Get()->GetPrimaryUser()->username_hash(), + GetMigrationMode(user_manager::UserManager::Get()->GetPrimaryUser(), + PolicyInitState::kAfterInit))) { // If migration has not been completed, do not enable lacros. return false; } @@ -451,8 +457,9 @@ return false; // If migration is already completed, it is not necessary to run again. - if (IsProfileMigrationCompletedForUser(user_manager->GetLocalState(), - user->username_hash())) { + if (IsProfileMigrationCompletedForUser( + user_manager->GetLocalState(), user->username_hash(), + GetMigrationMode(user, PolicyInitState::kAfterInit))) { return false; } @@ -469,6 +476,8 @@ } bool IsAshWebBrowserEnabled() { + // Note that if you are updating this function, please also update the + // *ForMigration variant to keep the logics consistent. // If Lacros is not a primary browser, Ash browser is always enabled. if (!IsLacrosPrimaryBrowser()) return true; @@ -495,7 +504,53 @@ return !base::FeatureList::IsEnabled(chromeos::features::kLacrosOnly); } +bool IsAshWebBrowserEnabledForMigration(const user_manager::User* user, + PolicyInitState policy_init_state) { + // If Lacros is not a primary browser, Ash browser is always enabled. + if (!IsLacrosPrimaryBrowserForMigration(user, policy_init_state)) + return true; + + LacrosAvailability lacros_availability; + if (policy_init_state == PolicyInitState::kBeforeInit) { + // Before Policy is initialized, the value won't be available. + // So, we'll use the value preserved in the feature flags. + // See also LacrosAvailabilityPolicyObserver how it will be propergated. + lacros_availability = DetermineLacrosAvailabilityFromPolicyValue( + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + kLacrosAvailabilityPolicySwitch)); + } else { + DCHECK_EQ(policy_init_state, PolicyInitState::kAfterInit); + lacros_availability = GetCachedLacrosAvailability(); + } + + switch (lacros_availability) { + case LacrosAvailability::kUserChoice: + break; + case LacrosAvailability::kLacrosDisallowed: + return true; + case LacrosAvailability::kSideBySide: + case LacrosAvailability::kLacrosPrimary: + // Note that for this *ForMigration variant, since there might not be a + // logged in user yet, the user's email address has to be passed + // explicitly. Normally, policy should override Finch. Due to + // complications in the Google rollout, in the short term Finch will + // override policy if Finch is enabling this feature. + if (gaia::IsGoogleInternalAccountEmail( + user->GetAccountId().GetUserEmail()) && + base::FeatureList::IsEnabled(chromeos::features::kLacrosOnly)) { + return false; + } + return true; + case LacrosAvailability::kLacrosOnly: + return false; + } + + return !base::FeatureList::IsEnabled(chromeos::features::kLacrosOnly); +} + bool IsLacrosPrimaryBrowser() { + // Note that if you are updating this function, please also update the + // *ForMigration variant to keep the logics consistent. if (g_lacros_primary_browser_for_test.has_value()) return g_lacros_primary_browser_for_test.value(); @@ -527,11 +582,60 @@ return base::FeatureList::IsEnabled(chromeos::features::kLacrosPrimary); } +bool IsLacrosPrimaryBrowserForMigration(const user_manager::User* user, + PolicyInitState policy_init_state) { + if (g_lacros_primary_browser_for_test.has_value()) + return g_lacros_primary_browser_for_test.value(); + + if (!IsLacrosEnabledForMigration(user, policy_init_state)) + return false; + + // Lacros-chrome will always be the primary browser if Lacros is enabled in + // web Kiosk session. + if (user->GetType() == user_manager::USER_TYPE_KIOSK_APP || + user->GetType() == user_manager::USER_TYPE_WEB_KIOSK_APP) { + return true; + } + + LacrosAvailability lacros_availability; + if (policy_init_state == PolicyInitState::kBeforeInit) { + // Before Policy is initialized, the value won't be available. + // So, we'll use the value preserved in the feature flags. + // See also LacrosAvailabilityPolicyObserver how it will be propergated. + lacros_availability = DetermineLacrosAvailabilityFromPolicyValue( + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + kLacrosAvailabilityPolicySwitch)); + } else { + DCHECK_EQ(policy_init_state, PolicyInitState::kAfterInit); + lacros_availability = GetCachedLacrosAvailability(); + } + + if (!IsLacrosPrimaryBrowserAllowedForMigration(user, lacros_availability)) + return false; + + switch (lacros_availability) { + case LacrosAvailability::kUserChoice: + break; + case LacrosAvailability::kLacrosDisallowed: + NOTREACHED(); + return false; + case LacrosAvailability::kSideBySide: + return false; + case LacrosAvailability::kLacrosPrimary: + case LacrosAvailability::kLacrosOnly: + return true; + } + + return base::FeatureList::IsEnabled(chromeos::features::kLacrosPrimary); +} + void SetLacrosPrimaryBrowserForTest(absl::optional<bool> value) { g_lacros_primary_browser_for_test = value; } bool IsLacrosPrimaryBrowserAllowed() { + // Note that if you are updating this function, please also update the + // *ForMigration variant to keep the logics consistent. if (!IsLacrosAllowedToBeEnabled()) return false; @@ -550,6 +654,27 @@ return true; } +bool IsLacrosPrimaryBrowserAllowedForMigration( + const user_manager::User* user, + LacrosAvailability lacros_availability) { + if (!IsLacrosAllowedToBeEnabledWithUser(user, lacros_availability)) + return false; + + switch (lacros_availability) { + case LacrosAvailability::kLacrosDisallowed: + return false; + case LacrosAvailability::kLacrosPrimary: + case LacrosAvailability::kLacrosOnly: + // Forcibly allow to use Lacros as a Primary respecting the policy. + return true; + default: + // Fallback others. + break; + } + + return true; +} + bool IsLacrosPrimaryFlagAllowed() { return IsLacrosPrimaryBrowserAllowed() && (GetCachedLacrosAvailability() == LacrosAvailability::kUserChoice); @@ -669,9 +794,9 @@ dict->SetStringKey(user_id_hash, version.GetString()); } -bool IsDataWipeRequired(const std::string& user_id_hash) { - base::Version data_version = - GetDataVer(g_browser_process->local_state(), user_id_hash); +bool IsDataWipeRequired(PrefService* local_state, + const std::string& user_id_hash) { + base::Version data_version = GetDataVer(local_state, user_id_hash); const base::Version& current_version = version_info::GetVersion(); base::Version required_version = base::Version(base::StringPiece(kRequiredDataVersion)); @@ -774,16 +899,37 @@ g_lacros_availability_cache.reset(); } +MigrationMode GetMigrationMode(const user_manager::User* user, + PolicyInitState policy_init_state) { + if (base::FeatureList::IsEnabled( + ash::features::kLacrosMoveProfileMigration) || + !IsAshWebBrowserEnabledForMigration(user, policy_init_state)) { + return MigrationMode::kMove; + } + + return MigrationMode::kCopy; +} + bool IsProfileMigrationCompletedForUser(PrefService* local_state, - const std::string& user_id_hash) { + const std::string& user_id_hash, + MigrationMode mode) { // Allows tests to avoid marking profile migration as completed by getting // user_id_hash of the logged in user and updating // g_browser_process->local_state() etc. if (g_profile_migration_completed_for_test) return true; - const auto* pref = - local_state->FindPreference(kProfileMigrationCompletedForUserPref); + std::string pref_name; + switch (mode) { + case MigrationMode::kCopy: + pref_name = kProfileMigrationCompletedForUserPref; + break; + case MigrationMode::kMove: + pref_name = kProfileMoveMigrationCompletedForUserPref; + break; + } + + const auto* pref = local_state->FindPreference(pref_name); // Return if the pref is not registered. This can happen in browsertests. In // such a case, assume that migration was completed. if (!pref) @@ -798,19 +944,36 @@ } void SetProfileMigrationCompletedForUser(PrefService* local_state, - const std::string& user_id_hash) { + const std::string& user_id_hash, + MigrationMode mode) { DictionaryPrefUpdate update(local_state, kProfileMigrationCompletedForUserPref); base::Value* dict = update.Get(); dict->SetBoolKey(user_id_hash, true); + + if (mode == MigrationMode::kMove) { + DictionaryPrefUpdate update(local_state, + kProfileMoveMigrationCompletedForUserPref); + base::Value* dict = update.Get(); + dict->SetBoolKey(user_id_hash, true); + } } void ClearProfileMigrationCompletedForUser(PrefService* local_state, const std::string& user_id_hash) { - DictionaryPrefUpdate update(local_state, - kProfileMigrationCompletedForUserPref); - base::Value* dict = update.Get(); - dict->RemoveKey(user_id_hash); + { + DictionaryPrefUpdate update(local_state, + kProfileMigrationCompletedForUserPref); + base::Value* dict = update.Get(); + dict->RemoveKey(user_id_hash); + } + + { + DictionaryPrefUpdate update(local_state, + kProfileMoveMigrationCompletedForUserPref); + base::Value* dict = update.Get(); + dict->RemoveKey(user_id_hash); + } } void SetProfileMigrationCompletedForTest(bool is_completed) {
diff --git a/chrome/browser/ash/crosapi/browser_util.h b/chrome/browser/ash/crosapi/browser_util.h index e0cc02b..e225697 100644 --- a/chrome/browser/ash/crosapi/browser_util.h +++ b/chrome/browser/ash/crosapi/browser_util.h
@@ -190,9 +190,23 @@ // enabled and is the only browser. bool IsAshWebBrowserEnabled(); +// Similar to `IsAshWebBrowserEnabled()` but it is calleable even before primary +// profile and policy are initialized. +// TODO(crbug.com/1265800): Refactor to reduce code duplication with +// `IsAshWebBrowserEnabled()`. +bool IsAshWebBrowserEnabledForMigration(const user_manager::User* user, + PolicyInitState policy_init_state); + // Returns true if the lacros should be used as a primary browser. bool IsLacrosPrimaryBrowser(); +// Similar to `IsLacrosPrimaryBrowser()` but is calleable even before primary +// profile and policy are initialized. +// TODO(crbug.com/1265800): Refactor to reduce code duplication with +// `IsLacrosPrimaryBrowser()`. +bool IsLacrosPrimaryBrowserForMigration(const user_manager::User* user, + PolicyInitState policy_init_state); + // Forces IsLacrosPrimaryBrowser() to return true or false for testing. // Passing absl::nullopt will reset the state. void SetLacrosPrimaryBrowserForTest(absl::optional<bool> value); @@ -203,6 +217,14 @@ // true, specifically, the feature is disabled by user/policy. bool IsLacrosPrimaryBrowserAllowed(); +// Similar to `IsLacrosPrimaryBrowserAllowed()` but is calleable even before +// primary profile and policy are initialized. +// TODO(crbug.com/1265800): Refactor to reduce code duplication with +// `IsLacrosPrimaryBrowserAllowed()`. +bool IsLacrosPrimaryBrowserAllowedForMigration( + const user_manager::User* user, + LacrosAvailability lacros_availability); + // Returns true if |chromeos::features::kLacrosPrimary| flag is allowed. bool IsLacrosPrimaryFlagAllowed(); @@ -250,7 +272,8 @@ // Checks if lacros' data directory needs to be wiped for backward incompatible // data. -bool IsDataWipeRequired(const std::string& user_id_hash); +bool IsDataWipeRequired(PrefService* local_state, + const std::string& user_id_hash); // Exposed for testing. The arguments are passed to // `IsDataWipeRequiredInternal()`. @@ -277,6 +300,10 @@ version_info::Channel GetLacrosSelectionUpdateChannel( LacrosSelection selection); +// Exposed for testing. Sets lacros-availability cache for testing. +void SetCachedLacrosAvailabilityForTesting( + LacrosAvailability lacros_availability); + // Exposed for testing. Returns the lacros integration suggested by the policy // lacros-availability, modified by Finch flags and user flags as appropriate. LacrosAvailability GetCachedLacrosAvailabilityForTesting(); @@ -289,15 +316,22 @@ // Returns true if the profile migration can run, but not yet completed. bool IsProfileMigrationAvailable(); +// Returns `MigrationMode::kMove` if LacrosOnly or `kLacrosMoveProfileMigration` +// is enabled and `MigrationMode::kCopy` otherwise. +MigrationMode GetMigrationMode(const user_manager::User* user, + PolicyInitState policy_init_state); + // Checks if profile migration has been completed. This is reset if profile // migration is initiated for example due to lacros data directory being wiped. bool IsProfileMigrationCompletedForUser(PrefService* local_state, - const std::string& user_id_hash); + const std::string& user_id_hash, + MigrationMode mode); // Sets the value of `kProfileMigrationCompletedForUser1Pref` to be true // for the user identified by `user_id_hash`. void SetProfileMigrationCompletedForUser(PrefService* local_state, - const std::string& user_id_hash); + const std::string& user_id_hash, + MigrationMode mode); // Clears the value of `kProfileMigrationCompletedForUser1Pref` for user // identified by `user_id_hash`.
diff --git a/chrome/browser/ash/crosapi/browser_util_unittest.cc b/chrome/browser/ash/crosapi/browser_util_unittest.cc index 026af60fe..64fa19b 100644 --- a/chrome/browser/ash/crosapi/browser_util_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_util_unittest.cc
@@ -162,13 +162,14 @@ // false. EXPECT_FALSE(browser_util::IsLacrosEnabled()); - browser_util::SetProfileMigrationCompletedForUser(&pref_service_, - user->username_hash()); + browser_util::SetProfileMigrationCompletedForUser( + &pref_service_, user->username_hash(), + browser_util::MigrationMode::kCopy); EXPECT_TRUE(browser_util::IsLacrosEnabled()); } -TEST_F(BrowserUtilTest, IsLacrosEnabledForMigrationBeforePolocyInit) { +TEST_F(BrowserUtilTest, IsLacrosEnabledForMigrationBeforePolicyInit) { // This sets `g_browser_process->local_state()` which activates the check // `IsProfileMigrationCompletedForUser()` inside `IsLacrosEnabled()`. ScopedLocalState scoped_local_state(&pref_service_); @@ -259,6 +260,8 @@ TEST_F(LacrosSupportBrowserUtilTest, AshWebBrowserEnabled) { base::test::ScopedFeatureList feature_list; AddRegularUser("user@managedchrome.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); // Lacros is not allowed. { @@ -267,6 +270,8 @@ EXPECT_FALSE(browser_util::IsLacrosAllowedToBeEnabled()); EXPECT_FALSE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } // Lacros is allowed but not enabled. @@ -276,6 +281,8 @@ EXPECT_TRUE(browser_util::IsLacrosAllowedToBeEnabled()); EXPECT_FALSE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } // Lacros is allowed and enabled by flag. @@ -286,6 +293,8 @@ EXPECT_TRUE(browser_util::IsLacrosAllowedToBeEnabled()); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } // Lacros is allowed and enabled by policy. @@ -295,6 +304,8 @@ EXPECT_TRUE(browser_util::IsLacrosAllowedToBeEnabled()); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } { ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosPrimary); @@ -302,22 +313,51 @@ EXPECT_TRUE(browser_util::IsLacrosAllowedToBeEnabled()); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } } +TEST_F(BrowserUtilTest, IsAshWebBrowserEnabledForMigration) { + // Add an user. + AddRegularUser("user@test.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); + + // Ash browser is enabled if Lacros is not enabled. + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kBeforeInit)); + + // Sets command line flag to emulate the situation where the Chrome + // restart happens. + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + cmdline->AppendSwitchASCII(browser_util::kLacrosAvailabilityPolicySwitch, + browser_util::kLacrosAvailabilityPolicyLacrosOnly); + + // Ash browser is disabled if LacrosOnly is enabled. + EXPECT_FALSE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kBeforeInit)); +} + TEST_F(BrowserUtilTest, IsAshWebBrowserDisabled) { base::test::ScopedFeatureList feature_list; AddRegularUser("user@managedchrome.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosOnly); // Lacros is allowed and enabled and is the only browser by policy. EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_FALSE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } TEST_F(BrowserUtilTest, IsAshWebBrowserDisabledByFlags) { AddRegularUser("user@test.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); { EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); } // Just enabling LacrosOnly feature is not enough. @@ -325,6 +365,8 @@ base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(chromeos::features::kLacrosOnly); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } // LacrosSupport only is not enough. @@ -334,6 +376,8 @@ {chromeos::features::kLacrosOnly, chromeos::features::kLacrosSupport}, {}); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } // All, LacrosOnly, LacrosPrimary and LacrosSupport are needed. @@ -344,18 +388,28 @@ chromeos::features::kLacrosSupport}, {}); EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_FALSE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } } TEST_F(LacrosSupportBrowserUtilTest, LacrosPrimaryBrowserByFlags) { AddRegularUser("user@test.com"); - { EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); } + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); + { + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); + } // Just enabling LacrosPrimary feature is not enough. { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(chromeos::features::kLacrosPrimary); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } // Both LacrosPrimary and LacrosSupport are needed. @@ -365,11 +419,15 @@ chromeos::features::kLacrosSupport}, {}); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } } TEST_F(BrowserUtilTest, LacrosPrimaryBrowser) { AddRegularUser("user@test.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); // Currently, only developer build can use Lacros as a primary // web browser. @@ -378,41 +436,65 @@ {chromeos::features::kLacrosPrimary, chromeos::features::kLacrosSupport}, {}); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } TEST_F(BrowserUtilTest, LacrosPrimaryBrowserAllowed) { AddRegularUser("user@test.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowed()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowedForMigration( + user, browser_util::GetCachedLacrosAvailabilityForTesting())); } TEST_F(BrowserUtilTest, ManagedAccountLacrosPrimary) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(chromeos::features::kLacrosSupport); AddRegularUser("user@managedchrome.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); { ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosDisallowed); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserAllowed()); + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserAllowedForMigration( + user, browser_util::GetCachedLacrosAvailabilityForTesting())); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } { ScopedLacrosAvailabilityCache cache(LacrosAvailability::kSideBySide); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowed()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowedForMigration( + user, browser_util::GetCachedLacrosAvailabilityForTesting())); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } { ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosPrimary); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowed()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowedForMigration( + user, browser_util::GetCachedLacrosAvailabilityForTesting())); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } { ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosOnly); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowed()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserAllowedForMigration( + user, browser_util::GetCachedLacrosAvailabilityForTesting())); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } } @@ -671,21 +753,35 @@ TEST_F(BrowserUtilTest, IsProfileMigrationCompletedForUser) { const std::string user_id_hash = "abcd"; - - // `IsLacrosDisabledAfterSkippedOrFailedMigration()` should return + // `IsProfileMigrationCompletedForUser()` should return // false by default. - EXPECT_FALSE(browser_util::IsProfileMigrationCompletedForUser(&pref_service_, - user_id_hash)); + EXPECT_FALSE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kCopy)); + EXPECT_FALSE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kMove)); - browser_util::SetProfileMigrationCompletedForUser(&pref_service_, - user_id_hash); - EXPECT_TRUE(browser_util::IsProfileMigrationCompletedForUser(&pref_service_, - user_id_hash)); + browser_util::SetProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kCopy); + EXPECT_TRUE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kCopy)); + EXPECT_FALSE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kMove)); browser_util::ClearProfileMigrationCompletedForUser(&pref_service_, user_id_hash); - EXPECT_FALSE(browser_util::IsProfileMigrationCompletedForUser(&pref_service_, - user_id_hash)); + EXPECT_FALSE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kCopy)); + EXPECT_FALSE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kMove)); + + // Setting completion for move sets completion for both copy (non move) and + // move. + browser_util::SetProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kMove); + EXPECT_TRUE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kCopy)); + EXPECT_TRUE(browser_util::IsProfileMigrationCompletedForUser( + &pref_service_, user_id_hash, browser_util::MigrationMode::kMove)); } TEST_F(BrowserUtilTest, IsAshBrowserSyncEnabled) { @@ -767,6 +863,8 @@ // precisely intended side-effects. TEST_F(BrowserUtilTest, LacrosGoogleRolloutUserChoice) { AddRegularUser("user@google.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); // Lacros availability is set by policy to user choice. ScopedLacrosAvailabilityCache cache(LacrosAvailability::kUserChoice); @@ -781,11 +879,15 @@ EXPECT_TRUE(browser_util::IsLacrosAllowedToBeEnabled()); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled()); } TEST_F(BrowserUtilTest, LacrosGoogleRolloutPrimary) { AddRegularUser("user@google.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); // Lacros availability is set by policy to primary. ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosPrimary); @@ -800,7 +902,11 @@ EXPECT_TRUE(browser_util::IsLacrosAllowedToBeEnabled()); EXPECT_TRUE(browser_util::IsLacrosEnabled()); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_FALSE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); } TEST_F(BrowserUtilTest, IsArcAvailable) {
diff --git a/chrome/browser/ash/crosapi/move_migrator.h b/chrome/browser/ash/crosapi/move_migrator.h index 358cddc9..902e7af 100644 --- a/chrome/browser/ash/crosapi/move_migrator.h +++ b/chrome/browser/ash/crosapi/move_migrator.h
@@ -139,7 +139,7 @@ MigrateResumeFromMoveSplitItems); FRIEND_TEST_ALL_PREFIXES(MoveMigratorMigrateTest, MigrateResumeFromMoveTmpDir); - friend class BrowserDataMigratorResumeOnSignInTest; + friend class BrowserDataMigratorResumeOnSignIn; friend class BrowserDataMigratorResumeRestartInSession; // These values are persisted to logs. Entries should not be renumbered and
diff --git a/chrome/browser/ash/crostini/crostini_simple_types.cc b/chrome/browser/ash/crostini/crostini_simple_types.cc index 03a16bd..0b495b1 100644 --- a/chrome/browser/ash/crostini/crostini_simple_types.cc +++ b/chrome/browser/ash/crostini/crostini_simple_types.cc
@@ -6,6 +6,77 @@ namespace crostini { +const char* CrostiniResultString(const CrostiniResult res) { +#define ENTRY(name) \ + case CrostiniResult::name: \ + return #name + switch (res) { + ENTRY(SUCCESS); + ENTRY(CREATE_DISK_IMAGE_FAILED); + ENTRY(VM_START_FAILED); + ENTRY(VM_STOP_FAILED); + ENTRY(DESTROY_DISK_IMAGE_FAILED); + ENTRY(LIST_VM_DISKS_FAILED); + ENTRY(CLIENT_ERROR); + ENTRY(CONTAINER_DOWNLOAD_TIMED_OUT); + ENTRY(CONTAINER_CREATE_CANCELLED); + ENTRY(CONTAINER_CREATE_FAILED); + ENTRY(CONTAINER_START_CANCELLED); + ENTRY(CONTAINER_START_FAILED); + ENTRY(INSTALL_LINUX_PACKAGE_FAILED); + ENTRY(BLOCKING_OPERATION_ALREADY_ACTIVE); + ENTRY(UNINSTALL_PACKAGE_FAILED); + ENTRY(SSHFS_MOUNT_ERROR); + ENTRY(OFFLINE_WHEN_UPGRADE_REQUIRED); + ENTRY(LOAD_COMPONENT_FAILED); + ENTRY(CROSTINI_UNINSTALLER_RUNNING); + ENTRY(UNKNOWN_ERROR); + ENTRY(CONTAINER_EXPORT_IMPORT_FAILED); + ENTRY(CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED); + ENTRY(CONTAINER_EXPORT_IMPORT_FAILED_VM_STARTED); + ENTRY(CONTAINER_EXPORT_IMPORT_FAILED_ARCHITECTURE); + ENTRY(NOT_ALLOWED); + ENTRY(CONTAINER_EXPORT_IMPORT_FAILED_SPACE); + ENTRY(GET_CONTAINER_SSH_KEYS_FAILED); + ENTRY(CONTAINER_EXPORT_IMPORT_CANCELLED); + ENTRY(RESTART_ABORTED); + ENTRY(RESTART_FAILED_VM_STOPPED); + ENTRY(UPGRADE_CONTAINER_STARTED); + ENTRY(UPGRADE_CONTAINER_ALREADY_RUNNING); + ENTRY(UPGRADE_CONTAINER_NOT_SUPPORTED); + ENTRY(UPGRADE_CONTAINER_ALREADY_UPGRADED); + ENTRY(UPGRADE_CONTAINER_FAILED); + ENTRY(CANCEL_UPGRADE_CONTAINER_FAILED); + ENTRY(CONCIERGE_START_FAILED); + ENTRY(CONTAINER_CONFIGURATION_FAILED); + ENTRY(LOAD_COMPONENT_UPDATE_IN_PROGRESS); + ENTRY(NEVER_FINISHED); + ENTRY(CONTAINER_SETUP_FAILED); + ENTRY(START_LXD_FAILED); + ENTRY(INSTALL_IMAGE_LOADER_TIMED_OUT); + ENTRY(CREATE_DISK_IMAGE_TIMED_OUT); + ENTRY(START_TERMINA_VM_TIMED_OUT); + ENTRY(START_LXD_TIMED_OUT); + ENTRY(CREATE_CONTAINER_TIMED_OUT); + ENTRY(SETUP_CONTAINER_TIMED_OUT); + ENTRY(START_CONTAINER_TIMED_OUT); + ENTRY(FETCH_SSH_KEYS_TIMED_OUT); + ENTRY(MOUNT_CONTAINER_TIMED_OUT); + ENTRY(UNKNOWN_STATE_TIMED_OUT); + ENTRY(NEED_UPDATE); + ENTRY(SHARE_PATHS_FAILED); + ENTRY(UNREGISTERED_APPLICATION); + ENTRY(VSH_CONNECT_FAILED); + ENTRY(CONTAINER_STOP_FAILED); + ENTRY(CONTAINER_STOP_CANCELLED); + ENTRY(WAYLAND_SERVER_CREATION_FAILED); + ENTRY(CONFIGURE_CONTAINER_TIMED_OUT); + ENTRY(RESTART_REQUEST_CANCELLED); + } +#undef ENTRY + return "unknown code"; +} + LinuxPackageInfo::LinuxPackageInfo() = default; LinuxPackageInfo::LinuxPackageInfo(LinuxPackageInfo&&) = default; LinuxPackageInfo::LinuxPackageInfo(const LinuxPackageInfo&) = default;
diff --git a/chrome/browser/ash/crostini/crostini_simple_types.h b/chrome/browser/ash/crostini/crostini_simple_types.h index b549f4b..e9cc07f 100644 --- a/chrome/browser/ash/crostini/crostini_simple_types.h +++ b/chrome/browser/ash/crostini/crostini_simple_types.h
@@ -29,6 +29,7 @@ // If you add anything here make sure to also update enums.xml and the plx // scripts in // https://plx.corp.google.com/home2/home/collections/c16e3c1474497b821 +// and CrostiniResultString in crostini_simple_types.cc. enum class CrostiniResult { SUCCESS = 0, // DBUS_ERROR = 1, @@ -107,6 +108,9 @@ // the top of this enum. }; +// Returns the string name of the CrostiniResult. +const char* CrostiniResultString(const CrostiniResult res); + using CrostiniSuccessCallback = base::OnceCallback<void(bool success, const std::string& failure_reason)>;
diff --git a/chrome/browser/ash/crostini/crostini_terminal.cc b/chrome/browser/ash/crostini/crostini_terminal.cc index 5b329732..eb758ab0 100644 --- a/chrome/browser/ash/crostini/crostini_terminal.cc +++ b/chrome/browser/ash/crostini/crostini_terminal.cc
@@ -137,8 +137,7 @@ // TODO(crbug.com/1308961): Migrate to use PWA pinned home tab when ready. // If opening a new tab, first pin home tab. full_restore::FullRestoreSaveHandler::GetInstance(); - GURL home( - base::StrCat({chrome::kChromeUIUntrustedTerminalURL, kTerminalHomePath})); + GURL home(GetTerminalHomeUrl()); Browser* browser = web_app::LaunchSystemWebAppImpl( profile, ash::SystemWebAppType::TERMINAL, home, params); if (!browser) { @@ -163,9 +162,9 @@ apps->RemoveKey(kCrostiniTerminalSystemAppId); } -const std::string& GetTerminalDefaultUrl() { - static const base::NoDestructor<std::string> url(base::StrCat( - {chrome::kChromeUIUntrustedTerminalURL, "html/terminal.html"})); +const std::string& GetTerminalHomeUrl() { + static const base::NoDestructor<std::string> url( + base::StrCat({chrome::kChromeUIUntrustedTerminalURL, kTerminalHomePath})); return *url; } @@ -220,10 +219,7 @@ } void LaunchTerminalHome(Profile* profile, int64_t display_id) { - LaunchTerminalWithUrl( - profile, display_id, - GURL(base::StrCat( - {chrome::kChromeUIUntrustedTerminalURL, kTerminalHomePath}))); + LaunchTerminalWithUrl(profile, display_id, GURL(GetTerminalHomeUrl())); } void LaunchTerminalWithUrl(Profile* profile,
diff --git a/chrome/browser/ash/crostini/crostini_terminal.h b/chrome/browser/ash/crostini/crostini_terminal.h index c647518..e304f35 100644 --- a/chrome/browser/ash/crostini/crostini_terminal.h +++ b/chrome/browser/ash/crostini/crostini_terminal.h
@@ -112,7 +112,7 @@ // Remove Terminal app id from crostini.registry.<terminal-app-id>. void RemoveTerminalFromRegistry(PrefService* prefs); -const std::string& GetTerminalDefaultUrl(); +const std::string& GetTerminalHomeUrl(); // Generate URL to launch terminal. GURL GenerateTerminalURL(
diff --git a/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc b/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc index e7fae10..5b21c636 100644 --- a/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc +++ b/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ash/dbus/encrypted_reporting_service_provider.h" +#include <limits> #include <memory> #include <utility> @@ -157,8 +158,22 @@ return; } + // Missive should always send the remaining storage capacity and new events + // rate. If not, probably an outdated version of missive is running. In this + // case, we ignore the effect of remaining storage capacity/new events rate + // and give it the max/min possible value. + const auto remaining_storage_capacity = + request.has_remaining_storage_capacity() + ? request.remaining_storage_capacity() + : std::numeric_limits<uint64_t>::max(); + const auto new_events_rate = + request.has_new_events_rate() ? request.new_events_rate() : 1U; auto records{reporting::EventUploadSizeController::BuildEncryptedRecords( - request.encrypted_record(), network_condition_service_)}; + request.encrypted_record(), + reporting::EventUploadSizeController(network_condition_service_, + new_events_rate, + remaining_storage_capacity, + /*enabled=*/false))}; DCHECK(upload_provider_); MissiveClient* const missive_client = MissiveClient::Get();
diff --git a/chrome/browser/ash/file_manager/trash_common_util.cc b/chrome/browser/ash/file_manager/trash_common_util.cc index cde7aff..e1e64a8 100644 --- a/chrome/browser/ash/file_manager/trash_common_util.cc +++ b/chrome/browser/ash/file_manager/trash_common_util.cc
@@ -4,6 +4,11 @@ #include "chrome/browser/ash/file_manager/trash_common_util.h" +#include "chrome/browser/ash/crostini/crostini_manager.h" +#include "chrome/browser/ash/drive/drive_integration_service.h" +#include "chrome/browser/ash/file_manager/path_util.h" +#include "chrome/browser/ash/file_manager/volume_manager.h" + namespace file_manager { namespace io_task { @@ -11,6 +16,22 @@ constexpr char kInfoFolderName[] = "info"; constexpr char kFilesFolderName[] = "files"; +TrashLocation::TrashLocation(const base::FilePath supplied_relative_folder_path, + const base::FilePath parent_path, + const base::FilePath prefix_path) + : relative_folder_path(supplied_relative_folder_path), + trash_parent_path(parent_path), + prefix_restore_path(prefix_path) {} + +TrashLocation::TrashLocation(const base::FilePath supplied_relative_folder_path, + const base::FilePath parent_path) + : relative_folder_path(supplied_relative_folder_path), + trash_parent_path(parent_path) {} +TrashLocation::~TrashLocation() = default; + +TrashLocation::TrashLocation(TrashLocation&& other) = default; +TrashLocation& TrashLocation::operator=(TrashLocation&& other) = default; + const base::FilePath GenerateTrashPath(const base::FilePath& trash_path, const std::string& subdir, const std::string& file_name) { @@ -22,5 +43,55 @@ return path; } +TrashPathsMap GenerateEnabledTrashLocationsForProfile( + Profile* profile, + const base::FilePath& base_path) { + TrashPathsMap enabled_trash_locations; + + enabled_trash_locations.try_emplace( + util::GetMyFilesFolderForProfile(profile), + TrashLocation(base::FilePath(kTrashFolderName), + util::GetMyFilesFolderForProfile(profile))); + enabled_trash_locations.try_emplace( + util::GetDownloadsFolderForProfile(profile), + TrashLocation(base::FilePath(kTrashFolderName), + util::GetDownloadsFolderForProfile(profile), + util::GetDownloadsFolderForProfile(profile).BaseName())); + + auto* integration_service = + drive::DriveIntegrationServiceFactory::FindForProfile(profile); + if (integration_service) { + enabled_trash_locations.try_emplace( + integration_service->GetMountPointPath(), + TrashLocation(base::FilePath(".Trash-1000"), + integration_service->GetMountPointPath())); + } + + // Ensure Crostini is running before adding it as an enabled path. + file_manager::VolumeManager* const volume_manager = + file_manager::VolumeManager::Get(profile); + if (crostini::CrostiniManager::GetForProfile(profile) && + crostini::IsCrostiniRunning(profile) && volume_manager) { + // A `base_path` is supplied in tests to ensure files are only added to + // temporary directories. If `base_path` has been supplied, use the mocked + // volume mount path instead of the real mount path. + const base::FilePath crostini_mount_point = + (base_path.empty()) + ? file_manager::util::GetCrostiniMountDirectory(profile) + : base_path.Append("crostini"); + base::WeakPtr<file_manager::Volume> volume = + volume_manager->FindVolumeFromPath(crostini_mount_point); + if (volume) { + enabled_trash_locations.try_emplace( + crostini_mount_point, + TrashLocation( + base::FilePath(".local").Append("share").Append("Trash"), + crostini_mount_point, volume->remote_mount_path())); + } + } + + return enabled_trash_locations; +} + } // namespace io_task } // namespace file_manager
diff --git a/chrome/browser/ash/file_manager/trash_common_util.h b/chrome/browser/ash/file_manager/trash_common_util.h index d8dc4723..c7b9ee0 100644 --- a/chrome/browser/ash/file_manager/trash_common_util.h +++ b/chrome/browser/ash/file_manager/trash_common_util.h
@@ -5,7 +5,12 @@ #ifndef CHROME_BROWSER_ASH_FILE_MANAGER_TRASH_COMMON_UTIL_H_ #define CHROME_BROWSER_ASH_FILE_MANAGER_TRASH_COMMON_UTIL_H_ +#include <map> + #include "base/files/file_path.h" +#include "storage/browser/file_system/file_system_url.h" + +class Profile; namespace file_manager { namespace io_task { @@ -19,11 +24,58 @@ // Constant representing the "files" folder name inside .Trash. extern const char kFilesFolderName[]; +struct TrashLocation { + TrashLocation(const base::FilePath supplied_relative_folder_path, + const base::FilePath parent_path, + const base::FilePath prefix_path); + // Constructor used when no prefix path is required. + TrashLocation(const base::FilePath supplied_relative_folder_path, + const base::FilePath parent_path); + ~TrashLocation(); + + TrashLocation(TrashLocation&& other); + TrashLocation& operator=(TrashLocation&& other); + + // The location of the .Trash/files folder. + storage::FileSystemURL trash_files; + + // The location of the .Trash/info folder. + storage::FileSystemURL trash_info; + + // The folder path for the Trash folder. This is parented by + // `trash_parent_path` and typically represents the .Trash folder. However, in + // some cases this can represent a path instead. This path must be relative + // from the `trash_parent_path`, i.e. not an absolute path. + base::FilePath relative_folder_path; + + // The parent folder path of this trash entry. + base::FilePath trash_parent_path; + + // For some trash directories, the restore path requires a prefix to ensure + // restoration is done correctly. + base::FilePath prefix_restore_path; + + // The free space on the underlying filesystem that .Trash is located on. + int64_t free_space; + + // Whether this directory require setting up. This is enabled once free space + // has been retrieved for the underlying file system. If false directory setup + // is skipped. + bool require_setup = false; +}; + // Helper to create a destination path for a file in one of the .Trash folders. const base::FilePath GenerateTrashPath(const base::FilePath& trash_path, const std::string& subdir, const std::string& file_name); +// Generate the list of currently enabled paths for trashing. It includes +// DriveFS and Crostini paths when they're enabled. +using TrashPathsMap = std::map<const base::FilePath, TrashLocation>; +TrashPathsMap GenerateEnabledTrashLocationsForProfile( + Profile* profile, + const base::FilePath& base_path); + } // namespace io_task } // namespace file_manager
diff --git a/chrome/browser/ash/file_manager/trash_io_task.cc b/chrome/browser/ash/file_manager/trash_io_task.cc index 17f28ae..1479cbe3f 100644 --- a/chrome/browser/ash/file_manager/trash_io_task.cc +++ b/chrome/browser/ash/file_manager/trash_io_task.cc
@@ -90,22 +90,6 @@ TrashEntry::TrashEntry(TrashEntry&& other) = default; TrashEntry& TrashEntry::operator=(TrashEntry&& other) = default; -TrashLocation::TrashLocation(const base::FilePath supplied_relative_folder_path, - const base::FilePath parent_path, - const base::FilePath prefix_path) - : relative_folder_path(supplied_relative_folder_path), - trash_parent_path(parent_path), - prefix_restore_path(prefix_path) {} - -TrashLocation::TrashLocation(const base::FilePath supplied_relative_folder_path, - const base::FilePath parent_path) - : relative_folder_path(supplied_relative_folder_path), - trash_parent_path(parent_path) {} -TrashLocation::~TrashLocation() = default; - -TrashLocation::TrashLocation(TrashLocation&& other) = default; -TrashLocation& TrashLocation::operator=(TrashLocation&& other) = default; - } // namespace TrashIOTask::TrashIOTask( @@ -148,48 +132,8 @@ // Build the list of known paths that are enabled, for now Downloads is a bind // mount at MyFiles/Downloads so treat them as separate volumes. - free_space_map_.try_emplace( - util::GetMyFilesFolderForProfile(profile_), - TrashLocation(base::FilePath(kTrashFolderName), - util::GetMyFilesFolderForProfile(profile_))); - free_space_map_.try_emplace( - util::GetDownloadsFolderForProfile(profile_), - TrashLocation(base::FilePath(kTrashFolderName), - util::GetDownloadsFolderForProfile(profile_), - util::GetDownloadsFolderForProfile(profile_).BaseName())); - - auto* integration_service = - drive::DriveIntegrationServiceFactory::FindForProfile(profile_); - if (integration_service) { - free_space_map_.try_emplace( - integration_service->GetMountPointPath(), - TrashLocation(base::FilePath(".Trash-1000"), - integration_service->GetMountPointPath())); - } - - // Ensure Crostini is running before adding it as an enabled path. - file_manager::VolumeManager* const volume_manager = - file_manager::VolumeManager::Get(profile_); - if (crostini::CrostiniManager::GetForProfile(profile_) && - crostini::IsCrostiniRunning(profile_) && volume_manager) { - // A `base_path_` is supplied in tests to ensure files are only added to - // temporary directories. If `base_path_` has been supplied, use the mocked - // volume mount path instead of the real mount path. - const base::FilePath crostini_mount_point = - (base_path_.empty()) - ? file_manager::util::GetCrostiniMountDirectory(profile_) - : base_path_.Append("crostini"); - base::WeakPtr<file_manager::Volume> volume = - volume_manager->FindVolumeFromPath(crostini_mount_point); - if (volume) { - free_space_map_.try_emplace( - crostini_mount_point, - TrashLocation( - base::FilePath(".local").Append("share").Append("Trash"), - crostini_mount_point, volume->remote_mount_path())); - } - } - + free_space_map_ = + GenerateEnabledTrashLocationsForProfile(profile_, base_path_); progress_.state = State::kInProgress; UpdateTrashEntry(0);
diff --git a/chrome/browser/ash/file_manager/trash_io_task.h b/chrome/browser/ash/file_manager/trash_io_task.h index 2695d08..1c4b57e 100644 --- a/chrome/browser/ash/file_manager/trash_io_task.h +++ b/chrome/browser/ash/file_manager/trash_io_task.h
@@ -16,6 +16,7 @@ #include "chrome/browser/ash/file_manager/file_manager_copy_or_move_hook_delegate.h" #include "chrome/browser/ash/file_manager/io_task.h" #include "chrome/browser/ash/file_manager/speedometer.h" +#include "chrome/browser/ash/file_manager/trash_common_util.h" #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_operation_runner.h" #include "storage/browser/file_system/file_system_url.h" @@ -51,46 +52,6 @@ int64_t source_file_size; }; -struct TrashLocation { - TrashLocation(const base::FilePath supplied_relative_folder_path, - const base::FilePath parent_path, - const base::FilePath prefix_path); - // Constructor used when no prefix path is required. - TrashLocation(const base::FilePath supplied_relative_folder_path, - const base::FilePath parent_path); - ~TrashLocation(); - - TrashLocation(TrashLocation&& other); - TrashLocation& operator=(TrashLocation&& other); - - // The location of the .Trash/files folder. - storage::FileSystemURL trash_files; - - // The location of the .Trash/info folder. - storage::FileSystemURL trash_info; - - // The folder path for the Trash folder. This is parented by - // `trash_parent_path` and typically represents the .Trash folder. However, in - // some cases this can represent a path instead. This path must be relative - // from the `trash_parent_path`, i.e. not an absolute path. - base::FilePath relative_folder_path; - - // The parent folder path of this trash entry. - base::FilePath trash_parent_path; - - // For some trash directories, the restore path requires a prefix to ensure - // restoration is done correctly. - base::FilePath prefix_restore_path; - - // The free space on the underlying filesystem that .Trash is located on. - int64_t free_space; - - // Whether this directory require setting up. This is enabled once free space - // has been retrieved for the underlying file system. If false directory setup - // is skipped. - bool require_setup = false; -}; - } // namespace // This class represents a trash task. A trash task attempts to trash zero or @@ -131,7 +92,6 @@ const base::FilePath& path); void SetCurrentOperationID( storage::FileSystemOperationRunner::OperationID id); - using TrashPathsMap = std::map<const base::FilePath, TrashLocation>; void ValidateAndDecrementFreeSpace(size_t source_idx, const TrashPathsMap::reverse_iterator& it); // Get the free disk space for `trash_parent_path` to know whether the
diff --git a/chrome/browser/ash/login/existing_user_controller.cc b/chrome/browser/ash/login/existing_user_controller.cc index 581018d..a658c1f 100644 --- a/chrome/browser/ash/login/existing_user_controller.cc +++ b/chrome/browser/ash/login/existing_user_controller.cc
@@ -949,7 +949,8 @@ if (BrowserDataMigratorImpl::MaybeForceResumeMoveMigration( g_browser_process->local_state(), user_context.GetAccountId(), - user_context.GetUserIDHash())) { + user_context.GetUserIDHash(), + crosapi::browser_util::PolicyInitState::kAfterInit)) { // TODO(crbug.com/1261730): Add an UMA. LOG(WARNING) << "Restarting Chrome to resume move migration."; return;
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash_browsertest.cc b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash_browsertest.cc index d8f9ee2..2357e6c9 100644 --- a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash_browsertest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash_browsertest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/test/bind.h" #include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" #include <functional> @@ -54,6 +55,7 @@ #include "content/public/test/browser_test.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-forward.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" #include "ui/aura/window.h" #include "ui/gfx/geometry/rect.h" @@ -874,23 +876,27 @@ bool expect_warning) { // First check for the permission to start screen sharing. // It should call DlpContentManager::CheckScreenShareRestriction(). - base::test::TestFuture<const blink::mojom::StreamDevices&, - blink::mojom::MediaStreamRequestResult, - std::unique_ptr<content::MediaStreamUI>> - test_future; + blink::mojom::MediaStreamRequestResult received_result = + blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS; + base::RunLoop run_loop; handler->HandleRequest( web_contents, request, - test_future.GetCallback<const blink::mojom::StreamDevices&, - blink::mojom::MediaStreamRequestResult, - std::unique_ptr<content::MediaStreamUI>>(), + base::BindLambdaForTesting( + [&received_result, &run_loop]( + const blink::mojom::StreamDevicesSet&, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI>) { + received_result = result; + run_loop.Quit(); + }), /*extension=*/nullptr); if (expect_warning) DismissDialog(expect_allowed); - ASSERT_TRUE(test_future.Wait()) << "MediaResponseCallback timed out."; + run_loop.Run(); EXPECT_EQ( - test_future.Get<1>(), + received_result, (expect_allowed ? blink::mojom::MediaStreamRequestResult::OK : blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED));
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.cc index 5d6f194..961919c3 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.cc
@@ -17,6 +17,15 @@ namespace policy { +namespace { + +// This command has an expiration time this high with the same reasons as for +// `DeviceCommandWipeUsersJob::kWipeUsersCommandExpirationTime`. +constexpr base::TimeDelta kRefreshMachineCertificateCommandExpirationTime = + base::Days(180); + +} // namespace + DeviceCommandRefreshMachineCertificateJob:: DeviceCommandRefreshMachineCertificateJob( ash::attestation::MachineCertificateUploader* @@ -32,6 +41,10 @@ RemoteCommand_Type_DEVICE_REFRESH_ENTERPRISE_MACHINE_CERTIFICATE; } +bool DeviceCommandRefreshMachineCertificateJob::IsExpired(base::TimeTicks now) { + return now > issued_time() + kRefreshMachineCertificateCommandExpirationTime; +} + void DeviceCommandRefreshMachineCertificateJob::RunImpl( CallbackWithResult succeeded_callback, CallbackWithResult failed_callback) {
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.h b/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.h index ea8cf4e..f1ff942 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.h +++ b/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.h
@@ -36,6 +36,7 @@ ash::attestation::MachineCertificateUploader* machine_certificate_uploader_; // RemoteCommandJob: + bool IsExpired(base::TimeTicks now) override; void RunImpl(CallbackWithResult succeeded_callback, CallbackWithResult failed_callback) override;
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job_unittest.cc new file mode 100644 index 0000000..0f97b65 --- /dev/null +++ b/chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job_unittest.cc
@@ -0,0 +1,170 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/policy/remote_commands/device_command_refresh_machine_certificate_job.h" + +#include <memory> +#include <utility> + +#include "base/run_loop.h" +#include "base/test/simple_test_clock.h" +#include "base/test/simple_test_tick_clock.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "chrome/browser/ash/attestation/mock_machine_certificate_uploader.h" +#include "components/policy/core/common/remote_commands/remote_command_job.h" +#include "components/policy/proto/device_management_backend.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +namespace { + +using ::ash::attestation::MachineCertificateUploader; +using ::ash::attestation::MockMachineCertificateUploader; +using ::testing::Invoke; +using ::testing::StrictMock; + +constexpr base::TimeDelta kWorldAge = base::Days(365); +constexpr base::TimeDelta kDefaultCommandAge = base::Minutes(10); +constexpr base::TimeDelta kVeryOldCommandAge = base::Days(175); +constexpr base::TimeDelta kTooOldCommandAge = base::Days(181); + +std::unique_ptr<RemoteCommandJob> CreateRefreshMachineCertificateJob( + const base::TimeDelta& age_of_command, + const base::TimeTicks& now, + MachineCertificateUploader* cert_uploader) { + // Create the job proto. + enterprise_management::RemoteCommand command_proto; + command_proto.set_type( + enterprise_management:: + RemoteCommand_Type_DEVICE_REFRESH_ENTERPRISE_MACHINE_CERTIFICATE); + constexpr RemoteCommandJob::UniqueIDType kUniqueID = 123456789; + command_proto.set_command_id(kUniqueID); + command_proto.set_age_of_command(age_of_command.InMilliseconds()); + + // Create the job and validate. + auto job = std::make_unique<DeviceCommandRefreshMachineCertificateJob>( + cert_uploader); + + EXPECT_TRUE( + job->Init(now, command_proto, enterprise_management::SignedData())); + EXPECT_EQ(kUniqueID, job->unique_id()); + EXPECT_EQ(RemoteCommandJob::NOT_STARTED, job->status()); + + return job; +} + +} // namespace + +class DeviceCommandRefreshMachineCertificateJobTest : public testing::Test { + public: + DeviceCommandRefreshMachineCertificateJobTest( + const DeviceCommandRefreshMachineCertificateJobTest&) = delete; + DeviceCommandRefreshMachineCertificateJobTest& operator=( + const DeviceCommandRefreshMachineCertificateJobTest&) = delete; + + protected: + DeviceCommandRefreshMachineCertificateJobTest() { + const base::Time initial_time = base::Time() + kWorldAge; + const base::TimeTicks initial_time_ticks = base::TimeTicks() + kWorldAge; + fake_clock_.SetNow(initial_time); + fake_tick_clock_.SetNowTicks(initial_time_ticks); + } + + ~DeviceCommandRefreshMachineCertificateJobTest() override = default; + + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + base::RunLoop run_loop_; + + base::SimpleTestClock fake_clock_; + base::SimpleTestTickClock fake_tick_clock_; + + StrictMock<MockMachineCertificateUploader> cert_uploader_; +}; + +TEST_F(DeviceCommandRefreshMachineCertificateJobTest, + ReturnsFailureWithoutCertificateUploader) { + std::unique_ptr<RemoteCommandJob> job = CreateRefreshMachineCertificateJob( + kDefaultCommandAge, fake_tick_clock_.NowTicks(), + /*cert_uploader=*/nullptr); + + EXPECT_CALL(cert_uploader_, RefreshAndUploadCertificate).Times(0); + + EXPECT_TRUE(job->Run(fake_clock_.Now(), fake_tick_clock_.NowTicks(), + run_loop_.QuitClosure())); + run_loop_.Run(); + + EXPECT_EQ(job->status(), RemoteCommandJob::FAILED); +} + +TEST_F(DeviceCommandRefreshMachineCertificateJobTest, + ReturnsFailureWhenCertificateUploaderFails) { + std::unique_ptr<RemoteCommandJob> job = CreateRefreshMachineCertificateJob( + kDefaultCommandAge, fake_tick_clock_.NowTicks(), &cert_uploader_); + + EXPECT_CALL(cert_uploader_, RefreshAndUploadCertificate) + .WillOnce(Invoke([](MachineCertificateUploader::UploadCallback callback) { + std::move(callback).Run(/*success=*/false); + })); + + EXPECT_TRUE(job->Run(fake_clock_.Now(), fake_tick_clock_.NowTicks(), + run_loop_.QuitClosure())); + + run_loop_.Run(); + + EXPECT_EQ(job->status(), RemoteCommandJob::FAILED); +} + +TEST_F(DeviceCommandRefreshMachineCertificateJobTest, + ReturnsSucessWhenCertificateUploaderSucceedes) { + std::unique_ptr<RemoteCommandJob> job = CreateRefreshMachineCertificateJob( + kDefaultCommandAge, fake_tick_clock_.NowTicks(), &cert_uploader_); + + EXPECT_CALL(cert_uploader_, RefreshAndUploadCertificate) + .WillOnce(Invoke([](MachineCertificateUploader::UploadCallback callback) { + std::move(callback).Run(/*success=*/true); + })); + + EXPECT_TRUE(job->Run(fake_clock_.Now(), fake_tick_clock_.NowTicks(), + run_loop_.QuitClosure())); + + run_loop_.Run(); + + EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED); +} + +TEST_F(DeviceCommandRefreshMachineCertificateJobTest, + ReturnsSuccessForAlmostExpiredCommand) { + std::unique_ptr<RemoteCommandJob> job = CreateRefreshMachineCertificateJob( + kVeryOldCommandAge, fake_tick_clock_.NowTicks(), &cert_uploader_); + + EXPECT_CALL(cert_uploader_, RefreshAndUploadCertificate) + .WillOnce(Invoke([](MachineCertificateUploader::UploadCallback callback) { + std::move(callback).Run(/*success=*/true); + })); + + EXPECT_TRUE(job->Run(fake_clock_.Now(), fake_tick_clock_.NowTicks(), + run_loop_.QuitClosure())); + + run_loop_.Run(); + + EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED); +} + +TEST_F(DeviceCommandRefreshMachineCertificateJobTest, + ReturnsExpiredForExpiredCommand) { + std::unique_ptr<RemoteCommandJob> job = CreateRefreshMachineCertificateJob( + kTooOldCommandAge, fake_tick_clock_.NowTicks(), &cert_uploader_); + + EXPECT_CALL(cert_uploader_, RefreshAndUploadCertificate).Times(0); + + EXPECT_FALSE(job->Run(fake_clock_.Now(), fake_tick_clock_.NowTicks(), + RemoteCommandJob::FinishedCallback())); + + EXPECT_EQ(job->status(), RemoteCommandJob::EXPIRED); +} + +} // namespace policy
diff --git a/chrome/browser/ash/web_applications/help_app/help_app_untrusted_ui_config.cc b/chrome/browser/ash/web_applications/help_app/help_app_untrusted_ui_config.cc index ea818b3..80d6965 100644 --- a/chrome/browser/ash/web_applications/help_app/help_app_untrusted_ui_config.cc +++ b/chrome/browser/ash/web_applications/help_app/help_app_untrusted_ui_config.cc
@@ -28,6 +28,7 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/system/statistics_provider.h" #include "components/prefs/pref_service.h" #include "components/user_manager/user_manager.h" @@ -91,6 +92,8 @@ source->AddBoolean( "HelpAppBackgroundPage", base::FeatureList::IsEnabled(features::kHelpAppBackgroundPage)); + source->AddBoolean("isCloudGamingDevice", + chromeos::features::IsCloudGamingDeviceEnabled()); Profile* profile = Profile::FromWebUI(web_ui); PrefService* pref_service = profile->GetPrefs();
diff --git a/chrome/browser/autofill/credit_card_accessory_controller_impl.cc b/chrome/browser/autofill/credit_card_accessory_controller_impl.cc index b51a5d9db9..9461d6a 100644 --- a/chrome/browser/autofill/credit_card_accessory_controller_impl.cc +++ b/chrome/browser/autofill/credit_card_accessory_controller_impl.cc
@@ -109,9 +109,7 @@ } bool ShouldCreateVirtualCard(const CreditCard* card) { - return base::FeatureList::IsEnabled( - features::kAutofillEnableMerchantBoundVirtualCards) && - card->virtual_card_enrollment_state() == CreditCard::ENROLLED; + return card->virtual_card_enrollment_state() == CreditCard::ENROLLED; } const CreditCard* UnwrapCardOrVirtualCard(
diff --git a/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc b/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc index 51e838b3..1383e6e 100644 --- a/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc +++ b/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc
@@ -92,8 +92,7 @@ void SetUp() override { scoped_feature_list_.InitWithFeatures( /*enabled_features=*/ - {features::kAutofillEnableMerchantBoundVirtualCards, - features::kAutofillEnableManualFallbackForVirtualCards, + {features::kAutofillEnableManualFallbackForVirtualCards, features::kAutofillShowUnmaskedCachedCardInManualFillingView}, /*disabled_features=*/{features::kAutofillFillMerchantPromoCodeFields}); ChromeRenderViewHostTestHarness::SetUp(); @@ -166,8 +165,7 @@ void SetUp() override { scoped_feature_list_.InitWithFeatures( /*enabled_features=*/ - {features::kAutofillEnableMerchantBoundVirtualCards, - features::kAutofillShowUnmaskedCachedCardInManualFillingView, + {features::kAutofillShowUnmaskedCachedCardInManualFillingView, features::kAutofillFillMerchantPromoCodeFields}, /*disabled_features=*/{}); ChromeRenderViewHostTestHarness::SetUp();
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index fc5aa6b..b322513 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -278,6 +278,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) #include "chrome/browser/apps/digital_goods/digital_goods_factory_stub.h" #include "chrome/browser/apps/digital_goods/digital_goods_lacros.h" +#include "chromeos/lacros/lacros_service.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \ @@ -304,6 +305,9 @@ #include "chrome/browser/speech/speech_recognition_service.h" #include "media/mojo/mojom/renderer_extensions.mojom.h" #include "media/mojo/mojom/speech_recognition.mojom.h" // nogncheck +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/crosapi/mojom/speech_recognition.mojom.h" +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) #endif // BUILDFLAG(ENABLE_SPEECH_SERVICE) #if BUILDFLAG(ENABLE_BROWSER_SPEECH_SERVICE) @@ -536,22 +540,30 @@ void BindSpeechRecognitionContextHandler( content::RenderFrameHost* frame_host, mojo::PendingReceiver<media::mojom::SpeechRecognitionContext> receiver) { + if (!captions::IsLiveCaptionFeatureSupported()) { + return; + } + +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // On LaCrOS, forward to Ash. + auto* service = chromeos::LacrosService::Get(); + if (service && service->IsAvailable<crosapi::mojom::SpeechRecognition>()) { + service->GetRemote<crosapi::mojom::SpeechRecognition>() + ->BindSpeechRecognitionContext(std::move(receiver)); + } +#else + // On other platforms (Ash, desktop), bind via the appropriate factory. Profile* profile = Profile::FromBrowserContext( frame_host->GetProcess()->GetBrowserContext()); - if (captions::IsLiveCaptionFeatureSupported()) { #if BUILDFLAG(ENABLE_BROWSER_SPEECH_SERVICE) - SpeechRecognitionServiceFactory::GetForProfile(profile) - ->BindSpeechRecognitionContext(std::move(receiver)); + auto* factory = SpeechRecognitionServiceFactory::GetForProfile(profile); #elif BUILDFLAG(IS_CHROMEOS_ASH) - CrosSpeechRecognitionServiceFactory::GetForProfile(profile) - ->BindSpeechRecognitionContext(std::move(receiver)); -#elif BUILDFLAG(IS_CHROMEOS_LACROS) - // TODO(b:223493879): Provide LaCrOS implementation, via go/crosapi. -#error "LaCrOS speech recognition service factory not implemented yet." + auto* factory = CrosSpeechRecognitionServiceFactory::GetForProfile(profile); #else #error "No speech recognition service factory on this platform." #endif - } + factory->BindSpeechRecognitionContext(std::move(receiver)); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) } void BindSpeechRecognitionClientBrowserInterfaceHandler( @@ -559,11 +571,20 @@ mojo::PendingReceiver<media::mojom::SpeechRecognitionClientBrowserInterface> receiver) { if (captions::IsLiveCaptionFeatureSupported()) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // On LaCrOS, forward to Ash. + auto* service = chromeos::LacrosService::Get(); + if (service && service->IsAvailable<crosapi::mojom::SpeechRecognition>()) { + service->GetRemote<crosapi::mojom::SpeechRecognition>() + ->BindSpeechRecognitionClientBrowserInterface(std::move(receiver)); + } +#else + // On other platforms (Ash, desktop), bind in this process. Profile* profile = Profile::FromBrowserContext( frame_host->GetProcess()->GetBrowserContext()); - SpeechRecognitionClientBrowserInterfaceFactory::GetForProfile(profile) ->BindReceiver(std::move(receiver)); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) } }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index b313a5e..be6cd5a 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -3806,6 +3806,7 @@ "../ash/policy/remote_commands/crd_host_delegate_unittest.cc", "../ash/policy/remote_commands/device_command_get_available_routines_job_unittest.cc", "../ash/policy/remote_commands/device_command_get_routine_update_job_unittest.cc", + "../ash/policy/remote_commands/device_command_refresh_machine_certificate_job_unittest.cc", "../ash/policy/remote_commands/device_command_remote_powerwash_job_unittest.cc", "../ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc", "../ash/policy/remote_commands/device_command_run_routine_job_unittest.cc",
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc index f16216cb..52a4fdb0 100644 --- a/chrome/browser/download/notification/download_item_notification.cc +++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -310,10 +310,10 @@ // |this| will be deleted before there's a chance for Close() to be called // through the delegate, so preemptively call it now. Close(false); + ShutDown(); + // This object may get deleted after this call. observer_->OnDownloadDestroyed(item_->GetContentId()); - - item_.reset(); } void DownloadItemNotification::DisablePopup() {
diff --git a/chrome/browser/download/notification/download_item_notification.h b/chrome/browser/download/notification/download_item_notification.h index 3f49c13..2c85a514 100644 --- a/chrome/browser/download/notification/download_item_notification.h +++ b/chrome/browser/download/notification/download_item_notification.h
@@ -34,9 +34,6 @@ public message_center::NotificationObserver, public DownloadUIModel::Observer { public: - using DownloadItemNotificationPtr = - std::unique_ptr<DownloadItemNotification, base::OnTaskRunnerDeleter>; - DownloadItemNotification(Profile* profile, DownloadUIModel::DownloadUIModelPtr item);
diff --git a/chrome/browser/download/notification/download_notification_manager.cc b/chrome/browser/download/notification/download_notification_manager.cc index 8906573..c75b6ba 100644 --- a/chrome/browser/download/notification/download_notification_manager.cc +++ b/chrome/browser/download/notification/download_notification_manager.cc
@@ -33,11 +33,9 @@ new DownloadItemModel(item), base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); ContentId contentId = model->GetContentId(); - DownloadItemNotification::DownloadItemNotificationPtr notification( - new DownloadItemNotification(profile_, std::move(model)), - base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); - notification->SetObserver(this); - items_.emplace(contentId, std::move(notification)); + items_.emplace(contentId, + new DownloadItemNotification(profile_, std::move(model))); + items_[contentId]->SetObserver(this); } void DownloadNotificationManager::OnDownloadDestroyed(
diff --git a/chrome/browser/download/notification/download_notification_manager.h b/chrome/browser/download/notification/download_notification_manager.h index 004b79a..c14377b 100644 --- a/chrome/browser/download/notification/download_notification_manager.h +++ b/chrome/browser/download/notification/download_notification_manager.h
@@ -38,8 +38,7 @@ friend class test::DownloadItemNotificationTest; Profile* profile_; - std::map<ContentId, DownloadItemNotification::DownloadItemNotificationPtr> - items_; + std::map<ContentId, std::unique_ptr<DownloadItemNotification>> items_; }; #endif // CHROME_BROWSER_DOWNLOAD_NOTIFICATION_DOWNLOAD_NOTIFICATION_MANAGER_H_
diff --git a/chrome/browser/extensions/api/terminal/crostini_startup_status.cc b/chrome/browser/extensions/api/terminal/crostini_startup_status.cc index c6b684ee..347dd47f 100644 --- a/chrome/browser/extensions/api/terminal/crostini_startup_status.cc +++ b/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
@@ -59,7 +59,8 @@ if (result != crostini::CrostiniResult::SUCCESS) { PrintAfterStage( kColor1RedBright, - base::StringPrintf("Error starting penguin container: %d\r\n", result)); + base::StringPrintf("\rError starting penguin container: %d (%s)\r\n", + result, CrostiniResultString(result))); crostini::RecordAppLaunchResultHistogram( crostini::CrostiniAppLaunchAppType::kTerminal, result); } else { @@ -82,7 +83,8 @@ PrintAfterStage( kColor1RedBright, base::StringPrintf( - "Error connecting shell to penguin container: %d\r\n", result)); + "\rError connecting shell to penguin container: %d (%s)\r\n", + result, CrostiniResultString(result))); } else { if (verbose_) { stage_index_ = kMaxStage + 1; // done.
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc index c6b11621..9a769941 100644 --- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc +++ b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -353,7 +353,8 @@ OpenVmshellProcess(user_id_hash, std::move(cmdline)); } else { const std::string msg = - base::StringPrintf("Error starting crostini for terminal: %d", result); + base::StringPrintf("Error starting crostini for terminal: %d (%s)", + result, CrostiniResultString(result)); LOG(ERROR) << msg; Respond(Error(msg)); } @@ -628,7 +629,7 @@ OpenWindow::Params::Create(args())); EXTENSION_FUNCTION_VALIDATE(params.get()); - const std::string* url = &crostini::GetTerminalDefaultUrl(); + const std::string* url = &crostini::GetTerminalHomeUrl(); bool as_tab = false; auto& data = params->data;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 28ca3371..550d0e3 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -410,11 +410,6 @@ "expiry_milestone": 106 }, { - "name": "autofill-enable-merchant-bound-virtual-cards", - "owners": [ "siashah", "siyua" ], - "expiry_milestone": 105 - }, - { "name": "autofill-enable-offer-notification-for-promo-codes", "owners": [ "jsaul@google.com", "siyua" ], "expiry_milestone": 105
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 76f58d1..271dd76f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -324,12 +324,6 @@ "Controls if different width limits are used for the popup that provides " "Autofill suggestions, depending on the type of data that is filled."; -const char kAutofillEnableMerchantBoundVirtualCardsName[] = - "Offer merchant bound virtual cards in Autofill"; -const char kAutofillEnableMerchantBoundVirtualCardsDescription[] = - "When enabled, Autofill will offer to use merchant bound virtual cards in " - "payment forms."; - const char kAutofillEnableManualFallbackForVirtualCardsName[] = "Show manual fallback for virtual cards"; const char kAutofillEnableManualFallbackForVirtualCardsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 144f98e..ace8655 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -191,9 +191,6 @@ extern const char kAutofillTypeSpecificPopupWidthName[]; extern const char kAutofillTypeSpecificPopupWidthDescription[]; -extern const char kAutofillEnableMerchantBoundVirtualCardsName[]; -extern const char kAutofillEnableMerchantBoundVirtualCardsDescription[]; - extern const char kAutofillEnableManualFallbackForVirtualCardsName[]; extern const char kAutofillEnableManualFallbackForVirtualCardsDescription[];
diff --git a/chrome/browser/language/android/BUILD.gn b/chrome/browser/language/android/BUILD.gn index c08e34a..5201e9fc 100644 --- a/chrome/browser/language/android/BUILD.gn +++ b/chrome/browser/language/android/BUILD.gn
@@ -15,6 +15,7 @@ "//base:base_java", "//chrome/browser/preferences:java", "//components/language/android:java", + "//components/language/android:ulp_delegate_java", "//third_party/android_deps:com_google_android_play_core_java", "//third_party/androidx:androidx_annotation_annotation_java", "//ui/android:ui_no_recycler_view_java",
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java index 685c57df..f539042 100644 --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java
@@ -5,18 +5,28 @@ package org.chromium.chrome.browser.language; import android.content.Context; +import android.os.Build; import android.preference.PreferenceManager; import android.text.TextUtils; +import androidx.annotation.ChecksSdkIntAtLeast; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; + +import org.chromium.base.BuildInfo; import org.chromium.base.BundleUtils; import org.chromium.base.LocaleUtils; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; +import org.chromium.components.language.LocaleManagerDelegate; +import org.chromium.components.language.LocaleManagerDelegateImpl; import org.chromium.ui.base.ResourceBundle; import java.util.Arrays; import java.util.Comparator; import java.util.HashSet; +import java.util.List; +import java.util.Locale; /** * Provides utility functions to assist with overriding the application language. @@ -49,10 +59,14 @@ } /** - * Get the value of application language shared preference or null if there is none. + * Get the value of application language shared preference or null if there is none. On T+ this + * method will use the {@link LocaleManager} service to get the App language. * @return String BCP-47 language tag (e.g. en-US). */ public static String getAppLanguagePref() { + if (shouldUseSystemManagedLocale()) { + return getSystemManagedAppLanguage(); + } return SharedPreferencesManager.getInstance().readString( ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, APP_LOCALE_USE_SYSTEM_LANGUAGE); } @@ -65,12 +79,46 @@ * @return String BCP-47 language tag (e.g. en-US). */ @SuppressWarnings("DefaultSharedPreferencesCheck") - protected static String getAppLanguagePrefStartUp(Context base) { + static String getAppLanguagePrefStartUp(Context base) { return PreferenceManager.getDefaultSharedPreferences(base).getString( ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, APP_LOCALE_USE_SYSTEM_LANGUAGE); } /** + * Get the value of system App language using {@link LocaleManager}, Android ensures this + * language is always supported by Chrome. If no override language is set + * |APP_LOCALE_USE_SYSTEM_LANGUAGE| is returned. Only used on Android T (API level 33). + * TODO(crbug.com/1333981) Move to Android T. + */ + @RequiresApi(Build.VERSION_CODES.S) + static @Nullable String getSystemManagedAppLanguage() { + Locale locale = getAppLocaleManagerDelegate().getApplicationLocale(); + if (locale == null) { + return APP_LOCALE_USE_SYSTEM_LANGUAGE; + } + return locale.toLanguageTag(); + } + + /** + * Gets the first original system locale from {@link LocaleManager}. This is the language that + * Chrome would use if there was no override set. If there are no possible UI languages en-US is + * returned since that is the default UI language in that case. Only used on Android T (API + * level 33). + * TODO(crbug.com/1333981) Move to Android T. + * @return The UI language of the system. + */ + @RequiresApi(Build.VERSION_CODES.S) + static Locale getSystemManagedOriginalLocale() { + List<Locale> locales = getAppLocaleManagerDelegate().getSystemLocales(); + for (Locale locale : locales) { + if (isSupportedUiLanguage(locale.toLanguageTag())) { + return locale; + } + } + return Locale.forLanguageTag("en-US"); + } + + /** * Download the language split. If successful set the application language shared preference. * If set to null the system language will be used. * @param languageName String BCP-47 code of language to download. @@ -92,8 +140,12 @@ // Wrap the install listener so that on success the app override preference is set. LanguageSplitInstaller.InstallListener wrappedListener = (success) -> { if (success) { - SharedPreferencesManager.getInstance().writeString( - ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, languageName); + if (shouldUseSystemManagedLocale()) { + setSystemManagedAppLanguage(languageName); + } else { + SharedPreferencesManager.getInstance().writeString( + ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, languageName); + } } listener.onComplete(success); }; @@ -109,6 +161,71 @@ } /** + * Sets the {@link LocaleManager} App language to |languageName|. + * TODO(crbug.com/1333981) Move to Android T. + */ + @RequiresApi(Build.VERSION_CODES.S) + private static void setSystemManagedAppLanguage(String languageName) { + getAppLocaleManagerDelegate().setApplicationLocale(languageName); + } + + /** + * Get the LocaleManagerDelegate for {@link LocaleManager}. + * Only used on Android T+ (API level 33). + * TODO(crbug.com/1333981) Move to Android T. + */ + @RequiresApi(Build.VERSION_CODES.S) + static LocaleManagerDelegate getAppLocaleManagerDelegate() { + return new LocaleManagerDelegateImpl(); + } + + /** + * Migrate the App override language from Chrome SharedPreferences to the {@link LocaleManager} + * service if needed. A migration is only attempted once on Android T and done if there is a + * Chrome SharedPreferences override language but no system App override language. + * TODO(crbug.com/1333981) Move to Android T. + * TODO(crbug.com/1334729) Remove migration after Oct 2023. + */ + @RequiresApi(Build.VERSION_CODES.S) + public static void maybeMigrateOverrideLanguage() { + String unset_token = "__UNSET__"; + String sharedPrefAppLanguage = SharedPreferencesManager.getInstance().readString( + ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, unset_token); + // Don't migrate if there is no preference set for the override language. + if (TextUtils.equals(sharedPrefAppLanguage, unset_token)) return; + + // Removed the old shared preference so a migration will not occur again. + removeSharedPrefAppLanguage(); + + // Don't migrate if the old override language was set to follow the system. + if (isFollowSystemLanguage(sharedPrefAppLanguage)) return; + + // Don't migrate if the Android system already has an App override language. This means that + // before the migration occurred a user set an App over language in the Android Settings. + if (!TextUtils.isEmpty(getAppLanguagePref())) return; + + // Set the existing override language as the system App override language. + setSystemManagedAppLanguage(sharedPrefAppLanguage); + } + + private static void removeSharedPrefAppLanguage() { + SharedPreferencesManager.getInstance().removeKey( + ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE); + } + + /** + * The LocaleManager API is only available on Android T. While using pre-release SDKs it is not + * possible to use Build.VERSION_CODES.T. This method uses {@link BuildInfo.isAtLeastT} to check + * that the current SDK is T (API level 33). + * TODO(crbug.com/1333981) Remove when on released versions of the SDK. + * @return True if the current Android SDK supports {@link LocaleManager} + */ + @ChecksSdkIntAtLeast(api = 33) + public static boolean shouldUseSystemManagedLocale() { + return BuildInfo.isAtLeastT(); + } + + /** * Return true if the base language of |languageCode| has multiple UI language variants (e.g. * pt-BR and pt-PT). * @param languageCode Language tag to look up.
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/GlobalAppLocaleController.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/GlobalAppLocaleController.java index 35e99ae..4f5a7d2 100644 --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/GlobalAppLocaleController.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/GlobalAppLocaleController.java
@@ -49,7 +49,7 @@ } // Set the original system language before Locale.getDefault() is overridden. - private final Locale mOriginalSystemLocale = Locale.getDefault(); + private Locale mOriginalSystemLocale = Locale.getDefault(); private String mOverrideLanguage; private boolean mIsOverridden; @@ -62,14 +62,28 @@ * @return boolean Whether or not an override language is set. */ public boolean init(Context base) { - mOverrideLanguage = AppLocaleUtils.getAppLanguagePrefStartUp(base); - - mIsOverridden = shouldOverrideAppLocale( - mOverrideLanguage, LocaleUtils.toLanguageTag(mOriginalSystemLocale)); + if (AppLocaleUtils.shouldUseSystemManagedLocale()) { + mIsOverridden = false; + } else { + mOverrideLanguage = AppLocaleUtils.getAppLanguagePrefStartUp(base); + mIsOverridden = shouldOverrideAppLocale( + mOverrideLanguage, LocaleUtils.toLanguageTag(mOriginalSystemLocale)); + } return mIsOverridden; } /** + * Preform setup actions when using {@link LocaleManager} that need to be done after the + * Application has started. + */ + public void maybeSetupLocaleManager() { + if (AppLocaleUtils.shouldUseSystemManagedLocale()) { + mOverrideLanguage = AppLocaleUtils.getSystemManagedAppLanguage(); + mOriginalSystemLocale = AppLocaleUtils.getSystemManagedOriginalLocale(); + } + } + + /** * If the application locale should be overridden returns an updated override Configuration. * Called early in {@link ChromeActivity#attachBaseContext}. * @param base The base Context for the application and has the system locales.
diff --git a/chrome/browser/media/media_access_handler.cc b/chrome/browser/media/media_access_handler.cc index 0078abc2..47337cf 100644 --- a/chrome/browser/media/media_access_handler.cc +++ b/chrome/browser/media/media_access_handler.cc
@@ -30,7 +30,12 @@ bool get_default_audio_device = audio_allowed; bool get_default_video_device = video_allowed; - blink::mojom::StreamDevices stream_devices; + // TOOD(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& stream_devices = + *stream_devices_set.stream_devices[0]; // Set an initial error result. If neither audio or video is allowed, we'll // never try to get any device below but will just create |ui| and return an @@ -85,5 +90,10 @@ ->RegisterMediaStream(web_contents, stream_devices); } - std::move(callback).Run(stream_devices, result, std::move(ui)); + if (!stream_devices.audio_device.has_value() && + !stream_devices.video_device.has_value()) { + stream_devices_set.stream_devices.clear(); + } + + std::move(callback).Run(stream_devices_set, result, std::move(ui)); }
diff --git a/chrome/browser/media/offscreen_tab.cc b/chrome/browser/media/offscreen_tab.cc index 370a2ea..3289268 100644 --- a/chrome/browser/media/offscreen_tab.cc +++ b/chrome/browser/media/offscreen_tab.cc
@@ -334,7 +334,7 @@ WebContents* contents, const content::MediaStreamRequest& request, content::MediaResponseCallback callback) { - std::move(callback).Run(blink::mojom::StreamDevices(), + std::move(callback).Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); }
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc index dd67a87..3c36463 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -253,7 +253,7 @@ if (!screen_capture_enabled || !origin_is_secure) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; @@ -262,7 +262,7 @@ if (!IsRequestApproved(web_contents, pending_request->request, extension, pending_request->is_allowlisted_extension)) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -273,7 +273,7 @@ pending_request->request.render_process_id, pending_request->request.render_frame_id))) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; @@ -351,7 +351,7 @@ if (request.video_type != blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; @@ -363,7 +363,7 @@ if (allowed_capture_level == AllowedScreenCaptureLevel::kDisallowed) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -379,7 +379,7 @@ if (request.requested_video_device_id.empty()) { if (allowed_capture_level < AllowedScreenCaptureLevel::kDesktop) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -388,7 +388,7 @@ if (system_media_permissions::CheckSystemScreenCapturePermission() != system_media_permissions::SystemPermission::kAllowed) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -423,7 +423,7 @@ // Received invalid device id. if (media_id.type == content::DesktopMediaID::TYPE_NONE) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; @@ -431,7 +431,7 @@ if (!IsMediaTypeAllowed(allowed_capture_level, media_id.type)) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -441,7 +441,7 @@ system_media_permissions::CheckSystemScreenCapturePermission() != system_media_permissions::SystemPermission::kAllowed) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -454,7 +454,7 @@ media_id.web_contents_id.render_process_id, media_id.web_contents_id.main_render_frame_id))) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::TAB_CAPTURE_FAILURE, /*ui=*/nullptr); return; @@ -489,7 +489,7 @@ pending_request->picker = picker_factory_->CreatePicker(); if (!pending_request->picker) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; @@ -614,7 +614,7 @@ if (media_id.is_null()) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); } else { @@ -670,19 +670,26 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(web_contents); - blink::mojom::StreamDevices devices; + // TODO(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& stream_devices = + *stream_devices_set.stream_devices[0]; std::unique_ptr<content::MediaStreamUI> ui = GetDevicesForDesktopCapture( pending_request->request, web_contents, media_id, capture_audio, pending_request->request.disable_local_echo, pending_request->should_display_notification, - pending_request->application_title, devices); - DCHECK(devices.audio_device.has_value() || devices.video_device.has_value()); + pending_request->application_title, stream_devices); + DCHECK(stream_devices.audio_device.has_value() || + stream_devices.video_device.has_value()); UpdateExtensionTrusted(pending_request->request, pending_request->is_allowlisted_extension); std::move(pending_request->callback) - .Run(devices, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); + .Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, + std::move(ui)); } #if BUILDFLAG(IS_CHROMEOS) @@ -702,7 +709,7 @@ if (!is_dlp_allowed) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return;
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc index 30eaaae4..54f985e5 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc
@@ -86,11 +86,17 @@ [](base::RunLoop* wait_loop, bool expect_result, blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::StreamDevices* devices_result, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { *request_result = result; - *devices_result = devices; + if (result == blink::mojom::MediaStreamRequestResult::OK) { + ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u); + *devices_result = *stream_devices_set.stream_devices[0]; + } else { + ASSERT_TRUE(stream_devices_set.stream_devices.empty()); + *devices_result = blink::mojom::StreamDevices(); + } EXPECT_TRUE(expect_result) << "MediaResponseCallback should not be " "called when expect_result is false."; wait_loop->Quit(); @@ -131,12 +137,16 @@ content::MediaResponseCallback callback = base::BindOnce( [](base::RunLoop* wait_loop, blink::mojom::MediaStreamRequestResult* request_result, - blink::mojom::StreamDevices* stream_devices_result, - const blink::mojom::StreamDevices& devices, + blink::mojom::StreamDevices* devices_result, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { *request_result = result; - *stream_devices_result = devices; + if (!stream_devices_set.stream_devices.empty()) { + *devices_result = *stream_devices_set.stream_devices[0]; + } else { + *devices_result = blink::mojom::StreamDevices(); + } wait_loop->Quit(); }, &wait_loop, request_result, stream_devices_result); @@ -306,12 +316,12 @@ [](base::RunLoop* wait_loop, blink::mojom::MediaStreamRequestResult* request_result, blink::MediaStreamDevices* devices_result, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { + ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u); *request_result = result; - *devices_result = - blink::StreamDevicesToMediaStreamDevicesList(devices); + *devices_result = blink::ToMediaStreamDevicesList(stream_devices_set); wait_loop->Quit(); }, &loop, &result, &devices);
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.cc b/chrome/browser/media/webrtc/display_media_access_handler.cc index c1cda77..5119f34 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler.cc +++ b/chrome/browser/media/webrtc/display_media_access_handler.cc
@@ -101,7 +101,7 @@ web_contents) == AllowedScreenCaptureLevel::kDisallowed) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -116,7 +116,7 @@ web_contents); if (observer) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); observer->OnDesktopCaptureRequest(); @@ -133,7 +133,7 @@ request.request_type != blink::MEDIA_DEVICE_UPDATE) { LOG(ERROR) << "Do not allow getDisplayMedia() on a backgrounded page."; std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -159,7 +159,7 @@ request.render_process_id, request.render_frame_id); if (!rfh) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; @@ -179,7 +179,7 @@ rfh->GetProcess(), bad_message::BadMessageReason:: RFH_DISPLAY_CAPTURE_PERMISSION_MISSING); std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -190,7 +190,7 @@ std::unique_ptr<DesktopMediaPicker> picker = picker_factory_->CreatePicker(); if (!picker) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -371,7 +371,7 @@ return; PendingAccessRequest& mutable_request = *mutable_queue.front(); std::move(mutable_request.callback) - .Run(blink::mojom::StreamDevices(), result, /*ui=*/nullptr); + .Run(blink::mojom::StreamDevicesSet(), result, /*ui=*/nullptr); mutable_queue.pop_front(); if (!mutable_queue.empty()) ProcessQueuedAccessRequest(mutable_queue, web_contents); @@ -398,15 +398,20 @@ (media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) && media_id.web_contents_id.disable_local_echo; - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& stream_devices = + *stream_devices_set.stream_devices[0]; std::unique_ptr<content::MediaStreamUI> ui = GetDevicesForDesktopCapture( pending_request.request, web_contents, media_id, media_id.audio_share, disable_local_echo, display_notification_, - GetApplicationTitle(web_contents), devices); + GetApplicationTitle(web_contents), stream_devices); UpdateTarget(pending_request.request, media_id); std::move(pending_request.callback) - .Run(devices, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); + .Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, + std::move(ui)); queue.pop_front(); if (!queue.empty())
diff --git a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc index ddf19262..5df2ca8 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc
@@ -97,11 +97,17 @@ [](base::RunLoop* wait_loop, blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::StreamDevices* devices_result, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { *request_result = result; - *devices_result = devices; + if (result == blink::mojom::MediaStreamRequestResult::OK) { + ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u); + *devices_result = *stream_devices_set.stream_devices[0]; + } else { + ASSERT_TRUE(stream_devices_set.stream_devices.empty()); + *devices_result = blink::mojom::StreamDevices(); + } wait_loop->Quit(); }, wait_loop, request_result, &devices_result); @@ -508,12 +514,17 @@ [](base::RunLoop* wait_loop, blink::mojom::MediaStreamRequestResult* request_result, blink::MediaStreamDevices* devices_result, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { *request_result = result; - *devices_result = - blink::StreamDevicesToMediaStreamDevicesList(devices); + if (result == blink::mojom::MediaStreamRequestResult::OK) { + ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u); + *devices_result = + blink::ToMediaStreamDevicesList(stream_devices_set); + } else { + ASSERT_TRUE(stream_devices_set.stream_devices.empty()); + } wait_loop->Quit(); }, &wait_loop[i], &result, &devices);
diff --git a/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc b/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc index 5f055a4e1..64c0e25 100644 --- a/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc +++ b/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc
@@ -150,7 +150,7 @@ blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE && !base::FeatureList::IsEnabled(features::kUserMediaScreenCapturing)) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); return; } @@ -166,7 +166,7 @@ return; } } - std::move(callback).Run(blink::mojom::StreamDevices(), + std::move(callback).Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); }
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc index cb163b9..9a4dbca 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -40,6 +40,7 @@ #include "content/public/test/mock_render_process_host.h" #include "extensions/common/constants.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/mediastream/media_stream_request.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" using content_settings::PageSpecificContentSettings; @@ -53,11 +54,12 @@ blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS) { } - void OnMediaStreamResponse(const blink::mojom::StreamDevices& devices, - blink::mojom::MediaStreamRequestResult result, - std::unique_ptr<content::MediaStreamUI> ui) { + void OnMediaStreamResponse( + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui) { blink::MediaStreamDevices devices_list = - blink::StreamDevicesToMediaStreamDevicesList(devices); + blink::ToMediaStreamDevicesList(stream_devices_set); EXPECT_EQ(devices_list.empty(), !ui); media_stream_devices_ = devices_list; media_stream_result_ = result; @@ -960,14 +962,16 @@ permission_bubble_media_access_handler_->HandleRequest( prompt_contents, CreateRequest(example_audio_id(), example_video_id(), false), - base::BindOnce([](const blink::mojom::StreamDevices& devices, - blink::mojom::MediaStreamRequestResult result, - std::unique_ptr<content::MediaStreamUI> ui) { - // The permission may be dismissed before we have a chance to delete the - // request. - EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED, - result); - }), + base::BindOnce( + [](const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui) { + // The permission may be dismissed before we have a chance to delete + // the request. + EXPECT_EQ( + blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED, + result); + }), nullptr); // Since the mock prompt factory holds a reference to the // PermissionRequestManager for the WebContents and uses that reference in its
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc index ee42739..0f0a43fab 100644 --- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc +++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -54,7 +54,7 @@ using content::BrowserThread; using MediaResponseCallback = - base::OnceCallback<void(const blink::mojom::StreamDevices& devices, + base::OnceCallback<void(const blink::mojom::StreamDevicesSet& devices, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui)>; @@ -214,7 +214,7 @@ // If screen capturing isn't enabled on Android, we'll use "invalid state" // as result, same as on desktop. std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, nullptr); return; } @@ -310,7 +310,7 @@ content::WebContents* web_contents, int64_t request_id, content::MediaStreamRequest request, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, bool blocked_by_permissions_policy, ContentSetting audio_setting, @@ -328,20 +328,40 @@ video_setting); } + // At most one stream is expected as this function is not used with the + // getDisplayMediaSet API (only used with getUserMedia). + DCHECK_LE(stream_devices_set.stream_devices.size(), 1u); + blink::mojom::StreamDevices devices; + if (!stream_devices_set.stream_devices.empty()) { + devices = *stream_devices_set.stream_devices[0]; + } + std::unique_ptr<content::MediaStreamUI> ui; if (devices.audio_device.has_value() || devices.video_device.has_value()) { ui = MediaCaptureDevicesDispatcher::GetInstance() ->GetMediaStreamCaptureIndicator() ->RegisterMediaStream(web_contents, devices); } - OnAccessRequestResponse(web_contents, request_id, devices, result, + OnAccessRequestResponse(web_contents, request_id, stream_devices_set, result, + std::move(ui)); +} + +void PermissionBubbleMediaAccessHandler::OnAccessRequestResponseForBinding( + content::WebContents* web_contents, + int64_t request_id, + blink::mojom::StreamDevicesSetPtr stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui) { + DCHECK(stream_devices_set); + DCHECK(ui); + OnAccessRequestResponse(web_contents, request_id, *stream_devices_set, result, std::move(ui)); } void PermissionBubbleMediaAccessHandler::OnAccessRequestResponse( content::WebContents* web_contents, int64_t request_id, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -379,10 +399,10 @@ // Using WeakPtr since callback can come at any time and we might be // destroyed. system_media_permissions::RequestSystemAudioCapturePermisson( - base::BindOnce( - &PermissionBubbleMediaAccessHandler::OnAccessRequestResponse, - weak_factory_.GetWeakPtr(), web_contents, request_id, devices, - result, std::move(ui))); + base::BindOnce(&PermissionBubbleMediaAccessHandler:: + OnAccessRequestResponseForBinding, + weak_factory_.GetWeakPtr(), web_contents, request_id, + stream_devices_set.Clone(), result, std::move(ui))); return; } else if (system_audio_permission == SystemPermission::kRestricted || system_audio_permission == SystemPermission::kDenied) { @@ -406,10 +426,10 @@ // Using WeakPtr since callback can come at any time and we might be // destroyed. system_media_permissions::RequestSystemVideoCapturePermisson( - base::BindOnce( - &PermissionBubbleMediaAccessHandler::OnAccessRequestResponse, - weak_factory_.GetWeakPtr(), web_contents, request_id, devices, - result, std::move(ui))); + base::BindOnce(&PermissionBubbleMediaAccessHandler:: + OnAccessRequestResponseForBinding, + weak_factory_.GetWeakPtr(), web_contents, request_id, + stream_devices_set.Clone(), result, std::move(ui))); return; } else if (system_video_permission == SystemPermission::kRestricted || system_video_permission == SystemPermission::kDenied) { @@ -439,7 +459,7 @@ base::Unretained(this), web_contents)); } - std::move(callback).Run(devices, final_result, std::move(ui)); + std::move(callback).Run(stream_devices_set, final_result, std::move(ui)); } void PermissionBubbleMediaAccessHandler::WebContentsDestroyed(
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.h b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.h index cf8903c..60633c9 100644 --- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.h +++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.h
@@ -60,16 +60,27 @@ content::WebContents* web_contents, int64_t request_id, content::MediaStreamRequest request, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, bool blocked_by_permissions_policy, ContentSetting audio_setting, ContentSetting video_setting); - void OnAccessRequestResponse(content::WebContents* web_contents, - int64_t request_id, - const blink::mojom::StreamDevices& devices, - blink::mojom::MediaStreamRequestResult result, - std::unique_ptr<content::MediaStreamUI> ui); + void OnAccessRequestResponse( + content::WebContents* web_contents, + int64_t request_id, + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui); + // OnAccessRequestResponse cannot be used together with base::BindOnce as + // StreamDevicesSet& cannot be captured (neither copyable nor movable). + // This method uses StreamDevicesSetPtr (movable) and forwards the data + // to OnAccessRequestResponse when calling the callback. + void OnAccessRequestResponseForBinding( + content::WebContents* web_contents, + int64_t request_id, + blink::mojom::StreamDevicesSetPtr stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui); // WebContentsCollection::Observer: void WebContentsDestroyed(content::WebContents* web_contents) override;
diff --git a/chrome/browser/media/webrtc/screen_capture_permission_handler_android.cc b/chrome/browser/media/webrtc/screen_capture_permission_handler_android.cc index 5e36a55e..757e7975 100644 --- a/chrome/browser/media/webrtc/screen_capture_permission_handler_android.cc +++ b/chrome/browser/media/webrtc/screen_capture_permission_handler_android.cc
@@ -31,7 +31,12 @@ ? blink::mojom::MediaStreamRequestResult::OK : blink::mojom::MediaStreamRequestResult::INVALID_STATE; - blink::mojom::StreamDevices devices; + // TODO(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& stream_devices = + *stream_devices_set.stream_devices[0]; std::unique_ptr<content::MediaStreamUI> ui; if (result == blink::mojom::MediaStreamRequestResult::OK) { if (request.video_type == @@ -40,20 +45,20 @@ screen_id.type = content::DesktopMediaID::TYPE_WEB_CONTENTS; screen_id.web_contents_id = content::WebContentsMediaCaptureId( request.render_process_id, request.render_frame_id); - devices.video_device = blink::MediaStreamDevice( + stream_devices.video_device = blink::MediaStreamDevice( request.video_type, screen_id.ToString(), "Current Tab"); } else { content::DesktopMediaID screen_id = content::DesktopMediaID( content::DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId); - devices.video_device = blink::MediaStreamDevice( + stream_devices.video_device = blink::MediaStreamDevice( request.video_type, screen_id.ToString(), "Screen"); } ui = MediaCaptureDevicesDispatcher::GetInstance() ->GetMediaStreamCaptureIndicator() - ->RegisterMediaStream(web_contents, devices); + ->RegisterMediaStream(web_contents, stream_devices); } - std::move(callback).Run(devices, result, std::move(ui)); + std::move(callback).Run(stream_devices_set, result, std::move(ui)); } } // namespace screen_capture
diff --git a/chrome/browser/media/webrtc/tab_capture_access_handler.cc b/chrome/browser/media/webrtc/tab_capture_access_handler.cc index b822143..da29f67f 100644 --- a/chrome/browser/media/webrtc/tab_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/tab_capture_access_handler.cc
@@ -128,7 +128,7 @@ if (!tab_capture_registry) { NOTREACHED(); std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -146,7 +146,7 @@ request.render_frame_id)); if (!can_show_web_contents.Run(target_web_contents)) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; @@ -159,7 +159,7 @@ if (!tab_capture_registry->VerifyRequest( request.render_process_id, request.render_frame_id, extension_id)) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -217,13 +217,20 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(web_contents); - blink::mojom::StreamDevices devices; - std::unique_ptr<content::MediaStreamUI> ui = - GetMediaStreamUI(request, web_contents, std::move(media_ui), devices); - DCHECK(devices.audio_device.has_value() || devices.video_device.has_value()); + // TOOD(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& stream_devices = + *stream_devices_set.stream_devices[0]; + std::unique_ptr<content::MediaStreamUI> ui = GetMediaStreamUI( + request, web_contents, std::move(media_ui), stream_devices); + DCHECK(stream_devices.audio_device.has_value() || + stream_devices.video_device.has_value()); UpdateExtensionTrusted(request, is_allowlisted_extension); - std::move(callback).Run(devices, blink::mojom::MediaStreamRequestResult::OK, + std::move(callback).Run(stream_devices_set, + blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); } @@ -246,7 +253,7 @@ std::move(media_ui)); } else { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); }
diff --git a/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc b/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc index f0ca643..c0e3114 100644 --- a/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc
@@ -66,11 +66,19 @@ [](base::RunLoop* wait_loop, bool expect_result, blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::StreamDevices* devices_result, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { + DCHECK(!devices_result->audio_device); + DCHECK(!devices_result->video_device); *request_result = result; - *devices_result = devices; + if (result == blink::mojom::MediaStreamRequestResult::OK) { + ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u); + *devices_result = *stream_devices_set.stream_devices[0]; + } else { + ASSERT_TRUE(stream_devices_set.stream_devices.empty()); + *devices_result = blink::mojom::StreamDevices(); + } if (!expect_result) { FAIL() << "MediaResponseCallback should not be called."; } @@ -212,4 +220,5 @@ EXPECT_FALSE(devices.video_device.has_value()); EXPECT_FALSE(devices.audio_device.has_value()); } + #endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc index 1b15d2a..d85856783 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -60,12 +60,6 @@ namespace { -// TPM family. We use the TPM 2.0 style encoding, e.g.: -// * TPM 1.2: "1.2" -> 0x312e3200 -// * TPM 2.0: "2.0" -> 0x322e3000 -constexpr int kTpmV1Family = 0x312e3200; -constexpr int kTpmV2Family = 0x322e3000; - void IncrementPrefValue(const char* path) { PrefService* pref = g_browser_process->local_state(); DCHECK(pref); @@ -151,7 +145,7 @@ base::BarrierClosure(4, std::move(done_callback)); InitTaskGetFullHardwareClass(barrier); InitTaskGetArcFeatures(barrier); - InitTaskGetTpmType(barrier); + InitTaskGetTpmFirmwareVersion(barrier); InitTaskGetCellularDeviceVariant(barrier); } @@ -189,16 +183,12 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } -void ChromeOSMetricsProvider::InitTaskGetTpmType(base::OnceClosure callback) { - base::RepeatingClosure barrier = base::BarrierClosure(2, std::move(callback)); +void ChromeOSMetricsProvider::InitTaskGetTpmFirmwareVersion( + base::OnceClosure callback) { chromeos::TpmManagerClient::Get()->GetVersionInfo( tpm_manager::GetVersionInfoRequest(), base::BindOnce(&ChromeOSMetricsProvider::OnTpmManagerGetVersionInfo, - weak_ptr_factory_.GetWeakPtr(), barrier)); - chromeos::TpmManagerClient::Get()->GetSupportedFeatures( - tpm_manager::GetSupportedFeaturesRequest(), - base::BindOnce(&ChromeOSMetricsProvider::OnTpmManagerGetSupportedFeatures, - weak_ptr_factory_.GetWeakPtr(), barrier)); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } void ChromeOSMetricsProvider::InitTaskGetCellularDeviceVariant( @@ -231,7 +221,9 @@ else if (has_touch == display::Display::TouchSupport::UNAVAILABLE) hardware->set_internal_display_supports_touch(false); - SetTpmType(system_profile_proto); + if (tpm_firmware_version_.has_value()) { + hardware->set_tpm_firmware_version(*tpm_firmware_version_); + } hardware->set_cellular_device_variant(cellular_device_variant_); @@ -418,69 +410,13 @@ base::OnceClosure callback, const tpm_manager::GetVersionInfoReply& reply) { if (reply.status() == tpm_manager::STATUS_SUCCESS) { - tpm_family_ = reply.family(); - gsc_version_ = reply.gsc_version(); + tpm_firmware_version_ = reply.firmware_version(); } else { LOG(ERROR) << "Failed to get TPM version info."; } std::move(callback).Run(); } -void ChromeOSMetricsProvider::OnTpmManagerGetSupportedFeatures( - base::OnceClosure callback, - const tpm_manager::GetSupportedFeaturesReply& reply) { - if (reply.status() == tpm_manager::STATUS_SUCCESS) { - tpm_support_runtime_selection_ = reply.support_runtime_selection(); - } else { - LOG(ERROR) << "Failed to get TPM supported features."; - } - std::move(callback).Run(); -} - -void ChromeOSMetricsProvider::SetTpmType( - metrics::SystemProfileProto* system_profile_proto) { - metrics::SystemProfileProto::Hardware* hardware = - system_profile_proto->mutable_hardware(); - if (!tpm_family_.has_value() || !gsc_version_.has_value() || - !tpm_support_runtime_selection_.has_value()) { - hardware->set_tpm_type( - metrics::SystemProfileProto::Hardware::TPM_TYPE_UNKNOWN); - return; - } - if (tpm_support_runtime_selection_.value()) { - // Runtime selection TPM type. - hardware->set_tpm_type( - metrics::SystemProfileProto::Hardware::TPM_TYPE_RUNTIME_SELECTION); - } else if (tpm_family_.value() == kTpmV1Family && - gsc_version_.value() == tpm_manager::GSC_VERSION_NOT_GSC) { - // Non-GSC TPM1.2 devices. - hardware->set_tpm_type(metrics::SystemProfileProto::Hardware::TPM_TYPE_1); - } else if (tpm_family_.value() == kTpmV2Family) { - // GSC devices should all be TPM2.0 family. - if (gsc_version_.value() == tpm_manager::GSC_VERSION_CR50) { - // CR50 devices. - hardware->set_tpm_type( - metrics::SystemProfileProto::Hardware::TPM_TYPE_CR50); - } else if (gsc_version_.value() == tpm_manager::GSC_VERSION_TI50) { - // TI50 devices. - hardware->set_tpm_type( - metrics::SystemProfileProto::Hardware::TPM_TYPE_TI50); - } else { - // Generic TPM2.0 devices are not reported yet. - LOG(WARNING) << "Unknown TPM type: generic TPM 2.0."; - hardware->set_tpm_type( - metrics::SystemProfileProto::Hardware::TPM_TYPE_UNKNOWN); - } - } else { - // Other combinations shouldn't appear. - LOG(WARNING) << "Unknown TPM type: TPM family = " - << static_cast<int>(tpm_family_.value()) << ", GSC version = " - << static_cast<int>(gsc_version_.value()); - hardware->set_tpm_type( - metrics::SystemProfileProto::Hardware::TPM_TYPE_UNKNOWN); - } -} - void ChromeOSMetricsProvider::UpdateUserTypeUMA() { if (!user_manager::UserManager::IsInitialized()) return;
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.h b/chrome/browser/metrics/chromeos_metrics_provider.h index 3e8405e..8cec326 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.h +++ b/chrome/browser/metrics/chromeos_metrics_provider.h
@@ -57,9 +57,9 @@ // is run. void InitTaskGetCellularDeviceVariant(base::OnceClosure callback); - // Retrieves TPM type using TpmManagerClient. When this task is complete, - // |callback| is run. - void InitTaskGetTpmType(base::OnceClosure callback); + // Retrieves TPM firmware version using TpmManagerClient. When this task is + // complete, |callback| is run. + void InitTaskGetTpmFirmwareVersion(base::OnceClosure callback); // metrics::MetricsProvider: void Init() override; @@ -96,8 +96,7 @@ void OnArcFeaturesParsed(base::OnceClosure callback, absl::optional<arc::ArcFeatures> features); - // Sets the TPM version info (tpm family and GSC version), then calls the - // callback. + // Sets the TPM firmware version, then calls the callback. void OnTpmManagerGetVersionInfo( base::OnceClosure callback, const tpm_manager::GetVersionInfoReply& reply); @@ -149,11 +148,8 @@ // ARC release version obtained from build properties. absl::optional<std::string> arc_release_ = absl::nullopt; - // The following three fields together determine the TPM - // (go/trusted-platform-module) type. - absl::optional<uint32_t> tpm_family_ = absl::nullopt; - absl::optional<tpm_manager::GscVersion> gsc_version_ = absl::nullopt; - absl::optional<bool> tpm_support_runtime_selection_ = absl::nullopt; + // The firmware version of the TPM (go/trusted-platform-module). + absl::optional<uint64_t> tpm_firmware_version_ = absl::nullopt; base::WeakPtrFactory<ChromeOSMetricsProvider> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc index c1695f7b..3b4ca93d 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
@@ -36,8 +36,7 @@ namespace { -constexpr int kTpmV1Family = 0x312e3200; -constexpr int kTpmV2Family = 0x322e3000; +constexpr int kTpmFirmwareVersion = 100; class FakeMultiDeviceSetupClientImplFactory : public ash::multidevice_setup::MultiDeviceSetupClientImpl::Factory { @@ -127,19 +126,6 @@ chromeos::LoginState::Initialize(); } - void CheckTpmType(const Hardware::TpmType& expected_tpm_type) { - TestChromeOSMetricsProvider provider; - provider.OnDidCreateMetricsLog(); - metrics::SystemProfileProto system_profile; - provider.ProvideSystemProfileMetrics(&system_profile); - - ASSERT_TRUE(system_profile.has_hardware()); - const Hardware::TpmType proto_tpm_type = - system_profile.hardware().tpm_type(); - - EXPECT_EQ(expected_tpm_type, proto_tpm_type); - } - void TearDown() override { // Destroy the login state tracker if it was initialized. chromeos::LoginState::Shutdown(); @@ -284,68 +270,20 @@ EXPECT_EQ(country, expected_country); } -TEST_F(ChromeOSMetricsProviderTest, TpmTypeRuntimeSelection) { - chromeos::TpmManagerClient::Get() - ->GetTestInterface() - ->mutable_supported_features_reply() - ->set_support_runtime_selection(true); - - CheckTpmType(Hardware::TPM_TYPE_RUNTIME_SELECTION); -} - -TEST_F(ChromeOSMetricsProviderTest, TpmTypeV1) { +TEST_F(ChromeOSMetricsProviderTest, TpmFirmwareVersion) { chromeos::TpmManagerClient::Get() ->GetTestInterface() ->mutable_version_info_reply() - ->set_family(kTpmV1Family); + ->set_firmware_version(kTpmFirmwareVersion); - CheckTpmType(Hardware::TPM_TYPE_1); -} + TestChromeOSMetricsProvider provider; + provider.OnDidCreateMetricsLog(); + metrics::SystemProfileProto system_profile; + provider.ProvideSystemProfileMetrics(&system_profile); -TEST_F(ChromeOSMetricsProviderTest, TpmTypeCr50) { - tpm_manager::GetVersionInfoReply* reply = chromeos::TpmManagerClient::Get() - ->GetTestInterface() - ->mutable_version_info_reply(); - reply->set_gsc_version(tpm_manager::GSC_VERSION_CR50); - reply->set_family(kTpmV2Family); + ASSERT_TRUE(system_profile.has_hardware()); + ASSERT_TRUE(system_profile.hardware().has_tpm_firmware_version()); - CheckTpmType(Hardware::TPM_TYPE_CR50); -} - -TEST_F(ChromeOSMetricsProviderTest, TpmTypeTi50) { - tpm_manager::GetVersionInfoReply* reply = chromeos::TpmManagerClient::Get() - ->GetTestInterface() - ->mutable_version_info_reply(); - reply->set_gsc_version(tpm_manager::GSC_VERSION_TI50); - reply->set_family(kTpmV2Family); - - CheckTpmType(Hardware::TPM_TYPE_TI50); -} - -TEST_F(ChromeOSMetricsProviderTest, TpmTypeInvalidFamily) { - chromeos::TpmManagerClient::Get() - ->GetTestInterface() - ->mutable_version_info_reply() - ->set_family(100); - - CheckTpmType(Hardware::TPM_TYPE_UNKNOWN); -} - -TEST_F(ChromeOSMetricsProviderTest, TpmTypeGenericTpm2) { - tpm_manager::GetVersionInfoReply* reply = chromeos::TpmManagerClient::Get() - ->GetTestInterface() - ->mutable_version_info_reply(); - reply->set_family(kTpmV2Family); - - CheckTpmType(Hardware::TPM_TYPE_UNKNOWN); -} - -TEST_F(ChromeOSMetricsProviderTest, TpmTypeInvalidGscWithFamilyV1) { - tpm_manager::GetVersionInfoReply* reply = chromeos::TpmManagerClient::Get() - ->GetTestInterface() - ->mutable_version_info_reply(); - reply->set_family(kTpmV1Family); - reply->set_gsc_version(tpm_manager::GSC_VERSION_CR50); - - CheckTpmType(Hardware::TPM_TYPE_UNKNOWN); + EXPECT_EQ(system_profile.hardware().tpm_firmware_version(), + kTpmFirmwareVersion); }
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.cc b/chrome/browser/password_manager/android/password_store_android_backend.cc index 26aa12c..cb72abf 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend.cc
@@ -340,11 +340,11 @@ } void PasswordStoreAndroidBackend::FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) { if (forms.empty()) { - std::move(callback).Run({}); + std::move(callback).Run(LoginsResult()); return; } @@ -693,12 +693,12 @@ LoginsOrErrorReply PasswordStoreAndroidBackend::ReportMetricsAndInvokeCallbackForLoginsRetrieval( const MetricInfix& metric_infix, - LoginsReply callback) { + LoginsOrErrorReply callback) { // TODO(https://crbug.com/1229655) Switch to using base::PassThrough to handle // this callback more gracefully when it's implemented. return base::BindOnce( [](PasswordStoreBackendMetricsRecorder metrics_recorder, - LoginsReply callback, LoginsResultOrError results) { + LoginsOrErrorReply callback, LoginsResultOrError results) { metrics_recorder.RecordMetrics( absl::holds_alternative<PasswordStoreBackendError>(results) ? SuccessStatus::kError
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.h b/chrome/browser/password_manager/android/password_store_android_backend.h index b23a03e..53754a75 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_backend.h
@@ -95,10 +95,6 @@ // like a bulk deletion just as well as the normal, rather small job load. using JobMap = base::small_map< std::unordered_map<JobId, JobReturnHandler, JobId::Hasher>>; - using AccumulatedLoginsReply = - base::OnceCallback<void(std::unique_ptr<LoginsResult>)>; - using AccumulatedPasswordStoreChangeListReply = - base::OnceCallback<void(std::unique_ptr<PasswordStoreChangeList>)>; // Implements PasswordStoreBackend interface. void InitBackend(RemoteChangesReceived stored_passwords_changed, @@ -110,7 +106,7 @@ void GetAllLoginsForAccountAsync(absl::optional<std::string> account, LoginsOrErrorReply callback) override; void FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) override; void AddLoginAsync(const PasswordForm& form, @@ -178,7 +174,7 @@ // |callback|. static LoginsOrErrorReply ReportMetricsAndInvokeCallbackForLoginsRetrieval( const MetricInfix& metric_infix, - LoginsReply callback); + LoginsOrErrorReply callback); // Creates a metrics recorder that records latency and success metrics for // store modification operation with |metric_infix| name prior to
diff --git a/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc b/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc index 71bf62a5..ff427688 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc
@@ -237,7 +237,7 @@ base::HistogramTester histogram_tester; backend().InitBackend(PasswordStoreAndroidBackend::RemoteChangesReceived(), base::RepeatingClosure(), base::DoNothing()); - base::MockCallback<LoginsReply> mock_reply; + base::MockCallback<LoginsOrErrorReply> mock_reply; const JobId kFirstJobId{1337}; EXPECT_CALL(*bridge(), GetLoginsForSignonRealm).WillOnce(Return(kFirstJobId)); @@ -277,8 +277,7 @@ expected_logins.push_back(std::make_unique<PasswordForm>(matching_federated)); expected_logins.push_back( std::make_unique<PasswordForm>(matching_signon_realm)); - EXPECT_CALL(mock_reply, - Run(UnorderedPasswordFormElementsAre(&expected_logins))); + EXPECT_CALL(mock_reply, Run(LoginsResultsOrErrorAre(&expected_logins))); task_environment_.FastForwardBy(kLatencyDelta); consumer().OnCompleteWithLogins(kSecondJobId, {matching_signon_realm}); @@ -294,7 +293,7 @@ base::HistogramTester histogram_tester; backend().InitBackend(PasswordStoreAndroidBackend::RemoteChangesReceived(), base::RepeatingClosure(), base::DoNothing()); - base::MockCallback<LoginsReply> mock_reply; + base::MockCallback<LoginsOrErrorReply> mock_reply; const JobId kFirstJobId{1337}; EXPECT_CALL(*bridge(), GetLoginsForSignonRealm).WillOnce(Return(kFirstJobId)); @@ -334,8 +333,7 @@ expected_logins.push_back(std::make_unique<PasswordForm>(psl_matching)); expected_logins.push_back( std::make_unique<PasswordForm>(psl_matching_federated)); - EXPECT_CALL(mock_reply, - Run(UnorderedPasswordFormElementsAre(&expected_logins))); + EXPECT_CALL(mock_reply, Run(LoginsResultsOrErrorAre(&expected_logins))); task_environment_.FastForwardBy(kLatencyDelta); consumer().OnCompleteWithLogins(kSecondJobId, {psl_matching, not_matching}); @@ -418,7 +416,6 @@ // Check that calling RemoveLoginsByURLAndTime triggers logins retrieval // first. - base::MockCallback<LoginsReply> mock_logins_reply; const JobId kGetLoginsJobId{13387}; EXPECT_CALL(*bridge(), GetAllLogins).WillOnce(Return(kGetLoginsJobId)); backend().RemoveLoginsByURLAndTimeAsync(url_filter, delete_begin, delete_end, @@ -473,7 +470,6 @@ // Check that calling RemoveLoginsCreatedBetween triggers logins retrieval // first. - base::MockCallback<LoginsReply> mock_logins_reply; const JobId kGetLoginsJobId{13387}; EXPECT_CALL(*bridge(), GetAllLogins).WillOnce(Return(kGetLoginsJobId)); backend().RemoveLoginsCreatedBetweenAsync(delete_begin, delete_end, @@ -756,7 +752,6 @@ backend().InitBackend(PasswordStoreAndroidBackend::RemoteChangesReceived(), base::RepeatingClosure(), base::DoNothing()); - base::MockCallback<LoginsReply> mock_logins_reply; const JobId kGetLoginsJobId{13387}; EXPECT_CALL(*bridge(), GetAllLogins(ExpectLocalAccount())) .WillOnce(Return(kGetLoginsJobId)); @@ -796,7 +791,6 @@ backend().InitBackend(PasswordStoreAndroidBackend::RemoteChangesReceived(), base::RepeatingClosure(), base::DoNothing()); - base::MockCallback<LoginsReply> mock_logins_reply; const JobId kGetLoginsJobId{13387}; EXPECT_CALL(*bridge(), GetAllLogins(ExpectLocalAccount())) .WillOnce(Return(kGetLoginsJobId));
diff --git a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc index 396ca84..769221c 100644 --- a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc +++ b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc
@@ -15,8 +15,12 @@ EventUploadSizeController::EventUploadSizeController( const NetworkConditionService& network_condition_service, + uint64_t new_events_rate, + uint64_t remaining_storage_capacity, bool enabled) : enabled_(enabled), + new_events_rate_(new_events_rate > 0 ? new_events_rate : 1), + remaining_storage_capacity_(remaining_storage_capacity), max_upload_size_(ComputeMaxUploadSize(network_condition_service)) {} bool EventUploadSizeController::IsMaximumUploadSizeReached() const { @@ -36,23 +40,22 @@ std::numeric_limits<uint64_t>::max() / kTimeCeiling); } -// static -uint64_t EventUploadSizeController::GetNewEventRate() { - return 1UL; +uint64_t EventUploadSizeController::GetNewEventsRate() const { + return new_events_rate_; } -// static -uint64_t EventUploadSizeController::GetRemainingStorageCapacity() { - return std::numeric_limits<uint64_t>::max(); +uint64_t EventUploadSizeController::GetRemainingStorageCapacity() const { + return remaining_storage_capacity_; } -// static uint64_t EventUploadSizeController::ComputeMaxUploadSize( - const NetworkConditionService& network_condition_service) { + const NetworkConditionService& network_condition_service) const { // Estimated acceptable time that a single connection can remain open. - const uint64_t time_open = - std::min(GetRemainingStorageCapacity() / GetNewEventRate(), kTimeCeiling); - return GetUploadRate(network_condition_service) * time_open - kOverhead; + const uint64_t time_open = std::min( + GetRemainingStorageCapacity() / GetNewEventsRate(), kTimeCeiling); + // Must always at least upload some decent amount. + return std::max<uint64_t>( + 2048U, GetUploadRate(network_condition_service) * time_open - kOverhead); } // static @@ -60,16 +63,13 @@ EventUploadSizeController::BuildEncryptedRecords( const google::protobuf::RepeatedPtrField<EncryptedRecord>& encrypted_records, - const NetworkConditionService& network_condition_service) { + EventUploadSizeController&& controller) { std::vector<reporting::EncryptedRecord> records; - reporting::EventUploadSizeController event_upload_size_controller( - network_condition_service, - /*enabled=*/false); for (auto& record : encrypted_records) { // Check if we have uploaded enough records after adding each record - event_upload_size_controller.AccountForRecord(record); + controller.AccountForRecord(record); records.push_back(std::move(record)); - if (event_upload_size_controller.IsMaximumUploadSizeReached()) { + if (controller.IsMaximumUploadSizeReached()) { break; } }
diff --git a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.h b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.h index d2d6ce6dcb..fface83 100644 --- a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.h +++ b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.h
@@ -18,20 +18,22 @@ // after a specified set of records has been uploaded. class EventUploadSizeController { public: + // If |enabled| is false, |IsMaximumUploadSizeReached| would always return + // false. For now, |enabled| should always be false in production code. + // TODO(b/214039157): A policy needs to be added to control whether to enable + // this feature. + EventUploadSizeController( + const NetworkConditionService& network_condition_service, + uint64_t new_events_rate, + uint64_t remaining_storage_capacity, + bool enabled = false); + // Build the vector of encrypted records based on the records in the upload - // request. Event upload size is factored in. - [[nodiscard]] static std::vector<reporting::EncryptedRecord> - BuildEncryptedRecords( + // request. Event upload size is adjusted. + [[nodiscard]] static std::vector<EncryptedRecord> BuildEncryptedRecords( const google::protobuf::RepeatedPtrField<EncryptedRecord>& encrypted_records, - const NetworkConditionService& network_condition_service); - - // Has the set maximum upload size been reached? Always returns false if - // adjustment based on network condition is not enabled. - bool IsMaximumUploadSizeReached() const; - - // Bumps up by the size of the record to be uploaded. - void AccountForRecord(const EncryptedRecord& record); + EventUploadSizeController&& controller); private: friend class EventUploadSizeControllerTest; @@ -44,37 +46,33 @@ // Size of overheads in each upload in bytes. Heuristically set by a human. static constexpr uint64_t kOverhead = 32; - // |enabled| should always be false in production code. - // TODO(b/214039157): A policy needs to be - // added to control whether to enable this feature. - explicit EventUploadSizeController( - const NetworkConditionService& network_condition_service, - bool enabled = false); - // Estimates upload rate (bytes/sec). static uint64_t GetUploadRate( const NetworkConditionService& network_condition_service); - // Estimates the rate at which new events are coming in (bytes/sec). For - // now, use a low new event rate, which means no local storage limit is - // taken into consideration: Missive code hasn't been ready for this and - // storage capacity is not a concern right now. This will likely change in - // the future. - static uint64_t GetNewEventRate(); - // Estimates the remaining storage capacity (bytes) here. For now, use a - // high remaining storage capacity, which means no local storage limit is - // taken into consideration: Missive code hasn't been ready for this and - // storage capacity is not a concern right now. This will likely change in - // the future. - static uint64_t GetRemainingStorageCapacity(); - // Computes the maximum upload size. - static uint64_t ComputeMaxUploadSize( - const NetworkConditionService& network_condition_service); + // Estimates the rate at which new events are coming in (bytes/sec). This + // estimate is informed by missive via dbus. + uint64_t GetNewEventsRate() const; + // Estimates the remaining storage capacity (bytes) here. This estimate is + // informed by missive via dbus. + uint64_t GetRemainingStorageCapacity() const; + // Computes the maximum upload size. + [[nodiscard]] uint64_t ComputeMaxUploadSize( + const NetworkConditionService& network_condition_service) const; + // Has the set maximum upload size been reached? Always returns false if + // adjustment based on network condition is not enabled. + bool IsMaximumUploadSizeReached() const; + // Bumps up by the size of the record to be uploaded. + void AccountForRecord(const EncryptedRecord& record); // Bumps up recorded already uploaded size. void RecordUploadedSize(uint64_t uploaded_size); // Is adjustment based on network condition enabled? const bool enabled_; + // The rate (bytes per seconds) at which new events are accepted by missive. + const uint64_t new_events_rate_; + // How much local storage is left as informed by missive. + const uint64_t remaining_storage_capacity_; // maximum upload size. const uint64_t max_upload_size_; // Already uploaded size.
diff --git a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller_unittest.cc b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller_unittest.cc index 9258c51..b05b2b0c 100644 --- a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller_unittest.cc
@@ -23,15 +23,22 @@ content::BrowserTaskEnvironment task_environment_; }; +// Although |EventUploadSizeController::AccountForRecord| and +// |EventUploadSizeController::IsMaximumUploadSizeReached| are private, the +// class is designed in a way that these two methods can be made public in the +// future without disruption. Hence, this test is kept here. TEST_F(EventUploadSizeControllerTest, AccountForRecordAddUp) { TestingNetworkConditionService network_condition_service(&task_environment_); network_condition_service.SetUploadRate(10000); EventUploadSizeController event_upload_size_controller( - network_condition_service, /*enabled=*/true); + network_condition_service, + /*new_events_rate=*/1U, + /*remaining_storage_capacity=*/std::numeric_limits<uint64_t>::max(), + /*enabled=*/true); // This number may change from time to time if we adapt the formula in the // future. const uint64_t max_upload_size = - EventUploadSizeController::ComputeMaxUploadSize( + event_upload_size_controller.ComputeMaxUploadSize( network_condition_service); LOG(INFO) << "The computed max upload size is " << max_upload_size; @@ -67,4 +74,6 @@ << " records of size " << record_size << " have been accounted for."; } +// TODO(b/214039157): Add test for |BuildEncryptedRecords|. + } // namespace reporting
diff --git a/chrome/browser/policy/test/media_stream_policy_browsertest.cc b/chrome/browser/policy/test/media_stream_policy_browsertest.cc index 78b2665..1d3b1952 100644 --- a/chrome/browser/policy/test/media_stream_policy_browsertest.cc +++ b/chrome/browser/policy/test/media_stream_policy_browsertest.cc
@@ -108,22 +108,29 @@ } } - void Accept(const blink::mojom::StreamDevices& devices, + void Accept(const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, bool blocked_by_permissions_policy, ContentSetting audio_setting, ContentSetting video_setting) { - if (policy_value_ || request_url_allowed_via_allowlist_) { - ASSERT_EQ(1, devices.audio_device.has_value() + - devices.video_device.has_value()); - if (devices.audio_device.has_value()) { - ASSERT_EQ("fake_dev", devices.audio_device.value().id); - } else if (devices.video_device.has_value()) { - ASSERT_EQ("fake_dev", devices.video_device.value().id); + if (result == blink::mojom::MediaStreamRequestResult::OK) { + ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u); + const blink::mojom::StreamDevices& devices = + *stream_devices_set.stream_devices[0]; + if (policy_value_ || request_url_allowed_via_allowlist_) { + ASSERT_EQ(1, devices.audio_device.has_value() + + devices.video_device.has_value()); + if (devices.audio_device.has_value()) { + ASSERT_EQ("fake_dev", devices.audio_device.value().id); + } else if (devices.video_device.has_value()) { + ASSERT_EQ("fake_dev", devices.video_device.value().id); + } + } else { + ASSERT_FALSE(devices.audio_device.has_value()); + ASSERT_FALSE(devices.video_device.has_value()); } } else { - ASSERT_FALSE(devices.audio_device.has_value()); - ASSERT_FALSE(devices.video_device.has_value()); + ASSERT_EQ(0u, stream_devices_set.stream_devices.size()); } }
diff --git a/chrome/browser/printing/prefs_util.cc b/chrome/browser/printing/prefs_util.cc index e30c9b8c..2879595f 100644 --- a/chrome/browser/printing/prefs_util.cc +++ b/chrome/browser/printing/prefs_util.cc
@@ -21,18 +21,22 @@ return absl::nullopt; const base::Value* paper_size_value = - prefs.Get(prefs::kPrintingPaperSizeDefault); - if (!paper_size_value || paper_size_value->DictEmpty()) + prefs.GetDictionary(prefs::kPrintingPaperSizeDefault); + if (!paper_size_value) return absl::nullopt; - const base::Value* custom_size = - paper_size_value->FindKey(kPaperSizeCustomSize); - if (custom_size) { - return gfx::Size(*custom_size->FindIntKey(kPaperSizeWidth), - *custom_size->FindIntKey(kPaperSizeHeight)); + const base::Value::Dict& paper_size_dict = paper_size_value->GetDict(); + if (paper_size_dict.empty()) + return absl::nullopt; + + const base::Value::Dict* custom_size_dict = + paper_size_dict.FindDict(kPaperSizeCustomSize); + if (custom_size_dict) { + return gfx::Size(*custom_size_dict->FindInt(kPaperSizeWidth), + *custom_size_dict->FindInt(kPaperSizeHeight)); } - const std::string* name = paper_size_value->FindStringKey(kPaperSizeName); + const std::string* name = paper_size_dict.FindString(kPaperSizeName); DCHECK(name); return ParsePaper(*name).size_um; }
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index eab42b0..ef6d61a0 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -204,12 +204,12 @@ return params; } -void UpdatePrintSettingsReplyOnIO( +void OnDidUpdatePrintSettings( std::unique_ptr<PrintSettings>& snooped_settings, scoped_refptr<PrintQueriesQueue> queue, std::unique_ptr<PrinterQuery> printer_query, mojom::PrintManagerHost::UpdatePrintSettingsCallback callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(printer_query); auto params = mojom::PrintPagesParams::New(); params->params = mojom::PrintParams::New(); @@ -225,15 +225,7 @@ params->params = GetPrintParams(); - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce( - [](mojom::PrintManagerHost::UpdatePrintSettingsCallback callback, - mojom::PrintPagesParamsPtr params, bool canceled) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::move(callback).Run(std::move(params), canceled); - }, - std::move(callback), std::move(params), canceled)); + std::move(callback).Run(std::move(params), canceled); if (printer_query->cookie() && printer_query->settings().dpi()) { queue->QueuePrinterQuery(std::move(printer_query)); @@ -242,25 +234,6 @@ } } -void UpdatePrintSettingsOnIO( - std::unique_ptr<PrintSettings>& snooped_settings, - int32_t cookie, - mojom::PrintManagerHost::UpdatePrintSettingsCallback callback, - scoped_refptr<PrintQueriesQueue> queue, - base::Value::Dict job_settings) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - std::unique_ptr<PrinterQuery> printer_query = queue->PopPrinterQuery(cookie); - if (!printer_query) { - printer_query = - queue->CreatePrinterQuery(content::GlobalRenderFrameHostId()); - } - auto* printer_query_ptr = printer_query.get(); - printer_query_ptr->SetSettings( - std::move(job_settings), - base::BindOnce(&UpdatePrintSettingsReplyOnIO, std::ref(snooped_settings), - queue, std::move(printer_query), std::move(callback))); -} - class PrintPreviewObserver : PrintPreviewUI::TestDelegate { public: explicit PrintPreviewObserver(bool wait_for_loaded) @@ -598,11 +571,18 @@ void UpdatePrintSettings(int32_t cookie, base::Value::Dict job_settings, UpdatePrintSettingsCallback callback) override { - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&UpdatePrintSettingsOnIO, std::ref(snooped_settings_), - cookie, std::move(callback), queue_, - std::move(job_settings))); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + std::unique_ptr<PrinterQuery> printer_query = + queue_->PopPrinterQuery(cookie); + if (!printer_query) { + printer_query = + queue_->CreatePrinterQuery(content::GlobalRenderFrameHostId()); + } + auto* printer_query_ptr = printer_query.get(); + printer_query_ptr->SetSettings( + std::move(job_settings), + base::BindOnce(&OnDidUpdatePrintSettings, std::ref(snooped_settings_), + queue_, std::move(printer_query), std::move(callback))); } std::unique_ptr<PrintSettings> snooped_settings_;
diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc index ee713c56..d9ae000 100644 --- a/chrome/browser/printing/print_job_worker.cc +++ b/chrome/browser/printing/print_job_worker.cc
@@ -130,18 +130,11 @@ PrintingContext::Create(printing_context_delegate_.get(), ShouldPrintingContextSkipSystemCalls())), thread_("Printing_Worker") { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } PrintJobWorker::~PrintJobWorker() { - // The object is normally deleted by PrintJob in the UI thread, but when the - // user cancels printing or in the case of print preview, the worker is - // destroyed with the PrinterQuery, which is on the I/O thread. - if (print_job_) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - } else { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - } + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); Stop(); }
diff --git a/chrome/browser/printing/print_preview_sticky_settings.cc b/chrome/browser/printing/print_preview_sticky_settings.cc index 1420bb0..a6aa9b3 100644 --- a/chrome/browser/printing/print_preview_sticky_settings.cc +++ b/chrome/browser/printing/print_preview_sticky_settings.cc
@@ -40,19 +40,20 @@ } void PrintPreviewStickySettings::SaveInPrefs(PrefService* prefs) const { - base::Value dict(base::Value::Type::DICTIONARY); + base::Value::Dict dict; if (printer_app_state_) - dict.SetKey(kSettingAppState, base::Value(*printer_app_state_)); - prefs->Set(prefs::kPrintPreviewStickySettings, dict); + dict.Set(kSettingAppState, *printer_app_state_); + prefs->SetDict(prefs::kPrintPreviewStickySettings, std::move(dict)); } void PrintPreviewStickySettings::RestoreFromPrefs(PrefService* prefs) { const base::Value* value = prefs->GetDictionary(prefs::kPrintPreviewStickySettings); - const base::Value* app_state = - value->FindKeyOfType(kSettingAppState, base::Value::Type::STRING); + if (!value) + return; + const std::string* app_state = value->GetDict().FindString(kSettingAppState); if (app_state) - StoreAppState(app_state->GetString()); + StoreAppState(*app_state); } base::flat_map<std::string, int> @@ -76,15 +77,18 @@ if (!sticky_settings_state_value || !sticky_settings_state_value->is_dict()) return {}; - base::Value* recent_destinations = - sticky_settings_state_value->FindListKey(kRecentDestinations); + base::Value::List* recent_destinations = + sticky_settings_state_value->GetDict().FindList(kRecentDestinations); if (!recent_destinations) return {}; std::vector<std::string> printers; - printers.reserve(recent_destinations->GetList().size()); - for (const auto& recent_destination : recent_destinations->GetList()) { - const std::string* printer_id = recent_destination.FindStringKey(kId); + printers.reserve(recent_destinations->size()); + for (const auto& recent_destination : *recent_destinations) { + if (!recent_destination.is_dict()) + continue; + const std::string* printer_id = + recent_destination.GetDict().FindString(kId); if (!printer_id) continue; printers.push_back(*printer_id);
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc index 3704cc6..e665eb42 100644 --- a/chrome/browser/printing/print_view_manager_base.cc +++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -97,38 +97,11 @@ chrome::ShowWarningMessageBox(nullptr, std::u16string(), message); } -#if BUILDFLAG(ENABLE_PRINT_PREVIEW) -void OnPrintSettingsDoneWrapper(PrintSettingsCallback settings_callback, - std::unique_ptr<PrinterQuery> query) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(std::move(settings_callback), std::move(query))); -} - -void CreateQueryWithSettings(base::Value::Dict job_settings, - content::GlobalRenderFrameHostId rfh_id, - scoped_refptr<PrintQueriesQueue> queue, - PrintSettingsCallback callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - PrintSettingsCallback callback_wrapper = - base::BindOnce(OnPrintSettingsDoneWrapper, std::move(callback)); - std::unique_ptr<printing::PrinterQuery> printer_query = - queue->CreatePrinterQuery(rfh_id); - auto* printer_query_ptr = printer_query.get(); - printer_query_ptr->SetSettings( - std::move(job_settings), - base::BindOnce(std::move(callback_wrapper), std::move(printer_query))); -} -#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) - -void GetDefaultPrintSettingsReplyOnIO( +void OnDidGetDefaultPrintSettings( scoped_refptr<PrintQueriesQueue> queue, std::unique_ptr<PrinterQuery> printer_query, mojom::PrintManagerHost::GetDefaultPrintSettingsCallback callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); mojom::PrintParamsPtr params = mojom::PrintParams::New(); if (printer_query && printer_query->last_status() == mojom::ResultCode::kSuccess) { @@ -136,8 +109,7 @@ params->document_cookie = printer_query->cookie(); } - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(params))); + std::move(callback).Run(std::move(params)); // If printing was enabled. if (printer_query) { @@ -150,26 +122,6 @@ } } -void GetDefaultPrintSettingsOnIO( - mojom::PrintManagerHost::GetDefaultPrintSettingsCallback callback, - scoped_refptr<PrintQueriesQueue> queue, - bool is_modifiable, - content::GlobalRenderFrameHostId rfh_id) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - std::unique_ptr<PrinterQuery> printer_query = queue->PopPrinterQuery(0); - if (!printer_query) - printer_query = queue->CreatePrinterQuery(rfh_id); - - // Loads default settings. This is asynchronous, only the mojo message sender - // will hang until the settings are retrieved. - auto* printer_query_ptr = printer_query.get(); - printer_query_ptr->GetDefaultSettings( - base::BindOnce(&GetDefaultPrintSettingsReplyOnIO, queue, - std::move(printer_query), std::move(callback)), - is_modifiable); -} - mojom::PrintPagesParamsPtr CreateEmptyPrintPagesParamsPtr() { auto params = mojom::PrintPagesParams::New(); params->params = mojom::PrintParams::New(); @@ -184,12 +136,12 @@ } #endif // BUILDFLAG(IS_WIN) -void UpdatePrintSettingsReplyOnIO( +void OnDidUpdatePrintSettings( scoped_refptr<PrintQueriesQueue> queue, std::unique_ptr<PrinterQuery> printer_query, mojom::PrintManagerHost::UpdatePrintSettingsCallback callback, base::WeakPtr<PrintViewManagerBase> manager) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(printer_query); mojom::PrintPagesParamsPtr params = CreateEmptyPrintPagesParamsPtr(); if (printer_query->last_status() == mojom::ResultCode::kSuccess) { @@ -200,16 +152,11 @@ } bool canceled = printer_query->last_status() == mojom::ResultCode::kCanceled; #if BUILDFLAG(IS_WIN) - if (canceled) { - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&NotifySystemDialogCancelled, std::move(manager))); - } + if (canceled) + NotifySystemDialogCancelled(std::move(manager)); #endif - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), std::move(params), canceled)); + std::move(callback).Run(std::move(params), canceled); if (printer_query->cookie() && printer_query->settings().dpi()) { queue->QueuePrinterQuery(std::move(printer_query)); @@ -217,33 +164,13 @@ printer_query->StopWorker(); } } - -void UpdatePrintSettingsOnIO( - int32_t cookie, - mojom::PrintManagerHost::UpdatePrintSettingsCallback callback, - scoped_refptr<PrintQueriesQueue> queue, - base::Value::Dict job_settings, - base::WeakPtr<PrintViewManagerBase> manager) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - std::unique_ptr<PrinterQuery> printer_query = queue->PopPrinterQuery(cookie); - if (!printer_query) { - printer_query = - queue->CreatePrinterQuery(content::GlobalRenderFrameHostId()); - } - auto* printer_query_ptr = printer_query.get(); - printer_query_ptr->SetSettings( - std::move(job_settings), - base::BindOnce(&UpdatePrintSettingsReplyOnIO, queue, - std::move(printer_query), std::move(callback), - std::move(manager))); -} #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) -void ScriptedPrintReplyOnIO( +void OnDidScriptedPrint( scoped_refptr<PrintQueriesQueue> queue, std::unique_ptr<PrinterQuery> printer_query, mojom::PrintManagerHost::ScriptedPrintCallback callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); mojom::PrintPagesParamsPtr params = CreateEmptyPrintPagesParamsPtr(); if (printer_query->last_status() == mojom::ResultCode::kSuccess && printer_query->settings().dpi()) { @@ -254,8 +181,7 @@ } bool has_valid_cookie = params->params->document_cookie; bool has_dpi = !params->params->dpi.IsEmpty(); - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(params))); + std::move(callback).Run(std::move(params)); if (has_dpi && has_valid_cookie) { queue->QueuePrinterQuery(std::move(printer_query)); @@ -264,29 +190,6 @@ } } -void ScriptedPrintOnIO(mojom::ScriptedPrintParamsPtr params, - mojom::PrintManagerHost::ScriptedPrintCallback callback, - scoped_refptr<PrintQueriesQueue> queue, - bool is_modifiable, - content::GlobalRenderFrameHostId rfh_id) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) - ModuleDatabase::GetInstance()->DisableThirdPartyBlocking(); -#endif - - std::unique_ptr<PrinterQuery> printer_query = - queue->PopPrinterQuery(params->cookie); - if (!printer_query) - printer_query = queue->CreatePrinterQuery(rfh_id); - - auto* printer_query_ptr = printer_query.get(); - printer_query_ptr->GetSettingsFromUser( - params->expected_pages_count, params->has_selection, params->margin_type, - params->is_scripted, is_modifiable, - base::BindOnce(&ScriptedPrintReplyOnIO, queue, std::move(printer_query), - std::move(callback))); -} - } // namespace PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents) @@ -369,10 +272,12 @@ weak_ptr_factory_.GetWeakPtr(), print_data, job_settings.FindInt(kSettingPreviewPageCount).value(), std::move(callback)); - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(CreateQueryWithSettings, std::move(job_settings), - rfh->GetGlobalId(), queue_, std::move(settings_callback))); + std::unique_ptr<printing::PrinterQuery> printer_query = + queue_->CreatePrinterQuery(rfh->GetGlobalId()); + auto* printer_query_ptr = printer_query.get(); + printer_query_ptr->SetSettings( + std::move(job_settings), + base::BindOnce(std::move(settings_callback), std::move(printer_query))); } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) @@ -424,9 +329,7 @@ } if (!printer_query->cookie() || !printer_query->settings().dpi()) { - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&PrinterQuery::StopWorker, std::move(printer_query))); + printer_query->StopWorker(); std::move(callback).Run(base::Value("Update settings failed")); return; } @@ -664,11 +567,19 @@ auto callback_wrapper = base::BindOnce(&PrintViewManagerBase::GetDefaultPrintSettingsReply, weak_ptr_factory_.GetWeakPtr(), std::move(callback)); - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&GetDefaultPrintSettingsOnIO, std::move(callback_wrapper), - queue_, !render_process_host->IsPdf(), - render_frame_host->GetGlobalId())); + std::unique_ptr<PrinterQuery> printer_query = queue_->PopPrinterQuery(0); + if (!printer_query) { + printer_query = + queue_->CreatePrinterQuery(render_frame_host->GetGlobalId()); + } + + // Loads default settings. This is asynchronous, only the mojo message sender + // will hang until the settings are retrieved. + auto* printer_query_ptr = printer_query.get(); + printer_query_ptr->GetDefaultSettings( + base::BindOnce(&OnDidGetDefaultPrintSettings, queue_, + std::move(printer_query), std::move(callback_wrapper)), + !render_process_host->IsPdf()); } #if BUILDFLAG(ENABLE_PRINT_PREVIEW) @@ -702,11 +613,17 @@ auto callback_wrapper = base::BindOnce(&PrintViewManagerBase::UpdatePrintSettingsReply, weak_ptr_factory_.GetWeakPtr(), std::move(callback)); - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&UpdatePrintSettingsOnIO, cookie, - std::move(callback_wrapper), queue_, - std::move(job_settings), weak_ptr_factory_.GetWeakPtr())); + std::unique_ptr<PrinterQuery> printer_query = queue_->PopPrinterQuery(cookie); + if (!printer_query) { + printer_query = + queue_->CreatePrinterQuery(content::GlobalRenderFrameHostId()); + } + auto* printer_query_ptr = printer_query.get(); + printer_query_ptr->SetSettings( + std::move(job_settings), + base::BindOnce(&OnDidUpdatePrintSettings, queue_, + std::move(printer_query), std::move(callback_wrapper), + weak_ptr_factory_.GetWeakPtr())); } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) @@ -1138,9 +1055,7 @@ queue_->PopPrinterQuery(current_cookie); if (!printer_query) return; - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&PrinterQuery::StopWorker, std::move(printer_query))); + printer_query->StopWorker(); } void PrintViewManagerBase::SendPrintingEnabled(bool enabled, @@ -1162,15 +1077,26 @@ content::RenderFrameHost* rfh, mojom::ScriptedPrintParamsPtr params, ScriptedPrintCallback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RenderProcessHost* render_process_host = rfh->GetProcess(); auto callback_wrapper = base::BindOnce( &PrintViewManagerBase::ScriptedPrintReply, weak_ptr_factory_.GetWeakPtr(), std::move(callback), render_process_host->GetID()); - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&ScriptedPrintOnIO, std::move(params), - std::move(callback_wrapper), queue_, - !render_process_host->IsPdf(), rfh->GetGlobalId())); +#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) + ModuleDatabase::GetInstance()->DisableThirdPartyBlocking(); +#endif + + std::unique_ptr<PrinterQuery> printer_query = + queue_->PopPrinterQuery(params->cookie); + if (!printer_query) + printer_query = queue_->CreatePrinterQuery(rfh->GetGlobalId()); + + auto* printer_query_ptr = printer_query.get(); + printer_query_ptr->GetSettingsFromUser( + params->expected_pages_count, params->has_selection, params->margin_type, + params->is_scripted, !render_process_host->IsPdf(), + base::BindOnce(&OnDidScriptedPrint, queue_, std::move(printer_query), + std::move(callback_wrapper))); } #if BUILDFLAG(ENABLE_PRINT_CONTENT_ANALYSIS)
diff --git a/chrome/browser/printing/printer_query.cc b/chrome/browser/printing/printer_query.cc index f4e6d3be..9bee269b 100644 --- a/chrome/browser/printing/printer_query.cc +++ b/chrome/browser/printing/printer_query.cc
@@ -48,7 +48,7 @@ PrinterQuery::PrinterQuery(content::GlobalRenderFrameHostId rfh_id) : cookie_(PrintSettings::NewCookie()), worker_(CreateWorker(rfh_id)) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } PrinterQuery::~PrinterQuery() { @@ -62,7 +62,7 @@ absl::optional<bool> maybe_is_modifiable, std::unique_ptr<PrintSettings> new_settings, mojom::ResultCode result) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); is_print_dialog_box_shown_ = false; last_status_ = result; if (result == mojom::ResultCode::kSuccess) { @@ -78,13 +78,12 @@ std::move(callback).Run(); } -void PrinterQuery::PostSettingsDoneToIO( - base::OnceClosure callback, - absl::optional<bool> maybe_is_modifiable, - std::unique_ptr<PrintSettings> new_settings, - mojom::ResultCode result) { +void PrinterQuery::PostSettingsDone(base::OnceClosure callback, + absl::optional<bool> maybe_is_modifiable, + std::unique_ptr<PrintSettings> new_settings, + mojom::ResultCode result) { // `this` is owned by `callback`, so `base::Unretained()` is safe. - content::GetIOThreadTaskRunner({})->PostTask( + content::GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&PrinterQuery::GetSettingsDone, base::Unretained(this), std::move(callback), maybe_is_modifiable, @@ -116,7 +115,7 @@ void PrinterQuery::GetDefaultSettings(base::OnceClosure callback, bool is_modifiable) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); StartWorker(); @@ -127,7 +126,7 @@ FROM_HERE, base::BindOnce(&PrintJobWorker::GetDefaultSettings, base::Unretained(worker_.get()), - base::BindOnce(&PrinterQuery::PostSettingsDoneToIO, + base::BindOnce(&PrinterQuery::PostSettingsDone, base::Unretained(this), std::move(callback), is_modifiable))); } @@ -138,7 +137,7 @@ bool is_scripted, bool is_modifiable, base::OnceClosure callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!is_print_dialog_box_shown_ || !is_scripted); StartWorker(); @@ -151,14 +150,14 @@ base::BindOnce(&PrintJobWorker::GetSettingsFromUser, base::Unretained(worker_.get()), expected_page_count, has_selection, margin_type, is_scripted, - base::BindOnce(&PrinterQuery::PostSettingsDoneToIO, + base::BindOnce(&PrinterQuery::PostSettingsDone, base::Unretained(this), std::move(callback), is_modifiable))); } void PrinterQuery::SetSettings(base::Value::Dict new_settings, base::OnceClosure callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); StartWorker(); // `this` is owned by `callback`, so `base::Unretained()` is safe. @@ -166,7 +165,7 @@ FROM_HERE, base::BindOnce(&PrintJobWorker::SetSettings, base::Unretained(worker_.get()), std::move(new_settings), - base::BindOnce(&PrinterQuery::PostSettingsDoneToIO, + base::BindOnce(&PrinterQuery::PostSettingsDone, base::Unretained(this), std::move(callback), /*maybe_is_modifiable=*/absl::nullopt))); } @@ -175,7 +174,7 @@ void PrinterQuery::SetSettingsFromPOD( std::unique_ptr<printing::PrintSettings> new_settings, base::OnceClosure callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); StartWorker(); // `this` is owned by `callback`, so `base::Unretained()` is safe. @@ -183,14 +182,14 @@ FROM_HERE, base::BindOnce(&PrintJobWorker::SetSettingsFromPOD, base::Unretained(worker_.get()), std::move(new_settings), - base::BindOnce(&PrinterQuery::PostSettingsDoneToIO, + base::BindOnce(&PrinterQuery::PostSettingsDone, base::Unretained(this), std::move(callback), /*maybe_is_modifiable=*/absl::nullopt))); } #endif void PrinterQuery::StartWorker() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(worker_); // Lazily create the worker thread. There is one worker thread per print job. @@ -199,7 +198,7 @@ } void PrinterQuery::StopWorker() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (worker_) { // http://crbug.com/66082: We're blocking on the PrinterQuery's worker @@ -213,7 +212,7 @@ bool PrinterQuery::PostTask(const base::Location& from_here, base::OnceClosure task) { - return content::GetIOThreadTaskRunner({})->PostTask(from_here, + return content::GetUIThreadTaskRunner({})->PostTask(from_here, std::move(task)); }
diff --git a/chrome/browser/printing/printer_query.h b/chrome/browser/printing/printer_query.h index c5b0a73..2f2d933 100644 --- a/chrome/browser/printing/printer_query.h +++ b/chrome/browser/printing/printer_query.h
@@ -30,10 +30,10 @@ base::RepeatingCallback<std::unique_ptr<PrintJobWorker>( content::GlobalRenderFrameHostId rfh_id)>; -// Query the printer for settings. +// Query the printer for settings. All code in this class runs in the UI +// thread. class PrinterQuery { public: - // Can only be called on the IO thread. explicit PrinterQuery(content::GlobalRenderFrameHostId rfh_id); PrinterQuery(const PrinterQuery&) = delete; @@ -43,8 +43,6 @@ // Detach the PrintJobWorker associated to this object. Virtual so that tests // can override. - // Called on the UI thread. - // TODO(thestig): Do `worker_` and `callback_` need locks? virtual std::unique_ptr<PrintJobWorker> DetachWorker(); const PrintSettings& settings() const; @@ -97,10 +95,10 @@ std::unique_ptr<PrintSettings> new_settings, mojom::ResultCode result); - void PostSettingsDoneToIO(base::OnceClosure callback, - absl::optional<bool> maybe_is_modifiable, - std::unique_ptr<PrintSettings> new_settings, - mojom::ResultCode result); + void PostSettingsDone(base::OnceClosure callback, + absl::optional<bool> maybe_is_modifiable, + std::unique_ptr<PrintSettings> new_settings, + mojom::ResultCode result); void SetSettingsForTest(std::unique_ptr<PrintSettings> settings);
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxBottomSheetNotice.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxBottomSheetNotice.java index ebad2e9a..e71e09f7 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxBottomSheetNotice.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxBottomSheetNotice.java
@@ -145,7 +145,7 @@ @Override public int getSheetContentDescriptionStringId() { - return R.string.privacy_sandbox_notice_sheet_content_description; + return R.string.privacy_sandbox_notice_sheet_title; } @Override
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 652be6b..8d5b19e 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -36,7 +36,6 @@ "background/command_handler_interface.js", "background/focus_bounds.js", "background/logging/log_store.js", - "background/output/output_ancestry_info.js", "background/output/output_format_parser.js", "background/output/output_format_tree.js", "background/output/output_logger.js", @@ -113,6 +112,7 @@ "background/math_handler.js", "background/media_automation_handler.js", "background/output/output.js", + "background/output/output_ancestry_info.js", "background/page_load_sound_handler.js", "background/panel/i_search.js", "background/panel/i_search_handler.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js index f5f1212..38abb510 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -3015,12 +3015,12 @@ .call(doGesture(Gesture.SWIPE_RIGHT4)) .expectSpeech('Shelf', 'Tool bar') .call(doGesture(Gesture.SWIPE_RIGHT4)) - .expectSpeech(/Status tray*/) + .expectSpeech(/Calendar*/) .call(doGesture(Gesture.SWIPE_RIGHT4)) .expectSpeech(/Address and search bar*/) .call(doGesture(Gesture.SWIPE_LEFT4)) - .expectSpeech(/Status tray*/) + .expectSpeech(/Calendar*/) .call(doGesture(Gesture.SWIPE_LEFT4)) .expectSpeech('Shelf', 'Tool bar')
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js index bda50e6b..7d8dd3a 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js
@@ -28,7 +28,6 @@ goog.require('Msgs'); goog.require('NavBraille'); goog.require('OutputAction'); -goog.require('OutputAncestryInfo'); goog.require('OutputContextOrder'); goog.require('OutputEarconAction'); goog.require('OutputEventType');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js index 3998e77b9..6616db3 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
@@ -6,6 +6,7 @@ * @fileoverview Provides output services for ChromeVox. */ import {EventSourceState} from '/chromevox/background/event_source.js'; +import {OutputAncestryInfo} from '/chromevox/background/output/output_ancestry_info.js'; import {EventSourceType} from '/chromevox/common/event_source_type.js'; const AriaCurrentState = chrome.automation.AriaCurrentState;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_ancestry_info.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_ancestry_info.js index b646c60..1eba5ad 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_ancestry_info.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_ancestry_info.js
@@ -7,12 +7,6 @@ * chains given the current node. */ -goog.provide('OutputAncestryInfo'); - -goog.require('constants'); -goog.require('OutputRoleInfo'); - -goog.scope(function() { const AutomationNode = chrome.automation.AutomationNode; const Dir = constants.Dir; const RoleType = chrome.automation.RoleType; @@ -24,7 +18,7 @@ * so are generally valid for the current call stack, wherein ancestry data is * stable. */ -OutputAncestryInfo = class { +export class OutputAncestryInfo { /** * @param {!AutomationNode} node The primary node to consider for ancestry * computation. @@ -156,5 +150,4 @@ } return rest.concat(contextFirst.reverse()); } -}; -}); // goog.scope +}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js index 4958b8b..e00ef6bd 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js
@@ -18,7 +18,6 @@ goog.require('Msgs'); goog.require('NavBraille'); goog.require('OutputAction'); -goog.require('OutputAncestryInfo'); goog.require('OutputContextOrder'); goog.require('OutputEarconAction'); goog.require('OutputEventType');
diff --git a/chrome/browser/resources/settings/autofill_page/password_list_item.ts b/chrome/browser/resources/settings/autofill_page/password_list_item.ts index 1ef567c..943fc50b 100644 --- a/chrome/browser/resources/settings/autofill_page/password_list_item.ts +++ b/chrome/browser/resources/settings/autofill_page/password_list_item.ts
@@ -22,7 +22,7 @@ import {Router} from '../router.js'; import {getTemplate} from './password_list_item.html.js'; -import {PasswordViewPageUrlParams} from './password_view.js'; +import {PasswordViewPageInteractions, PasswordViewPageUrlParams, recordPasswordViewInteraction} from './password_view.js'; import {ShowPasswordMixin, ShowPasswordMixinInterface} from './show_password_mixin.js'; export type PasswordMoreActionsClickedEvent = CustomEvent<{ @@ -123,6 +123,8 @@ params.set(PasswordViewPageUrlParams.ON_DEVICE, 'true'); } } + recordPasswordViewInteraction( + PasswordViewPageInteractions.CREDENTIAL_ROW_CLICKED); Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params); }
diff --git a/chrome/browser/resources/settings/autofill_page/password_view.ts b/chrome/browser/resources/settings/autofill_page/password_view.ts index a8f48ae..272d350 100644 --- a/chrome/browser/resources/settings/autofill_page/password_view.ts +++ b/chrome/browser/resources/settings/autofill_page/password_view.ts
@@ -61,6 +61,33 @@ ON_DEVICE = 'onDevice', } +export function recordPasswordViewInteraction( + interaction: PasswordViewPageInteractions) { + chrome.metricsPrivate.recordEnumerationValue( + 'PasswordManager.PasswordViewPage.UserActions', interaction, + PasswordViewPageInteractions.COUNT); +} + +/** + * Should be kept in sync with + * |password_manager::metrics_util::PasswordViewPageInteractions|. + * These values are persisted to logs. Entries should not be renumbered and + * numeric values should never be reused. + */ +export enum PasswordViewPageInteractions { + CREDENTIAL_ROW_CLICKED = 0, + CREDENTIAL_FOUND = 1, + CREDENTIAL_NOT_FOUND = 2, + USERNAME_COPY_BUTTON_CLICKED = 3, + PASSWORD_COPY_BUTTON_CLICKED = 4, + PASSWORD_SHOW_BUTTON_CLICKED = 5, + PASSWORD_EDIT_BUTTON_CLICKED = 6, + PASSWORD_DELETE_BUTTON_CLICKED = 7, + CREDENTIAL_EDITED = 8, + // Must be last. + COUNT = 9, +} + export class PasswordViewElement extends PasswordViewElementBase { static get is() { return 'password-view'; @@ -246,6 +273,8 @@ /** Handler to copy the password from the password field. */ private onCopyPasswordButtonClick_() { assert(!this.isFederated_()); + recordPasswordViewInteraction( + PasswordViewPageInteractions.PASSWORD_COPY_BUTTON_CLICKED); this.requestPlaintextPassword( this.credential!.getAnyId(), chrome.passwordsPrivate.PlaintextReason.COPY) @@ -255,11 +284,15 @@ /** Handler to copy the username from the username field. */ private onCopyUsernameButtonClick_() { navigator.clipboard.writeText(this.credential!.username); + recordPasswordViewInteraction( + PasswordViewPageInteractions.USERNAME_COPY_BUTTON_CLICKED); } /** Handler for the remove button. */ private onDeleteButtonClick_() { assert(this.credential); + recordPasswordViewInteraction( + PasswordViewPageInteractions.PASSWORD_DELETE_BUTTON_CLICKED); if (!this.removePassword(this.credential)) { return; } @@ -271,6 +304,8 @@ /** Handler to open edit dialog for the password. */ private onEditButtonClick_() { assert(!this.isFederated_()); + recordPasswordViewInteraction( + PasswordViewPageInteractions.PASSWORD_EDIT_BUTTON_CLICKED); this.requestPlaintextPassword( this.credential!.getAnyId(), chrome.passwordsPrivate.PlaintextReason.EDIT) @@ -287,6 +322,12 @@ private onSavedPasswordEdited_(event: SavedPasswordEditedEvent) { this.recentlyEdited_ = true; const newUsername = event.detail.username; + if (event.detail.username !== this.credential!.username || + event.detail.password !== this.credential!.password || + event.detail.note !== this.credential!.note) { + recordPasswordViewInteraction( + PasswordViewPageInteractions.CREDENTIAL_EDITED); + } if (this.credential!.username === newUsername) { return; } @@ -339,6 +380,8 @@ this.isPasswordVisible_ = false; return; } + recordPasswordViewInteraction( + PasswordViewPageInteractions.PASSWORD_SHOW_BUTTON_CLICKED); this.requestPlaintextPassword( this.credential!.getAnyId(), chrome.passwordsPrivate.PlaintextReason.VIEW) @@ -384,6 +427,8 @@ if (!this.recentlyEdited_) { // Rerouting might have happened due to the edited username. Do not // reroute back. + recordPasswordViewInteraction( + PasswordViewPageInteractions.CREDENTIAL_NOT_FOUND); Router.getInstance().navigateTo(routes.PASSWORDS); } return; @@ -395,6 +440,8 @@ } this.showEditDialog_ = false; this.recentlyEdited_ = false; + recordPasswordViewInteraction( + PasswordViewPageInteractions.CREDENTIAL_FOUND); } }
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 716df35e..3ca328d 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -176,6 +176,8 @@ "images/icon_pair_bluetooth.svg", "images/keyboard_shortcut_dark.svg", "images/keyboard_shortcut.svg", + "images/multidevice_permission_setup_connecting.svg", + "images/multidevice_permission_setup_connecting_dark.svg", "images/notification_access_connecting_dark.svg", "images/notification_access_connecting.svg", "images/notification_access_error_dark.svg",
diff --git a/chrome/browser/resources/settings/chromeos/images/multidevice_permission_setup_connecting.svg b/chrome/browser/resources/settings/chromeos/images/multidevice_permission_setup_connecting.svg new file mode 100644 index 0000000..1c3e3a4 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/images/multidevice_permission_setup_connecting.svg
@@ -0,0 +1,16 @@ +<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M192.841 132.878H164.379C163.813 132.858 163.276 132.624 162.875 132.224C162.475 131.823 162.241 131.286 162.221 130.72V69.1586C162.221 68.5861 162.448 68.0371 162.853 67.6323C163.258 67.2274 163.807 67 164.379 67H192.841C193.408 67.0199 193.945 67.2537 194.346 67.6543C194.746 68.0549 194.98 68.5925 195 69.1586V130.64C195 131.22 194.776 131.777 194.373 132.195C193.97 132.612 193.421 132.857 192.841 132.878Z" fill="#D2E3FC"/> +<path d="M192.841 132.878H164.379C163.813 132.858 163.276 132.624 162.875 132.224C162.475 131.823 162.241 131.286 162.221 130.72V69.1586C162.221 68.5861 162.448 68.0371 162.853 67.6323C163.258 67.2274 163.807 67 164.379 67H192.841C193.408 67.0199 193.945 67.2537 194.346 67.6543C194.746 68.0549 194.98 68.5925 195 69.1586V130.64C195 131.22 194.776 131.777 194.373 132.195C193.97 132.612 193.421 132.857 192.841 132.878Z" fill="#D2E3FC"/> +<path d="M82.4315 68.7887L63.0038 71.7468C60.4806 72.1285 58.2123 73.4969 56.6979 75.551C55.1836 77.6051 54.5473 80.1766 54.9289 82.6998C55.3106 85.2231 56.679 87.4914 58.7331 89.0057C60.7872 90.52 63.3587 91.1564 65.882 90.7747L85.3097 87.7366C86.6019 87.604 87.8537 87.2103 88.9892 86.5794C90.1247 85.9485 91.1203 85.0936 91.9155 84.0665C92.7108 83.0394 93.2892 81.8615 93.6157 80.6042C93.9422 79.3469 94.0099 78.0364 93.8149 76.7521C93.6198 75.4679 93.1659 74.2366 92.4808 73.1329C91.7957 72.0293 90.8936 71.0763 89.8292 70.3317C88.7648 69.5871 87.5603 69.0664 86.2887 68.8011C85.017 68.5359 83.7048 68.5316 82.4315 68.7887V68.7887ZM90.9861 77.1833C91.1335 78.1132 91.095 79.0631 90.8727 79.978C90.6504 80.8928 90.2487 81.7545 89.691 82.513C89.1333 83.2715 88.4306 83.9118 87.6236 84.3967C86.8166 84.8817 85.9214 85.2017 84.9899 85.3382L65.4823 88.3762C63.5951 88.6625 61.6715 88.1873 60.1347 87.0553C58.5979 85.9233 57.5737 84.2272 57.2875 82.3401C57.0012 80.4529 57.4763 78.5294 58.6083 76.9925C59.7403 75.4557 61.4365 74.4315 63.3236 74.1453L82.8312 71.1072C84.7182 70.8328 86.6369 71.3185 88.166 72.4578C89.695 73.5971 90.7093 75.2967 90.9861 77.1833V77.1833Z" fill="#EA4335"/> +<path d="M111.853 75.9543C112.705 75.8262 113.482 75.3967 114.044 74.7438C114.607 74.0909 114.916 73.258 114.916 72.3965C114.916 71.535 114.607 70.7021 114.044 70.0493C113.482 69.3964 112.705 68.9669 111.853 68.8388C111.341 68.7618 110.818 68.7963 110.321 68.9397C109.824 69.0832 109.363 69.3323 108.971 69.67C108.578 70.0078 108.264 70.4262 108.048 70.8968C107.832 71.3673 107.72 71.8789 107.72 72.3965C107.72 72.9142 107.832 73.4258 108.048 73.8963C108.264 74.3669 108.578 74.7853 108.971 75.1231C109.363 75.4608 109.824 75.7099 110.321 75.8534C110.818 75.9968 111.341 76.0312 111.853 75.9543Z" fill="#34A853"/> +<path d="M65.0825 80.5412L37.9797 87.8965C37.8584 87.9148 37.7448 87.9675 37.6526 88.0485C37.5604 88.1295 37.4935 88.2353 37.4598 88.3533C37.4261 88.4713 37.427 88.5965 37.4625 88.714C37.498 88.8314 37.5665 88.9362 37.6599 89.0158L57.6472 108.843C57.7366 108.913 57.8413 108.961 57.9527 108.983C58.0642 109.005 58.1792 109 58.2883 108.968C58.3975 108.937 58.4977 108.881 58.5808 108.803C58.6639 108.726 58.7276 108.63 58.7665 108.523L65.9619 81.3407C65.9781 81.2247 65.9658 81.1065 65.926 80.9964C65.8861 80.8863 65.82 80.7875 65.7333 80.7087C65.6467 80.6299 65.5421 80.5735 65.4287 80.5443C65.3153 80.5151 65.1964 80.5141 65.0825 80.5412V80.5412Z" fill="#FBBC04"/> +<path d="M162.221 92.184C159.493 92.3074 156.825 91.3607 154.786 89.5457L152.067 87.1473L150.868 86.1879L149.909 85.6282C148.871 85.0934 147.738 84.7704 146.574 84.6782C145.411 84.5859 144.24 84.7262 143.132 85.0908C142.023 85.4554 140.998 86.0371 140.116 86.802C139.234 87.5668 138.514 88.4995 137.996 89.5457C136.959 91.6489 136.789 94.0748 137.522 96.3022C138.254 98.5296 139.831 100.381 141.914 101.458L142.953 101.858H143.033L144.472 102.258L147.99 102.977C150.703 103.591 153.078 105.222 154.626 107.534L156.385 110.173C156.871 111.028 157.404 111.856 157.983 112.651C159.165 113.993 160.606 115.081 162.221 115.849" fill="#D2E3FC"/> +<path d="M162.221 115.929L163.1 116.329C166.132 117.459 169.481 117.391 172.465 116.138C175.448 114.885 177.842 112.541 179.157 109.585C180.472 106.628 180.61 103.281 179.543 100.226C178.476 97.171 176.284 94.6381 173.414 93.1434C170.953 91.9657 168.189 91.5749 165.499 92.0241L162.381 92.184H162.221" fill="#4285F4"/> +<path d="M137.676 75.4746C135.083 75.4746 132.548 76.2436 130.392 77.6843C128.236 79.1251 126.555 81.1728 125.563 83.5687C124.57 85.9645 124.311 88.6008 124.817 91.1442C125.323 93.6877 126.571 96.0239 128.405 97.8576C130.239 99.6913 132.575 100.94 135.118 101.446C137.662 101.952 140.298 101.692 142.694 100.7C145.09 99.7075 147.138 98.0269 148.578 95.8707C150.019 93.7145 150.788 91.1795 150.788 88.5863C150.788 86.8644 150.449 85.1594 149.79 83.5687C149.131 81.9779 148.165 80.5325 146.948 79.3149C145.73 78.0974 144.285 77.1316 142.694 76.4727C141.103 75.8138 139.398 75.4746 137.676 75.4746V75.4746ZM137.676 77.8731C139.795 77.8731 141.867 78.5014 143.628 79.6786C145.39 80.8558 146.763 82.5289 147.574 84.4865C148.385 86.4441 148.597 88.5982 148.184 90.6763C147.77 92.7545 146.75 94.6634 145.252 96.1617C143.753 97.6599 141.845 98.6803 139.766 99.0936C137.688 99.507 135.534 99.2948 133.577 98.484C131.619 97.6731 129.946 96.3 128.769 94.5382C127.591 92.7764 126.963 90.7051 126.963 88.5863C126.963 85.745 128.092 83.02 130.101 81.0109C132.11 79.0018 134.835 77.8731 137.676 77.8731Z" fill="#4285F4"/> +<path d="M182.608 70.198C182.699 70.1972 182.789 70.216 182.873 70.253C182.956 70.2901 183.03 70.3445 183.091 70.4126C183.151 70.4808 183.197 70.5611 183.224 70.6481C183.251 70.7352 183.259 70.8271 183.247 70.9175C183.249 71.0742 183.192 71.2258 183.089 71.3437C182.986 71.4616 182.843 71.5375 182.688 71.5571H176.372C176.208 71.5397 176.055 71.4668 175.939 71.3504C175.823 71.234 175.75 71.0812 175.732 70.9175C175.741 70.7548 175.799 70.5988 175.899 70.4702C175.999 70.3416 176.136 70.2466 176.292 70.198H182.608Z" fill="#4285F4"/> +<path d="M172.934 71.717C173.146 71.717 173.349 71.6328 173.499 71.4828C173.649 71.3329 173.733 71.1295 173.733 70.9175C173.746 70.8094 173.734 70.6998 173.699 70.597C173.663 70.4941 173.605 70.4007 173.528 70.3237C173.451 70.2467 173.357 70.1883 173.255 70.1526C173.152 70.117 173.042 70.1052 172.934 70.118C172.722 70.118 172.519 70.2022 172.369 70.3522C172.219 70.5021 172.134 70.7055 172.134 70.9175C172.153 71.1235 172.243 71.3165 172.389 71.4628C172.535 71.609 172.728 71.699 172.934 71.717V71.717Z" fill="#4285F4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M147.67 84.8287C148.454 84.9747 149.21 85.2446 149.909 85.6282L150.468 85.948C150.693 86.8091 150.8 87.6965 150.788 88.5863C150.786 91.4062 149.875 94.1503 148.19 96.4114C146.505 98.6726 144.136 100.33 141.434 101.138C140.559 100.633 139.776 99.9843 139.116 99.2195C141.68 98.855 144.028 97.5803 145.731 95.6281C147.433 93.676 148.377 91.1766 148.39 88.5863C148.39 87.2995 148.146 86.0243 147.67 84.8287V84.8287Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M57.1675 82.6998C57.4874 84.3125 58.3385 85.7715 59.5848 86.8439C60.8311 87.9163 62.4007 88.5402 64.0431 88.616L63.4835 90.6147C61.5081 90.421 59.6455 89.6039 58.1651 88.2817C56.6847 86.9594 55.6634 85.2005 55.2487 83.2594L57.1675 82.6998Z" fill="white"/> +<path d="M15.1142 98.9295C18.2762 97.8175 21.743 97.9508 24.8102 99.3025C27.8775 100.654 30.3152 103.123 31.6281 106.207C32.9411 109.291 33.0309 112.759 31.8793 115.906C30.7276 119.054 28.4209 121.646 25.4277 123.154C24.5942 123.627 23.7089 124.003 22.7894 124.273" fill="#EE5FFA"/> +<path d="M8.95813 76.064L24.868 130.19L79.7132 129.47V132.588L23.6688 133.308C23.3502 133.307 23.0399 133.207 22.7816 133.02C22.5234 132.834 22.3303 132.571 22.2297 132.268L6 76.9435L8.95813 76.064Z" fill="#4285F4"/> +</svg>
diff --git a/chrome/browser/resources/settings/chromeos/images/multidevice_permission_setup_connecting_dark.svg b/chrome/browser/resources/settings/chromeos/images/multidevice_permission_setup_connecting_dark.svg new file mode 100644 index 0000000..f345fb2f --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/images/multidevice_permission_setup_connecting_dark.svg
@@ -0,0 +1,16 @@ +<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M192.841 132.878H164.379C163.813 132.858 163.276 132.624 162.875 132.224C162.475 131.823 162.241 131.286 162.221 130.72V69.1586C162.221 68.5861 162.448 68.0371 162.853 67.6323C163.258 67.2274 163.807 67 164.379 67H192.841C193.408 67.0199 193.945 67.2537 194.346 67.6543C194.746 68.0549 194.98 68.5925 195 69.1586V130.64C195 131.22 194.776 131.777 194.373 132.195C193.97 132.612 193.421 132.857 192.841 132.878Z" fill="#8AB4F8" fill-opacity="0.4"/> +<path d="M192.841 132.878H164.379C163.813 132.858 163.276 132.624 162.875 132.224C162.475 131.823 162.241 131.286 162.221 130.72V69.1586C162.221 68.5861 162.448 68.0371 162.853 67.6323C163.258 67.2274 163.807 67 164.379 67H192.841C193.408 67.0199 193.945 67.2537 194.346 67.6543C194.746 68.0549 194.98 68.5925 195 69.1586V130.64C195 131.22 194.776 131.777 194.373 132.195C193.97 132.612 193.421 132.857 192.841 132.878Z" fill="#8AB4F8" fill-opacity="0.4"/> +<path d="M82.4315 68.7887L63.0038 71.7468C60.4806 72.1285 58.2123 73.4969 56.6979 75.551C55.1836 77.6051 54.5473 80.1766 54.9289 82.6998C55.3106 85.2231 56.679 87.4914 58.7331 89.0057C60.7872 90.52 63.3587 91.1564 65.882 90.7747L85.3097 87.7366C86.6019 87.604 87.8537 87.2103 88.9892 86.5794C90.1247 85.9485 91.1203 85.0936 91.9155 84.0665C92.7108 83.0394 93.2892 81.8615 93.6157 80.6042C93.9422 79.3469 94.0099 78.0364 93.8149 76.7521C93.6198 75.4679 93.1659 74.2366 92.4808 73.1329C91.7957 72.0293 90.8936 71.0763 89.8292 70.3317C88.7648 69.5871 87.5603 69.0664 86.2887 68.8011C85.017 68.5359 83.7048 68.5316 82.4315 68.7887V68.7887ZM90.9861 77.1833C91.1335 78.1132 91.095 79.0631 90.8727 79.978C90.6504 80.8928 90.2487 81.7545 89.691 82.513C89.1333 83.2715 88.4306 83.9118 87.6236 84.3967C86.8166 84.8817 85.9214 85.2017 84.9899 85.3382L65.4823 88.3762C63.5951 88.6625 61.6715 88.1873 60.1347 87.0553C58.5979 85.9233 57.5737 84.2272 57.2875 82.3401C57.0012 80.4529 57.4763 78.5294 58.6083 76.9925C59.7403 75.4557 61.4365 74.4315 63.3236 74.1453L82.8312 71.1072C84.7182 70.8328 86.6369 71.3185 88.166 72.4578C89.695 73.5971 90.7093 75.2967 90.9861 77.1833V77.1833Z" fill="#EA4335"/> +<path d="M111.853 75.9543C112.705 75.8262 113.482 75.3967 114.044 74.7438C114.607 74.0909 114.916 73.258 114.916 72.3965C114.916 71.535 114.607 70.7021 114.044 70.0493C113.482 69.3964 112.705 68.9669 111.853 68.8388C111.341 68.7618 110.818 68.7963 110.321 68.9397C109.824 69.0832 109.363 69.3323 108.971 69.67C108.578 70.0078 108.264 70.4262 108.048 70.8968C107.832 71.3673 107.72 71.8789 107.72 72.3965C107.72 72.9142 107.832 73.4258 108.048 73.8963C108.264 74.3669 108.578 74.7853 108.971 75.1231C109.363 75.4608 109.824 75.7099 110.321 75.8534C110.818 75.9968 111.341 76.0312 111.853 75.9543Z" fill="#5BB974"/> +<path d="M65.0825 80.5412L37.9797 87.8965C37.8584 87.9148 37.7448 87.9675 37.6526 88.0485C37.5604 88.1295 37.4935 88.2353 37.4598 88.3533C37.4261 88.4713 37.427 88.5965 37.4625 88.714C37.498 88.8314 37.5665 88.9362 37.6599 89.0158L57.6472 108.843C57.7366 108.913 57.8413 108.961 57.9527 108.983C58.0642 109.005 58.1792 109 58.2883 108.968C58.3975 108.937 58.4977 108.881 58.5808 108.803C58.6639 108.726 58.7276 108.63 58.7665 108.523L65.9619 81.3407C65.9781 81.2247 65.9658 81.1065 65.926 80.9964C65.8861 80.8863 65.82 80.7875 65.7333 80.7087C65.6467 80.6299 65.5421 80.5735 65.4287 80.5443C65.3153 80.5151 65.1964 80.5141 65.0825 80.5412V80.5412Z" fill="#FBBC04"/> +<path d="M162.221 92.184C159.493 92.3074 156.825 91.3607 154.786 89.5457L152.067 87.1473L150.868 86.1879L149.909 85.6282C148.871 85.0934 147.738 84.7704 146.574 84.6782C145.411 84.5859 144.24 84.7262 143.132 85.0908C142.023 85.4554 140.998 86.0371 140.116 86.802C139.234 87.5668 138.514 88.4995 137.996 89.5457C136.959 91.6489 136.789 94.0748 137.522 96.3022C138.254 98.5296 139.831 100.381 141.914 101.458L142.953 101.858H143.033L144.472 102.258L147.99 102.977C150.703 103.591 153.078 105.222 154.626 107.534L156.385 110.173C156.871 111.028 157.404 111.856 157.983 112.651C159.165 113.993 160.606 115.081 162.221 115.849" fill="#8AB4F8" fill-opacity="0.4"/> +<path d="M162.221 115.929L163.1 116.329C166.132 117.459 169.481 117.391 172.465 116.138C175.448 114.885 177.842 112.541 179.157 109.585C180.472 106.628 180.61 103.281 179.543 100.226C178.476 97.171 176.284 94.6381 173.414 93.1434C170.953 91.9657 168.189 91.5749 165.499 92.0241L162.381 92.184H162.221" fill="#669DF6"/> +<path d="M137.676 75.4746C135.083 75.4746 132.548 76.2436 130.392 77.6843C128.236 79.1251 126.555 81.1728 125.563 83.5687C124.57 85.9645 124.311 88.6008 124.817 91.1442C125.323 93.6877 126.571 96.0239 128.405 97.8576C130.239 99.6913 132.575 100.94 135.118 101.446C137.662 101.952 140.298 101.692 142.694 100.7C145.09 99.7075 147.138 98.0269 148.578 95.8707C150.019 93.7145 150.788 91.1795 150.788 88.5863C150.788 86.8644 150.449 85.1594 149.79 83.5687C149.131 81.9779 148.165 80.5325 146.948 79.3149C145.73 78.0974 144.285 77.1316 142.694 76.4727C141.103 75.8138 139.398 75.4746 137.676 75.4746V75.4746ZM137.676 77.8731C139.795 77.8731 141.867 78.5014 143.628 79.6786C145.39 80.8558 146.763 82.5289 147.574 84.4865C148.385 86.4441 148.597 88.5982 148.184 90.6763C147.77 92.7545 146.75 94.6634 145.252 96.1617C143.753 97.6599 141.845 98.6803 139.766 99.0936C137.688 99.507 135.534 99.2948 133.577 98.484C131.619 97.6731 129.946 96.3 128.769 94.5382C127.591 92.7764 126.963 90.7051 126.963 88.5863C126.963 85.745 128.092 83.02 130.101 81.0109C132.11 79.0018 134.835 77.8731 137.676 77.8731Z" fill="#669DF6"/> +<path d="M182.608 70.1979C182.699 70.1972 182.789 70.216 182.873 70.253C182.956 70.29 183.03 70.3444 183.091 70.4126C183.151 70.4807 183.197 70.561 183.224 70.6481C183.251 70.7352 183.259 70.827 183.247 70.9174C183.249 71.0741 183.192 71.2257 183.089 71.3436C182.986 71.4615 182.843 71.5375 182.688 71.557H176.372C176.208 71.5397 176.055 71.4667 175.939 71.3503C175.823 71.2339 175.75 71.0811 175.732 70.9174C175.741 70.7548 175.799 70.5987 175.899 70.4701C175.999 70.3415 176.136 70.2465 176.292 70.1979H182.608Z" fill="#669DF6"/> +<path d="M172.934 71.7169C173.146 71.7169 173.349 71.6327 173.499 71.4828C173.649 71.3328 173.733 71.1295 173.733 70.9174C173.746 70.8094 173.734 70.6998 173.699 70.5969C173.663 70.4941 173.605 70.4006 173.528 70.3237C173.451 70.2467 173.357 70.1882 173.255 70.1526C173.152 70.1169 173.042 70.1051 172.934 70.118C172.722 70.118 172.519 70.2022 172.369 70.3521C172.219 70.5021 172.134 70.7054 172.134 70.9174C172.153 71.1234 172.243 71.3165 172.389 71.4627C172.535 71.6089 172.728 71.6989 172.934 71.7169V71.7169Z" fill="#669DF6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M147.67 84.8286C148.454 84.9747 149.21 85.2445 149.909 85.6281L150.468 85.9479C150.693 86.809 150.8 87.6964 150.788 88.5862C150.786 91.4061 149.875 94.1503 148.19 96.4114C146.505 98.6725 144.136 100.33 141.434 101.138C140.559 100.633 139.776 99.9842 139.116 99.2195C141.68 98.8549 144.028 97.5802 145.731 95.6281C147.433 93.6759 148.377 91.1765 148.39 88.5862C148.39 87.2994 148.146 86.0242 147.67 84.8286V84.8286Z" fill="#323336"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M57.1675 82.6998C57.4874 84.3126 58.3385 85.7716 59.5848 86.844C60.8311 87.9164 62.4007 88.5403 64.0431 88.6161L63.4835 90.6148C61.5081 90.4211 59.6455 89.604 58.1651 88.2817C56.6847 86.9595 55.6634 85.2006 55.2487 83.2595L57.1675 82.6998Z" fill="#323336"/> +<path d="M15.1142 98.9295C18.2762 97.8175 21.743 97.9508 24.8102 99.3025C27.8775 100.654 30.3152 103.123 31.6281 106.207C32.9411 109.291 33.0309 112.759 31.8793 115.906C30.7276 119.054 28.4209 121.646 25.4277 123.154C24.5942 123.627 23.7089 124.003 22.7894 124.273" fill="#F882FE"/> +<path d="M8.95813 76.064L24.868 130.19L79.7132 129.47V132.588L23.6688 133.308C23.3502 133.307 23.0399 133.207 22.7816 133.02C22.5234 132.834 22.3303 132.571 22.2297 132.268L6 76.9434L8.95813 76.064Z" fill="#669DF6"/> +</svg>
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.html b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.html index 9dd0ff5..8af3e1e3 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.html +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.html
@@ -15,7 +15,7 @@ #illustration { background-image: - url(chrome://os-settings/images/notification_access_connecting.svg); + url(chrome://os-settings/images/multidevice_permission_setup_connecting.svg); background-position: center center; background-repeat: no-repeat; background-size: contain; @@ -28,7 +28,7 @@ @media(prefers-color-scheme: dark) { #illustration { background-image: url( - chrome://os-settings/images/notification_access_connecting_dark.svg); + chrome://os-settings/images/multidevice_permission_setup_connecting_dark.svg); } }
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.cc b/chrome/browser/supervised_user/supervised_user_settings_service.cc index b5bfba6..bae11637 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service.cc +++ b/chrome/browser/supervised_user/supervised_user_settings_service.cc
@@ -137,6 +137,17 @@ return website_approval_callback_list_.Add(callback); } +void SupervisedUserSettingsService::RecordLocalWebsiteApproval( + const std::string& host) { + // Write the sync setting. + std::string setting_key = MakeSplitSettingKey( + supervised_users::kContentPackManualBehaviorHosts, host); + SaveItem(setting_key, std::make_unique<base::Value>(true)); + + // Now notify subscribers of the updates. + website_approval_callback_list_.Notify(setting_key); +} + base::CallbackListSubscription SupervisedUserSettingsService::SubscribeForShutdown( const ShutdownCallback& callback) { @@ -168,16 +179,10 @@ return prefix + kSplitSettingKeySeparator + key; } -void SupervisedUserSettingsService::UploadItem( +void SupervisedUserSettingsService::SaveItem( const std::string& key, std::unique_ptr<base::Value> value) { - DCHECK(!SettingShouldApplyToPrefs(key)); - PushItemToSync(key, std::move(value)); -} - -void SupervisedUserSettingsService::PushItemToSync( - const std::string& key, - std::unique_ptr<base::Value> value) { + // Update the value in our local dict, and push the changes to sync. std::string key_suffix = key; base::Value* dict = nullptr; if (sync_processor_) { @@ -200,6 +205,15 @@ dict = GetQueuedItems(); } dict->SetKey(key_suffix, base::Value::FromUniquePtrValue(std::move(value))); + + // Now notify subscribers of the updates. + // For simplicity and consistency with ProcessSyncChanges() we notify both + // settings keys. + store_->ReportValueChanged(kAtomicSettings, + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + store_->ReportValueChanged(kSplitSettings, + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + InformSubscribers(); } void SupervisedUserSettingsService::SetLocalSetting(
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.h b/chrome/browser/supervised_user/supervised_user_settings_service.h index a515ea1..57dfbc9 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service.h +++ b/chrome/browser/supervised_user/supervised_user_settings_service.h
@@ -107,6 +107,12 @@ [[nodiscard]] base::CallbackListSubscription SubscribeForNewWebsiteApproval( const WebsiteApprovalCallback& callback); + // Records that a website has been locally approved for this user. + // + // This handles updating local and remote state for this setting, and + // notifying observers. + void RecordLocalWebsiteApproval(const std::string& host); + // Subscribe for a notification when the keyed service is shut down. The // subscription can be destroyed to unsubscribe. base::CallbackListSubscription SubscribeForShutdown( @@ -127,12 +133,14 @@ static std::string MakeSplitSettingKey(const std::string& prefix, const std::string& key); - // Uploads an item to the Sync server. Items are the same data structure as - // supervised user settings (i.e. key-value pairs, as described at the top of - // the file), but they are only uploaded (whereas supervised user settings are - // only downloaded), and never passed to the preference system. - // An example of an uploaded item is an access request to a blocked URL. - void UploadItem(const std::string& key, std::unique_ptr<base::Value> value); + // Sets an item locally and uploads it to the Sync server. + // + // This handles notifying subscribers of the change. + // + // This may be called regardless of whether the sync server has completed + // initialization; in either case the local changes will be handled + // immediately. + void SaveItem(const std::string& key, std::unique_ptr<base::Value> value); // Sets the setting with the given |key| to a copy of the given |value|. void SetLocalSetting(const std::string& key, @@ -184,9 +192,6 @@ // subclass whenever the settings change. void InformSubscribers(); - void PushItemToSync(const std::string& key, - std::unique_ptr<base::Value> value); - // Used for persisting the settings. Unlike other PrefStores, this one is not // directly hooked up to the PrefService. scoped_refptr<PersistentPrefStore> store_;
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc index ddd20c7..7bb620d 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc
@@ -84,15 +84,15 @@ void UploadSplitItem(const std::string& key, const std::string& value) { split_items_.SetKey(key, base::Value(value)); - settings_service_.UploadItem( + settings_service_.SaveItem( SupervisedUserSettingsService::MakeSplitSettingKey(kSplitItemName, key), std::make_unique<base::Value>(value)); } void UploadAtomicItem(const std::string& value) { atomic_setting_value_ = std::make_unique<base::Value>(value); - settings_service_.UploadItem(kAtomicItemName, - std::make_unique<base::Value>(value)); + settings_service_.SaveItem(kAtomicItemName, + std::make_unique<base::Value>(value)); } void VerifySyncDataItem(syncer::SyncData sync_data) { @@ -122,6 +122,40 @@ settings_.reset(settings->DeepCopy()); } + // Check that a single website approval has been added correctly. + void CheckWebsiteApproval( + syncer::SyncChange::SyncChangeType expected_sync_change_type, + const std::string& expected_key) { + // Check that we are uploading sync data. + ASSERT_EQ(1u, sync_processor_->changes().size()); + syncer::SyncChange sync_change = sync_processor_->changes()[0]; + ASSERT_TRUE(sync_change.IsValid()); + EXPECT_EQ(expected_sync_change_type, sync_change.change_type()); + EXPECT_EQ( + sync_change.sync_data().GetSpecifics().managed_user_setting().name(), + expected_key); + EXPECT_EQ(absl::optional<base::Value>(true), + base::JSONReader::Read(sync_change.sync_data() + .GetSpecifics() + .managed_user_setting() + .value())); + + // It should also show up in local Sync data. + syncer::SyncDataList sync_data = settings_service_.GetAllSyncDataForTesting( + syncer::SUPERVISED_USER_SETTINGS); + for (const syncer::SyncData& sync_data_item : sync_data) { + if (sync_data_item.GetSpecifics().managed_user_setting().name().compare( + expected_key) == 0) { + EXPECT_EQ( + absl::optional<base::Value>(true), + base::JSONReader::Read( + sync_data_item.GetSpecifics().managed_user_setting().value())); + return; + } + } + FAIL() << "Expected key not found in local sync data"; + } + // testing::Test overrides: void SetUp() override { TestingPrefStore* pref_store = new TestingPrefStore; @@ -411,3 +445,26 @@ StartSyncing(sync_data); ASSERT_EQ(0u, sync_processor_->changes().size()); } + +TEST_F(SupervisedUserSettingsServiceTest, RecordLocalWebsiteApproval) { + // Record a website approval before sync is enabled. + settings_service_.RecordLocalWebsiteApproval("youtube.com"); + + // Uploading should produce changes when we start syncing. + StartSyncing(syncer::SyncDataList()); + CheckWebsiteApproval(syncer::SyncChange::ACTION_ADD, + "ContentPackManualBehaviorHosts:youtube.com"); + + // Uploading after we have started syncing should work too. + sync_processor_->changes().clear(); + settings_service_.RecordLocalWebsiteApproval("photos.google.com"); + CheckWebsiteApproval(syncer::SyncChange::ACTION_ADD, + "ContentPackManualBehaviorHosts:photos.google.com"); + + // Uploading an item with a previously seen key should create an UPDATE + // action. + sync_processor_->changes().clear(); + settings_service_.RecordLocalWebsiteApproval("youtube.com"); + CheckWebsiteApproval(syncer::SyncChange::ACTION_UPDATE, + "ContentPackManualBehaviorHosts:youtube.com"); +}
diff --git a/chrome/browser/supervised_user/web_approvals_manager.cc b/chrome/browser/supervised_user/web_approvals_manager.cc index f1a342f..6cd2974fd 100644 --- a/chrome/browser/supervised_user/web_approvals_manager.cc +++ b/chrome/browser/supervised_user/web_approvals_manager.cc
@@ -3,14 +3,23 @@ // found in the LICENSE file. #include "chrome/browser/supervised_user/web_approvals_manager.h" +#include <string> #include "base/bind.h" #include "base/callback.h" +#include "base/json/json_reader.h" #include "base/logging.h" +#include "base/values.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/supervised_user/android/website_parent_approval.h" #include "chrome/browser/supervised_user/permission_request_creator.h" +#include "chrome/browser/supervised_user/supervised_user_constants.h" +#include "chrome/browser/supervised_user/supervised_user_settings_service.h" +#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" #include "components/url_matcher/url_util.h" +#include "content/public/browser/web_contents.h" #include "url/gurl.h" #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -48,10 +57,14 @@ } std::move(callback).Run(true); #elif BUILDFLAG(IS_ANDROID) + SupervisedUserSettingsService* settings_service = + SupervisedUserSettingsServiceFactory::GetForKey( + Profile::FromBrowserContext(web_contents->GetBrowserContext()) + ->GetProfileKey()); WebsiteParentApproval::RequestLocalApproval( web_contents, url, base::BindOnce(&WebApprovalsManager::OnLocalApprovalRequestCompleted, - weak_ptr_factory_.GetWeakPtr())); + weak_ptr_factory_.GetWeakPtr(), settings_service, url)); std::move(callback).Run(true); #endif } @@ -123,8 +136,13 @@ } void WebApprovalsManager::OnLocalApprovalRequestCompleted( + SupervisedUserSettingsService* settings_service, + const GURL& url, bool request_approved) { - // TODO(crbug.com/1324945): write sync data, output metrics. + // TODO(crbug.com/1324945): output metrics. VLOG(0) << "Local URL approval final result: " << request_approved; - NOTIMPLEMENTED(); + + if (request_approved) { + settings_service->RecordLocalWebsiteApproval(url.host()); + } }
diff --git a/chrome/browser/supervised_user/web_approvals_manager.h b/chrome/browser/supervised_user/web_approvals_manager.h index 51bad64..3e10764 100644 --- a/chrome/browser/supervised_user/web_approvals_manager.h +++ b/chrome/browser/supervised_user/web_approvals_manager.h
@@ -15,6 +15,7 @@ class GURL; class PermissionRequestCreator; +class SupervisedUserSettingsService; namespace content { class WebContents; @@ -85,7 +86,10 @@ // Called to indicate that a URL access request has completed (either // successfully or not). - void OnLocalApprovalRequestCompleted(bool request_approved); + void OnLocalApprovalRequestCompleted( + SupervisedUserSettingsService* settings_service, + const GURL& url, + bool request_approved); // Stores remote approval request creators. // The creators are cleared during shutdown.
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index fd3c36b..446f40f1 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -97,7 +97,7 @@ // changed default theme assets, if you need themes to recreate their generated // images (which are cached), if you changed how missing values are // generated, or if you changed any constants. -const int kThemePackVersion = 101; +const int kThemePackVersion = 100; // IDs that are in the DataPack won't clash with the positive integer // uint16_t. kHeaderID should always have the maximum value because we want the @@ -1129,7 +1129,8 @@ {TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE, kColorWindowControlButtonBackgroundActive}, {TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_INACTIVE, - kColorWindowControlButtonBackgroundInactive}}; + kColorWindowControlButtonBackgroundInactive}, + }; for (const auto& entry : kThemePropertiesMap) { SkColor color;
diff --git a/chrome/browser/themes/theme_helper.cc b/chrome/browser/themes/theme_helper.cc index 0ea1acb..11a0b68 100644 --- a/chrome/browser/themes/theme_helper.cc +++ b/chrome/browser/themes/theme_helper.cc
@@ -38,6 +38,97 @@ // unpacked on the filesystem.) constexpr char kDefaultThemeGalleryID[] = "hkacjpbfdknhflllbcmjibkdeoafencn"; +// Returns an array of light and dark mode versions of the given color id +// Ex: [light mode, dark mode] +const std::array<SkColor, 2> GetTabGroupColors(int color_id) { + // Depending on UI variation enabled, dark mode saved group chip colors are + // calculated by blending the default dark mode toolbar color with the tab + // strip group colors at 24% or 48% alpha. + const SkColor default_dark_toolbar_color = + TP::GetDefaultColor(TP::COLOR_TOOLBAR, false, true); + float tab_group_chip_alpha = 0.24f; + + // Flat version of dark mode colors used in bookmarks bar to fill + // the buttons. + const SkColor kFlatGrey = SkColorSetRGB(0x5D, 0x5E, 0x62); + const SkColor kFlatBlue = SkColorSetRGB(0x49, 0x54, 0x68); + const SkColor kFlatRed = SkColorSetRGB(0x62, 0x4A, 0x4B); + const SkColor kFlatGreen = SkColorSetRGB(0x47, 0x59, 0x50); + const SkColor kFlatYellow = SkColorSetRGB(0x65, 0x5C, 0x44); + const SkColor kFlatCyan = SkColorSetRGB(0x45, 0x5D, 0x65); + const SkColor kFlatPurple = SkColorSetRGB(0x58, 0x4A, 0x68); + const SkColor kFlatPink = SkColorSetRGB(0x65, 0x4A, 0x5D); + const SkColor kFlatOrange = color_utils::AlphaBlend( + gfx::kGoogleOrange300, default_dark_toolbar_color, tab_group_chip_alpha); + + switch (color_id) { + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE: + case TP::COLOR_TAB_GROUP_DIALOG_BLUE: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE: + return {gfx::kGoogleBlue600, gfx::kGoogleBlue300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE: + return {gfx::kGoogleBlue050, kFlatBlue}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED: + case TP::COLOR_TAB_GROUP_DIALOG_RED: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED: + return {gfx::kGoogleRed600, gfx::kGoogleRed300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED: + return {gfx::kGoogleRed050, kFlatRed}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW: + case TP::COLOR_TAB_GROUP_DIALOG_YELLOW: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW: + return {gfx::kGoogleYellow600, gfx::kGoogleYellow300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW: + return {gfx::kGoogleYellow050, kFlatYellow}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN: + case TP::COLOR_TAB_GROUP_DIALOG_GREEN: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN: + return {gfx::kGoogleGreen700, gfx::kGoogleGreen300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN: + return {gfx::kGoogleGreen050, kFlatGreen}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK: + case TP::COLOR_TAB_GROUP_DIALOG_PINK: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK: + return {gfx::kGooglePink700, gfx::kGooglePink300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK: + return {gfx::kGooglePink050, kFlatPink}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE: + case TP::COLOR_TAB_GROUP_DIALOG_PURPLE: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE: + return {gfx::kGooglePurple500, gfx::kGooglePurple300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE: + return {gfx::kGooglePurple050, kFlatPurple}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN: + case TP::COLOR_TAB_GROUP_DIALOG_CYAN: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN: + return {gfx::kGoogleCyan900, gfx::kGoogleCyan300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN: + return {gfx::kGoogleCyan050, kFlatCyan}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE: + case TP::COLOR_TAB_GROUP_DIALOG_ORANGE: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE: + return {gfx::kGoogleOrange400, gfx::kGoogleOrange300}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE: + return {gfx::kGoogleOrange050, kFlatOrange}; + case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY: + return {gfx::kGoogleGrey100, kFlatGrey}; + case TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY: + case TP::COLOR_TAB_GROUP_DIALOG_GREY: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY: + case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY: + default: + return {gfx::kGoogleGrey700, gfx::kGoogleGrey300}; + } +} + SkColor IncreaseLightness(SkColor color, double percent) { color_utils::HSL result; color_utils::SkColorToHSL(color, &result); @@ -223,6 +314,10 @@ int id, bool incognito, const CustomThemeSupplier* theme_supplier) const { + if (TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY <= id && + id <= TP::MAX_COLOR_BOOKMARK_BAR) + return GetTabGroupColor(id, incognito, theme_supplier); + const absl::optional<SkColor> omnibox_color = GetOmniboxColor(id, incognito, theme_supplier); if (omnibox_color.has_value()) @@ -602,3 +697,32 @@ return absl::nullopt; } } + +SkColor ThemeHelper::GetTabGroupColor( + int id, + bool incognito, + const CustomThemeSupplier* theme_supplier) const { + // Deal with tab group colors in the tabstrip. + if (id <= TP::MAX_COLOR_TABSTRIP_INACTIVE) { + int tab_color_id = id < TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY + ? TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_ACTIVE + : TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_INACTIVE; + + return GetTabGroupColors(id)[color_utils::IsDark( + GetColor(tab_color_id, incognito, theme_supplier))]; + } + + // Deal with the rest of the tab group colors. + bool use_dark_mode_colors; + if (id >= TP::COLOR_TAB_GROUP_DIALOG_GREY && + id <= TP::MAX_COLOR_BOOKMARK_BAR) { + // To support custom themes, assume that the dark mode palette is more + // appropriate for bookmark chips, tab group dialog bubble, and context sub + // menu when the bookmark bar appears to be light text on dark bookmark bar. + use_dark_mode_colors = !color_utils::IsDark( + GetColor(TP::COLOR_BOOKMARK_TEXT, incognito, theme_supplier)); + } else { + use_dark_mode_colors = UseDarkModeColors(theme_supplier); + } + return GetTabGroupColors(id)[incognito || use_dark_mode_colors]; +}
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h index 14a6806..599ca7f 100644 --- a/chrome/browser/themes/theme_properties.h +++ b/chrome/browser/themes/theme_properties.h
@@ -179,6 +179,71 @@ // kThemePackVersion in browser_theme_pack.cc, or else themes will display // incorrectly. + // Note: All tab group color ids must be grouped together consecutively and + // grouped together by use (eg grouped by dialog, context menu etc). + // This permits range checking and reduces redundant code. If you change or + // add to any of the below color ids, change the relevant code in + // ThemeHelper. + + // The colors used for tab groups in the tabstrip. + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN, + COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN, + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, + // The colors used for tab groups in the bubble dialog view. + COLOR_TAB_GROUP_DIALOG_GREY, + COLOR_TAB_GROUP_DIALOG_BLUE, + COLOR_TAB_GROUP_DIALOG_RED, + COLOR_TAB_GROUP_DIALOG_YELLOW, + COLOR_TAB_GROUP_DIALOG_GREEN, + COLOR_TAB_GROUP_DIALOG_PINK, + COLOR_TAB_GROUP_DIALOG_PURPLE, + COLOR_TAB_GROUP_DIALOG_CYAN, + COLOR_TAB_GROUP_DIALOG_ORANGE, + // The colors used for tab groups in the context submenu. + COLOR_TAB_GROUP_CONTEXT_MENU_GREY, + COLOR_TAB_GROUP_CONTEXT_MENU_BLUE, + COLOR_TAB_GROUP_CONTEXT_MENU_RED, + COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW, + COLOR_TAB_GROUP_CONTEXT_MENU_GREEN, + COLOR_TAB_GROUP_CONTEXT_MENU_PINK, + COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE, + COLOR_TAB_GROUP_CONTEXT_MENU_CYAN, + COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE, + // The colors used for saved tab group chips on the bookmark bar. + COLOR_TAB_GROUP_BOOKMARK_BAR_GREY, + COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE, + COLOR_TAB_GROUP_BOOKMARK_BAR_RED, + COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW, + COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN, + COLOR_TAB_GROUP_BOOKMARK_BAR_PINK, + COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE, + COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN, + COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, + // If additional colors are ever added, update these references to those + // colors + MAX_COLOR_TABSTRIP_INACTIVE = + COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, + MAX_COLOR_BOOKMARK_BAR = COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, + + // /!\ If you make any changes to this enum, you must also increment + // kThemePackVersion in browser_theme_pack.cc, or else themes will display + // incorrectly. + // Calculated representative colors for the background of window control // buttons. COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE,
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index 4c3ae66..5d2c348a9 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -212,6 +212,79 @@ kColorTabForegroundInactiveFrameActive}, {TP::COLOR_TAB_FOREGROUND_INACTIVE_FRAME_INACTIVE, kColorTabForegroundInactiveFrameInactive}, + // The colors used for tab groups in the tabstrip. + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE, + kColorTabGroupTabStripFrameActiveBlue}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN, + kColorTabGroupTabStripFrameActiveCyan}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN, + kColorTabGroupTabStripFrameActiveGreen}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY, + kColorTabGroupTabStripFrameActiveGrey}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE, + kColorTabGroupTabStripFrameActiveOrange}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK, + kColorTabGroupTabStripFrameActivePink}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE, + kColorTabGroupTabStripFrameActivePurple}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED, + kColorTabGroupTabStripFrameActiveRed}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW, + kColorTabGroupTabStripFrameActiveYellow}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE, + kColorTabGroupTabStripFrameInactiveBlue}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN, + kColorTabGroupTabStripFrameInactiveCyan}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN, + kColorTabGroupTabStripFrameInactiveGreen}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY, + kColorTabGroupTabStripFrameInactiveGrey}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, + kColorTabGroupTabStripFrameInactiveOrange}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK, + kColorTabGroupTabStripFrameInactivePink}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE, + kColorTabGroupTabStripFrameInactivePurple}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED, + kColorTabGroupTabStripFrameInactiveRed}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW, + kColorTabGroupTabStripFrameInactiveYellow}, + // The colors used for tab groups in the bubble dialog view. + {TP::COLOR_TAB_GROUP_DIALOG_BLUE, kColorTabGroupDialogBlue}, + {TP::COLOR_TAB_GROUP_DIALOG_CYAN, kColorTabGroupDialogCyan}, + {TP::COLOR_TAB_GROUP_DIALOG_GREEN, kColorTabGroupDialogGreen}, + {TP::COLOR_TAB_GROUP_DIALOG_GREY, kColorTabGroupDialogGrey}, + {TP::COLOR_TAB_GROUP_DIALOG_ORANGE, kColorTabGroupDialogOrange}, + {TP::COLOR_TAB_GROUP_DIALOG_PINK, kColorTabGroupDialogPink}, + {TP::COLOR_TAB_GROUP_DIALOG_PURPLE, kColorTabGroupDialogPurple}, + {TP::COLOR_TAB_GROUP_DIALOG_RED, kColorTabGroupDialogRed}, + {TP::COLOR_TAB_GROUP_DIALOG_YELLOW, kColorTabGroupDialogYellow}, + // The colors used for tab groups in the context submenu. + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE, kColorTabGroupContextMenuBlue}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN, kColorTabGroupContextMenuCyan}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN, kColorTabGroupContextMenuGreen}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY, kColorTabGroupContextMenuGrey}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK, kColorTabGroupContextMenuPink}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE, + kColorTabGroupContextMenuPurple}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE, + kColorTabGroupContextMenuOrange}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED, kColorTabGroupContextMenuRed}, + {TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW, + kColorTabGroupContextMenuYellow}, + // The colors used for saved tab group chips on the bookmark bar. + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE, kColorTabGroupBookmarkBarBlue}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN, kColorTabGroupBookmarkBarCyan}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN, kColorTabGroupBookmarkBarGreen}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY, kColorTabGroupBookmarkBarGrey}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, + kColorTabGroupBookmarkBarOrange}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK, kColorTabGroupBookmarkBarPink}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE, + kColorTabGroupBookmarkBarPurple}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED, kColorTabGroupBookmarkBarRed}, + {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW, + kColorTabGroupBookmarkBarYellow}, {TP::COLOR_TAB_STROKE_FRAME_ACTIVE, kColorTabStrokeFrameActive}, {TP::COLOR_TAB_STROKE_FRAME_INACTIVE, kColorTabStrokeFrameInactive}, // Toolbar and associated colors.
diff --git a/chrome/browser/themes/theme_service_test_utils.h b/chrome/browser/themes/theme_service_test_utils.h index e2f2bf7..dc06778 100644 --- a/chrome/browser/themes/theme_service_test_utils.h +++ b/chrome/browser/themes/theme_service_test_utils.h
@@ -27,6 +27,7 @@ {ThemeProperties::COLOR_OMNIBOX_RESULTS_TEXT_SECONDARY_SELECTED, 1}, {ThemeProperties::COLOR_STATUS_BUBBLE_INACTIVE, 1}, {ThemeProperties::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_INACTIVE, 1}, + {ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, 1}, {ThemeProperties::COLOR_TAB_STROKE_FRAME_INACTIVE, 1}, {ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR_FRAME_INACTIVE, 1}, {ThemeProperties::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_INACTIVE, 1}});
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index a2af5f5..51a04a5 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1054,9 +1054,6 @@ <message name="IDS_PRIVACY_SANDBOX_NOTICE_DESCRIPTION_THREE" desc="A conclusion paragraph for the entire page. It sits beneath the “More control over the ads you see” subtitle but it’s no more associated with that topic than “Limit sharing between sites”.* “in Chrome settings”: The URL is chrome://settings/privacySandbox. We don’t make it a live link because we need the users to stay in this moment until they make a choice."> You can learn more about these features in Chrome settings. </message> - <message name="IDS_PRIVACY_SANDBOX_NOTICE_SHEET_CONTENT_DESCRIPTION" desc="The content description for the Privacy Sandbox prompt bottom sheet. Read as accessibility string when tapping on the bottom sheet."> - Privacy Sandbox prompt - </message> <message name="IDS_PRIVACY_SANDBOX_NOTICE_SHEET_OPENED_HALF" desc="The accessibility string read when the Privacy Sandbox prompt bottom sheet is half opened."> Privacy Sandbox prompt opened at half height </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_SANDBOX_NOTICE_SHEET_CONTENT_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_SANDBOX_NOTICE_SHEET_CONTENT_DESCRIPTION.png.sha1 deleted file mode 100644 index 50dbffa..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_SANDBOX_NOTICE_SHEET_CONTENT_DESCRIPTION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9f27660570f53ee8dc580168160c1d2dbb8126b1 \ No newline at end of file
diff --git a/chrome/browser/ui/ash/ash_web_view_impl.cc b/chrome/browser/ui/ash/ash_web_view_impl.cc index 2c877dd..268355f 100644 --- a/chrome/browser/ui/ash/ash_web_view_impl.cc +++ b/chrome/browser/ui/ash/ash_web_view_impl.cc
@@ -136,7 +136,7 @@ content::MediaResponseCallback callback) { if (!params_.can_record_media) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>()); return;
diff --git a/chrome/browser/ui/ash/assistant/assistant_timers_browsertest.cc b/chrome/browser/ui/ash/assistant/assistant_timers_browsertest.cc index c1cdb2c..8a63195 100644 --- a/chrome/browser/ui/ash/assistant/assistant_timers_browsertest.cc +++ b/chrome/browser/ui/ash/assistant/assistant_timers_browsertest.cc
@@ -305,9 +305,20 @@ }); } +// TODO(crbug.com/1334910): Disable AssistantTimersBrowserTest. +// ShouldTickNotificationsAtRegularIntervals on chromeos, +// because it is failing on linux-chromeos-chrome. +#if BUILDFLAG(IS_CHROMEOS) +#define MAYBE_ShouldTickNotificationsAtRegularIntervals \ + DISABLED_ShouldTickNotificationsAtRegularIntervals +#else +#define MAYBE_ShouldTickNotificationsAtRegularIntervals \ + ShouldTickNotificationsAtRegularIntervals +#endif + // Verifies that timer notifications are ticked at regular intervals. IN_PROC_BROWSER_TEST_F(AssistantTimersBrowserTest, - ShouldTickNotificationsAtRegularIntervals) { + MAYBE_ShouldTickNotificationsAtRegularIntervals) { // Observe notifications. MockMessageCenterObserver mock; base::ScopedObservation<MessageCenter, MessageCenterObserver>
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm index 8bc0261..0b6a8b9b 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm
@@ -30,7 +30,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/image_model.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/color/color_provider.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_util_mac.h" @@ -346,11 +345,11 @@ // Set the icon of the group to the group color circle. AppController* controller = base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - const auto& color_provider = [controller lastActiveColorProvider]; - const ui::ColorId color_id = - GetTabGroupContextMenuColorId(group->visual_data.color()); + const auto& theme = [controller lastActiveThemeProvider]; + const int color_id = + GetTabGroupContextMenuColorIdDeprecated(group->visual_data.color()); gfx::ImageSkia group_icon = gfx::CreateVectorIcon( - kTabGroupIcon, gfx::kFaviconSize, color_provider.GetColor(color_id)); + kTabGroupIcon, gfx::kFaviconSize, theme.GetColor(color_id)); // Create the submenu. base::scoped_nsobject<NSMenu> submenu([[NSMenu alloc] init]);
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm index 55e367c1..d386d34 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
@@ -68,6 +68,7 @@ protected: void SetUp() override { BrowserWithTestWindowTest::SetUp(); + appController_.reset([[AppController alloc] init]); [appController_ setLastProfileForTesting:profile()]; previousApplicationDelegate_ = [NSApp delegate];
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h index 5db6f618c..3893e98 100644 --- a/chrome/browser/ui/color/chrome_color_id.h +++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -306,54 +306,93 @@ E(kColorTabHoverCardForeground, \ ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND) \ /* The colors used for tab groups in the tabstrip. */ \ - E_CPONLY(kColorTabGroupTabStripFrameActiveGrey) \ - E_CPONLY(kColorTabGroupTabStripFrameActiveBlue) \ - E_CPONLY(kColorTabGroupTabStripFrameActiveRed) \ - E_CPONLY(kColorTabGroupTabStripFrameActiveYellow) \ - E_CPONLY(kColorTabGroupTabStripFrameActiveGreen) \ - E_CPONLY(kColorTabGroupTabStripFrameActivePink) \ - E_CPONLY(kColorTabGroupTabStripFrameActivePurple) \ - E_CPONLY(kColorTabGroupTabStripFrameActiveCyan) \ - E_CPONLY(kColorTabGroupTabStripFrameActiveOrange) \ - E_CPONLY(kColorTabGroupTabStripFrameInactiveGrey) \ - E_CPONLY(kColorTabGroupTabStripFrameInactiveBlue) \ - E_CPONLY(kColorTabGroupTabStripFrameInactiveRed) \ - E_CPONLY(kColorTabGroupTabStripFrameInactiveYellow) \ - E_CPONLY(kColorTabGroupTabStripFrameInactiveGreen) \ - E_CPONLY(kColorTabGroupTabStripFrameInactivePink) \ - E_CPONLY(kColorTabGroupTabStripFrameInactivePurple) \ - E_CPONLY(kColorTabGroupTabStripFrameInactiveCyan) \ - E_CPONLY(kColorTabGroupTabStripFrameInactiveOrange) \ + E(kColorTabGroupTabStripFrameActiveGrey, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY) \ + E(kColorTabGroupTabStripFrameActiveBlue, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE) \ + E(kColorTabGroupTabStripFrameActiveRed, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED) \ + E(kColorTabGroupTabStripFrameActiveYellow, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW) \ + E(kColorTabGroupTabStripFrameActiveGreen, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN) \ + E(kColorTabGroupTabStripFrameActivePink, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK) \ + E(kColorTabGroupTabStripFrameActivePurple, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE) \ + E(kColorTabGroupTabStripFrameActiveCyan, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN) \ + E(kColorTabGroupTabStripFrameActiveOrange, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE) \ + E(kColorTabGroupTabStripFrameInactiveGrey, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY) \ + E(kColorTabGroupTabStripFrameInactiveBlue, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE) \ + E(kColorTabGroupTabStripFrameInactiveRed, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED) \ + E(kColorTabGroupTabStripFrameInactiveYellow, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW) \ + E(kColorTabGroupTabStripFrameInactiveGreen, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN) \ + E(kColorTabGroupTabStripFrameInactivePink, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK) \ + E(kColorTabGroupTabStripFrameInactivePurple, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE) \ + E(kColorTabGroupTabStripFrameInactiveCyan, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN) \ + E(kColorTabGroupTabStripFrameInactiveOrange, \ + ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE) \ /* The colors used for tab groups in the bubble dialog view. */ \ - E_CPONLY(kColorTabGroupDialogGrey) \ - E_CPONLY(kColorTabGroupDialogBlue) \ - E_CPONLY(kColorTabGroupDialogRed) \ - E_CPONLY(kColorTabGroupDialogYellow) \ - E_CPONLY(kColorTabGroupDialogGreen) \ - E_CPONLY(kColorTabGroupDialogPink) \ - E_CPONLY(kColorTabGroupDialogPurple) \ - E_CPONLY(kColorTabGroupDialogCyan) \ - E_CPONLY(kColorTabGroupDialogOrange) \ + E(kColorTabGroupDialogGrey, ThemeProperties::COLOR_TAB_GROUP_DIALOG_GREY) \ + E(kColorTabGroupDialogBlue, ThemeProperties::COLOR_TAB_GROUP_DIALOG_BLUE) \ + E(kColorTabGroupDialogRed, ThemeProperties::COLOR_TAB_GROUP_DIALOG_RED) \ + E(kColorTabGroupDialogYellow, \ + ThemeProperties::COLOR_TAB_GROUP_DIALOG_YELLOW) \ + E(kColorTabGroupDialogGreen, ThemeProperties::COLOR_TAB_GROUP_DIALOG_GREEN) \ + E(kColorTabGroupDialogPink, ThemeProperties::COLOR_TAB_GROUP_DIALOG_PINK) \ + E(kColorTabGroupDialogPurple, \ + ThemeProperties::COLOR_TAB_GROUP_DIALOG_PURPLE) \ + E(kColorTabGroupDialogCyan, ThemeProperties::COLOR_TAB_GROUP_DIALOG_CYAN) \ + E(kColorTabGroupDialogOrange, \ + ThemeProperties::COLOR_TAB_GROUP_DIALOG_ORANGE) \ /* The colors used for tab groups in the context submenu. */ \ - E_CPONLY(kColorTabGroupContextMenuBlue) \ - E_CPONLY(kColorTabGroupContextMenuCyan) \ - E_CPONLY(kColorTabGroupContextMenuGreen) \ - E_CPONLY(kColorTabGroupContextMenuGrey) \ - E_CPONLY(kColorTabGroupContextMenuOrange) \ - E_CPONLY(kColorTabGroupContextMenuPink) \ - E_CPONLY(kColorTabGroupContextMenuPurple) \ - E_CPONLY(kColorTabGroupContextMenuRed) \ - E_CPONLY(kColorTabGroupContextMenuYellow) \ + E(kColorTabGroupContextMenuBlue, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE) \ + E(kColorTabGroupContextMenuCyan, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN) \ + E(kColorTabGroupContextMenuGreen, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN) \ + E(kColorTabGroupContextMenuGrey, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_GREY) \ + E(kColorTabGroupContextMenuOrange, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE) \ + E(kColorTabGroupContextMenuPink, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_PINK) \ + E(kColorTabGroupContextMenuPurple, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE) \ + E(kColorTabGroupContextMenuRed, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_RED) \ + E(kColorTabGroupContextMenuYellow, \ + ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW) \ /* The colors used for saved tab group chips on the bookmark bar. */ \ - E_CPONLY(kColorTabGroupBookmarkBarGrey) \ - E_CPONLY(kColorTabGroupBookmarkBarBlue) \ - E_CPONLY(kColorTabGroupBookmarkBarRed) \ - E_CPONLY(kColorTabGroupBookmarkBarYellow) \ - E_CPONLY(kColorTabGroupBookmarkBarGreen) \ - E_CPONLY(kColorTabGroupBookmarkBarPink) \ - E_CPONLY(kColorTabGroupBookmarkBarPurple) \ - E_CPONLY(kColorTabGroupBookmarkBarCyan) \ - E_CPONLY(kColorTabGroupBookmarkBarOrange) \ + E(kColorTabGroupBookmarkBarGrey, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY) \ + E(kColorTabGroupBookmarkBarBlue, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE) \ + E(kColorTabGroupBookmarkBarRed, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_RED) \ + E(kColorTabGroupBookmarkBarYellow, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW) \ + E(kColorTabGroupBookmarkBarGreen, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN) \ + E(kColorTabGroupBookmarkBarPink, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK) \ + E(kColorTabGroupBookmarkBarPurple, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE) \ + E(kColorTabGroupBookmarkBarCyan, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN) \ + E(kColorTabGroupBookmarkBarOrange, \ + ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE) \ E(kColorTabStrokeFrameActive, \ ThemeProperties::COLOR_TAB_STROKE_FRAME_ACTIVE) \ E(kColorTabStrokeFrameInactive, \
diff --git a/chrome/browser/ui/tabs/tab_group_theme.cc b/chrome/browser/ui/tabs/tab_group_theme.cc index 5ad43a7..728572d 100644 --- a/chrome/browser/ui/tabs/tab_group_theme.cc +++ b/chrome/browser/ui/tabs/tab_group_theme.cc
@@ -13,37 +13,37 @@ using TP = ThemeProperties; using TabGroupColorId = tab_groups::TabGroupColorId; -ui::ColorId GetTabGroupTabStripColorId(TabGroupColorId group_color_id, - bool active_frame) { +int GetTabGroupTabStripColorId(TabGroupColorId group_color_id, + bool active_frame) { static constexpr auto group_id_map = base::MakeFixedFlatMap<TabGroupColorId, std::array<int, 2>>({ {TabGroupColorId::kGrey, - {kColorTabGroupTabStripFrameInactiveGrey, - kColorTabGroupTabStripFrameActiveGrey}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY}}, {TabGroupColorId::kBlue, - {kColorTabGroupTabStripFrameInactiveGrey, - kColorTabGroupTabStripFrameActiveBlue}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE}}, {TabGroupColorId::kRed, - {kColorTabGroupTabStripFrameInactiveRed, - kColorTabGroupTabStripFrameActiveRed}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED}}, {TabGroupColorId::kYellow, - {kColorTabGroupTabStripFrameInactiveYellow, - kColorTabGroupTabStripFrameActiveYellow}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW}}, {TabGroupColorId::kGreen, - {kColorTabGroupTabStripFrameInactiveGreen, - kColorTabGroupTabStripFrameActiveGreen}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN}}, {TabGroupColorId::kPink, - {kColorTabGroupTabStripFrameInactivePink, - kColorTabGroupTabStripFrameActivePink}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK}}, {TabGroupColorId::kPurple, - {kColorTabGroupTabStripFrameInactivePink, - kColorTabGroupTabStripFrameActivePurple}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE}}, {TabGroupColorId::kCyan, - {kColorTabGroupTabStripFrameInactiveCyan, - kColorTabGroupTabStripFrameActiveCyan}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN}}, {TabGroupColorId::kOrange, - {kColorTabGroupTabStripFrameInactiveOrange, - kColorTabGroupTabStripFrameActiveOrange}}, + {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, + TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE}}, }); return group_id_map.at(group_color_id)[active_frame]; @@ -85,18 +85,18 @@ return group_id_map.at(group_color_id)[active_frame]; } -ui::ColorId GetTabGroupDialogColorId(TabGroupColorId group_color_id) { +int GetTabGroupDialogColorId(TabGroupColorId group_color_id) { static constexpr auto group_id_map = base::MakeFixedFlatMap<TabGroupColorId, int>({ - {TabGroupColorId::kGrey, kColorTabGroupDialogGrey}, - {TabGroupColorId::kBlue, kColorTabGroupDialogBlue}, - {TabGroupColorId::kRed, kColorTabGroupDialogRed}, - {TabGroupColorId::kYellow, kColorTabGroupDialogYellow}, - {TabGroupColorId::kGreen, kColorTabGroupDialogGreen}, - {TabGroupColorId::kPink, kColorTabGroupDialogPink}, - {TabGroupColorId::kPurple, kColorTabGroupDialogPurple}, - {TabGroupColorId::kCyan, kColorTabGroupDialogCyan}, - {TabGroupColorId::kOrange, kColorTabGroupDialogOrange}, + {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_DIALOG_GREY}, + {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_DIALOG_BLUE}, + {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_DIALOG_RED}, + {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_DIALOG_YELLOW}, + {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_DIALOG_GREEN}, + {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_DIALOG_PINK}, + {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_DIALOG_PURPLE}, + {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_DIALOG_CYAN}, + {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_DIALOG_ORANGE}, }); return group_id_map.at(group_color_id); @@ -119,19 +119,35 @@ return group_id_map.at(group_color_id); } -ui::ColorId GetTabGroupBookmarkColorId( - tab_groups::TabGroupColorId group_color_id) { +int GetTabGroupContextMenuColorIdDeprecated(TabGroupColorId group_color_id) { static constexpr auto group_id_map = base::MakeFixedFlatMap<TabGroupColorId, int>({ - {TabGroupColorId::kGrey, kColorTabGroupBookmarkBarGrey}, - {TabGroupColorId::kBlue, kColorTabGroupBookmarkBarBlue}, - {TabGroupColorId::kRed, kColorTabGroupBookmarkBarRed}, - {TabGroupColorId::kYellow, kColorTabGroupBookmarkBarYellow}, - {TabGroupColorId::kGreen, kColorTabGroupBookmarkBarGreen}, - {TabGroupColorId::kPink, kColorTabGroupBookmarkBarPink}, - {TabGroupColorId::kPurple, kColorTabGroupBookmarkBarPurple}, - {TabGroupColorId::kCyan, kColorTabGroupBookmarkBarCyan}, - {TabGroupColorId::kOrange, kColorTabGroupBookmarkBarOrange}, + {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY}, + {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE}, + {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED}, + {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW}, + {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN}, + {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK}, + {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE}, + {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN}, + {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE}, + }); + + return group_id_map.at(group_color_id); +} + +int GetTabGroupBookmarkColorId(tab_groups::TabGroupColorId group_color_id) { + static constexpr auto group_id_map = + base::MakeFixedFlatMap<TabGroupColorId, int>({ + {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY}, + {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE}, + {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED}, + {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW}, + {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN}, + {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK}, + {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE}, + {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN}, + {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE}, }); return group_id_map.at(group_color_id);
diff --git a/chrome/browser/ui/tabs/tab_group_theme.h b/chrome/browser/ui/tabs/tab_group_theme.h index 2c56bd5..be5a1ed 100644 --- a/chrome/browser/ui/tabs/tab_group_theme.h +++ b/chrome/browser/ui/tabs/tab_group_theme.h
@@ -8,21 +8,23 @@ #include "components/tab_groups/tab_group_color.h" #include "ui/color/color_id.h" -ui::ColorId GetTabGroupTabStripColorId( - tab_groups::TabGroupColorId group_color_id, - bool active_frame); +int GetTabGroupTabStripColorId(tab_groups::TabGroupColorId group_color_id, + bool active_frame); ui::ColorId GetThumbnailTabStripTabGroupColorId( tab_groups::TabGroupColorId group_color_id, bool active_frame); -ui::ColorId GetTabGroupDialogColorId( - tab_groups::TabGroupColorId group_color_id); +int GetTabGroupDialogColorId(tab_groups::TabGroupColorId group_color_id); ui::ColorId GetTabGroupContextMenuColorId( tab_groups::TabGroupColorId group_color_id); -ui::ColorId GetTabGroupBookmarkColorId( +// TODO(crbug.com/1292029): Remove this function which returns color id for +// ThemeService, not for ColorProvider. +int GetTabGroupContextMenuColorIdDeprecated( tab_groups::TabGroupColorId group_color_id); +int GetTabGroupBookmarkColorId(tab_groups::TabGroupColorId group_color_id); + #endif // CHROME_BROWSER_UI_TABS_TAB_GROUP_THEME_H_
diff --git a/chrome/browser/ui/view_ids.h b/chrome/browser/ui/view_ids.h index 76b6815..0a4ad745 100644 --- a/chrome/browser/ui/view_ids.h +++ b/chrome/browser/ui/view_ids.h
@@ -99,6 +99,9 @@ // The Download shelf. VIEW_ID_DOWNLOAD_SHELF, + // The header in the App Identity Update dialog. + VIEW_ID_APP_IDENTITY_UPDATE_HEADER, + // Used in chrome/browser/ui/cocoa/view_id_util_browsertest.mm. // If you add new ids, make sure the above test passes. VIEW_ID_PREDEFINED_COUNT,
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc index 1acd818e..0d5cf2e 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc
@@ -121,16 +121,16 @@ } void SavedTabGroupButton::OnPaintBackground(gfx::Canvas* canvas) { - const ui::ColorProvider* const cp = GetColorProvider(); + const ui::ThemeProvider* const tp = GetThemeProvider(); gfx::PointF center_point_f = gfx::PointF(width() / 2, height() / 2); gfx::RectF rect_f = gfx::RectF(width(), height()); rect_f.Inset(1.0f); // Relies on logic in theme_helper.cc to determine dark/light palette. SkColor background_color = - cp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); + tp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); SkColor text_and_outline_color = - cp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); + tp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); SetEnabledTextColors(text_and_outline_color); // Draw background. @@ -176,11 +176,11 @@ // We don't always have a theme provider (ui tests, for example). SkColor text_color = gfx::kPlaceholderColor; - const ui::ColorProvider* const cp = GetColorProvider(); - if (cp) { + const ui::ThemeProvider* const tp = GetThemeProvider(); + if (tp) { SkColor background_color = - cp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); - text_color = cp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); + tp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); + text_color = tp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); text_color = color_utils::PickGoogleColor( text_color, background_color, color_utils::kMinimumReadableContrastRatio);
diff --git a/chrome/browser/ui/views/tabs/color_picker_view.cc b/chrome/browser/ui/views/tabs/color_picker_view.cc index 75a4f024..7ea92f03 100644 --- a/chrome/browser/ui/views/tabs/color_picker_view.cc +++ b/chrome/browser/ui/views/tabs/color_picker_view.cc
@@ -150,7 +150,7 @@ DCHECK_EQ(bounds.width(), bounds.height()); const SkColor color = - GetColorProvider()->GetColor(GetTabGroupDialogColorId(color_id_)); + GetThemeProvider()->GetColor(GetTabGroupDialogColorId(color_id_)); cc::PaintFlags flags; flags.setStyle(cc::PaintFlags::kFill_Style);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 995bf8c..5e00e54 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1601,7 +1601,7 @@ SkColor TabStrip::GetPaintedGroupColor( const tab_groups::TabGroupColorId& color_id) const { - return GetColorProvider()->GetColor( + return GetThemeProvider()->GetColor( GetTabGroupTabStripColorId(color_id, ShouldPaintAsActiveFrame())); }
diff --git a/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.cc b/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.cc index 866df25..d7308ac0 100644 --- a/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.cc +++ b/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h" #include "chrome/browser/web_applications/web_app_callback_app_identity.h" @@ -88,8 +89,11 @@ DISTANCE_CONTROL_LIST_VERTICAL))) .AddChildren( views::Builder<views::Label>() + .SetID(VIEW_ID_APP_IDENTITY_UPDATE_HEADER) .SetTextContext(views::style::CONTEXT_LABEL) - .SetText(l10n_util::GetStringUTF16(IDS_WEBAPP_UPDATE_EXPLANATION)) + .SetText(icon_change ? l10n_util::GetStringUTF16( + IDS_WEBAPP_UPDATE_EXPLANATION) + : std::u16string()) .SetHorizontalAlignment(gfx::ALIGN_LEFT) .SetMultiLine(true), views::Builder<views::TableLayoutView>()
diff --git a/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view_browsertest.cc index dd13125..6a98955 100644 --- a/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view_browsertest.cc
@@ -8,13 +8,28 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/test/test_browser_dialog.h" +#include "chrome/browser/ui/view_ids.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/browser/web_applications/web_app_callback_app_identity.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/test/browser_test.h" #include "ui/gfx/image/image_skia.h" +#include "ui/views/controls/label.h" +#include "ui/views/test/widget_test.h" #include "ui/views/widget/any_widget_observer.h" +#include "ui/views/widget/root_view.h" + +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/shell.h" +#endif + +namespace { + +// The length of the App Identity Update dialog explanation message. +constexpr int kMessageHeaderLength = 88; + +} // namespace class WebAppIdentityUpdateConfirmationViewBrowserTest : public DialogBrowserTest { @@ -36,21 +51,75 @@ void ShowUi(const std::string& name) override { gfx::ImageSkia image; auto* bitmap = image.bitmap(); + std::u16string old_name = u"Old App Title"; + std::u16string new_name = title_change_ ? u"New App Title" : old_name; chrome::ShowWebAppIdentityUpdateDialog( - app_id_, true, false, u"Old App Title", u"New App Title", *bitmap, + app_id_, title_change_, icon_change_, old_name, new_name, *bitmap, *bitmap, browser()->tab_strip_model()->GetActiveWebContents(), base::DoNothing()); } + bool VerifyUi() override { + if (!DialogBrowserTest::VerifyUi()) + return false; + + views::Widget::Widgets widgets; +#if BUILDFLAG(IS_CHROMEOS_ASH) + for (aura::Window* root_window : ash::Shell::GetAllRootWindows()) + views::Widget::GetAllChildWidgets(root_window, &widgets); +#else + widgets = views::test::WidgetTest::GetAllWidgets(); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + + for (views::Widget* widget : widgets) { + if (!widget->GetRootView()) + continue; + views::View* view = widget->GetRootView()->GetViewByID( + VIEW_ID_APP_IDENTITY_UPDATE_HEADER); + if (view) { + views::Label* label = (views::Label*)view; + return (icon_change_ ? kMessageHeaderLength : 0) == + label->GetText().size(); + } + } + + // The correct view was not found. + return false; + } + protected: raw_ptr<web_app::WebAppProvider> provider_ = nullptr; + // Whether the UI should show that the title has changed. + bool title_change_ = true; + + // Whether the UI should show that the app icon has changed. + bool icon_change_ = true; + std::string app_id_; }; IN_PROC_BROWSER_TEST_F(WebAppIdentityUpdateConfirmationViewBrowserTest, - InvokeUi_default) { + InvokeUi_title_change) { app_id_ = "TestAppIdentity"; + title_change_ = true; + icon_change_ = false; + ShowAndVerifyUi(); +} + +IN_PROC_BROWSER_TEST_F(WebAppIdentityUpdateConfirmationViewBrowserTest, + InvokeUi_icon_change) { + app_id_ = "TestAppIdentity"; + title_change_ = false; + icon_change_ = true; + ShowAndVerifyUi(); +} + +IN_PROC_BROWSER_TEST_F(WebAppIdentityUpdateConfirmationViewBrowserTest, + InvokeUi_both_change) { + app_id_ = "TestAppIdentity"; + title_change_ = true; + icon_change_ = true; ShowAndVerifyUi(); }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index 0ca5602..2ac094eb 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -106,17 +106,15 @@ PrintPreviewUI::TestDelegate* g_test_delegate = nullptr; void StopWorker(int document_cookie) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (document_cookie <= 0) return; scoped_refptr<PrintQueriesQueue> queue = g_browser_process->print_job_manager()->queue(); std::unique_ptr<PrinterQuery> printer_query = queue->PopPrinterQuery(document_cookie); - if (printer_query) { - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&PrinterQuery::StopWorker, std::move(printer_query))); - } + if (printer_query) + printer_query->StopWorker(); } bool IsValidPageNumber(uint32_t page_number, uint32_t page_count) {
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc index 80901ce..556af552 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -536,13 +536,16 @@ app->paused = IsPaused(web_app->app_id()); // Add the intent filters for PWAs. - base::Extend(app->intent_filters, - apps_util::CreateIntentFiltersForWebApp( - web_app->app_id(), IsNoteTakingWebApp(*web_app), - registrar().GetAppScope(web_app->app_id()), - registrar().GetAppShareTarget(web_app->app_id()), - provider_->os_integration_manager().GetEnabledFileHandlers( - web_app->app_id()))); + base::Extend( + app->intent_filters, + apps_util::CreateIntentFiltersForWebApp( + web_app->app_id(), registrar().GetAppScope(web_app->app_id()), + registrar().GetAppShareTarget(web_app->app_id()), + provider_->os_integration_manager().GetEnabledFileHandlers( + web_app->app_id()))); + + if (IsNoteTakingWebApp(*web_app)) + app->intent_filters.push_back(apps_util::CreateNoteTakingFilter()); #if BUILDFLAG(IS_CHROMEOS_ASH) if (web_app->app_id() == crostini::kCrostiniTerminalSystemAppId) { @@ -626,13 +629,16 @@ : apps::mojom::OptionalBool::kFalse; // Add the intent filters for PWAs. - base::Extend(app->intent_filters, - apps_util::CreateWebAppIntentFilters( - web_app->app_id(), IsNoteTakingWebApp(*web_app), - registrar().GetAppScope(web_app->app_id()), - registrar().GetAppShareTarget(web_app->app_id()), - provider_->os_integration_manager().GetEnabledFileHandlers( - web_app->app_id()))); + base::Extend( + app->intent_filters, + apps_util::CreateWebAppIntentFilters( + web_app->app_id(), registrar().GetAppScope(web_app->app_id()), + registrar().GetAppShareTarget(web_app->app_id()), + provider_->os_integration_manager().GetEnabledFileHandlers( + web_app->app_id()))); + + if (IsNoteTakingWebApp(*web_app)) + app->intent_filters.push_back(apps_util::CreateNoteTakingFilterMojom()); #if BUILDFLAG(IS_CHROMEOS_ASH) if (web_app->app_id() == crostini::kCrostiniTerminalSystemAppId) {
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc index 791a05c..da7717c6 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc
@@ -549,8 +549,17 @@ .AwaitNextRegistration(url, RegistrationResultCode::kTimeout); } +// crbug.com/1334849: All/ExternallyManagedBrowserTestWithPrefMigrationRead. +// ReinstallPolicyAppWithLocallyInstalledApp/1 is failing on Mac builders. +#if BUILDFLAG(IS_MAC) +#define MAYBE_ReinstallPolicyAppWithLocallyInstalledApp \ + DISABLED_ReinstallPolicyAppWithLocallyInstalledApp +#else +#define MAYBE_ReinstallPolicyAppWithLocallyInstalledApp \ + ReinstallPolicyAppWithLocallyInstalledApp +#endif IN_PROC_BROWSER_TEST_P(ExternallyManagedBrowserTestWithPrefMigrationRead, - ReinstallPolicyAppWithLocallyInstalledApp) { + MAYBE_ReinstallPolicyAppWithLocallyInstalledApp) { ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/banners/manifest_test_page.html"));
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto index 776f0f08..3161cbb 100644 --- a/chrome/browser/web_applications/proto/web_app.proto +++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -125,7 +125,7 @@ // app_id is a hash of launch_url. app_id is the client tag for sync system. // app_id is the storage key in ModelTypeStore. message WebAppProto { - reserved "is_in_sync_install"; + reserved "is_in_sync_install", "is_placeholder"; reserved 53; // Synced data. It is replicated across all devices with WEB_APPS. @@ -343,6 +343,9 @@ repeated ManagementToExternalConfigInfo management_to_external_config_info = 52; + // Stores whether the app is a placeholder app or not. + // optional bool is_placeholder = 53; + // The amount of storage (in bytes) used by the app and its related data. optional uint64 app_size_in_bytes = 54; optional uint64 data_size_in_bytes = 55;
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc index f57aeae..743cc9e 100644 --- a/chrome/browser/web_applications/web_app_registrar_unittest.cc +++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -29,6 +29,7 @@ #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_registry_update.h" #include "chrome/browser/web_applications/web_app_sync_bridge.h" +#include "chrome/browser/web_applications/web_app_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" @@ -67,6 +68,15 @@ return registry; } +int CountApps(const WebAppRegistrar::AppSet& app_set) { + int count = 0; + for (const auto& web_app : app_set) { + EXPECT_FALSE(web_app.is_uninstalling()); + ++count; + } + return count; +} + } // namespace class WebAppRegistrarTest : public WebAppTest { @@ -219,6 +229,7 @@ const WebApp* app2 = registrar().GetAppById(app_id2); EXPECT_EQ(app_id2, app2->app_id()); EXPECT_FALSE(registrar().is_empty()); + EXPECT_EQ(CountApps(registrar().GetApps()), 2); UnregisterApp(app_id); EXPECT_FALSE(registrar().IsInstalled(app_id)); @@ -234,6 +245,7 @@ EXPECT_FALSE(registrar().IsInstalled(app_id2)); EXPECT_EQ(nullptr, registrar().GetAppById(app_id2)); EXPECT_TRUE(registrar().is_empty()); + EXPECT_EQ(CountApps(registrar().GetApps()), 0); } TEST_F(WebAppRegistrarTest, DestroyRegistrarOwningRegisteredApps) { @@ -1195,19 +1207,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) -namespace { - -int CountApps(const WebAppRegistrar::AppSet& app_set) { - int count = 0; - for (const auto& web_app : app_set) { - EXPECT_FALSE(web_app.is_uninstalling()); - ++count; - } - return count; -} - -} // namespace - class WebAppRegistrarAshTest : public WebAppTest, public WithCrosapiParam { public: WebAppRegistrarAshTest() { @@ -1278,6 +1277,7 @@ EXPECT_EQ(registrar.GetAppScope(uninstalling_id), GURL("https://example.com/uninstalling/")); EXPECT_TRUE(registrar.GetAppUserDisplayMode(uninstalling_id).has_value()); + EXPECT_FALSE(base::Contains(registrar.GetAppIds(), uninstalling_id)); } INSTANTIATE_TEST_SUITE_P(All, @@ -1287,4 +1287,87 @@ WithCrosapiParam::ParamToString); #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) + +enum class SystemWebAppsInLacrosParam { + kDisabled = 0, + kEnabled = 1, +}; + +class WebAppRegistrarLacrosTest + : public WebAppTest, + public testing::WithParamInterface<SystemWebAppsInLacrosParam> { + public: + WebAppRegistrarLacrosTest() { + if (GetParam() == SystemWebAppsInLacrosParam::kEnabled) { + EnableSystemWebAppsInLacrosForTesting(); + } + } + ~WebAppRegistrarLacrosTest() override = default; +}; + +TEST_P(WebAppRegistrarLacrosTest, SourceSupported) { + const GURL example_url("https://example.com/my-app/start"); + const GURL swa_url("chrome://swa/start"); + const GURL uninstalling_url("https://example.com/uninstalling/start"); + + AppId example_id; + AppId swa_id; + AppId uninstalling_id; + WebAppRegistrarMutable registrar(profile()); + { + Registry registry; + + auto example_app = test::CreateWebApp(example_url); + example_id = example_app->app_id(); + registry.emplace(example_id, std::move(example_app)); + + auto swa_app = test::CreateWebApp(swa_url, WebAppManagement::Type::kSystem); + swa_id = swa_app->app_id(); + registry.emplace(swa_id, std::move(swa_app)); + + auto uninstalling_app = test::CreateWebApp(uninstalling_url); + uninstalling_app->SetIsUninstalling(true); + uninstalling_id = uninstalling_app->app_id(); + registry.emplace(uninstalling_id, std::move(uninstalling_app)); + + registrar.InitRegistry(std::move(registry)); + } + + EXPECT_EQ(registrar.FindAppWithUrlInScope(example_url), example_id); + EXPECT_EQ(registrar.GetAppScope(example_id), + GURL("https://example.com/my-app/")); + EXPECT_TRUE(registrar.GetAppUserDisplayMode(example_id).has_value()); + EXPECT_EQ(registrar.CountUserInstalledApps(), 1); + + if (GetParam() == SystemWebAppsInLacrosParam::kEnabled) { + EXPECT_EQ(CountApps(registrar.GetApps()), 2); + + EXPECT_EQ(registrar.FindAppWithUrlInScope(swa_url), swa_id); + EXPECT_EQ(registrar.GetAppScope(swa_id), GURL("chrome://swa/")); + EXPECT_TRUE(registrar.GetAppUserDisplayMode(swa_id).has_value()); + } else { + // System web apps are managed by Ash, excluded in Lacros + // WebAppRegistrar. + EXPECT_EQ(CountApps(registrar.GetApps()), 1); + + EXPECT_FALSE(registrar.FindAppWithUrlInScope(swa_url).has_value()); + EXPECT_TRUE(registrar.GetAppScope(swa_id).is_empty()); + EXPECT_FALSE(registrar.GetAppUserDisplayMode(swa_id).has_value()); + } + + EXPECT_FALSE(registrar.FindAppWithUrlInScope(uninstalling_url).has_value()); + EXPECT_EQ(registrar.GetAppScope(uninstalling_id), + GURL("https://example.com/uninstalling/")); + EXPECT_TRUE(registrar.GetAppUserDisplayMode(uninstalling_id).has_value()); + EXPECT_FALSE(base::Contains(registrar.GetAppIds(), uninstalling_id)); +} + +INSTANTIATE_TEST_SUITE_P( + All, + WebAppRegistrarLacrosTest, + ::testing::Values(SystemWebAppsInLacrosParam::kDisabled, + SystemWebAppsInLacrosParam::kEnabled)); +#endif + } // namespace web_app
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 7689fe8..9fea8361 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1654688617-d23b8156b805598a45b784d8578978f0c92fdea7.profdata +chrome-linux-main-1654754267-4bfb5de5fcbd13950fe7846c3764dc3ee00bb4ec.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index e727fc2..aee9fd9 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1654646316-9b55f15613fdf4b173a3441da8eb24cea3c025f2.profdata +chrome-mac-arm-main-1654754267-f55881de7cb7ab7f6874fc8dcd15a98817ed9037.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 34994077..efc34ec 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1654711203-74f8f2cf690324b24d13480305ed0edfb442b3ca.profdata +chrome-mac-main-1654754267-c999caf0e723fd14761c6ad69c86eb79289b1a54.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index d58ec07..68a1733 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1654711203-dd1524393825bce89244c153ae7bb5d820cccb69.profdata +chrome-win32-main-1654754267-5f0b445a485a25d93d14831fc32fe8ef85f35ec7.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 487c333..4bd7218 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1654711203-175391225b82ab2927479a4285505e2be51664cb.profdata +chrome-win64-main-1654754267-1e2ca9cfbab7985f9fe8a0d36d29dc23f286e0c5.profdata
diff --git a/chrome/test/data/webrtc/peerconnection_getstats.js b/chrome/test/data/webrtc/peerconnection_getstats.js index a235fa6..b47962d6 100644 --- a/chrome/test/data/webrtc/peerconnection_getstats.js +++ b/chrome/test/data/webrtc/peerconnection_getstats.js
@@ -94,17 +94,7 @@ packetsReceived: 'number', packetsLost: 'number', jitter: 'number', - packetsDiscarded: 'number', - packetsRepaired: 'number', - burstPacketsLost: 'number', - burstPacketsDiscarded: 'number', - burstLossCount: 'number', - burstDiscardCount: 'number', - burstLossRate: 'number', - burstDiscardRate: 'number', - gapLossRate: 'number', - gapDiscardRate: 'number', -}); + }); /* * RTCInboundRTPStreamStats @@ -117,28 +107,22 @@ remoteId: 'string', framesDecoded: 'number', keyFramesDecoded: 'number', - frameBitDepth: 'number', qpSum: 'number', totalDecodeTime: 'number', totalProcessingDelay: 'number', totalInterFrameDelay: 'number', totalSquaredInterFrameDelay: 'number', lastPacketReceivedTimestamp: 'number', - averageRtcpInterval: 'number', fecPacketsReceived: 'number', fecPacketsDiscarded: 'number', bytesReceived: 'number', headerBytesReceived: 'number', - packetsFailedDecryption: 'number', - packetsDuplicated: 'number', - perDscpPacketsReceived: 'object', + packetsDiscarded: 'number', nackCount: 'number', firCount: 'number', pliCount: 'number', - sliCount: 'number', frameWidth: 'number', frameHeight: 'number', - frameBitDepth: 'number', framesPerSecond: 'number', jitterBufferDelay: 'number', jitterBufferTargetDelay: 'number', @@ -187,8 +171,6 @@ */ let kRTCSentRtpStreamStats = new RTCStats(kRTCRtpStreamStats, { packetsSent: 'number', - packetsDiscardedOnSend: 'number', - fecPacketsSent: 'number', bytesSent: 'number', bytesDiscardedOnSend: 'number', }); @@ -203,27 +185,22 @@ mediaSourceId: 'string', senderId: 'string', remoteId: 'string', - lastPacketSentTimestamp: 'number', retransmittedPacketsSent: 'number', retransmittedBytesSent: 'number', headerBytesSent: 'number', targetBitrate: 'number', totalEncodedBytesTarget: 'number', - frameBitDepth: 'number', framesEncoded: 'number', keyFramesEncoded: 'number', qpSum: 'number', totalEncodeTime: 'number', totalPacketSendDelay: 'number', - averageRtcpInterval: 'number', qualityLimitationReason: 'string', qualityLimitationDurations: 'object', qualityLimitationResolutionChanges: 'number', - perDscpPacketsSent: 'object', nackCount: 'number', firCount: 'number', pliCount: 'number', - sliCount: 'number', encoderImplementation: 'string', rid: 'string', frameWidth: 'number', @@ -285,7 +262,6 @@ const kRTCVideoSourceStats = new RTCStats(kRTCMediaSourceStats, { width: 'number', height: 'number', - bitDepth: 'number', frames: 'number', framesPerSecond: 'number', }); @@ -330,8 +306,6 @@ let kRTCPeerConnectionStats = new RTCStats(null, { dataChannelsOpened: 'number', dataChannelsClosed: 'number', - dataChannelsRequested: 'number', - dataChannelsAccepted: 'number', }); addRTCStatsToAllowlist( Presence.MANDATORY, 'peer-connection', kRTCPeerConnectionStats); @@ -369,7 +343,6 @@ let kRTCVideoHandlerStats = new RTCStats(kRTCMediaHandlerStats, { frameWidth: 'number', frameHeight: 'number', - framesPerSecond: 'number', }); /* @@ -408,8 +381,6 @@ framesReceived: 'number', framesDecoded: 'number', framesDropped: 'number', - partialFramesLost: 'number', - fullFramesLost: 'number', }); // TODO(hbos): When receiver is implemented, make presence MANDATORY. addRTCStatsToAllowlist( @@ -434,7 +405,6 @@ let kRTCAudioHandlerStats = new RTCStats(kRTCMediaHandlerStats, { audioLevel: 'number', totalAudioEnergy: 'number', - voiceActivityFlag: 'boolean', totalSamplesDuration: 'number', }); @@ -447,7 +417,6 @@ mediaSourceId: 'string', echoReturnLoss: 'number', echoReturnLossEnhancement: 'number', - totalSamplesSent: 'number', }); // TODO(hbos): When sender is implemented, make presence MANDATORY. addRTCStatsToAllowlist(Presence.OPTIONAL, 'sender', kRTCAudioSenderStats); @@ -574,7 +543,6 @@ priority: 'number', nominated: 'boolean', writable: 'boolean', - readable: 'boolean', packetsSent: 'number', packetsReceived: 'number', bytesSent: 'number', @@ -587,12 +555,7 @@ requestsSent: 'number', responsesReceived: 'number', responsesSent: 'number', - retransmissionsReceived: 'number', - retransmissionsSent: 'number', - consentRequestsReceived: 'number', consentRequestsSent: 'number', - consentResponsesReceived: 'number', - consentResponsesSent: 'number', packetsDiscardedOnSend: 'number', bytesDiscardedOnSend: 'number', });
diff --git a/chromecast/browser/cast_web_view_default.cc b/chromecast/browser/cast_web_view_default.cc index e3e7bce..14d325a0 100644 --- a/chromecast/browser/cast_web_view_default.cc +++ b/chromecast/browser/cast_web_view_default.cc
@@ -245,7 +245,7 @@ !params_->allow_media_access) { LOG(WARNING) << __func__ << ": media access is disabled."; std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>()); return; @@ -258,7 +258,10 @@ DVLOG(2) << __func__ << " audio_devices=" << audio_devices.size() << " video_devices=" << video_devices.size(); - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; if (request.audio_type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { const blink::MediaStreamDevice* device = GetRequestedDeviceOrDefault( @@ -281,7 +284,8 @@ } } - std::move(callback).Run(devices, blink::mojom::MediaStreamRequestResult::OK, + std::move(callback).Run(stream_devices_set, + blink::mojom::MediaStreamRequestResult::OK, std::unique_ptr<content::MediaStreamUI>()); }
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.cc b/chromeos/dbus/session_manager/fake_session_manager_client.cc index 0e8d0520..1ce3d340 100644 --- a/chromeos/dbus/session_manager/fake_session_manager_client.cc +++ b/chromeos/dbus/session_manager/fake_session_manager_client.cc
@@ -411,7 +411,7 @@ const cryptohome::AccountIdentifier& cryptohome_id, const bool is_move) { request_browser_data_migration_called_ = true; - + request_browser_data_migration_for_move_called_ = is_move; return true; }
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.h b/chromeos/dbus/session_manager/fake_session_manager_client.h index 112f53ea..e7ed013 100644 --- a/chromeos/dbus/session_manager/fake_session_manager_client.h +++ b/chromeos/dbus/session_manager/fake_session_manager_client.h
@@ -326,6 +326,10 @@ return request_browser_data_migration_called_; } + bool request_browser_data_migration_for_move_called() const { + return request_browser_data_migration_for_move_called_; + } + private: // Called in response to writing owner key file specified in new device // policy - used for in-memory fake only. @@ -398,6 +402,7 @@ std::string login_password_; bool request_browser_data_migration_called_ = false; + bool request_browser_data_migration_for_move_called_ = false; // Contains last request passed to StartArcMiniContainer login_manager::StartArcMiniContainerRequest
diff --git a/chromeos/lacros/lacros_service.cc b/chromeos/lacros/lacros_service.cc index b7c03646..5e2f7383 100644 --- a/chromeos/lacros/lacros_service.cc +++ b/chromeos/lacros/lacros_service.cc
@@ -66,6 +66,7 @@ #include "chromeos/crosapi/mojom/screen_manager.mojom.h" #include "chromeos/crosapi/mojom/select_file.mojom.h" #include "chromeos/crosapi/mojom/sharesheet.mojom.h" +#include "chromeos/crosapi/mojom/speech_recognition.mojom.h" #include "chromeos/crosapi/mojom/sync.mojom.h" #include "chromeos/crosapi/mojom/system_display.mojom.h" #include "chromeos/crosapi/mojom/task_manager.mojom.h" @@ -388,6 +389,10 @@ &crosapi::mojom::Crosapi::BindSharesheet, Crosapi::MethodMinVersions::kBindSharesheetMinVersion>(); ConstructRemote< + crosapi::mojom::SpeechRecognition, + &crosapi::mojom::Crosapi::BindSpeechRecognition, + Crosapi::MethodMinVersions::kBindSpeechRecognitionMinVersion>(); + ConstructRemote< crosapi::mojom::StructuredMetricsService, &crosapi::mojom::Crosapi::BindStructuredMetricsService, Crosapi::MethodMinVersions::kBindStructuredMetricsServiceMinVersion>();
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 0a2d6d6..4e9c8d3d 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -2342,13 +2342,9 @@ if (web_form.IsNull()) { const WebElement& body = document.Body(); if (!body.IsNull()) { - SCOPED_UMA_HISTOGRAM_TIMER( - "PasswordManager.ButtonTitlePerformance.NoFormTag"); button_titles = InferButtonTitlesForForm(body); } } else { - SCOPED_UMA_HISTOGRAM_TIMER( - "PasswordManager.ButtonTitlePerformance.HasFormTag"); button_titles = InferButtonTitlesForForm(web_form); } form_position->second = std::move(button_titles);
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc index 7db2eba..ca8c3d1 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -389,12 +389,6 @@ bool AutofillSuggestionGenerator::ShouldShowVirtualCardOption( const CreditCard* candidate_card, const FormStructure& form_structure) const { - // If virtual card experiment is disabled: - if (!base::FeatureList::IsEnabled( - features::kAutofillEnableMerchantBoundVirtualCards)) { - return false; - } - // If the form is an incomplete form and the incomplete form experiment is // disabled, do not offer a virtual card option. We will likely not be able to // fill in all information, and the user doesn't have the info either.
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc index 6b54216..5c78e9ae 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
@@ -33,8 +33,6 @@ AutofillSuggestionGeneratorTest() = default; void SetUp() override { - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillEnableMerchantBoundVirtualCards); autofill_client_.SetPrefs(test::PrefServiceForTesting()); personal_data_.Init(/*profile_database=*/database_, /*account_database=*/nullptr,
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc index ad1527b..c456ee87 100644 --- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc +++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -8249,9 +8249,8 @@ TEST_P(BrowserAutofillManagerStructuredProfileTest, GetCreditCardSuggestions_VirtualCard) { base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitWithFeatures( - {features::kAutofillEnableMerchantBoundVirtualCards}, - {features::kAutofillSuggestVirtualCardsOnIncompleteForm}); + scoped_feature_list.InitAndDisableFeature( + features::kAutofillSuggestVirtualCardsOnIncompleteForm); personal_data().ClearCreditCards(); CreditCard masked_server_card(CreditCard::MASKED_SERVER_CARD,
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc index 09a4ad3..c0e335dd 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -4938,9 +4938,6 @@ // Test that we log specific suggestion shown form events for virtual credit // cards. TEST_P(AutofillMetricsIFrameTest, VirtualCreditCardShownFormEvents) { - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillEnableMerchantBoundVirtualCards); - // Set up our form data. https:// is required. FormData form; form.name = u"TestForm";
diff --git a/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc b/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc index 022ce0a..bfc8f4f 100644 --- a/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc +++ b/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc
@@ -190,8 +190,6 @@ // Before showing OTP dialog, let's load required risk data if it's not // prepared. Risk data is only required for unmask request. Not required for // select challenge option request. - // TODO(crbug.com/1243475): Explore the possibility of sending one - // LoadRiskData request per session. if (risk_data_.empty()) { autofill_client_->LoadRiskData( base::BindOnce(&CreditCardOtpAuthenticator::OnDidGetUnmaskRiskData,
diff --git a/components/autofill/core/browser/payments/full_card_request.cc b/components/autofill/core/browser/payments/full_card_request.cc index 9ab7577..8d2f612 100644 --- a/components/autofill/core/browser/payments/full_card_request.cc +++ b/components/autofill/core/browser/payments/full_card_request.cc
@@ -297,14 +297,9 @@ // to avoid an unwanted registration prompt. unmask_response_details_ = response_details; - const std::u16string cvc = - (base::FeatureList::IsEnabled( - features::kAutofillAlwaysReturnCloudTokenizedCard) || - base::FeatureList::IsEnabled( - features::kAutofillEnableMerchantBoundVirtualCards)) && - !response_details.dcvv.empty() - ? base::UTF8ToUTF16(response_details.dcvv) - : request_->user_response.cvc; + const std::u16string cvc = !response_details.dcvv.empty() + ? base::UTF8ToUTF16(response_details.dcvv) + : request_->user_response.cvc; if (result_delegate_) result_delegate_->OnFullCardRequestSucceeded(*this, request_->card, cvc);
diff --git a/components/autofill/core/browser/payments/full_card_request_unittest.cc b/components/autofill/core/browser/payments/full_card_request_unittest.cc index e81295d..7abd030 100644 --- a/components/autofill/core/browser/payments/full_card_request_unittest.cc +++ b/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -381,8 +381,6 @@ // Verify getting the full PAN, the expiration and the dCVV for a virtual card. TEST_F(FullCardRequestTest, GetFullCardPanAndExpirationAndDcvvForVirtualCard) { - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillEnableMerchantBoundVirtualCards); EXPECT_CALL( *result_delegate(), OnFullCardRequestSucceeded(testing::Ref(*request()),
diff --git a/components/autofill/core/browser/ui/autofill_image_fetcher.cc b/components/autofill/core/browser/ui/autofill_image_fetcher.cc index aa6c31f5..c2199eb 100644 --- a/components/autofill/core/browser/ui/autofill_image_fetcher.cc +++ b/components/autofill/core/browser/ui/autofill_image_fetcher.cc
@@ -19,7 +19,9 @@ namespace autofill { namespace { + constexpr char kUmaClientName[] = "AutofillImageFetcher"; + constexpr net::NetworkTrafficAnnotationTag kCardArtImageTrafficAnnotation = net::DefineNetworkTrafficAnnotation("autofill_image_fetcher_card_art_image", R"( @@ -48,6 +50,11 @@ } } })"); + +// Defines the expiration of the fetched image in the disk cache of the image +// fetcher. +constexpr base::TimeDelta kDiskCacheExpiry = base::Minutes(10); + } // namespace ImageFetchOperation::ImageFetchOperation(size_t image_count, @@ -121,8 +128,7 @@ image_fetcher::ImageFetcherParams params(kCardArtImageTrafficAnnotation, kUmaClientName); - params.set_hold_for_expiration_interval(base::Minutes( - features::kAutofillImageFetcherDiskCacheExpirationInMinutes.Get())); + params.set_hold_for_expiration_interval(kDiskCacheExpiry); image_fetcher_->FetchImage( card_art_url, base::BindOnce(&AutofillImageFetcher::OnCardArtImageFetched, operation,
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc index 204b69e..26e44d4 100644 --- a/components/autofill/core/common/autofill_payments_features.cc +++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -53,16 +53,10 @@ const base::Feature kAutofillCreditCardUploadFeedback{ "AutofillCreditCardUploadFeedback", base::FEATURE_DISABLED_BY_DEFAULT}; -// When enabled, merchant bound virtual cards will be offered when users -// interact with a payment form. -const base::Feature kAutofillEnableMerchantBoundVirtualCards{ - "AutofillEnableMerchantBoundVirtualCards", - base::FEATURE_ENABLED_BY_DEFAULT}; - // When enabled, enable manual falling component for virtual cards on Android. const base::Feature kAutofillEnableManualFallbackForVirtualCards{ "AutofillEnableManualFallbackForVirtualCards", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // When enabled, a notification will be displayed on page navigation if the // domain has an eligible merchant promo code offer or reward. @@ -105,7 +99,12 @@ // page. const base::Feature kAutofillEnableUpdateVirtualCardEnrollment{ "AutofillEnableUpdateVirtualCardEnrollment", - base::FEATURE_DISABLED_BY_DEFAULT}; +#if BUILDFLAG(IS_IOS) + base::FEATURE_DISABLED_BY_DEFAULT +#else + base::FEATURE_ENABLED_BY_DEFAULT +#endif +}; // When enabled, the option of using cloud token virtual card will be offered // when all requirements are met. @@ -142,13 +141,6 @@ const base::Feature kAutofillFillMerchantPromoCodeFields{ "AutofillFillMerchantPromoCodeFields", base::FEATURE_DISABLED_BY_DEFAULT}; -// The merchant bound virtual card feature introduces new customized card art -// images. This parameter defines the expiration of the fetched image in the -// disk cache of the image fetcher. -const base::FeatureParam<int> kAutofillImageFetcherDiskCacheExpirationInMinutes{ - &kAutofillEnableMerchantBoundVirtualCards, - "autofill_image_fetcher_disk_cache_expiration_in_minutes", 10}; - // When enabled, Autofill will attempt to find merchant promo/coupon/gift code // fields when parsing forms. const base::Feature kAutofillParseMerchantPromoCodeFields{
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h index 6ecd0b21..aaa4ff0 100644 --- a/components/autofill/core/common/autofill_payments_features.h +++ b/components/autofill/core/common/autofill_payments_features.h
@@ -22,7 +22,6 @@ extern const base::Feature kAutofillCreditCardAuthentication; extern const base::Feature kAutofillCreditCardUploadFeedback; extern const base::Feature kAutofillEnableManualFallbackForVirtualCards; -extern const base::Feature kAutofillEnableMerchantBoundVirtualCards; extern const base::Feature kAutofillEnableOfferNotificationForPromoCodes; extern const base::Feature kAutofillEnableOffersInClankKeyboardAccessory; extern const base::Feature kAutofillEnableSendingBcnInGetUploadDetails; @@ -37,8 +36,6 @@ extern const base::Feature kAutofillEnableVirtualCardMetadata; extern const base::Feature kAutofillEnforceDelaysInStrikeDatabase; extern const base::Feature kAutofillFillMerchantPromoCodeFields; -extern const base::FeatureParam<int> - kAutofillImageFetcherDiskCacheExpirationInMinutes; extern const base::Feature kAutofillParseMerchantPromoCodeFields; extern const base::Feature kAutofillRemoveCardExpiryFromDownstreamSuggestion; extern const base::Feature kAutofillSaveCardDismissOnNavigation;
diff --git a/components/exo/extended_drag_source.cc b/components/exo/extended_drag_source.cc index 93e80a9..256c124 100644 --- a/components/exo/extended_drag_source.cc +++ b/components/exo/extended_drag_source.cc
@@ -167,6 +167,9 @@ if (source_) source_->RemoveObserver(this); + if (drag_source_window_) + drag_source_window_->RemoveObserver(this); + DCHECK_EQ(instance_, this); instance_ = nullptr; } @@ -217,6 +220,8 @@ drag_event_source_ = source; drag_source_window_ = drag_source_window ? drag_source_window->GetToplevelWindow() : nullptr; + if (drag_source_window_) + drag_source_window_->AddObserver(this); MaybeLockCursor(); if (dragged_window_holder_ && dragged_window_holder_->toplevel_window()) @@ -267,6 +272,11 @@ source_ = nullptr; } +void ExtendedDragSource::OnWindowDestroyed(aura::Window* window) { + if (drag_source_window_ == window) + drag_source_window_ = nullptr; +} + void ExtendedDragSource::MaybeLockCursor() { if (delegate_->ShouldLockCursor()) { ash::Shell::Get()->cursor_manager()->LockCursor(); @@ -330,9 +340,8 @@ aura::Window* toplevel = dragged_window_holder_->toplevel_window(); DCHECK(toplevel); - DCHECK(drag_source_window_); toplevel->SetProperty(ash::kIsDraggingTabsKey, true); - if (drag_source_window_ != toplevel) { + if (drag_source_window_ && drag_source_window_ != toplevel) { toplevel->SetProperty(ash::kTabDraggingSourceWindowKey, drag_source_window_); } @@ -349,7 +358,6 @@ aura::Window* toplevel = dragged_window_holder_->toplevel_window(); DCHECK(toplevel); - DCHECK(drag_source_window_); // The |toplevel| window for the dragged surface has just been created and // it's about to be mapped. Calculate and set its position based on @@ -360,7 +368,7 @@ auto toplevel_bounds = gfx::Rect({screen_location, toplevel->bounds().size()}); auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( - drag_source_window_); + drag_source_window_ ? drag_source_window_ : toplevel); toplevel->SetBoundsInScreen(toplevel_bounds, display); if (WMHelper::GetInstance()->InTabletMode()) { @@ -383,6 +391,8 @@ aura::client::kAnimationsDisabledKey); } event_blocker_.reset(); + if (drag_source_window_) + drag_source_window_->RemoveObserver(this); drag_source_window_ = nullptr; UnlockCursor(); } @@ -399,4 +409,8 @@ : absl::nullopt; } +aura::Window* ExtendedDragSource::GetDragSourceWindowForTesting() { + return drag_source_window_; +} + } // namespace exo
diff --git a/components/exo/extended_drag_source.h b/components/exo/extended_drag_source.h index f1fa7c1a..3ce4f3aa 100644 --- a/components/exo/extended_drag_source.h +++ b/components/exo/extended_drag_source.h
@@ -36,6 +36,7 @@ class Surface; class ExtendedDragSource : public DataSourceObserver, + public aura::WindowObserver, public ash::ToplevelWindowDragDelegate { public: class Delegate { @@ -84,8 +85,12 @@ // DataSourceObserver: void OnDataSourceDestroying(DataSource* source) override; + // aura::WindowObserver: + void OnWindowDestroyed(aura::Window* window) override; + aura::Window* GetDraggedWindowForTesting(); absl::optional<gfx::Vector2d> GetDragOffsetForTesting() const; + aura::Window* GetDragSourceWindowForTesting(); private: class DraggedWindowHolder;
diff --git a/components/exo/extended_drag_source_unittest.cc b/components/exo/extended_drag_source_unittest.cc index 2c41254..bf27395 100644 --- a/components/exo/extended_drag_source_unittest.cc +++ b/components/exo/extended_drag_source_unittest.cc
@@ -533,6 +533,33 @@ EXPECT_TRUE(surface->window()->GetBoundsInScreen().origin().IsOrigin()); } +// Regression test for crbug.com/1330125. +// In exo, the drag source window could be destroyed while the dragged window +// is updating its visibility. The example in this bug was while merging a +// single-tab browser window in and out of another browser window. +TEST_F(ExtendedDragSourceTest, DestroyDragSourceWindowWhileDragging) { + auto shell_surface = + exo::test::ShellSurfaceBuilder({32, 32}).BuildShellSurface(); + auto* surface = shell_surface->root_surface(); + // Start hidden so when it's shown later it triggers the memory violation. + shell_surface->GetWidget()->Hide(); + + extended_drag_source_->Drag(surface, gfx::Vector2d()); + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + EXPECT_EQ(window, extended_drag_source_->GetDraggedWindowForTesting()); + + auto drag_source_window = CreateToplevelTestWindow({20, 30, 200, 100}); + extended_drag_source_->OnToplevelWindowDragStarted( + {70.0, 70.0}, ui::mojom::DragEventSource::kMouse, + drag_source_window.get()); + EXPECT_EQ(extended_drag_source_->GetDragSourceWindowForTesting(), + drag_source_window.get()); + drag_source_window.reset(); + EXPECT_EQ(extended_drag_source_->GetDragSourceWindowForTesting(), nullptr); + // Without the fix, in asan build, this should cause the use-after-free. + shell_surface->GetWidget()->Show(); +} + TEST_F(ExtendedDragSourceTest, DragRequestsInRow_NoCrash) { // Create and map a toplevel shell surface, but hidden. auto shell_surface =
diff --git a/components/offline_pages/content/background_loader/background_loader_contents.cc b/components/offline_pages/content/background_loader/background_loader_contents.cc index 9f46f0b..18671155 100644 --- a/components/offline_pages/content/background_loader/background_loader_contents.cc +++ b/components/offline_pages/content/background_loader/background_loader_contents.cc
@@ -116,7 +116,7 @@ content::MediaResponseCallback callback) { // No permissions granted, act as if dismissed. std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED, std::unique_ptr<content::MediaStreamUI>()); }
diff --git a/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc b/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc index bd7518bd..01898850 100644 --- a/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc +++ b/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc
@@ -37,9 +37,10 @@ bool download() { return download_; } bool can_download_delegate_called() { return delegate_called_; } - void MediaAccessCallback(const blink::mojom::StreamDevices& devices, - blink::mojom::MediaStreamRequestResult result, - std::unique_ptr<content::MediaStreamUI> ui); + void MediaAccessCallback( + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui); blink::mojom::StreamDevices& devices() { return devices_; } blink::mojom::MediaStreamRequestResult request_result() { return request_result_; @@ -91,10 +92,15 @@ } void BackgroundLoaderContentsTest::MediaAccessCallback( - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<content::MediaStreamUI> ui) { - devices_ = devices; + if (result == blink::mojom::MediaStreamRequestResult::OK) { + ASSERT_FALSE(stream_devices_set.stream_devices.empty()); + devices_ = *stream_devices_set.stream_devices[0]; + } else { + ASSERT_TRUE(stream_devices_set.stream_devices.empty()); + } request_result_ = result; media_stream_ui_.reset(ui.get()); waiter_.Signal();
diff --git a/components/password_manager/core/browser/fake_password_store_backend.cc b/components/password_manager/core/browser/fake_password_store_backend.cc index f8e62903..40b3179b 100644 --- a/components/password_manager/core/browser/fake_password_store_backend.cc +++ b/components/password_manager/core/browser/fake_password_store_backend.cc
@@ -70,7 +70,7 @@ } void FakePasswordStoreBackend::FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) { base::SequencedTaskRunnerHandle::Get()->PostTaskAndReplyWithResult(
diff --git a/components/password_manager/core/browser/fake_password_store_backend.h b/components/password_manager/core/browser/fake_password_store_backend.h index c65a2ba..e5981af 100644 --- a/components/password_manager/core/browser/fake_password_store_backend.h +++ b/components/password_manager/core/browser/fake_password_store_backend.h
@@ -53,7 +53,7 @@ void GetAllLoginsForAccountAsync(absl::optional<std::string> account, LoginsOrErrorReply callback) override; void FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) override; void AddLoginAsync(const PasswordForm& form,
diff --git a/components/password_manager/core/browser/mock_password_store_backend.h b/components/password_manager/core/browser/mock_password_store_backend.h index 9cd33fd..1819c82 100644 --- a/components/password_manager/core/browser/mock_password_store_backend.h +++ b/components/password_manager/core/browser/mock_password_store_backend.h
@@ -58,7 +58,7 @@ (override)); MOCK_METHOD(void, FillMatchingLoginsAsync, - (LoginsReply callback, + (LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms), (override));
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index 4c60e71..81d9945 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -401,4 +401,9 @@ add_credential_from_settings_user_interaction); } +void LogPasswordNoteActionInSettings(PasswordNoteAction action) { + base::UmaHistogramEnumeration("PasswordManager.PasswordNoteActionInSettings", + action); +} + } // namespace password_manager::metrics_util
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index 2abc106..8d51c952 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -531,6 +531,24 @@ kMaxValue = kBoth, }; +// Used to record usage of the note field in password editing / adding flows in +// the settings UI. These values are persisted to logs. Entries should not be +// renumbered and numeric values should never be reused. +enum class PasswordNoteAction { + // A new credential is added from settings, with the note field not empty. + kNoteAddedInAddDialog = 0, + // Note changed from empty to non-empty from the password edit dialog in + // settings. + kNoteAddedInEditDialog = 1, + // Note changed from non-empty to another non-empty from the password edit + // dialog in settings. + kNoteEditedInEditDialog = 2, + // Note changed from non-empty to empty from the password edit dialog in + // settings. + kNoteRemovedInEditDialog = 3, + kMaxValue = kNoteRemovedInEditDialog, +}; + std::string GetPasswordAccountStorageUserStateHistogramSuffix( PasswordAccountStorageUserState user_state); @@ -549,6 +567,33 @@ // The user has enabled Sync. kSyncing = 2, }; + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class PasswordViewPageInteractions { + // The credential row is clicked in the password list in settings. + kCredentialRowClicked = 0, + // The user opens the password view page to view an existing credential. + kCredentialFound = 1, + // The user opens the password view page to view an non-existing credential. + // This will close the settings password view page. + kCredentialNotFound = 2, + // The copy username button in settings password view page is clicked. + kUsernameCopyButtonClicked = 3, + // The copy password button in settings password view page is clicked. + kPasswordCopyButtonClicked = 4, + // The show password button in settings password view page is clicked and the + // password is revealed. + kPasswordShowButtonClicked = 5, + // The edit button in settings password view page is clicked. + kPasswordEditButtonClicked = 6, + // The delete button in settings password view page is clicked. + kPasswordDeleteButtonClicked = 7, + // The credential's username, password or note is edited in settings password + // view page. + kCredentialEdited = 8, + kMaxValue = kCredentialEdited, +}; std::string GetPasswordAccountStorageUsageLevelHistogramSuffix( PasswordAccountStorageUsageLevel usage_level); @@ -734,6 +779,10 @@ AddCredentialFromSettingsUserInteractions add_credential_from_settings_user_interaction); +// Log how the user interaction with the note field in password add / edit +// dialogs. +void LogPasswordNoteActionInSettings(PasswordNoteAction action); + } // namespace metrics_util } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index bde2a1e4..a4019669 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -220,8 +220,9 @@ if (!backend_) return; // Once the shutdown started, ignore new requests. backend_->FillMatchingLoginsAsync( - base::BindOnce(&PasswordStore::UnblocklistInternal, this, - std::move(completion)), + base::BindOnce(&GetLoginsOrEmptyListOnFailure) + .Then(base::BindOnce(&PasswordStore::UnblocklistInternal, this, + std::move(completion))), FormSupportsPSL(form_digest), {form_digest}); } @@ -239,8 +240,10 @@ if (affiliated_match_helper_) { auto branding_injection_for_affiliations_callback = - base::BindOnce(&PasswordStore::InjectAffiliationAndBrandingInformation, - this, request_handler->AffiliatedLoginsClosure()); + base::BindOnce(&GetLoginsOrEmptyListOnFailure) + .Then(base::BindOnce( + &PasswordStore::InjectAffiliationAndBrandingInformation, this, + request_handler->AffiliatedLoginsClosure())); // `Shutdown` resets the affiliated_match_helper_ before shutting down the // backend_. Therefore, base::Unretained is safe here. affiliated_match_helper_->GetAffiliatedAndroidAndWebRealms( @@ -254,8 +257,10 @@ } auto branding_injection_callback = - base::BindOnce(&PasswordStore::InjectAffiliationAndBrandingInformation, - this, request_handler->LoginsForFormClosure()); + base::BindOnce(&GetLoginsOrEmptyListOnFailure) + .Then(base::BindOnce( + &PasswordStore::InjectAffiliationAndBrandingInformation, this, + request_handler->LoginsForFormClosure())); backend_->FillMatchingLoginsAsync(std::move(branding_injection_callback), FormSupportsPSL(form), {form});
diff --git a/components/password_manager/core/browser/password_store_backend.h b/components/password_manager/core/browser/password_store_backend.h index eaee80d..f3ff0eb4 100644 --- a/components/password_manager/core/browser/password_store_backend.h +++ b/components/password_manager/core/browser/password_store_backend.h
@@ -113,9 +113,8 @@ // If |include_psl|==true, the PSL-matched forms are also included. // If multiple forms are given, those will be concatenated. // Callback is called on the main sequence. - // TODO(crbug.com/1217071): Check whether this needs OptionalLoginsReply, too. virtual void FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) = 0;
diff --git a/components/password_manager/core/browser/password_store_backend_migration_decorator.cc b/components/password_manager/core/browser/password_store_backend_migration_decorator.cc index 7be31105..69aba51db 100644 --- a/components/password_manager/core/browser/password_store_backend_migration_decorator.cc +++ b/components/password_manager/core/browser/password_store_backend_migration_decorator.cc
@@ -193,7 +193,7 @@ } void PasswordStoreBackendMigrationDecorator::FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) { active_backend_->FillMatchingLoginsAsync(std::move(callback), include_psl,
diff --git a/components/password_manager/core/browser/password_store_backend_migration_decorator.h b/components/password_manager/core/browser/password_store_backend_migration_decorator.h index 90b42add..130b74e 100644 --- a/components/password_manager/core/browser/password_store_backend_migration_decorator.h +++ b/components/password_manager/core/browser/password_store_backend_migration_decorator.h
@@ -106,7 +106,7 @@ void GetAllLoginsForAccountAsync(absl::optional<std::string> account, LoginsOrErrorReply callback) override; void FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) override; void AddLoginAsync(const PasswordForm& form,
diff --git a/components/password_manager/core/browser/password_store_built_in_backend.cc b/components/password_manager/core/browser/password_store_built_in_backend.cc index c8e9fca3..afcfe0b 100644 --- a/components/password_manager/core/browser/password_store_built_in_backend.cc +++ b/components/password_manager/core/browser/password_store_built_in_backend.cc
@@ -10,6 +10,7 @@ #include "base/task/thread_pool.h" #include "components/password_manager/core/browser/login_database.h" #include "components/password_manager/core/browser/login_database_async_helper.h" +#include "components/password_manager/core/browser/password_store_backend.h" #include "components/password_manager/core/browser/password_store_backend_metrics_recorder.h" #include "components/password_manager/core/browser/password_store_util.h" #include "components/sync/model/proxy_model_type_controller_delegate.h" @@ -128,13 +129,13 @@ } void PasswordStoreBuiltInBackend::FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(helper_); if (forms.empty()) { - std::move(callback).Run({}); + std::move(callback).Run(LoginsResult()); return; }
diff --git a/components/password_manager/core/browser/password_store_built_in_backend.h b/components/password_manager/core/browser/password_store_built_in_backend.h index 743a17d..c10900f 100644 --- a/components/password_manager/core/browser/password_store_built_in_backend.h +++ b/components/password_manager/core/browser/password_store_built_in_backend.h
@@ -57,7 +57,7 @@ void GetAllLoginsForAccountAsync(absl::optional<std::string> account, LoginsOrErrorReply callback) override; void FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) override; void AddLoginAsync(const PasswordForm& form,
diff --git a/components/password_manager/core/browser/password_store_built_in_backend_unittest.cc b/components/password_manager/core/browser/password_store_built_in_backend_unittest.cc index f0d7015..dd284804 100644 --- a/components/password_manager/core/browser/password_store_built_in_backend_unittest.cc +++ b/components/password_manager/core/browser/password_store_built_in_backend_unittest.cc
@@ -23,6 +23,7 @@ #include "components/os_crypt/os_crypt_mocker.h" #include "components/password_manager/core/browser/login_database.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" +#include "components/password_manager/core/browser/password_store_backend.h" #include "components/password_manager/core/browser/password_store_change.h" #include "components/password_manager/core/browser/password_store_consumer.h" #include "testing/gmock/include/gmock/gmock.h" @@ -80,13 +81,8 @@ class MockPasswordStoreBackendTester { public: MOCK_METHOD(void, HandleChanges, (absl::optional<PasswordStoreChangeList>)); - MOCK_METHOD(void, - LoginsReceivedConstRef, - (const std::vector<std::unique_ptr<PasswordForm>>&)); + MOCK_METHOD(void, LoginsReceivedConstRef, (const LoginsResult&)); - void HandleLogins(std::vector<std::unique_ptr<PasswordForm>> results) { - LoginsReceivedConstRef(results); - } void HandleLoginsOrError(LoginsResultOrError results) { LoginsReceivedConstRef(std::move(absl::get<LoginsResult>(results))); }
diff --git a/components/password_manager/core/browser/password_store_proxy_backend.cc b/components/password_manager/core/browser/password_store_proxy_backend.cc index 81771127..68ef5fa 100644 --- a/components/password_manager/core/browser/password_store_proxy_backend.cc +++ b/components/password_manager/core/browser/password_store_proxy_backend.cc
@@ -436,25 +436,25 @@ } void PasswordStoreProxyBackend::FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) { - auto handler = - base::MakeRefCounted<ShadowTrafficMetricsRecorder<LoginsResultImpl>>( - MethodName("FillMatchingLoginsAsync")); + auto handler = base::MakeRefCounted< + ShadowTrafficMetricsRecorder<LoginsResultOrErrorImpl>>( + MethodName("FillMatchingLoginsAsync")); main_backend()->FillMatchingLoginsAsync( - base::BindOnce( - &ShadowTrafficMetricsRecorder<LoginsResultImpl>::RecordMainResult, - handler) + base::BindOnce(&ShadowTrafficMetricsRecorder< + LoginsResultOrErrorImpl>::RecordMainResult, + handler) .Then(std::move(callback)), include_psl, forms); if (ShouldExecuteReadOperationsOnShadowBackend( prefs_, sync_delegate_->IsSyncingPasswordsEnabled())) { shadow_backend()->FillMatchingLoginsAsync( - base::BindOnce( - &ShadowTrafficMetricsRecorder<LoginsResultImpl>::RecordShadowResult, - handler), + base::BindOnce(&ShadowTrafficMetricsRecorder< + LoginsResultOrErrorImpl>::RecordShadowResult, + handler), include_psl, forms); } }
diff --git a/components/password_manager/core/browser/password_store_proxy_backend.h b/components/password_manager/core/browser/password_store_proxy_backend.h index 0f2904b..00774a4 100644 --- a/components/password_manager/core/browser/password_store_proxy_backend.h +++ b/components/password_manager/core/browser/password_store_proxy_backend.h
@@ -51,7 +51,7 @@ void GetAllLoginsForAccountAsync(absl::optional<std::string> account, LoginsOrErrorReply callback) override; void FillMatchingLoginsAsync( - LoginsReply callback, + LoginsOrErrorReply callback, bool include_psl, const std::vector<PasswordFormDigest>& forms) override; void AddLoginAsync(const PasswordForm& form,
diff --git a/components/password_manager/core/browser/password_store_proxy_backend_unittest.cc b/components/password_manager/core/browser/password_store_proxy_backend_unittest.cc index cd2a079..3c286ba 100644 --- a/components/password_manager/core/browser/password_store_proxy_backend_unittest.cc +++ b/components/password_manager/core/browser/password_store_proxy_backend_unittest.cc
@@ -269,13 +269,12 @@ } TEST_F(PasswordStoreProxyBackendTest, UseMainBackendToFillMatchingLoginsAsync) { - base::MockCallback<LoginsReply> mock_reply; + base::MockCallback<LoginsOrErrorReply> mock_reply; std::vector<std::unique_ptr<PasswordForm>> expected_logins = CreateTestLogins(); - EXPECT_CALL(mock_reply, - Run(UnorderedPasswordFormElementsAre(&expected_logins))); + EXPECT_CALL(mock_reply, Run(LoginsResultsOrErrorAre(&expected_logins))); EXPECT_CALL(built_in_backend(), FillMatchingLoginsAsync) - .WillOnce(WithArg<0>(Invoke([](LoginsReply reply) -> void { + .WillOnce(WithArg<0>(Invoke([](LoginsOrErrorReply reply) -> void { std::move(reply).Run(CreateTestLogins()); }))); EXPECT_CALL(sync_delegate(), IsSyncingPasswordsEnabled)
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc index a3366f8..51de29a 100644 --- a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc +++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
@@ -11,6 +11,7 @@ #include "base/check.h" #include "base/containers/cxx20_erase.h" +#include "base/notreached.h" #include "base/observer_list.h" #include "base/ranges/algorithm.h" #include "components/password_manager/core/browser/password_form.h" @@ -24,6 +25,7 @@ using password_manager::metrics_util::IsPasswordChanged; using password_manager::metrics_util::IsPasswordNoteChanged; using password_manager::metrics_util::IsUsernameChanged; +using password_manager::metrics_util::PasswordNoteAction; using PasswordNote = password_manager::PasswordNote; using Store = password_manager::PasswordForm::Store; using SavedPasswordsView = @@ -53,14 +55,26 @@ form.signon_realm = credential.signon_realm; form.username_value = credential.username; form.password_value = credential.password; - if (!credential.note.value.empty()) { + if (!credential.note.value.empty()) form.notes = {credential.note}; - } + DCHECK(!credential.stored_in.empty()); form.in_store = *credential.stored_in.begin(); return form; } +PasswordNoteAction CalculatePasswordNoteAction(bool old_note_empty, + bool new_note_empty) { + if (old_note_empty && !new_note_empty) + return PasswordNoteAction::kNoteAddedInEditDialog; + if (!old_note_empty && new_note_empty) + return PasswordNoteAction::kNoteRemovedInEditDialog; + if (!old_note_empty && !new_note_empty) + return PasswordNoteAction::kNoteEditedInEditDialog; + NOTREACHED(); + return PasswordNoteAction::kNoteEditedInEditDialog; +} + } // namespace namespace password_manager { @@ -151,6 +165,10 @@ metrics_util::LogUserInteractionsWhenAddingCredentialFromSettings( metrics_util::AddCredentialFromSettingsUserInteractions:: kCredentialAdded); + if (!form.notes.empty() && form.notes[0].value.length() > 0) { + metrics_util::LogPasswordNoteActionInSettings( + PasswordNoteAction::kNoteAddedInAddDialog); + } return true; } @@ -263,6 +281,7 @@ } if (note_changed) { + bool old_note_empty = false; // if the old note doesn't exist, the note is just created. const auto& note_itr = base::ranges::find_if(new_form.notes, &std::u16string::empty, @@ -270,12 +289,17 @@ if (note_itr == new_form.notes.end()) { new_form.notes.emplace_back(new_note, /*date_created=*/base::Time::Now()); + old_note_empty = true; } else { if (note_itr->value.empty()) { note_itr->date_created = base::Time::Now(); + old_note_empty = true; } note_itr->value = new_note; } + + metrics_util::LogPasswordNoteActionInSettings( + CalculatePasswordNoteAction(old_note_empty, new_note.empty())); } if (username_changed) {
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc index 084b55e3..bdd532ff 100644 --- a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc +++ b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
@@ -139,6 +139,8 @@ PasswordForm form = CreateTestPasswordForm(PasswordForm::Store::kProfileStore); form.url = GURL("https://;/invalid"); + + base::HistogramTester histogram_tester; EXPECT_CALL(observer, OnSavedPasswordsChanged).Times(0); EXPECT_FALSE(presenter().AddPassword(form)); RunUntilIdle(); @@ -149,6 +151,8 @@ EXPECT_FALSE(presenter().AddPassword(form)); RunUntilIdle(); EXPECT_TRUE(store().IsEmpty()); + histogram_tester.ExpectTotalCount( + "PasswordManager.PasswordNoteActionInSettings", 0); presenter().RemoveObserver(&observer); } @@ -160,10 +164,14 @@ PasswordForm form = CreateTestPasswordForm(PasswordForm::Store::kProfileStore); form.password_value = u""; + + base::HistogramTester histogram_tester; EXPECT_CALL(observer, OnSavedPasswordsChanged).Times(0); EXPECT_FALSE(presenter().AddPassword(form)); RunUntilIdle(); EXPECT_TRUE(store().IsEmpty()); + histogram_tester.ExpectTotalCount( + "PasswordManager.PasswordNoteActionInSettings", 0); presenter().RemoveObserver(&observer); } @@ -379,6 +387,8 @@ histogram_tester.ExpectUniqueSample( "PasswordManager.PasswordEditUpdatedValues", metrics_util::PasswordEditUpdatedValues::kPassword, 1); + histogram_tester.ExpectTotalCount( + "PasswordManager.PasswordNoteActionInSettings", 0); presenter().RemoveObserver(&observer); } @@ -396,6 +406,7 @@ const std::u16string kNewNoteValue = u"new note"; + base::HistogramTester histogram_tester; EXPECT_TRUE(presenter().EditSavedPasswords( forms, form.username_value, form.password_value, kNewNoteValue)); RunUntilIdle(); @@ -408,6 +419,9 @@ EXPECT_THAT( store().stored_passwords(), ElementsAre(Pair(form.signon_realm, ElementsAre(expected_updated_form)))); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordNoteActionInSettings", + metrics_util::PasswordNoteAction::kNoteAddedInEditDialog, 1); } TEST_F(SavedPasswordsPresenterTest, EditingNotesShouldNotResetPasswordIssues) { @@ -449,6 +463,7 @@ const std::u16string kNewNoteValue = u"new note"; + base::HistogramTester histogram_tester; EXPECT_TRUE(presenter().EditSavedPasswords( forms, form.username_value, form.password_value, kNewNoteValue)); RunUntilIdle(); @@ -458,6 +473,9 @@ EXPECT_THAT( store().stored_passwords(), ElementsAre(Pair(form.signon_realm, ElementsAre(expected_updated_form)))); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordNoteActionInSettings", + metrics_util::PasswordNoteAction::kNoteEditedInEditDialog, 1); } TEST_F(SavedPasswordsPresenterTest, EditNoteAsEmpty) { @@ -469,6 +487,7 @@ store().AddLogin(form); RunUntilIdle(); + base::HistogramTester histogram_tester; EXPECT_TRUE(presenter().EditSavedPasswords(forms, form.username_value, form.password_value, u"")); RunUntilIdle(); @@ -478,6 +497,9 @@ EXPECT_THAT( store().stored_passwords(), ElementsAre(Pair(form.signon_realm, ElementsAre(expected_updated_form)))); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordNoteActionInSettings", + metrics_util::PasswordNoteAction::kNoteRemovedInEditDialog, 1); } TEST_F(SavedPasswordsPresenterTest, @@ -547,6 +569,8 @@ histogram_tester.ExpectBucketCount( "PasswordManager.PasswordEditUpdatedValues", metrics_util::PasswordEditUpdatedValues::kBoth, 1); + histogram_tester.ExpectTotalCount( + "PasswordManager.PasswordNoteActionInSettings", 0); presenter().RemoveObserver(&observer); } @@ -834,6 +858,51 @@ presenter().RemoveObserver(&observer); } +// Tests AddPassword stores passwords with or without note +TEST_F(SavedPasswordsPresenterWithTwoStoresTest, + AddPasswordStoresNoteIfExists) { + StrictMockSavedPasswordsPresenterObserver observer; + presenter().AddObserver(&observer); + + // Add a password without a note. + PasswordForm form = + CreateTestPasswordForm(PasswordForm::Store::kProfileStore, /*index=*/0); + form.type = password_manager::PasswordForm::Type::kManuallyAdded; + form.date_created = base::Time::Now(); + form.date_password_modified = base::Time::Now(); + + PasswordForm form2 = + CreateTestPasswordForm(PasswordForm::Store::kProfileStore, /*index=*/1); + form2.type = password_manager::PasswordForm::Type::kManuallyAdded; + form2.date_created = base::Time::Now(); + form2.date_password_modified = base::Time::Now(); + form2.notes = {PasswordNote(u"new note", base::Time::Now())}; + + base::HistogramTester histogram_tester; + EXPECT_CALL(observer, OnSavedPasswordsChanged(ElementsAre(form))); + EXPECT_TRUE(presenter().AddPassword(form)); + RunUntilIdle(); + EXPECT_THAT(profile_store().stored_passwords(), + ElementsAre(Pair(form.signon_realm, ElementsAre(form)))); + histogram_tester.ExpectTotalCount( + "PasswordManager.PasswordNoteActionInSettings", 0); + + // Add a password with note. + EXPECT_CALL(observer, + OnSavedPasswordsChanged(UnorderedElementsAre(form, form2))); + EXPECT_TRUE(presenter().AddPassword(form2)); + RunUntilIdle(); + EXPECT_THAT( + profile_store().stored_passwords(), + UnorderedElementsAre(Pair(form.signon_realm, ElementsAre(form)), + Pair(form2.signon_realm, ElementsAre(form2)))); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordNoteActionInSettings", + metrics_util::PasswordNoteAction::kNoteAddedInAddDialog, 1); + + presenter().RemoveObserver(&observer); +} + TEST_F(SavedPasswordsPresenterWithTwoStoresTest, AddPasswordFailWhenUsernameAlreadyExistsForTheSameDomain) { StrictMockSavedPasswordsPresenterObserver observer;
diff --git a/components/reporting/storage/storage.cc b/components/reporting/storage/storage.cc index 93de91a..6856bfd7 100644 --- a/components/reporting/storage/storage.cc +++ b/components/reporting/storage/storage.cc
@@ -455,8 +455,8 @@ directory_, /*recursive=*/false, base::FileEnumerator::FILES, base::StrCat({kEncryptionKeyFilePrefix, FILE_PATH_LITERAL("*")})); - base::FilePath full_name; - while (full_name = dir_enum.Next(), !full_name.empty()) { + for (auto full_name = dir_enum.Next(); !full_name.empty(); + full_name = dir_enum.Next()) { if (!all_key_files->emplace(full_name).second) { // Duplicate file name. Should not happen. continue;
diff --git a/components/services/app_service/public/cpp/instance_registry.h b/components/services/app_service/public/cpp/instance_registry.h index d0f78ea..c367c927 100644 --- a/components/services/app_service/public/cpp/instance_registry.h +++ b/components/services/app_service/public/cpp/instance_registry.h
@@ -66,6 +66,8 @@ // Observe(nullptr)). virtual void OnInstanceRegistryWillBeDestroyed(InstanceRegistry* cache) = 0; + InstanceRegistry* instance_registry() const { return instance_registry_; } + protected: // Use this constructor when the observer |this| is tied to a single // InstanceRegistry for its entire lifetime, or until the observee (the
diff --git a/components/services/app_service/public/cpp/instance_registry_unittest.cc b/components/services/app_service/public/cpp/instance_registry_unittest.cc index 190cb16..cf519dc 100644 --- a/components/services/app_service/public/cpp/instance_registry_unittest.cc +++ b/components/services/app_service/public/cpp/instance_registry_unittest.cc
@@ -87,9 +87,7 @@ class InstanceRecursiveObserver : public apps::InstanceRegistry::Observer { public: explicit InstanceRecursiveObserver(apps::InstanceRegistry* instance_registry) - : instance_registry_(instance_registry) { - Observe(instance_registry); - } + : apps::InstanceRegistry::Observer(instance_registry) {} ~InstanceRecursiveObserver() override = default; @@ -124,7 +122,7 @@ // apps::InstanceRegistry::Observer overrides. void OnInstanceUpdate(const apps::InstanceUpdate& outer) override { int num_instance = 0; - instance_registry_->ForEachInstance( + instance_registry()->ForEachInstance( [&outer, &num_instance](const apps::InstanceUpdate& inner) { if (outer.InstanceId() == inner.InstanceId()) { ExpectEq(outer, inner); @@ -132,12 +130,12 @@ num_instance++; }); - EXPECT_TRUE(instance_registry_->ForOneInstance( + EXPECT_TRUE(instance_registry()->ForOneInstance( outer.InstanceId(), [&outer](const apps::InstanceUpdate& inner) { ExpectEq(outer, inner); })); - EXPECT_TRUE(instance_registry_->ForInstancesWithWindow( + EXPECT_TRUE(instance_registry()->ForInstancesWithWindow( outer.Window(), [&outer](const apps::InstanceUpdate& inner) { if (outer.InstanceId() == inner.InstanceId()) { ExpectEq(outer, inner); @@ -156,7 +154,7 @@ super_recursive_instance_params_.pop_back(); break; } - instance_registry_->CreateOrUpdateInstance(std::move(*params)); + instance_registry()->CreateOrUpdateInstance(std::move(*params)); super_recursive_instance_params_.pop_back(); } @@ -168,7 +166,7 @@ super_recursive_instances_.pop_back(); break; } - instance_registry_->OnInstance(std::move(instance)); + instance_registry()->OnInstance(std::move(instance)); super_recursive_instances_.pop_back(); } @@ -191,7 +189,6 @@ EXPECT_EQ(outer.BrowserContext(), inner.BrowserContext()); } - apps::InstanceRegistry* instance_registry_ = nullptr; int expected_num_instances_ = -1; int num_instances_seen_on_instance_update_ = 0;
diff --git a/components/sync/driver/glue/sync_engine_impl.cc b/components/sync/driver/glue/sync_engine_impl.cc index feb151e..03c85185 100644 --- a/components/sync/driver/glue/sync_engine_impl.cc +++ b/components/sync/driver/glue/sync_engine_impl.cc
@@ -245,6 +245,18 @@ last_poll_time)); } +void SyncEngineImpl::StartHandlingInvalidations() { + if (sync_invalidations_service_) { + // Sync invalidation service must be subscribed to data types by this time. + // Without that, incoming invalidations would be filtered out. + DCHECK(sync_invalidations_service_->GetInterestedDataTypes().has_value()); + + // Adding a listener several times is safe. Only first adding replays last + // incoming messages. + sync_invalidations_service_->AddListener(this); + } +} + void SyncEngineImpl::SetEncryptionPassphrase( const std::string& passphrase, const KeyDerivationParams& key_derivation_params) { @@ -433,10 +445,6 @@ invalidation::InvalidatorState::INVALIDATIONS_ENABLED); } - if (sync_invalidations_service_) { - sync_invalidations_service_->AddListener(this); - } - active_devices_provider_->SetActiveDevicesChangedCallback(base::BindRepeating( &SyncEngineImpl::OnActiveDevicesChanged, weak_ptr_factory_.GetWeakPtr())); @@ -578,15 +586,18 @@ void SyncEngineImpl::OnInvalidationReceived(const std::string& payload) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug.com/1082122): check that sync engine is fully initialized and - // store incoming invalidations until then. + + absl::optional<ModelTypeSet> interested_data_types = + sync_invalidations_service_->GetInterestedDataTypes(); + + // Interested data types must be initialized before handling invalidations to + // prevent missing incoming invalidations which were received during + // configuration. + DCHECK(interested_data_types.has_value()); sync_task_runner_->PostTask( FROM_HERE, - base::BindOnce( - &SyncEngineBackend::DoOnStandaloneInvalidationReceived, backend_, - payload, - sync_invalidations_service_->GetInterestedDataTypes().value_or( - ModelTypeSet()))); + base::BindOnce(&SyncEngineBackend::DoOnStandaloneInvalidationReceived, + backend_, payload, *interested_data_types)); } // static
diff --git a/components/sync/driver/glue/sync_engine_impl.h b/components/sync/driver/glue/sync_engine_impl.h index a672e96..18ff8ea8 100644 --- a/components/sync/driver/glue/sync_engine_impl.h +++ b/components/sync/driver/glue/sync_engine_impl.h
@@ -75,6 +75,7 @@ base::Time GetLastSyncedTimeForDebugging() const override; void StartConfiguration() override; void StartSyncingWithServer() override; + void StartHandlingInvalidations() override; void SetEncryptionPassphrase( const std::string& passphrase, const KeyDerivationParams& key_derivation_params) override;
diff --git a/components/sync/driver/glue/sync_engine_impl_unittest.cc b/components/sync/driver/glue/sync_engine_impl_unittest.cc index b9ada85..f5bf5e6c 100644 --- a/components/sync/driver/glue/sync_engine_impl_unittest.cc +++ b/components/sync/driver/glue/sync_engine_impl_unittest.cc
@@ -294,6 +294,8 @@ void DownloadReady(ModelTypeSet succeeded_types, ModelTypeSet failed_types) { engine_types_.PutAll(succeeded_types); + + backend_->StartSyncingWithServer(); std::move(quit_loop_).Run(); } @@ -678,8 +680,8 @@ ShouldInvalidateDataTypesOnIncomingInvalidation) { enabled_types_.PutAll({syncer::BOOKMARKS, syncer::PREFERENCES}); - EXPECT_CALL(mock_sync_invalidations_service_, AddListener(backend_.get())); InitializeBackend(/*expect_success=*/true); + ConfigureDataTypes(); sync_pb::SyncInvalidationsPayload payload; sync_pb::SyncInvalidationsPayload::DataTypeInvalidation* @@ -705,7 +707,6 @@ enabled_types_.Remove(syncer::BOOKMARKS); enabled_types_.Put(syncer::PREFERENCES); - EXPECT_CALL(mock_sync_invalidations_service_, AddListener(backend_.get())); InitializeBackend(/*expect_success=*/true); ConfigureDataTypes(); @@ -728,10 +729,20 @@ EXPECT_EQ(1, fake_manager_->GetInvalidationCount(ModelType::PREFERENCES)); } +TEST_F(SyncEngineImplWithSyncInvalidationsForWalletAndOfferTest, + ShouldStartHandlingInvalidations) { + ON_CALL(mock_sync_invalidations_service_, GetInterestedDataTypes()) + .WillByDefault(Return(enabled_types_)); + EXPECT_CALL(mock_sync_invalidations_service_, AddListener(backend_.get())); + backend_->StartHandlingInvalidations(); +} + TEST_F(SyncEngineImplWithSyncInvalidationsTest, UseOldInvalidationsOnlyForWalletAndOffer) { enabled_types_.PutAll({AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_OFFER}); + EXPECT_CALL(mock_sync_invalidations_service_, GetInterestedDataTypes()) + .WillRepeatedly(Return(enabled_types_)); InitializeBackend(/*expect_success=*/true); EXPECT_CALL( invalidator_, @@ -756,6 +767,8 @@ EXPECT_CALL(invalidator_, UpdateInterestedTopics(_, invalidation::TopicSet())); EXPECT_CALL(invalidator_, UnsubscribeFromUnregisteredTopics); + EXPECT_CALL(mock_sync_invalidations_service_, GetInterestedDataTypes()) + .WillRepeatedly(Return(enabled_types_)); InitializeBackend(/*expect_success=*/true); EXPECT_CALL(invalidator_, UpdateInterestedTopics).Times(0);
diff --git a/components/sync/driver/sync_service_impl.cc b/components/sync/driver/sync_service_impl.cc index 8bc9671..d147589 100644 --- a/components/sync/driver/sync_service_impl.cc +++ b/components/sync/driver/sync_service_impl.cc
@@ -914,7 +914,12 @@ NotifyObservers(); + // Update configured data types and start handling incoming invalidations. The + // order is important to guarantee that data types are configured to prevent + // filtering out invalidations. If there are incoming invalidations, they will + // be handled immediately after StartHandlingInvalidations() call. UpdateDataTypesForInvalidations(); + engine_->StartHandlingInvalidations(); if (migrator_.get() && migrator_->state() != BackendMigrator::IDLE) { // Migration in progress. Let the migrator know we just finished
diff --git a/components/sync/driver/sync_service_impl_unittest.cc b/components/sync/driver/sync_service_impl_unittest.cc index f7d8dfc..453aa8e 100644 --- a/components/sync/driver/sync_service_impl_unittest.cc +++ b/components/sync/driver/sync_service_impl_unittest.cc
@@ -1138,6 +1138,7 @@ SetInterestedDataTypes(AllOf(ContainsDataType(BOOKMARKS), ContainsDataType(DEVICE_INFO)))); InitializeForNthSync(); + EXPECT_TRUE(engine()->started_handling_invalidations()); } TEST_F(SyncServiceImplTestWithSyncInvalidationsServiceCreated,
diff --git a/components/sync/engine/sync_engine.h b/components/sync/engine/sync_engine.h index 8152d999..52e0f8f1 100644 --- a/components/sync/engine/sync_engine.h +++ b/components/sync/engine/sync_engine.h
@@ -114,6 +114,10 @@ // browser from the cloud / sync servers. virtual void StartSyncingWithServer() = 0; + // Starts handling incoming standalone invalidations. This method must be + // called when data types are configured. + virtual void StartHandlingInvalidations() = 0; + // Asynchronously set a new passphrase for encryption. Note that it is an // error to call SetEncryptionPassphrase under the following circumstances: // - An explicit passphrase has already been set
diff --git a/components/sync/invalidations/fcm_handler.cc b/components/sync/invalidations/fcm_handler.cc index 188c579..03044bb 100644 --- a/components/sync/invalidations/fcm_handler.cc +++ b/components/sync/invalidations/fcm_handler.cc
@@ -101,6 +101,9 @@ void FCMHandler::AddListener(InvalidationsListener* listener) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (listeners_.HasObserver(listener)) { + return; + } listeners_.AddObserver(listener); // Immediately replay any buffered messages received before the |listener|
diff --git a/components/sync/invalidations/fcm_handler.h b/components/sync/invalidations/fcm_handler.h index 874b7e9..2bdad61b 100644 --- a/components/sync/invalidations/fcm_handler.h +++ b/components/sync/invalidations/fcm_handler.h
@@ -59,10 +59,14 @@ // Returns if the handler is listening for incoming invalidations. bool IsListening() const; - // Add or remove a new listener which will be notified on each new incoming - // invalidation. |listener| must not be nullptr. When added, some previously - // received messages will be immediately replayed. + // Add a new |listener| which will be notified on each new incoming + // invalidation. |listener| must not be nullptr. Does nothing if the + // |listener| has already been added before. When a new |listener| is added, + // previously received messages will be immediately replayed. void AddListener(InvalidationsListener* listener); + + // Removes |listener|, does nothing if it wasn't added before. |listener| must + // not be nullptr. void RemoveListener(InvalidationsListener* listener); // Add or remove an FCM token change observer. |observer| must not be nullptr.
diff --git a/components/sync/invalidations/fcm_handler_unittest.cc b/components/sync/invalidations/fcm_handler_unittest.cc index 7260b7c..32a0521 100644 --- a/components/sync/invalidations/fcm_handler_unittest.cc +++ b/components/sync/invalidations/fcm_handler_unittest.cc
@@ -266,6 +266,9 @@ EXPECT_CALL(mock_listener, OnInvalidationReceived(kPayloadValue1)); EXPECT_CALL(mock_listener, OnInvalidationReceived(kPayloadValue2)); fcm_handler_.AddListener(&mock_listener); + + // Adding the same listener twice should have no effect. + fcm_handler_.AddListener(&mock_listener); fcm_handler_.RemoveListener(&mock_listener); }
diff --git a/components/sync/invalidations/sync_invalidations_service.h b/components/sync/invalidations/sync_invalidations_service.h index 2e11947..c312831 100644 --- a/components/sync/invalidations/sync_invalidations_service.h +++ b/components/sync/invalidations/sync_invalidations_service.h
@@ -32,10 +32,14 @@ // Start or stop listening to invalidations. virtual void SetActive(bool active) = 0; - // Add or remove a new listener which will be notified on each new incoming - // invalidation. |listener| must not be nullptr. If there is no such - // |listener| then RemoveListener will do nothing. + // Add a new |listener| which will be notified on each new incoming + // invalidation. |listener| must not be nullptr. Does nothing if the + // |listener| has already been added before. When a new |listener| is added, + // previously received messages will be immediately replayed. virtual void AddListener(InvalidationsListener* listener) = 0; + + // Removes |listener|, does nothing if it wasn't added before. |listener| must + // not be nullptr. virtual void RemoveListener(InvalidationsListener* listener) = 0; // Add or remove an FCM token change observer. |observer| must not be nullptr.
diff --git a/components/sync/test/engine/fake_sync_engine.cc b/components/sync/test/engine/fake_sync_engine.cc index aa81553..d8bb2de2 100644 --- a/components/sync/test/engine/fake_sync_engine.cc +++ b/components/sync/test/engine/fake_sync_engine.cc
@@ -72,6 +72,10 @@ void FakeSyncEngine::StartSyncingWithServer() {} +void FakeSyncEngine::StartHandlingInvalidations() { + started_handling_invalidations_ = true; +} + void FakeSyncEngine::SetEncryptionPassphrase( const std::string& passphrase, const KeyDerivationParams& key_derivation_params) {}
diff --git a/components/sync/test/engine/fake_sync_engine.h b/components/sync/test/engine/fake_sync_engine.h index 6565d46a..9617bbd3 100644 --- a/components/sync/test/engine/fake_sync_engine.h +++ b/components/sync/test/engine/fake_sync_engine.h
@@ -39,6 +39,10 @@ return authenticated_account_id_; } + bool started_handling_invalidations() { + return started_handling_invalidations_; + } + // Manual completion of Initialize(), required if auto-completion was disabled // in the constructor. void TriggerInitializationCompletion(bool success); @@ -62,6 +66,8 @@ void StartConfiguration() override; + void StartHandlingInvalidations() override; + void StartSyncingWithServer() override; void SetEncryptionPassphrase( @@ -109,6 +115,7 @@ bool initialized_ = false; const SyncStatus default_sync_status_; CoreAccountId authenticated_account_id_; + bool started_handling_invalidations_ = false; }; } // namespace syncer
diff --git a/components/sync/test/engine/mock_sync_engine.h b/components/sync/test/engine/mock_sync_engine.h index 15ecc14..98119d9 100644 --- a/components/sync/test/engine/mock_sync_engine.h +++ b/components/sync/test/engine/mock_sync_engine.h
@@ -46,6 +46,7 @@ MOCK_METHOD(base::Time, GetLastSyncedTimeForDebugging, (), (const override)); MOCK_METHOD(void, StartConfiguration, (), (override)); MOCK_METHOD(void, StartSyncingWithServer, (), (override)); + MOCK_METHOD(void, StartHandlingInvalidations, (), (override)); MOCK_METHOD(void, SetEncryptionPassphrase, (const std::string&, const KeyDerivationParams&),
diff --git a/components/viz/common/resources/transferable_resource.h b/components/viz/common/resources/transferable_resource.h index 6d4d7ec..4f07426 100644 --- a/components/viz/common/resources/transferable_resource.h +++ b/components/viz/common/resources/transferable_resource.h
@@ -38,6 +38,9 @@ // other words, the resource will be returned only when gpu commands are // completed. kGpuCommandsCompleted, + // Commands submitted (release fence) - a resource will be returned after + // gpu service submitted commands to the gpu and provide the fence. + kReleaseFence, }; TransferableResource();
diff --git a/components/viz/service/display/display_resource_provider.cc b/components/viz/service/display/display_resource_provider.cc index 766002c..6f80ebf 100644 --- a/components/viz/service/display/display_resource_provider.cc +++ b/components/viz/service/display/display_resource_provider.cc
@@ -8,6 +8,7 @@ #include <string> #include "base/atomic_sequence_num.h" +#include "base/notreached.h" #include "base/numerics/safe_math.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" @@ -306,9 +307,9 @@ } } -bool DisplayResourceProvider::ReadLockFenceHasPassed( +bool DisplayResourceProvider::ResourceFenceHasPassed( const ChildResource* resource) { - return !resource->read_lock_fence || resource->read_lock_fence->HasPassed(); + return !resource->resource_fence || resource->resource_fence->HasPassed(); } DisplayResourceProvider::CanDeleteNowResult @@ -322,7 +323,7 @@ // Defer this resource deletion. return CanDeleteNowResult::kNo; - } else if (!ReadLockFenceHasPassed(&resource)) { + } else if (!ResourceFenceHasPassed(&resource)) { // TODO(dcastagna): see if it's possible to use this logic for // the branch above too, where the resource is locked or still exported. // We can't postpone the deletion, so we'll have to lose it.
diff --git a/components/viz/service/display/display_resource_provider.h b/components/viz/service/display/display_resource_provider.h index 5d89762..be07f99 100644 --- a/components/viz/service/display/display_resource_provider.h +++ b/components/viz/service/display/display_resource_provider.h
@@ -162,10 +162,16 @@ // Sets the current read fence. If a resource is locked for read // and has read fences enabled, the resource will not allow writes - // until this fence has passed. - void SetReadLockFence(ResourceFence* fence) { - current_read_lock_fence_ = fence; + // until this fence has passed. This is used if a client uses + // TransferableResource::SynchronizationType::kGpuCommandsCompleted. + void SetGpuCommandsCompletedFence(ResourceFence* fence) { + current_gpu_commands_completed_fence_ = fence; } + // Sets the current release fence. If a client uses + // TransferableResource::SynchronizationType::kReleaseFence, resources must be + // returned only after a release fence is stored in this resource fence. + // Returned only when gpu commands and the gpu fence are submitted. + void SetReleaseFence(ResourceFence* fence) { current_release_fence_ = fence; } // Creates accounting for a child. Returns a child ID. surface_id is used to // associate resources to the surface they belong to. This is used for @@ -333,12 +339,14 @@ // mapped for use in the display compositor. base::UnguessableToken shared_bitmap_tracing_guid; - // A fence used for accessing a gpu resource for reading, that ensures any - // writing done to the resource has been completed. This is implemented and - // used to implement transferring ownership of the resource from the client - // to the service, and in the GL drawing code before reading from the - // texture. - scoped_refptr<ResourceFence> read_lock_fence; + // A fence used for returning resources after the display compositor has + // completed accessing the resources it received from a client. This can + // either be a read lock or a release fence. If the |transferable| has + // synchronization type set as kGpuCommandsCompleted, the resource can be + // returned after ResourceFence::HasPassed is true. If the |transferable| + // has the synchronization type set as kReleaseFence, the resource can be + // returned after the fence has a release fence set. + scoped_refptr<ResourceFence> resource_fence; // SkiaRenderer specific details about this resource. Added to ChildResource // to avoid map lookups further down the pipeline. @@ -371,10 +379,7 @@ ChildResource* TryGetResource(ResourceId id); void TryReleaseResource(ResourceId id, ChildResource* resource); - // Binds the given GL resource to a texture target for sampling using the - // specified filter for both minification and magnification. Returns the - // texture target used. The resource must be locked for reading. - bool ReadLockFenceHasPassed(const ChildResource* resource); + bool ResourceFenceHasPassed(const ChildResource* resource); void DeleteAndReturnUnusedResourcesToChild( ChildMap::iterator child_it, @@ -404,7 +409,8 @@ ChildMap children_; base::flat_map<int, std::vector<ResourceId>> batched_returning_resources_; - scoped_refptr<ResourceFence> current_read_lock_fence_; + scoped_refptr<ResourceFence> current_gpu_commands_completed_fence_; + scoped_refptr<ResourceFence> current_release_fence_; // Keep track of whether deleted resources should be batched up or returned // immediately. int batch_return_resources_lock_count_ = 0;
diff --git a/components/viz/service/display/display_resource_provider_skia.cc b/components/viz/service/display/display_resource_provider_skia.cc index fcd0506f..6e4ea305 100644 --- a/components/viz/service/display/display_resource_provider_skia.cc +++ b/components/viz/service/display/display_resource_provider_skia.cc
@@ -84,6 +84,13 @@ continue; } + if (resource.transferable.synchronization_type == + TransferableResource::SynchronizationType::kReleaseFence) { + // The resource might have never been used. + if (resource.resource_fence) + resource.release_fence = resource.resource_fence->GetGpuFenceHandle(); + } + const bool is_lost = can_delete == CanDeleteNowResult::kYesButLoseResource; to_return.emplace_back(child_id, resource.sync_token(), @@ -167,12 +174,20 @@ } resource.locked_for_external_use = true; - if (resource.transferable.synchronization_type == - TransferableResource::SynchronizationType::kGpuCommandsCompleted) { - if (resource_provider_->current_read_lock_fence_.get()) - resource_provider_->current_read_lock_fence_->Set(); - resource.read_lock_fence = resource_provider_->current_read_lock_fence_; + switch (resource.transferable.synchronization_type) { + case TransferableResource::SynchronizationType::kGpuCommandsCompleted: + resource.resource_fence = + resource_provider_->current_gpu_commands_completed_fence_; + break; + case TransferableResource::SynchronizationType::kReleaseFence: + resource.resource_fence = resource_provider_->current_release_fence_; + break; + default: + break; } + + if (resource.resource_fence) + resource.resource_fence->Set(); } DCHECK(base::Contains(resources_, std::make_pair(id, &resource)));
diff --git a/components/viz/service/display/display_resource_provider_skia_unittest.cc b/components/viz/service/display/display_resource_provider_skia_unittest.cc index 6a1486cd..878db98 100644 --- a/components/viz/service/display/display_resource_provider_skia_unittest.cc +++ b/components/viz/service/display/display_resource_provider_skia_unittest.cc
@@ -17,10 +17,12 @@ #include "base/callback_helpers.h" #include "base/check.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "build/build_config.h" #include "components/viz/client/client_resource_provider.h" #include "components/viz/common/resources/release_callback.h" #include "components/viz/common/resources/returned_resource.h" +#include "components/viz/common/resources/transferable_resource.h" #include "components/viz/test/test_context_provider.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,6 +31,7 @@ #include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/skia/include/core/SkColorSpace.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/gpu_fence_handle.h" using testing::_; using testing::ByMove; @@ -296,138 +299,218 @@ child_resource_provider_->RemoveImportedResource(id1); } -class TestFence : public ResourceFence { +class TestGpuCommandsCompletedFence : public ResourceFence { public: - TestFence() = default; + TestGpuCommandsCompletedFence() = default; // ResourceFence implementation. void Set() override {} bool HasPassed() override { return passed; } + gfx::GpuFenceHandle GetGpuFenceHandle() override { + NOTREACHED(); + return gfx::GpuFenceHandle(); + } bool passed = false; private: - ~TestFence() override = default; + ~TestGpuCommandsCompletedFence() override = default; +}; + +class TestReleaseFence : public ResourceFence { + public: + TestReleaseFence() = default; + + // ResourceFence implementation. + void Set() override {} + bool HasPassed() override { return release_fence_.has_value(); } + gfx::GpuFenceHandle GetGpuFenceHandle() override { + return HasPassed() ? release_fence_->Clone() : gfx::GpuFenceHandle(); + } + + void SetReleaseFence(gfx::GpuFenceHandle release_fence) { + release_fence_ = std::move(release_fence); + } + + private: + ~TestReleaseFence() override = default; + + absl::optional<gfx::GpuFenceHandle> release_fence_; }; TEST_F(DisplayResourceProviderSkiaTest, - ReadLockFenceStopsReturnToChildOrDelete) { - MockReleaseCallback release; - TransferableResource tran1 = CreateResource(RGBA_8888); - tran1.synchronization_type = - TransferableResource::SynchronizationType::kGpuCommandsCompleted; - ResourceId id1 = child_resource_provider_->ImportResource( - tran1, base::BindOnce(&MockReleaseCallback::Released, - base::Unretained(&release))); + ResourceFenceStopsReturnToChildOrDelete) { + const std::vector<TransferableResource::SynchronizationType> + kSynchronizationTypes = { + TransferableResource::SynchronizationType::kGpuCommandsCompleted, + TransferableResource::SynchronizationType::kReleaseFence}; + for (auto sync_type : kSynchronizationTypes) { + MockReleaseCallback release; + TransferableResource tran1 = CreateResource(RGBA_8888); + tran1.synchronization_type = sync_type; + ResourceId id1 = child_resource_provider_->ImportResource( + tran1, base::BindOnce(&MockReleaseCallback::Released, + base::Unretained(&release))); - std::vector<ReturnedResource> returned_to_child; - int child_id = resource_provider_->CreateChild( - GetReturnCallback(&returned_to_child), SurfaceId()); + std::vector<ReturnedResource> returned_to_child; + int child_id = resource_provider_->CreateChild( + GetReturnCallback(&returned_to_child), SurfaceId()); - // Transfer some resources to the parent. - std::vector<TransferableResource> list; - child_resource_provider_->PrepareSendToParent( - {id1}, &list, - static_cast<RasterContextProvider*>(child_context_provider_.get())); - ASSERT_EQ(1u, list.size()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_EQ(list[0].synchronization_type, - TransferableResource::SynchronizationType::kGpuCommandsCompleted); + // Transfer some resources to the parent. + std::vector<TransferableResource> list; + child_resource_provider_->PrepareSendToParent( + {id1}, &list, + static_cast<RasterContextProvider*>(child_context_provider_.get())); + ASSERT_EQ(1u, list.size()); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_EQ(list[0].synchronization_type, sync_type); - resource_provider_->ReceiveFromChild(child_id, list); + resource_provider_->ReceiveFromChild(child_id, list); - // In DisplayResourceProvider's namespace, use the mapped resource id. - std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map = - resource_provider_->GetChildToParentMap(child_id); + // In DisplayResourceProvider's namespace, use the mapped resource id. + std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map = + resource_provider_->GetChildToParentMap(child_id); - scoped_refptr<TestFence> fence(new TestFence); - resource_provider_->SetReadLockFence(fence.get()); - { - ResourceId parent_id = resource_map[list.front().id]; - lock_set_->LockResource(parent_id, /*maybe_concurrent_reads=*/true, - /*is_video_plane=*/false); - lock_set_->UnlockResources(GenSyncToken()); - } - resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet()); - EXPECT_EQ(0u, returned_to_child.size()); + scoped_refptr<ResourceFence> fence; + TestGpuCommandsCompletedFence* gpu_commands_completed_fence = nullptr; + TestReleaseFence* release_fence = nullptr; + if (sync_type == + TransferableResource::SynchronizationType::kGpuCommandsCompleted) { + fence = base::MakeRefCounted<TestGpuCommandsCompletedFence>(); + gpu_commands_completed_fence = + static_cast<TestGpuCommandsCompletedFence*>(fence.get()); + resource_provider_->SetGpuCommandsCompletedFence(fence.get()); + } else { + ASSERT_EQ(TransferableResource::SynchronizationType::kReleaseFence, + sync_type); + fence = base::MakeRefCounted<TestReleaseFence>(); + release_fence = static_cast<TestReleaseFence*>(fence.get()); + resource_provider_->SetReleaseFence(fence.get()); + } - resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet()); - EXPECT_EQ(0u, returned_to_child.size()); - fence->passed = true; - - resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet()); - EXPECT_EQ(1u, returned_to_child.size()); - - child_resource_provider_->ReceiveReturnsFromParent( - std::move(returned_to_child)); - EXPECT_CALL(release, Released(_, _)); - child_resource_provider_->RemoveImportedResource(id1); -} - -TEST_F(DisplayResourceProviderSkiaTest, ReadLockFenceDestroyChild) { - MockReleaseCallback release; - - TransferableResource tran1 = CreateResource(RGBA_8888); - tran1.synchronization_type = - TransferableResource::SynchronizationType::kGpuCommandsCompleted; - ResourceId id1 = child_resource_provider_->ImportResource( - tran1, base::BindOnce(&MockReleaseCallback::Released, - base::Unretained(&release))); - - TransferableResource tran2 = CreateResource(RGBA_8888); - ASSERT_EQ(tran2.synchronization_type, - TransferableResource::SynchronizationType::kSyncToken); - ResourceId id2 = child_resource_provider_->ImportResource( - tran2, base::BindOnce(&MockReleaseCallback::Released, - base::Unretained(&release))); - - std::vector<ReturnedResource> returned_to_child; - int child_id = resource_provider_->CreateChild( - GetReturnCallback(&returned_to_child), SurfaceId()); - - // Transfer resources to the parent. - std::vector<TransferableResource> list; - child_resource_provider_->PrepareSendToParent( - {id1, id2}, &list, - static_cast<RasterContextProvider*>(child_context_provider_.get())); - ASSERT_EQ(2u, list.size()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - - resource_provider_->ReceiveFromChild(child_id, list); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map = - resource_provider_->GetChildToParentMap(child_id); - - scoped_refptr<TestFence> fence(new TestFence); - resource_provider_->SetReadLockFence(fence.get()); - { - for (auto& resource : list) { - ResourceId parent_id = resource_map[resource.id]; + { + ResourceId parent_id = resource_map[list.front().id]; lock_set_->LockResource(parent_id, /*maybe_concurrent_reads=*/true, /*is_video_plane=*/false); + lock_set_->UnlockResources(GenSyncToken()); } - lock_set_->UnlockResources(GenSyncToken()); + + resource_provider_->DeclareUsedResourcesFromChild(child_id, + ResourceIdSet()); + EXPECT_EQ(0u, returned_to_child.size()); + + resource_provider_->DeclareUsedResourcesFromChild(child_id, + ResourceIdSet()); + EXPECT_EQ(0u, returned_to_child.size()); + + if (gpu_commands_completed_fence) { + gpu_commands_completed_fence->passed = true; + } else { + gfx::GpuFenceHandle fake_handle; +#if BUILDFLAG(IS_POSIX) + const int32_t kFenceFd = dup(1); + fake_handle.owned_fd.reset(kFenceFd); +#endif + release_fence->SetReleaseFence(std::move(fake_handle)); + } + + resource_provider_->DeclareUsedResourcesFromChild(child_id, + ResourceIdSet()); + EXPECT_EQ(1u, returned_to_child.size()); + +#if BUILDFLAG(IS_POSIX) + if (release_fence) + EXPECT_FALSE(returned_to_child.begin()->release_fence.is_null()); + else + EXPECT_TRUE(returned_to_child.begin()->release_fence.is_null()); +#endif + + child_resource_provider_->ReceiveReturnsFromParent( + std::move(returned_to_child)); + EXPECT_CALL(release, Released(_, _)); + child_resource_provider_->RemoveImportedResource(id1); } - EXPECT_EQ(0u, returned_to_child.size()); +} - EXPECT_EQ(2u, resource_provider_->num_resources()); +TEST_F(DisplayResourceProviderSkiaTest, ResourceFenceDestroyChild) { + const std::vector<TransferableResource::SynchronizationType> + kSynchronizationTypes = { + TransferableResource::SynchronizationType::kGpuCommandsCompleted, + TransferableResource::SynchronizationType::kReleaseFence}; + for (auto sync_type : kSynchronizationTypes) { + MockReleaseCallback release; - resource_provider_->DestroyChild(child_id); + TransferableResource tran1 = CreateResource(RGBA_8888); + tran1.synchronization_type = sync_type; + ResourceId id1 = child_resource_provider_->ImportResource( + tran1, base::BindOnce(&MockReleaseCallback::Released, + base::Unretained(&release))); - EXPECT_EQ(0u, resource_provider_->num_resources()); - EXPECT_EQ(2u, returned_to_child.size()); + TransferableResource tran2 = CreateResource(RGBA_8888); + ASSERT_EQ(tran2.synchronization_type, + TransferableResource::SynchronizationType::kSyncToken); + ResourceId id2 = child_resource_provider_->ImportResource( + tran2, base::BindOnce(&MockReleaseCallback::Released, + base::Unretained(&release))); - // id1 should be lost and id2 should not. - EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1); - EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1); + std::vector<ReturnedResource> returned_to_child; + int child_id = resource_provider_->CreateChild( + GetReturnCallback(&returned_to_child), SurfaceId()); - child_resource_provider_->ReceiveReturnsFromParent( - std::move(returned_to_child)); - EXPECT_CALL(release, Released(_, _)).Times(2); - child_resource_provider_->RemoveImportedResource(id1); - child_resource_provider_->RemoveImportedResource(id2); + // Transfer resources to the parent. + std::vector<TransferableResource> list; + child_resource_provider_->PrepareSendToParent( + {id1, id2}, &list, + static_cast<RasterContextProvider*>(child_context_provider_.get())); + ASSERT_EQ(2u, list.size()); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); + + resource_provider_->ReceiveFromChild(child_id, list); + + // In DisplayResourceProvider's namespace, use the mapped resource id. + std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map = + resource_provider_->GetChildToParentMap(child_id); + + scoped_refptr<ResourceFence> fence; + if (sync_type == + TransferableResource::SynchronizationType::kGpuCommandsCompleted) { + fence = base::MakeRefCounted<TestGpuCommandsCompletedFence>(); + resource_provider_->SetGpuCommandsCompletedFence(fence.get()); + } else { + ASSERT_EQ(TransferableResource::SynchronizationType::kReleaseFence, + sync_type); + fence = base::MakeRefCounted<TestReleaseFence>(); + resource_provider_->SetReleaseFence(fence.get()); + } + + { + for (auto& resource : list) { + ResourceId parent_id = resource_map[resource.id]; + lock_set_->LockResource(parent_id, /*maybe_concurrent_reads=*/true, + /*is_video_plane=*/false); + } + lock_set_->UnlockResources(GenSyncToken()); + } + EXPECT_EQ(0u, returned_to_child.size()); + + EXPECT_EQ(2u, resource_provider_->num_resources()); + + resource_provider_->DestroyChild(child_id); + + EXPECT_EQ(0u, resource_provider_->num_resources()); + EXPECT_EQ(2u, returned_to_child.size()); + + // id1 should be lost and id2 should not. + EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1); + EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1); + + child_resource_provider_->ReceiveReturnsFromParent( + std::move(returned_to_child)); + EXPECT_CALL(release, Released(_, _)).Times(2); + child_resource_provider_->RemoveImportedResource(id1); + child_resource_provider_->RemoveImportedResource(id2); + } } // Test that ScopedBatchReturnResources batching works.
diff --git a/components/viz/service/display/resource_fence.h b/components/viz/service/display/resource_fence.h index dc4153e..59e1101 100644 --- a/components/viz/service/display/resource_fence.h +++ b/components/viz/service/display/resource_fence.h
@@ -7,6 +7,8 @@ #include "base/memory/ref_counted.h" +#include "ui/gfx/gpu_fence_handle.h" + namespace viz { // An abstract interface used to ensure reading from resources passed between @@ -16,8 +18,16 @@ ResourceFence(const ResourceFence&) = delete; ResourceFence& operator=(const ResourceFence&) = delete; + // Notifies the fence is needed. virtual void Set() = 0; + // Tells if the fence is ready. virtual bool HasPassed() = 0; + // A release fence which availability depends on the type of resource fence + // (managed by DisplayResourceProvider and + // TransferableResource::synchronization_type). The client must ensure that + // HasPassed is true before trying to access the release fence handle. + // Otherwise, it's not guaranteed that the fence handle is valid. + virtual gfx::GpuFenceHandle GetGpuFenceHandle() = 0; protected: friend class base::RefCountedThreadSafe<ResourceFence>;
diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h index 2378966..a6557e3 100644 --- a/components/viz/service/display/skia_output_surface.h +++ b/components/viz/service/display/skia_output_surface.h
@@ -17,6 +17,7 @@ #include "components/viz/service/display/overlay_processor_interface.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkYUVAInfo.h" +#include "ui/gfx/gpu_fence_handle.h" #if BUILDFLAG(IS_WIN) #include "components/viz/service/display/dc_layer_overlay.h" @@ -129,8 +130,13 @@ // play the DDL back on GPU thread on a cached SkSurface. // Optionally the caller may specify |on_finished| callback to be called after // the GPU has finished processing all submitted commands. The callback may be - // called on a different thread. - virtual void EndPaint(base::OnceClosure on_finished) = 0; + // called on a different thread. The caller may also specify + // |return_release_fence_cb| callback to be called after all commands are + // submitted. The callback will return the release fence which will be + // signaled once the submitted commands are processed. + virtual void EndPaint(base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> + return_release_fence_cb) = 0; // Make a promise SkImage from a render pass id. The render pass has been // painted with BeginPaintRenderPass and FinishPaintRenderPass. The format
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 7d5298d..059a1a4b 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -700,22 +700,30 @@ sk_sp<SkImage> sk_image_; }; -class SkiaRenderer::FrameResourceFence : public ResourceFence { +// A read lock based fence that is signaled after gpu commands are completed +// meaning the resource has been read. +class SkiaRenderer::FrameResourceGpuCommandsCompletedFence + : public ResourceFence { public: - FrameResourceFence() = default; - - FrameResourceFence(const FrameResourceFence&) = delete; - FrameResourceFence& operator=(const FrameResourceFence&) = delete; + FrameResourceGpuCommandsCompletedFence() = default; + FrameResourceGpuCommandsCompletedFence( + const FrameResourceGpuCommandsCompletedFence&) = delete; + FrameResourceGpuCommandsCompletedFence& operator=( + const FrameResourceGpuCommandsCompletedFence&) = delete; // ResourceFence implementation. void Set() override { set_ = true; } bool HasPassed() override { return event_.IsSignaled(); } + gfx::GpuFenceHandle GetGpuFenceHandle() override { + NOTREACHED(); + return gfx::GpuFenceHandle(); + } bool WasSet() { return set_; } void Signal() { event_.Signal(); } private: - ~FrameResourceFence() override = default; + ~FrameResourceGpuCommandsCompletedFence() override = default; // Accessed only from compositor thread. bool set_ = false; @@ -723,6 +731,41 @@ base::WaitableEvent event_; }; +// FrameResourceFence that gets a ReleaseFence which is later set to returned +// resources. +class SkiaRenderer::FrameResourceReleaseFence : public ResourceFence { + public: + FrameResourceReleaseFence() = default; + FrameResourceReleaseFence(const FrameResourceReleaseFence&) = delete; + FrameResourceReleaseFence& operator=(const FrameResourceReleaseFence&) = + delete; + + // ResourceFence implementation: + void Set() override { set_ = true; } + // If the fence handle has been set, |this| has passed aka the callback has + // been called. + bool HasPassed() override { return release_fence_.has_value(); } + gfx::GpuFenceHandle GetGpuFenceHandle() override { + return HasPassed() ? release_fence_.value().Clone() : gfx::GpuFenceHandle(); + } + + bool WasSet() { return set_; } + void SetReleaseFenceCallback(gfx::GpuFenceHandle release_fence) { + release_fence_ = std::move(release_fence); + } + + private: + ~FrameResourceReleaseFence() override = default; + + // Accessed only from compositor thread. + bool set_ = false; + + // This is made optional so that the value is set after + // SetReleaseFenceCallback is called. Otherwise, there is no way to know if + // the fence has been set and a null handle is a "valid" handle. + absl::optional<gfx::GpuFenceHandle> release_fence_; +}; + SkiaRenderer::SkiaRenderer(const RendererSettings* settings, const DebugRendererSettings* debug_settings, OutputSurface* output_surface, @@ -739,9 +782,17 @@ DCHECK(skia_output_surface_); lock_set_for_external_use_.emplace(resource_provider, skia_output_surface_); - current_frame_resource_fence_ = base::MakeRefCounted<FrameResourceFence>(); - this->resource_provider()->SetReadLockFence( - current_frame_resource_fence_.get()); + // There can be different synchronization types requested for different + // resources. Some of them may require SyncToken, others - ReadLockFence, and + // others may need ReleaseFence. SyncTokens are set when the output surface + // is flushed and external resources are released. However, other resources + // require additional setup, which helps to handle that. + current_gpu_commands_completed_fence_ = + base::MakeRefCounted<FrameResourceGpuCommandsCompletedFence>(); + current_release_fence_ = base::MakeRefCounted<FrameResourceReleaseFence>(); + this->resource_provider()->SetGpuCommandsCompletedFence( + current_gpu_commands_completed_fence_.get()); + this->resource_provider()->SetReleaseFence(current_release_fence_.get()); #if OS_ANDROID use_real_color_space_for_stream_video_ = @@ -758,7 +809,8 @@ void SkiaRenderer::BeginDrawingFrame() { TRACE_EVENT0("viz", "SkiaRenderer::BeginDrawingFrame"); - DCHECK(!current_frame_resource_fence_->WasSet()); + DCHECK(!current_gpu_commands_completed_fence_->WasSet()); + DCHECK(!current_release_fence_->WasSet()); } void SkiaRenderer::FinishDrawingFrame() { @@ -2414,7 +2466,8 @@ } void SkiaRenderer::ScheduleOverlays() { - DCHECK(!current_frame_resource_fence_->WasSet()); + DCHECK(!current_gpu_commands_completed_fence_->WasSet()); + DCHECK(!current_release_fence_->WasSet()); // Always add an empty set of locks to be used in either SwapBuffersSkipped() // or SwapBuffersComplete(). @@ -2526,7 +2579,8 @@ NOTREACHED(); #endif // BUILDFLAG(IS_ANDROID) - DCHECK(!current_frame_resource_fence_->WasSet()); + DCHECK(!current_gpu_commands_completed_fence_->WasSet()); + DCHECK(!current_release_fence_->WasSet()); skia_output_surface_->ScheduleOverlays( std::move(current_frame()->overlay_list), std::move(sync_tokens)); @@ -2871,16 +2925,7 @@ if (is_root_render_pass && UsingSkiaForDelegatedInk()) DrawDelegatedInkTrail(); - base::OnceClosure on_finished_callback; - // Signal |current_frame_resource_fence_| when the root render pass is - // finished. - if (current_frame_resource_fence_->WasSet()) { - on_finished_callback = base::BindOnce( - &FrameResourceFence::Signal, std::move(current_frame_resource_fence_)); - current_frame_resource_fence_ = base::MakeRefCounted<FrameResourceFence>(); - resource_provider()->SetReadLockFence(current_frame_resource_fence_.get()); - } - skia_output_surface_->EndPaint(std::move(on_finished_callback)); + EndPaint(/*failed=*/false); // Defer flushing drawing task for root render pass, to avoid extra // MakeCurrent() call. It is expensive on GL. @@ -2946,9 +2991,17 @@ // TODO(penghuang): check supported format correctly. gpu::Capabilities caps; caps.texture_format_bgra8888 = true; + +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // TODO(crbug.com/1317015): add support RGBA_F16 in LaCrOS. + auto format = color_space.IsHDR() + ? RGBA_1010102 + : PlatformColor::BestSupportedTextureFormat(caps); +#else auto format = color_space.IsHDR() ? RGBA_F16 : PlatformColor::BestSupportedTextureFormat(caps); +#endif uint32_t usage = gpu::SHARED_IMAGE_USAGE_DISPLAY; if (requirements.generate_mipmap) usage |= gpu::SHARED_IMAGE_USAGE_MIPMAP; @@ -3188,7 +3241,7 @@ if (!content_image) { DLOG(ERROR) << "MakePromiseSkImageFromRenderPass() in " "PrepareRenderPassOverlay() failed."; - skia_output_surface_->EndPaint(base::NullCallback()); + EndPaint(/*failed=*/true); return; } @@ -3208,14 +3261,7 @@ current_canvas_ = nullptr; - base::OnceClosure on_finished_callback; - if (current_frame_resource_fence_->WasSet()) { - on_finished_callback = base::BindOnce( - &FrameResourceFence::Signal, std::move(current_frame_resource_fence_)); - current_frame_resource_fence_ = base::MakeRefCounted<FrameResourceFence>(); - resource_provider()->SetReadLockFence(current_frame_resource_fence_.get()); - } - skia_output_surface_->EndPaint(std::move(on_finished_callback)); + EndPaint(/*failed=*/false); // Adjust |bounds_rect| to contain the whole buffer and at the right location. overlay->bounds_rect.set_origin(gfx::PointF(filter_bounds.origin())); @@ -3223,6 +3269,39 @@ } #endif // BUILDFLAG(IS_APPLE) || defined(USE_OZONE) +void SkiaRenderer::EndPaint(bool failed) { + base::OnceClosure on_finished_callback; + base::OnceCallback<void(gfx::GpuFenceHandle)> on_return_release_fence_cb; + // If SkiaRenderer has not failed, prepare callbacks and pass them to + // SkiaOutputSurface. + if (!failed) { + // Signal |current_frame_resource_fence_| when the root render pass is + // finished. + if (current_gpu_commands_completed_fence_->WasSet()) { + on_finished_callback = + base::BindOnce(&FrameResourceGpuCommandsCompletedFence::Signal, + std::move(current_gpu_commands_completed_fence_)); + current_gpu_commands_completed_fence_ = + base::MakeRefCounted<FrameResourceGpuCommandsCompletedFence>(); + resource_provider()->SetGpuCommandsCompletedFence( + current_gpu_commands_completed_fence_.get()); + } + + // Return a release fence to the |current_release_fence_| + // when the root render pass is finished. + if (current_release_fence_->WasSet()) { + on_return_release_fence_cb = + base::BindOnce(&FrameResourceReleaseFence::SetReleaseFenceCallback, + std::move(current_release_fence_)); + current_release_fence_ = + base::MakeRefCounted<FrameResourceReleaseFence>(); + resource_provider()->SetReleaseFence(current_release_fence_.get()); + } + } + skia_output_surface_->EndPaint(std::move(on_finished_callback), + std::move(on_return_release_fence_cb)); +} + bool SkiaRenderer::IsRenderPassResourceAllocated( const AggregatedRenderPassId& render_pass_id) const { auto it = render_pass_backings_.find(render_pass_id);
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index c7bceb8..7922aee 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -264,6 +264,11 @@ OverlayProcessorInterface::PlatformOverlayCandidate* overlay); #endif + // Sets up callbacks for frame resource fences and passes them to + // SkiaOutputSurface by calling EndPaint on that. If |failed|, + // SkiaOutputSurface::EndPaint will be called with null callbacks. + void EndPaint(bool failed); + DisplayResourceProviderSkia* resource_provider() { return static_cast<DisplayResourceProviderSkia*>(resource_provider_); } @@ -288,8 +293,12 @@ raw_ptr<SkCanvas> root_canvas_ = nullptr; raw_ptr<SkCanvas> current_canvas_ = nullptr; raw_ptr<SkSurface> current_surface_ = nullptr; - class FrameResourceFence; - scoped_refptr<FrameResourceFence> current_frame_resource_fence_; + + class FrameResourceGpuCommandsCompletedFence; + scoped_refptr<FrameResourceGpuCommandsCompletedFence> + current_gpu_commands_completed_fence_; + class FrameResourceReleaseFence; + scoped_refptr<FrameResourceReleaseFence> current_release_fence_; bool disable_picture_quad_image_filtering_ = false; bool is_scissor_enabled_ = false;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index 33311cb..74fd2601 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -624,7 +624,9 @@ return current_paint_->recorder()->getCanvas(); } -void SkiaOutputSurfaceImpl::EndPaint(base::OnceClosure on_finished) { +void SkiaOutputSurfaceImpl::EndPaint( + base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(current_paint_); auto ddl = current_paint_->recorder()->detach(); @@ -649,7 +651,8 @@ &SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame, base::Unretained(impl_on_gpu_.get()), std::move(ddl), std::move(overdraw_ddl), std::move(images_in_current_paint_), - resource_sync_tokens_, std::move(on_finished), draw_rectangle_); + resource_sync_tokens_, std::move(on_finished), + std::move(return_release_fence_cb), draw_rectangle_); EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_), /*make_current=*/true, /*need_framebuffer=*/true); draw_rectangle_.reset(); @@ -658,7 +661,8 @@ &SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass, base::Unretained(impl_on_gpu_.get()), current_paint_->mailbox(), std::move(ddl), std::move(images_in_current_paint_), - resource_sync_tokens_, std::move(on_finished)); + resource_sync_tokens_, std::move(on_finished), + std::move(return_release_fence_cb)); EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_), /*make_current=*/true, /*need_framebuffer=*/false); }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index e0dc4826..685a700 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -117,7 +117,9 @@ sk_sp<SkColorSpace> color_space, bool is_overlay, const gpu::Mailbox& mailbox) override; - void EndPaint(base::OnceClosure on_finished) override; + void EndPaint(base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> + return_release_fence_cb) override; void MakePromiseSkImage(ImageContext* image_context) override; sk_sp<SkImage> MakePromiseSkImageFromRenderPass( const AggregatedRenderPassId& id,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 713a175..39fd934 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -12,6 +12,7 @@ #include "base/callback_helpers.h" #include "base/debug/crash_logging.h" #include "base/memory/raw_ptr.h" +#include "base/notreached.h" #include "base/task/bind_post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" @@ -38,6 +39,7 @@ #include "components/viz/service/display_embedder/skia_output_surface_dependency.h" #include "components/viz/service/display_embedder/skia_render_copy_results.h" #include "gpu/command_buffer/common/swap_buffers_complete_params.h" +#include "gpu/command_buffer/service/external_semaphore.h" #include "gpu/command_buffer/service/gr_shader_cache.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/scheduler.h" @@ -68,10 +70,14 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/gpu_fence_handle.h" +#include "ui/gl/gl_fence.h" #include "ui/gl/gl_surface.h" #if BUILDFLAG(ENABLE_VULKAN) #include "components/viz/service/display_embedder/skia_output_device_vulkan.h" +#include "gpu/vulkan/vulkan_device_queue.h" +#include "gpu/vulkan/vulkan_function_pointers.h" +#include "gpu/vulkan/vulkan_implementation.h" #include "gpu/vulkan/vulkan_util.h" #if BUILDFLAG(IS_ANDROID) #include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb.h" @@ -398,6 +404,7 @@ std::vector<ImageContextImpl*> image_contexts, std::vector<gpu::SyncToken> sync_tokens, base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb, absl::optional<gfx::Rect> draw_rectangle) { TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame"); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -480,7 +487,24 @@ end_semaphores.insert(end_semaphores.end(), end_paint_semaphores.begin(), end_paint_semaphores.end()); +#if BUILDFLAG(ENABLE_VULKAN) + // Semaphores for release fences for vulkan should be created before flush. + if (!return_release_fence_cb.is_null() && is_using_vulkan()) { + const bool result = CreateAndStoreExternalSemaphoreVulkan(end_semaphores); + // A release fence will be created on submit as some platforms may use + // VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT handle types for their + // external semaphore. That handle type has COPY transference. Vulkan spec + // says that semaphore has to be signaled, or have an associated semaphore + // signal operation pending execution. Thus, delay importing the handle + // and creating the fence until commands are submitted. + pending_release_fence_cbs_.emplace_back( + result ? end_semaphores.back() : GrBackendSemaphore(), + std::move(return_release_fence_cb)); + } +#endif + const bool end_semaphores_empty = end_semaphores.empty(); + auto result = scoped_output_device_paint_->Flush(vulkan_context_provider_, std::move(end_semaphores), std::move(on_finished)); @@ -491,6 +515,22 @@ FailedSkiaFlush("output_sk_surface()->flush() failed."); return; } + + gfx::GpuFenceHandle release_fence; + if (!return_release_fence_cb.is_null() && is_using_gl()) { + DCHECK(release_fence.is_null()); + release_fence = CreateReleaseFenceForGL(); + } + + if (!return_release_fence_cb.is_null() && is_using_dawn()) + NOTIMPLEMENTED() << "Release fences with dawn are not supported."; + + if (!return_release_fence_cb.is_null()) { + // Returning fences for Vulkan is delayed. See the comment above. + DCHECK(!is_using_vulkan()); + PostTaskToClientThread(base::BindOnce(std::move(return_release_fence_cb), + std::move(release_fence))); + } } } @@ -535,7 +575,8 @@ sk_sp<SkDeferredDisplayList> ddl, std::vector<ImageContextImpl*> image_contexts, std::vector<gpu::SyncToken> sync_tokens, - base::OnceClosure on_finished) { + base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb) { TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass"); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(ddl); @@ -586,6 +627,22 @@ backing_representation->SetCleared(); destroy_after_swap_.emplace_back(std::move(ddl)); +#if BUILDFLAG(ENABLE_VULKAN) + // Semaphores for release fences for vulkan should be created before flush. + if (!return_release_fence_cb.is_null() && is_using_vulkan()) { + const bool result = CreateAndStoreExternalSemaphoreVulkan(end_semaphores); + // A release fence will be created on submit as some platforms may use + // VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT handle types for their + // external semaphore. That handle type has COPY transference. Vulkan spec + // says that semaphore has to be signaled, or have an associated semaphore + // signal operation pending execution. Thus, delay importing the handle + // and creating the fence until commands are submitted. + pending_release_fence_cbs_.emplace_back( + result ? end_semaphores.back() : GrBackendSemaphore(), + std::move(return_release_fence_cb)); + } +#endif + GrFlushInfo flush_info = { .fNumSemaphores = end_semaphores.size(), .fSignalSemaphores = end_semaphores.data(), @@ -594,6 +651,7 @@ &flush_info); if (on_finished) gpu::AddCleanupTaskForSkiaFlush(std::move(on_finished), &flush_info); + auto result = surface->flush(flush_info); if (result != GrSemaphoresSubmitted::kYes && !(begin_semaphores.empty() && end_semaphores.empty())) { @@ -601,6 +659,24 @@ FailedSkiaFlush("offscreen.surface()->flush() failed."); return; } + + // If GL is used, create the release fence after flush. + gfx::GpuFenceHandle release_fence; + if (!return_release_fence_cb.is_null() && is_using_gl()) { + DCHECK(release_fence.is_null()); + release_fence = CreateReleaseFenceForGL(); + } + + if (!return_release_fence_cb.is_null() && is_using_dawn()) + NOTIMPLEMENTED() << "Release fences with dawn are not supported."; + + if (!return_release_fence_cb.is_null()) { + // Returning fences for Vulkan is delayed. See the comment above. + DCHECK(!is_using_vulkan()); + PostTaskToClientThread(base::BindOnce(std::move(return_release_fence_cb), + std::move(release_fence))); + } + bool sync_cpu = gpu::ShouldVulkanSyncCpuForSkiaSubmit(vulkan_context_provider_); if (sync_cpu) { @@ -1788,6 +1864,20 @@ promise_image_access_helper_.EndAccess(); scoped_output_device_paint_.reset(); +#if BUILDFLAG(ENABLE_VULKAN) + while (!pending_release_fence_cbs_.empty()) { + auto& item = pending_release_fence_cbs_.front(); + auto release_fence = CreateReleaseFenceForVulkan(item.first); + if (release_fence.is_null()) + LOG(ERROR) << "Unable to create a release fence for Vulkan."; + PostTaskToClientThread( + base::BindOnce(std::move(item.second), std::move(release_fence))); + pending_release_fence_cbs_.pop_front(); + } +#else + DCHECK(pending_release_fence_cbs_.empty()); +#endif + if (frame) { if (waiting_for_full_damage_) { // If we're using partial swap, we need to check whether the sub-buffer @@ -2009,4 +2099,57 @@ output_device_->DiscardBackbuffer(); } +#if BUILDFLAG(ENABLE_VULKAN) +gfx::GpuFenceHandle SkiaOutputSurfaceImplOnGpu::CreateReleaseFenceForVulkan( + const GrBackendSemaphore& semaphore) { + DCHECK(is_using_vulkan()); + + if (semaphore.vkSemaphore() == VK_NULL_HANDLE) + return {}; + + auto* implementation = vulkan_context_provider_->GetVulkanImplementation(); + VkDevice device = + vulkan_context_provider_->GetDeviceQueue()->GetVulkanDevice(); + + auto handle = + implementation->GetSemaphoreHandle(device, semaphore.vkSemaphore()); + if (!handle.is_valid()) { + vkDestroySemaphore(device, semaphore.vkSemaphore(), + /*pAllocator=*/nullptr); + LOG(ERROR) << "Failed to create a release fence for Vulkan."; + return {}; + } + return std::move(handle).ToGpuFenceHandle(); +} + +bool SkiaOutputSurfaceImplOnGpu::CreateAndStoreExternalSemaphoreVulkan( + std::vector<GrBackendSemaphore>& end_semaphores) { + DCHECK(is_using_vulkan()); + + auto* implementation = vulkan_context_provider_->GetVulkanImplementation(); + VkDevice device = + vulkan_context_provider_->GetDeviceQueue()->GetVulkanDevice(); + + VkSemaphore semaphore = implementation->CreateExternalSemaphore(device); + if (semaphore == VK_NULL_HANDLE) { + LOG(ERROR) + << "Creation of an external semaphore for a release fence failed."; + return false; + } + + end_semaphores.emplace_back(); + end_semaphores.back().initVulkan(semaphore); + return true; +} +#endif + +gfx::GpuFenceHandle SkiaOutputSurfaceImplOnGpu::CreateReleaseFenceForGL() { + if (gl::GLFence::IsGpuFenceSupported()) { + auto fence = gl::GLFence::CreateForGpuFence(); + if (fence) + return fence->GetGpuFence()->GetGpuFenceHandle().Clone(); + } + return {}; +} + } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index 0be8048a..47b069b 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_ #define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_ +#include <deque> #include <map> #include <memory> #include <utility> @@ -41,6 +42,7 @@ #include "third_party/skia/include/core/SkPromiseImageTexture.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrBackendSemaphore.h" +#include "ui/gfx/gpu_fence_handle.h" namespace gfx { namespace mojom { @@ -137,12 +139,14 @@ const gfx::ColorSpace& color_space, float device_scale_factor, gfx::OverlayTransform transform); - void FinishPaintCurrentFrame(sk_sp<SkDeferredDisplayList> ddl, - sk_sp<SkDeferredDisplayList> overdraw_ddl, - std::vector<ImageContextImpl*> image_contexts, - std::vector<gpu::SyncToken> sync_tokens, - base::OnceClosure on_finished, - absl::optional<gfx::Rect> draw_rectangle); + void FinishPaintCurrentFrame( + sk_sp<SkDeferredDisplayList> ddl, + sk_sp<SkDeferredDisplayList> overdraw_ddl, + std::vector<ImageContextImpl*> image_contexts, + std::vector<gpu::SyncToken> sync_tokens, + base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb, + absl::optional<gfx::Rect> draw_rectangle); void ScheduleOutputSurfaceAsOverlay( const OverlayProcessorInterface::OutputSurfaceOverlayPlane& output_surface_plane); @@ -157,11 +161,13 @@ void SwapBuffersSkipped(); void EnsureBackbuffer(); void DiscardBackbuffer(); - void FinishPaintRenderPass(const gpu::Mailbox& mailbox, - sk_sp<SkDeferredDisplayList> ddl, - std::vector<ImageContextImpl*> image_contexts, - std::vector<gpu::SyncToken> sync_tokens, - base::OnceClosure on_finished); + void FinishPaintRenderPass( + const gpu::Mailbox& mailbox, + sk_sp<SkDeferredDisplayList> ddl, + std::vector<ImageContextImpl*> image_contexts, + std::vector<gpu::SyncToken> sync_tokens, + base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb); // Deletes resources for RenderPasses in |ids|. Also takes ownership of // |images_contexts| and destroys them on GPU thread. void RemoveRenderPassResource( @@ -296,6 +302,8 @@ gpu_preferences_.gr_context_type == gpu::GrContextType::kDawn; } + bool is_using_gl() const { return !is_using_vulkan() && !is_using_dawn(); } + // Helper for `CopyOutput()` method, handles the RGBA format. void CopyOutputRGBA(SkSurface* surface, copy_output::RenderPassGeometry geometry, @@ -377,6 +385,19 @@ void ReleaseAsyncReadResultHelpers(); +#if BUILDFLAG(ENABLE_VULKAN) + // Creates a release fence. The semaphore is an external semaphore created + // by CreateAndStoreExternalSemaphoreVulkan(). May destroy VkSemaphore that + // the |semaphore| stores if creation of a release fence fails. In this case, + // invalid fence handle is returned. + gfx::GpuFenceHandle CreateReleaseFenceForVulkan( + const GrBackendSemaphore& semaphore); + // Returns true if succeess. + bool CreateAndStoreExternalSemaphoreVulkan( + std::vector<GrBackendSemaphore>& end_semaphores); +#endif + gfx::GpuFenceHandle CreateReleaseFenceForGL(); + class ReleaseCurrent { public: ReleaseCurrent(scoped_refptr<gl::GLSurface> gl_surface, @@ -479,6 +500,13 @@ // Tracking for ongoing AsyncReadResults. base::flat_set<AsyncReadResultHelper*> async_read_result_helpers_; + // Pending release fence callbacks. These callbacks can be delayed if Vulkan + // external semaphore type has copy transference, which means importing + // semaphores has to be delayed until submission. + std::deque<std::pair<GrBackendSemaphore, + base::OnceCallback<void(gfx::GpuFenceHandle)>>> + pending_release_fence_cbs_; + THREAD_CHECKER(thread_checker_); base::WeakPtr<SkiaOutputSurfaceImplOnGpu> weak_ptr_;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc index a44fbb46..8d69440 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/bind.h" +#include "base/callback_forward.h" #include "base/callback_helpers.h" #include "base/run_loop.h" #include "cc/test/fake_output_surface_client.h" @@ -23,6 +24,7 @@ #include "gpu/command_buffer/service/service_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/gpu_fence_handle.h" #include "ui/gl/gl_implementation.h" namespace viz { @@ -45,8 +47,10 @@ void SetUpSkiaOutputSurfaceImpl(); // Paints and submits root RenderPass with a solid color rect of |size|. - gpu::SyncToken PaintRootRenderPass(const gfx::Rect& output_rect, - base::OnceClosure closure); + gpu::SyncToken PaintRootRenderPass( + const gfx::Rect& output_rect, + base::OnceClosure closure, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence); void CheckSyncTokenOnGpuThread(const gpu::SyncToken& sync_token); void CopyRequestCallbackOnGpuThread(const gfx::Rect& output_rect, @@ -87,13 +91,15 @@ gpu::SyncToken SkiaOutputSurfaceImplTest::PaintRootRenderPass( const gfx::Rect& rect, - base::OnceClosure closure) { + base::OnceClosure closure, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence) { SkPaint paint; paint.setColor(kOutputColor); SkCanvas* root_canvas = output_surface_->BeginPaintCurrentFrame(); root_canvas->drawRect( SkRect::MakeXYWH(rect.x(), rect.y(), rect.height(), rect.width()), paint); - output_surface_->EndPaint(std::move(closure)); + output_surface_->EndPaint(std::move(closure), + std::move(return_release_fence)); return output_surface_->Flush(); } @@ -142,9 +148,14 @@ bool on_finished_called = false; base::OnceClosure on_finished = base::BindOnce([](bool* result) { *result = true; }, &on_finished_called); + bool on_return_release_fence_called = false; + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb = + base::BindOnce( + [](bool* result, gfx::GpuFenceHandle handle) { *result = true; }, + &on_return_release_fence_called); - gpu::SyncToken sync_token = - PaintRootRenderPass(output_rect, std::move(on_finished)); + gpu::SyncToken sync_token = PaintRootRenderPass( + output_rect, std::move(on_finished), std::move(return_release_fence_cb)); EXPECT_TRUE(sync_token.HasData()); // Copy the output @@ -176,6 +187,10 @@ output_surface_->ScheduleGpuTaskForTesting(std::move(closure), {sync_token}); BlockMainThread(); EXPECT_TRUE(on_finished_called); + + // Let the cb to come back. + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(on_return_release_fence_called); } // Draws two frames and calls Reshape() between the two frames changing the @@ -189,7 +204,8 @@ // Draw something, it's not important what. base::RunLoop run_loop; - PaintRootRenderPass(kSurfaceRect, run_loop.QuitClosure()); + PaintRootRenderPass(kSurfaceRect, run_loop.QuitClosure(), + base::DoNothing()); OutputSurfaceFrame frame; frame.size = kSurfaceRect.size(); @@ -231,7 +247,7 @@ geometry.sampling_bounds = output_rect; geometry.readback_offset = gfx::Vector2d(0, 0); - PaintRootRenderPass(kSurfaceRect, base::DoNothing()); + PaintRootRenderPass(kSurfaceRect, base::DoNothing(), base::DoNothing()); output_surface_->CopyOutput(AggregatedRenderPassId{0}, geometry, color_space, std::move(request), gpu::Mailbox()); output_surface_->SwapBuffersSkipped(kSurfaceRect); @@ -272,7 +288,7 @@ geometry.sampling_bounds = output_rect; geometry.readback_offset = gfx::Vector2d(0, 0); - PaintRootRenderPass(kSurfaceRect, base::DoNothing()); + PaintRootRenderPass(kSurfaceRect, base::DoNothing(), base::DoNothing()); output_surface_->CopyOutput(AggregatedRenderPassId{0}, geometry, color_space, std::move(request), gpu::Mailbox()); output_surface_->SwapBuffersSkipped(kSurfaceRect);
diff --git a/components/viz/test/fake_skia_output_surface.cc b/components/viz/test/fake_skia_output_surface.cc index 8c07fb66..b20aa542 100644 --- a/components/viz/test/fake_skia_output_surface.cc +++ b/components/viz/test/fake_skia_output_surface.cc
@@ -26,6 +26,7 @@ #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" #include "third_party/skia/include/gpu/gl/GrGLTypes.h" +#include "ui/gfx/gpu_fence_handle.h" #include "ui/gfx/presentation_feedback.h" #include "ui/gfx/swap_result.h" #include "ui/gl/gl_utils.h" @@ -184,13 +185,17 @@ return sk_surface->getCanvas(); } -void FakeSkiaOutputSurface::EndPaint(base::OnceClosure on_finished) { +void FakeSkiaOutputSurface::EndPaint( + base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); sk_surfaces_[current_render_pass_id_]->flushAndSubmit(); current_render_pass_id_ = AggregatedRenderPassId{0}; if (on_finished) std::move(on_finished).Run(); + if (return_release_fence_cb) + std::move(return_release_fence_cb).Run(gfx::GpuFenceHandle()); } sk_sp<SkImage> FakeSkiaOutputSurface::MakePromiseSkImageFromRenderPass(
diff --git a/components/viz/test/fake_skia_output_surface.h b/components/viz/test/fake_skia_output_surface.h index e9893a0..01b7f015 100644 --- a/components/viz/test/fake_skia_output_surface.h +++ b/components/viz/test/fake_skia_output_surface.h
@@ -72,7 +72,9 @@ sk_sp<SkColorSpace> color_space, bool is_overlay, const gpu::Mailbox& mailbox) override; - void EndPaint(base::OnceClosure on_finished) override; + void EndPaint(base::OnceClosure on_finished, + base::OnceCallback<void(gfx::GpuFenceHandle)> + return_release_fence_cb) override; void MakePromiseSkImage(ImageContext* image_context) override; sk_sp<SkImage> MakePromiseSkImageFromRenderPass( const AggregatedRenderPassId& id,
diff --git a/components/webrtc/media_stream_devices_controller.cc b/components/webrtc/media_stream_devices_controller.cc index e9cd2d78..353ed84da 100644 --- a/components/webrtc/media_stream_devices_controller.cc +++ b/components/webrtc/media_stream_devices_controller.cc
@@ -63,7 +63,7 @@ // The RFH may have been destroyed by the time the request is processed. if (!rfh) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false, {}, {}); return; @@ -71,7 +71,7 @@ if (rfh->GetLastCommittedOrigin().GetURL().is_empty()) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, false, {}, {}); return; @@ -79,7 +79,7 @@ if (rfh->GetLastCommittedOrigin().GetURL() != request.security_origin) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN, false, {}, {}); return; @@ -166,7 +166,7 @@ MediaStreamDevicesController::~MediaStreamDevicesController() { if (!callback_.is_null()) { std::move(callback_).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false, {}, {}); } @@ -202,16 +202,21 @@ return video_setting_ == CONTENT_SETTING_ASK; } -blink::mojom::StreamDevices MediaStreamDevicesController::GetDevices( +blink::mojom::StreamDevicesSetPtr MediaStreamDevicesController::GetDevices( ContentSetting audio_setting, ContentSetting video_setting) { bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW; bool video_allowed = video_setting == CONTENT_SETTING_ALLOW; + blink::mojom::StreamDevicesSetPtr stream_devices_set = + blink::mojom::StreamDevicesSet::New(); if (!audio_allowed && !video_allowed) - return blink::mojom::StreamDevices(); + return nullptr; - blink::mojom::StreamDevices devices; + // TODO(crbug.com/1300883): Generalize to multiple streams. + stream_devices_set->stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set->stream_devices[0]; switch (request_.request_type) { case blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY: { // For open device request, when requested device_id is empty, pick @@ -303,14 +308,14 @@ } } // switch - return devices; + return stream_devices_set; } void MediaStreamDevicesController::RunCallback( bool blocked_by_permissions_policy) { CHECK(callback_); - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSetPtr stream_devices_set; // If all requested permissions are allowed then the callback should report // success, otherwise we report |denial_reason_|. blink::mojom::MediaStreamRequestResult request_result = @@ -319,7 +324,14 @@ audio_setting_ == CONTENT_SETTING_DEFAULT) && (video_setting_ == CONTENT_SETTING_ALLOW || video_setting_ == CONTENT_SETTING_DEFAULT)) { - devices = GetDevices(audio_setting_, video_setting_); + stream_devices_set = GetDevices(audio_setting_, video_setting_); + DCHECK(!stream_devices_set || + stream_devices_set->stream_devices.size() <= 1u); + blink::mojom::StreamDevices devices; + if (stream_devices_set && !stream_devices_set->stream_devices.empty()) { + devices = *stream_devices_set->stream_devices[0]; + } + if (!devices.audio_device.has_value() && !devices.video_device.has_value()) { // Even if all requested permissions are allowed, if there are no devices @@ -329,9 +341,10 @@ } else { DCHECK_NE(blink::mojom::MediaStreamRequestResult::OK, denial_reason_); request_result = denial_reason_; + stream_devices_set = blink::mojom::StreamDevicesSet::New(); } - std::move(callback_).Run(devices, request_result, + std::move(callback_).Run(*stream_devices_set, request_result, blocked_by_permissions_policy, audio_setting_, video_setting_); }
diff --git a/components/webrtc/media_stream_devices_controller.h b/components/webrtc/media_stream_devices_controller.h index 6f0043b..1787b41 100644 --- a/components/webrtc/media_stream_devices_controller.h +++ b/components/webrtc/media_stream_devices_controller.h
@@ -34,11 +34,12 @@ // renderer. class MediaStreamDevicesController { public: - typedef base::OnceCallback<void(const blink::mojom::StreamDevices& devices, - blink::mojom::MediaStreamRequestResult result, - bool blocked_by_permissions_policy, - ContentSetting audio_setting, - ContentSetting video_setting)> + typedef base::OnceCallback<void( + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + bool blocked_by_permissions_policy, + ContentSetting audio_setting, + ContentSetting video_setting)> ResultCallback; // Requests the mic/camera permissions described in |request|, using @@ -74,8 +75,8 @@ // Returns a list of devices available for the request for the given // audio/video permission settings. - blink::mojom::StreamDevices GetDevices(ContentSetting audio_setting, - ContentSetting video_setting); + blink::mojom::StreamDevicesSetPtr GetDevices(ContentSetting audio_setting, + ContentSetting video_setting); // Runs |callback_| with the current audio/video permission settings. void RunCallback(bool blocked_by_permissions_policy);
diff --git a/content/browser/media/capture_handle_manager.cc b/content/browser/media/capture_handle_manager.cc index ec0c2d8..a2174789 100644 --- a/content/browser/media/capture_handle_manager.cc +++ b/content/browser/media/capture_handle_manager.cc
@@ -253,10 +253,12 @@ void CaptureHandleManager::OnTabCaptureDevicesUpdated( const std::string& label, - const blink::mojom::StreamDevices& new_devices, + blink::mojom::StreamDevicesSetPtr new_stream_devices_set, GlobalRenderFrameHostId capturer, DeviceCaptureHandleChangeCallback handle_change_callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(new_stream_devices_set); + DCHECK_EQ(1u, new_stream_devices_set->stream_devices.size()); // Pause tracking of all old devices. for (auto& capture : captures_) { @@ -266,6 +268,8 @@ } // Start tracking any new devices; resume tracking of changed devices. + const blink::mojom::StreamDevices& new_devices = + *new_stream_devices_set->stream_devices[0]; if (new_devices.audio_device.has_value()) { OnTabCaptureStarted(label, new_devices.audio_device.value(), capturer, handle_change_callback);
diff --git a/content/browser/media/capture_handle_manager.h b/content/browser/media/capture_handle_manager.h index 7476bca..00d1c9ca 100644 --- a/content/browser/media/capture_handle_manager.h +++ b/content/browser/media/capture_handle_manager.h
@@ -50,7 +50,7 @@ // then calling OnTabCaptureStarted() on all |new_devices|. void OnTabCaptureDevicesUpdated( const std::string& label, - const blink::mojom::StreamDevices& new_devices, + blink::mojom::StreamDevicesSetPtr new_stream_devices, GlobalRenderFrameHostId capturer, DeviceCaptureHandleChangeCallback handle_change_callback);
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc index 6b6b9c2..2ca95be 100644 --- a/content/browser/media/session/media_session_impl.cc +++ b/content/browser/media/session/media_session_impl.cc
@@ -319,8 +319,6 @@ return; } - image_cache_.clear(); - auto new_origin = url::Origin::Create(navigation_handle->GetURL()); if (navigation_handle->IsInPrimaryMainFrame() && !new_origin.IsSameOriginWith(origin_)) { @@ -889,8 +887,10 @@ } } - if (source_icon) - image_cache_.emplace(image_url, bitmap); + if (source_icon) { + GetPageData(web_contents()->GetPrimaryPage()) + .AddImageCache(image_url, bitmap); + } std::move(callback).Run(bitmap); } @@ -1299,9 +1299,12 @@ } // Check the cache. - if (source_icon && base::Contains(image_cache_, image.src)) { - std::move(callback).Run(image_cache_.at(image.src)); - return; + PageData& page_data = GetPageData(web_contents()->GetPrimaryPage()); + if (source_icon) { + if (auto* bitmap = page_data.GetImageCache(image.src)) { + std::move(callback).Run(*bitmap); + return; + } } const gfx::Size preferred_size(desired_size_px, desired_size_px); @@ -1868,6 +1871,22 @@ should_throttle_duration_update_ = should_throttle; } +bool MediaSessionImpl::HasImageCacheForTest(const GURL& image_url) const { + return GetPageData(web_contents()->GetPrimaryPage()).GetImageCache(image_url); +} + +MediaSessionImpl::PageData::PageData(content::Page& page) + : PageUserData(page) {} + +MediaSessionImpl::PageData::~PageData() = default; + +MediaSessionImpl::PageData& MediaSessionImpl::GetPageData( + content::Page& page) const { + return *PageData::GetOrCreateForPage(page); +} + +PAGE_USER_DATA_KEY_IMPL(MediaSessionImpl::PageData); + WEB_CONTENTS_USER_DATA_KEY_IMPL(MediaSessionImpl); } // namespace content
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h index 4c490fdb..583375d5 100644 --- a/content/browser/media/session/media_session_impl.h +++ b/content/browser/media/session/media_session_impl.h
@@ -21,6 +21,7 @@ #include "content/browser/media/session/media_session_uma_helper.h" #include "content/common/content_export.h" #include "content/public/browser/media_session.h" +#include "content/public/browser/page_user_data.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "mojo/public/cpp/bindings/receiver_set.h" @@ -321,6 +322,8 @@ // Returns the Audio Focus request ID associated with this media session. const base::UnguessableToken& GetRequestId() const; + CONTENT_EXPORT bool HasImageCacheForTest(const GURL& image_url) const; + private: friend class content::WebContentsUserData<MediaSessionImpl>; friend class MediaSessionImplBrowserTest; @@ -525,6 +528,37 @@ url::Origin origin_; absl::optional<std::string> audio_device_id_for_origin_; + class PageData : public content::PageUserData<PageData> { + public: + explicit PageData(content::Page& page); + + PageData(const PageData&) = delete; + PageData& operator=(const PageData&) = delete; + + ~PageData() override; + + void AddImageCache(const GURL& image_url, const SkBitmap& bitmap) { + image_cache_.emplace(image_url, bitmap); + } + + const SkBitmap* GetImageCache(const GURL& image_url) const { + auto it = image_cache_.find(image_url); + if (it == image_cache_.end()) + return nullptr; + + return &it->second; + } + + PAGE_USER_DATA_KEY_DECL(); + + private: + // Cache of images that have been requested by clients. + base::flat_map<GURL, SkBitmap> image_cache_; + }; + + // Returns the PageData for the specified |page|. + PageData& GetPageData(content::Page& page) const; + #if BUILDFLAG(IS_ANDROID) std::unique_ptr<MediaSessionAndroid> session_android_; #endif // BUILDFLAG(IS_ANDROID) @@ -539,9 +573,6 @@ std::vector<media_session::MediaImage>> images_; - // Cache of images that have been requested by clients. - base::flat_map<GURL, SkBitmap> image_cache_; - // The collection of all managed services (non-owned pointers). The services // are owned by RenderFrameHost and should be registered on creation and // unregistered on destroy.
diff --git a/content/browser/media/session/media_session_impl_browsertest.cc b/content/browser/media/session/media_session_impl_browsertest.cc index 8944652..44e3418 100644 --- a/content/browser/media/session/media_session_impl_browsertest.cc +++ b/content/browser/media/session/media_session_impl_browsertest.cc
@@ -3231,6 +3231,75 @@ EXPECT_NE(player_observer->GetAudioOutputSinkId(player_1), "speaker1"); } +IN_PROC_BROWSER_TEST_F(MediaSessionImplPrerenderingBrowserTest, + DontClearFaviconCacheOnPrerenderNavigation) { + { + std::vector<media_session::MediaImage> expected_images; + media_session::MediaImage test_image; + test_image.src = + embedded_test_server()->GetURL("example.com", "/favicon.ico"); + test_image.sizes.emplace_back(kDefaultFaviconSize); + expected_images.emplace_back(test_image); + + media_session::test::MockMediaSessionMojoObserver observer(*media_session_); + + observer.WaitForExpectedImagesOfType( + media_session::mojom::MediaSessionImageType::kSourceIcon, + expected_images); + } + + std::vector<gfx::Size> valid_sizes; + valid_sizes.emplace_back(gfx::Size(100, 100)); + valid_sizes.emplace_back(gfx::Size(200, 200)); + + GURL test_image_src = favicon_server().GetURL("/favicon.ico"); + EXPECT_FALSE(media_session_->HasImageCacheForTest(test_image_src)); + + std::vector<blink::mojom::FaviconURLPtr> favicons; + favicons.emplace_back(blink::mojom::FaviconURL::New( + test_image_src, blink::mojom::FaviconIconType::kFavicon, valid_sizes)); + + media_session_->DidUpdateFaviconURL(shell()->web_contents()->GetMainFrame(), + favicons); + media_session::MediaImage test_image; + test_image.src = test_image_src; + test_image.sizes = valid_sizes; + + { + EXPECT_EQ(0, get_favicon_calls()); + + base::RunLoop run_loop; + media_session_->GetMediaImageBitmap( + test_image, 100, 100, + base::BindLambdaForTesting([&](const SkBitmap&) { run_loop.Quit(); })); + run_loop.Run(); + + EXPECT_EQ(2, get_favicon_calls()); + } + + EXPECT_TRUE(media_session_->HasImageCacheForTest(test_image_src)); + + // Prerender the next page. + auto prerender_url = + embedded_test_server()->GetURL("example.com", "/title2.html"); + int host_id = prerender_helper_.AddPrerender(prerender_url); + content::RenderFrameHost* prerender_rfh = + prerender_helper_.GetPrerenderedMainFrameHost(host_id); + EXPECT_NE(prerender_rfh, nullptr); + + { + base::RunLoop run_loop; + media_session_->GetMediaImageBitmap( + test_image, 100, 100, + base::BindLambdaForTesting([&](const SkBitmap&) { run_loop.Quit(); })); + run_loop.Run(); + + EXPECT_EQ(3, get_favicon_calls()); + } + + EXPECT_TRUE(media_session_->HasImageCacheForTest(test_image_src)); +} + class MediaSessionImplWithBackForwardCacheBrowserTest : public MediaSessionImplBrowserTest { protected:
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index 08629d4..32a9346 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -70,11 +70,42 @@ constexpr int kRenderId = 6; constexpr int kRequesterId = 7; constexpr int kPageRequestId = 8; -constexpr const char* kRegularVideoDeviceId = "stub_device_0"; +constexpr const char* kRegularVideoDeviceId1 = "stub_device_1"; +constexpr const char* kRegularVideoDeviceId2 = "stub_device_2"; constexpr const char* kDepthVideoDeviceId = "stub_device_1 (depth)"; constexpr media::VideoCaptureApi kStubCaptureApi = media::VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE; +bool DoStreamDevicesHaveSameTypes(const blink::mojom::StreamDevices& lhs, + const blink::mojom::StreamDevices& rhs) { + return lhs.audio_device.has_value() == rhs.audio_device.has_value() && + lhs.video_device.has_value() == rhs.video_device.has_value(); +} + +MATCHER_P(SameTypesAs, + expected_stream_devices_set_ref, + "Compares if two StreamDevices objects contain the same number and " + "type of MediaStreamDevice objects.") { + const blink::mojom::StreamDevicesSet& stream_devices_set = arg; + const blink::mojom::StreamDevicesSet& expected_stream_devices_set = + expected_stream_devices_set_ref.get(); + + if (stream_devices_set.stream_devices.size() != + expected_stream_devices_set.stream_devices.size()) { + return false; + } + + for (size_t i = 0; i < stream_devices_set.stream_devices.size(); ++i) { + if (!DoStreamDevicesHaveSameTypes( + *stream_devices_set.stream_devices[i], + *expected_stream_devices_set.stream_devices[i])) { + return false; + } + } + + return true; +} + void AudioInputDevicesEnumerated(base::OnceClosure quit_closure, media::AudioDeviceDescriptions* out, const MediaDeviceEnumeration& enumeration) { @@ -99,10 +130,9 @@ ~MockMediaStreamDispatcherHost() override {} // A list of mock methods. - MOCK_METHOD3(OnStreamGenerationSuccess, + MOCK_METHOD2(OnStreamGenerationSuccess, void(int request_id, - int audio_array_size, - int video_array_size)); + const blink::mojom::StreamDevicesSet& stream_devices_set)); MOCK_METHOD2(OnStreamGenerationFailure, void(int request_id, blink::mojom::MediaStreamRequestResult result)); @@ -193,21 +223,7 @@ return; } - DCHECK(stream_devices_set); - - size_t audio_devices_count = base::ranges::count_if( - stream_devices_set->stream_devices, - [](const blink::mojom::StreamDevicesPtr& devices) { - return devices->audio_device.has_value(); - }); - size_t video_devices_count = base::ranges::count_if( - stream_devices_set->stream_devices, - [](const blink::mojom::StreamDevicesPtr& devices) { - return devices->video_device.has_value(); - }); - - OnStreamGenerationSuccess(request_id, audio_devices_count, - video_devices_count); + OnStreamGenerationSuccess(request_id, *stream_devices_set); // Simulate the stream started event back to host for UI testing. OnStreamStarted(label); @@ -327,7 +343,7 @@ } void SetUp() override { - stub_video_device_ids_.emplace_back(kRegularVideoDeviceId); + stub_video_device_ids_.emplace_back(kRegularVideoDeviceId1); stub_video_device_ids_.emplace_back(kDepthVideoDeviceId); ON_CALL(*mock_video_capture_provider_, GetDeviceInfosAsync(_)) .WillByDefault(Invoke( @@ -380,31 +396,34 @@ return fake_ui; } - virtual void SetupFakeUI(bool expect_started) { + virtual void SetupFakeUI( + bool expect_started, + const std::vector<std::pair<std::string, std::string>>& + devices_ids_to_select = {}) { media_stream_manager_->UseFakeUIFactoryForTests( base::BindRepeating(&MediaStreamDispatcherHostTest::CreateMockUI, base::Unretained(this), expect_started)); } - void GenerateStreamAndWaitForResult(int page_request_id, - const blink::StreamControls& controls) { + void GenerateStreamAndWaitForResult( + int page_request_id, + const blink::StreamControls& controls, + const blink::mojom::StreamDevicesSet& expectation) { base::RunLoop run_loop; - int expected_audio_array_size = - (controls.audio.requested && !audio_device_descriptions_.empty()) ? 1 - : 0; - int expected_video_array_size = - (controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0; - EXPECT_CALL(*host_, OnStreamGenerationSuccess(page_request_id, - expected_audio_array_size, - expected_video_array_size)); + EXPECT_CALL(*host_, + OnStreamGenerationSuccess(page_request_id, + SameTypesAs(std::ref(expectation)))); host_->OnGenerateStreams(page_request_id, controls, run_loop.QuitClosure()); run_loop.Run(); - EXPECT_FALSE(DoesContainRawIds(audio_device(/*stream_index=*/0u))); - EXPECT_FALSE(DoesContainRawIds(video_device(/*stream_index=*/0u))); - EXPECT_TRUE( - DoesEveryDeviceMapToRawId(audio_device(/*stream_index=*/0u), origin_)); - EXPECT_TRUE( - DoesEveryDeviceMapToRawId(video_device(/*stream_index=*/0u), origin_)); + for (const blink::mojom::StreamDevicesPtr& stream_devices : + host_->stream_devices_set_->stream_devices) { + EXPECT_FALSE(DoesContainRawIds(stream_devices->audio_device)); + EXPECT_FALSE(DoesContainRawIds(stream_devices->video_device)); + EXPECT_TRUE( + DoesEveryDeviceMapToRawId(stream_devices->audio_device, origin_)); + EXPECT_TRUE( + DoesEveryDeviceMapToRawId(stream_devices->video_device, origin_)); + } } void GenerateStreamAndWaitForFailure( @@ -526,10 +545,14 @@ }; TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) { + stub_video_device_ids_.emplace_back(kRegularVideoDeviceId2); blink::StreamControls controls(false, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); @@ -539,7 +562,11 @@ blink::StreamControls controls(true, false); SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + blink::MediaStreamDevice(), absl::nullopt)); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(video_device(/*stream_index=*/0u).has_value()); @@ -612,8 +639,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) { blink::StreamControls controls(true, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + blink::MediaStreamDevice(), blink::MediaStreamDevice())); SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); @@ -630,8 +660,11 @@ // See also MediaStreamManager::GenerateStream and other tests here. controls.video.device_id = source_id; + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + blink::MediaStreamDevice(), blink::MediaStreamDevice())); SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); // We specified the generation and expect to get // one audio and one depth video stream. @@ -646,8 +679,11 @@ blink::StreamControls controls(false, true); // Generate first stream. + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); // Check the latest generated stream. EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); @@ -660,7 +696,7 @@ .session_id(); // Generate second stream. - GenerateStreamAndWaitForResult(kPageRequestId + 1, controls); + GenerateStreamAndWaitForResult(kPageRequestId + 1, controls, expectation); // Check the latest generated stream. EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); @@ -682,7 +718,10 @@ blink::StreamControls controls(false, true); // Generate first stream. - GenerateStreamAndWaitForResult(kPageRequestId, controls); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); @@ -711,8 +750,11 @@ blink::StreamControls controls(false, true); // Generate first stream. + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); // Check the latest generated stream. EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); @@ -720,9 +762,7 @@ const std::string label1 = host_->label_; const std::string device_id1 = video_device(/*stream_index=*/0u).value().id; const base::UnguessableToken session_id1 = - host_->stream_devices_set_->stream_devices[0] - ->video_device.value() - .session_id(); + video_device(/*stream_index=*/0u).value().session_id(); // Generate second stream from another render frame. host_ = std::make_unique<MockMediaStreamDispatcherHost>( @@ -733,7 +773,7 @@ host_->SetMediaStreamDeviceObserverForTesting( host_->BindNewPipeAndPassRemote()); - GenerateStreamAndWaitForResult(kPageRequestId + 1, controls); + GenerateStreamAndWaitForResult(kPageRequestId + 1, controls, expectation); // Check the latest generated stream. EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); @@ -781,13 +821,21 @@ base::RunLoop run_loop; host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure()); - int expected_audio_array_size = - (controls.audio.requested && !audio_device_descriptions_.empty()) ? 1 : 0; - int expected_video_array_size = - (controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0; - EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId, - expected_audio_array_size, - expected_video_array_size)) + absl::optional<blink::MediaStreamDevice> expected_audio_device; + if (controls.audio.requested && !audio_device_descriptions_.empty()) { + expected_audio_device = blink::MediaStreamDevice(); + } + + absl::optional<blink::MediaStreamDevice> expected_video_device; + if (controls.video.requested && !stub_video_device_ids_.empty()) { + expected_video_device = blink::MediaStreamDevice(); + } + + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + expected_audio_device, expected_video_device)); + EXPECT_CALL(*host_, OnStreamGenerationSuccess( + kPageRequestId, SameTypesAs(std::ref(expectation)))) .Times(1); run_loop.Run(); @@ -809,13 +857,21 @@ host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure()); run_loop.RunUntilIdle(); - int expected_audio_array_size = - (controls.audio.requested && !audio_device_descriptions_.empty()) ? 1 : 0; - int expected_video_array_size = - (controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0; - EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId, - expected_audio_array_size, - expected_video_array_size)) + absl::optional<blink::MediaStreamDevice> expected_audio_device; + if (controls.audio.requested && !audio_device_descriptions_.empty()) { + expected_audio_device = blink::MediaStreamDevice(); + } + + absl::optional<blink::MediaStreamDevice> expected_video_device; + if (controls.video.requested && !stub_video_device_ids_.empty()) { + expected_video_device = blink::MediaStreamDevice(); + } + + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + expected_audio_device, expected_video_device)); + EXPECT_CALL(*host_, OnStreamGenerationSuccess( + kPageRequestId, SameTypesAs(std::ref(expectation)))) .Times(1); focus_ = true; @@ -836,13 +892,20 @@ blink::StreamControls controls(false, true); // Generate first stream. + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); SetupFakeUI(true); { InSequence s; - EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId, 0, 1)); + EXPECT_CALL(*host_, + OnStreamGenerationSuccess(kPageRequestId, + SameTypesAs(std::ref(expectation)))); // Generate second stream. - EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1)); + EXPECT_CALL(*host_, + OnStreamGenerationSuccess(kPageRequestId + 1, + SameTypesAs(std::ref(expectation)))); } base::RunLoop run_loop1; base::RunLoop run_loop2; @@ -860,6 +923,10 @@ ASSERT_GE(audio_device_descriptions_.size(), 1u); ASSERT_GE(stub_video_device_ids_.size(), 1u); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + blink::MediaStreamDevice(), blink::MediaStreamDevice())); + media::AudioDeviceDescriptions::const_iterator audio_it = audio_device_descriptions_.begin(); for (; audio_it != audio_device_descriptions_.end(); ++audio_it) { @@ -870,7 +937,7 @@ controls.audio.device_id = source_id; SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_EQ(audio_device(/*stream_index=*/0u).value().id, source_id); } @@ -881,7 +948,7 @@ blink::StreamControls controls(true, true); controls.video.device_id = source_id; - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_EQ(video_device(/*stream_index=*/0u).value().id, source_id); } } @@ -922,8 +989,12 @@ TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) { blink::StreamControls controls(false, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); + SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); std::string stream_request_label = host_->label_; blink::MediaStreamDevice current_video_device = @@ -951,8 +1022,11 @@ TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) { blink::StreamControls controls(true, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + blink::MediaStreamDevice(), blink::MediaStreamDevice())); SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); std::string request_label1 = host_->label_; blink::MediaStreamDevice current_video_device = @@ -968,7 +1042,7 @@ 1u, media_stream_manager_->GetDevicesOpenedByRequest(request_label1).size()); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); std::string request_label2 = host_->label_; blink::MediaStreamDevices request1_devices = @@ -988,12 +1062,18 @@ GenerateTwoStreamsAndStopDeviceWhileWaitingForSecondStream) { blink::StreamControls controls(false, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); + SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); // Generate a second stream. - EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1)); + EXPECT_CALL(*host_, + OnStreamGenerationSuccess(kPageRequestId + 1, + SameTypesAs(std::ref(expectation)))); base::RunLoop run_loop1; host_->OnGenerateStreams(kPageRequestId + 1, controls, @@ -1029,12 +1109,16 @@ TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreams) { blink::StreamControls controls(false, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); + SetupFakeUI(true); // Create first group of streams. size_t generated_streams = 3; for (size_t i = 0; i < generated_streams; ++i) - GenerateStreamAndWaitForResult(kPageRequestId + i, controls); + GenerateStreamAndWaitForResult(kPageRequestId + i, controls, expectation); media_stream_manager_->CancelAllRequests(kProcessId, kRenderId, kRequesterId); base::RunLoop().RunUntilIdle(); @@ -1043,6 +1127,10 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { blink::StreamControls controls(false, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); + base::OnceClosure close_callback; media_stream_manager_->UseFakeUIFactoryForTests(base::BindRepeating( [](base::OnceClosure* close_callback) { @@ -1055,7 +1143,7 @@ }, &close_callback)); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); @@ -1070,8 +1158,13 @@ // being unplugged. TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) { blink::StreamControls controls(true, true); + + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + blink::MediaStreamDevice(), blink::MediaStreamDevice())); + SetupFakeUI(true); - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); @@ -1092,8 +1185,12 @@ SetupFakeUI(true); blink::StreamControls controls(false, true); + blink::mojom::StreamDevicesSet expectation; + expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New( + absl::nullopt, blink::MediaStreamDevice())); + // Generate first stream. - GenerateStreamAndWaitForResult(kPageRequestId, controls); + GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); const std::string label1 = host_->label_;
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 570785c4..d95b8bf 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -2119,7 +2119,7 @@ DeviceRequest* request = FindRequest(label); if (!request) return MediaStreamDevices(); - return blink::StreamDevicesToMediaStreamDevicesList(request->devices); + return blink::ToMediaStreamDevicesList(request->devices); } bool MediaStreamManager::FindExistingRequestedDevice( @@ -2407,8 +2407,7 @@ if (request->open_device_cb) { std::move(request->open_device_cb) .Run(true /* success */, label, - blink::StreamDevicesToMediaStreamDevicesList(request->devices) - .front()); + blink::ToMediaStreamDevicesList(request->devices).front()); } } @@ -2739,9 +2738,19 @@ void MediaStreamManager::HandleAccessRequestResponse( const std::string& label, const media::AudioParameters& output_parameters, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& devices_set, MediaStreamRequestResult result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK((result == MediaStreamRequestResult::OK && + devices_set.stream_devices.size() == 1u) || + (result != MediaStreamRequestResult::OK && + devices_set.stream_devices.empty())); + + blink::mojom::StreamDevices devices; + if (result == MediaStreamRequestResult::OK) { + DCHECK_EQ(1u, devices_set.stream_devices.size()); + devices = *devices_set.stream_devices[0]; + } DeviceRequest* request = FindRequest(label); if (!request) { // The request has been canceled before the UI returned. @@ -3251,8 +3260,7 @@ RequestTypeToString(request->request_type()))); MediaStreamUI::SourceCallback device_changed_cb; - if (EnableChangeSource( - blink::StreamDevicesToMediaStreamDevicesList(request->devices)) && + if (EnableChangeSource(blink::ToMediaStreamDevicesList(request->devices)) && base::FeatureList::IsEnabled(features::kDesktopCaptureChangeSource)) { device_changed_cb = base::BindRepeating( &MediaStreamManager::ChangeMediaStreamSourceFromBrowser, @@ -3573,7 +3581,12 @@ GlobalRenderFrameHostId capturer) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - blink::mojom::StreamDevices filtered_new_devices; + blink::mojom::StreamDevicesSetPtr filtered_new_devices_set = + blink::mojom::StreamDevicesSet::New(); + filtered_new_devices_set->stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& filtered_new_devices = + *filtered_new_devices_set->stream_devices[0]; if (new_devices.video_device.has_value() && WebContentsMediaCaptureId::Parse(new_devices.video_device->id, nullptr)) { filtered_new_devices.video_device = new_devices.video_device.value(); @@ -3587,7 +3600,7 @@ base::BindOnce( &CaptureHandleManager::OnTabCaptureDevicesUpdated, base::Unretained(&capture_handle_manager_), label, - std::move(filtered_new_devices), capturer, + std::move(filtered_new_devices_set), capturer, base::BindPostTask( GetIOThreadTaskRunner({}), base::BindRepeating(&MediaStreamManager::OnCaptureHandleChange,
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 58ddc29..1a5b981 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -459,7 +459,7 @@ void HandleAccessRequestResponse( const std::string& label, const media::AudioParameters& output_parameters, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& devices_set, blink::mojom::MediaStreamRequestResult result); void HandleChangeSourceRequestResponse( const std::string& label,
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/content/browser/renderer_host/media/media_stream_ui_proxy.cc index 6b0216da..5f29cdce 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -72,10 +72,19 @@ bool is_from_timer); #endif + // The type blink::mojom::StreamDevices is not movable, therefore stream + // devices cannot be captured for usage with PostTask. + void ProcessAccessRequestResponseForPostTask( + int render_process_id, + int render_frame_id, + blink::mojom::StreamDevicesSetPtr stream_devices_set_ptr, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<MediaStreamUI> stream_ui); + void ProcessAccessRequestResponse( int render_process_id, int render_frame_id, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<MediaStreamUI> stream_ui); @@ -137,7 +146,7 @@ if (!render_delegate) { ProcessAccessRequestResponse( request->render_process_id, request->render_frame_id, - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, std::unique_ptr<MediaStreamUI>()); return; @@ -213,15 +222,40 @@ } #endif -void MediaStreamUIProxy::Core::ProcessAccessRequestResponse( +void MediaStreamUIProxy::Core::ProcessAccessRequestResponseForPostTask( int render_process_id, int render_frame_id, - const blink::mojom::StreamDevices& devices, + blink::mojom::StreamDevicesSetPtr stream_devices_set_ptr, blink::mojom::MediaStreamRequestResult result, std::unique_ptr<MediaStreamUI> stream_ui) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(stream_devices_set_ptr); + ProcessAccessRequestResponse(render_process_id, render_frame_id, + *stream_devices_set_ptr, result, + std::move(stream_ui)); +} - blink::mojom::StreamDevices filtered_devices; +void MediaStreamUIProxy::Core::ProcessAccessRequestResponse( + int render_process_id, + int render_frame_id, + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<MediaStreamUI> stream_ui) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK((result != blink::mojom::MediaStreamRequestResult::OK && + stream_devices_set.stream_devices.empty()) || + (result == blink::mojom::MediaStreamRequestResult::OK && + stream_devices_set.stream_devices.size() == 1u)); + + blink::mojom::StreamDevicesSetPtr filtered_devices_set = + blink::mojom::StreamDevicesSet::New(); + blink::mojom::StreamDevices devices; + if (!stream_devices_set.stream_devices.empty()) { + devices = *stream_devices_set.stream_devices[0]; + filtered_devices_set->stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + } + auto* host = RenderFrameHostImpl::FromID(render_process_id, render_frame_id); if (devices.audio_device.has_value()) { const blink::MediaStreamDevice& audio_device = devices.audio_device.value(); @@ -229,7 +263,7 @@ blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE || IsFeatureEnabled(host, tests_use_fake_render_frame_hosts_, blink::mojom::PermissionsPolicyFeature::kMicrophone)) { - filtered_devices.audio_device = audio_device; + filtered_devices_set->stream_devices[0]->audio_device = audio_device; } } @@ -239,14 +273,17 @@ blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE || IsFeatureEnabled(host, tests_use_fake_render_frame_hosts_, blink::mojom::PermissionsPolicyFeature::kCamera)) { - filtered_devices.video_device = video_device; + filtered_devices_set->stream_devices[0]->video_device = video_device; } } - if (!filtered_devices.audio_device.has_value() && - !filtered_devices.video_device.has_value() && - result == blink::mojom::MediaStreamRequestResult::OK) + if ((filtered_devices_set->stream_devices.empty() || + (!filtered_devices_set->stream_devices[0]->audio_device.has_value() && + !filtered_devices_set->stream_devices[0]->video_device.has_value())) && + result == blink::mojom::MediaStreamRequestResult::OK) { result = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED; + filtered_devices_set->stream_devices.clear(); + } if (stream_ui) { // Callbacks that were supplied to the existing `ui_` are no longer @@ -264,7 +301,7 @@ GetIOThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&MediaStreamUIProxy::ProcessAccessRequestResponse, proxy_, - std::move(filtered_devices), result)); + std::move(filtered_devices_set), result)); } void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() { @@ -407,11 +444,11 @@ #endif void MediaStreamUIProxy::ProcessAccessRequestResponse( - const blink::mojom::StreamDevices& devices, + blink::mojom::StreamDevicesSetPtr stream_devices_set, blink::mojom::MediaStreamRequestResult result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!response_callback_.is_null()); - std::move(response_callback_).Run(devices, result); + std::move(response_callback_).Run(*stream_devices_set, result); } void MediaStreamUIProxy::ProcessStopRequestFromUI() { @@ -482,9 +519,9 @@ GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce( - &MediaStreamUIProxy::Core::ProcessAccessRequestResponse, + &MediaStreamUIProxy::Core::ProcessAccessRequestResponseForPostTask, core_->GetWeakPtr(), request->render_process_id, - request->render_frame_id, blink::mojom::StreamDevices(), + request->render_frame_id, blink::mojom::StreamDevicesSet::New(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, std::unique_ptr<MediaStreamUI>())); return; @@ -492,7 +529,12 @@ // Use the first capture device of the same media type in the list for the // fake UI. - blink::mojom::StreamDevices devices_to_use; + blink::mojom::StreamDevicesSetPtr devices_set_to_use = + blink::mojom::StreamDevicesSet::New(); + devices_set_to_use->stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices_to_use = + *devices_set_to_use->stream_devices[0]; for (const blink::MediaStreamDevice& device : devices_) { if (!devices_to_use.audio_device.has_value() && blink::IsAudioInputMediaType(request->audio_type) && @@ -519,15 +561,18 @@ const bool is_devices_empty = !devices_to_use.audio_device.has_value() && !devices_to_use.video_device.has_value(); + if (is_devices_empty) { + devices_set_to_use->stream_devices.clear(); + } GetUIThreadTaskRunner({})->PostTask( FROM_HERE, - base::BindOnce(&MediaStreamUIProxy::Core::ProcessAccessRequestResponse, - core_->GetWeakPtr(), request->render_process_id, - request->render_frame_id, devices_to_use, - is_devices_empty - ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE - : blink::mojom::MediaStreamRequestResult::OK, - std::unique_ptr<MediaStreamUI>())); + base::BindOnce( + &MediaStreamUIProxy::Core::ProcessAccessRequestResponseForPostTask, + core_->GetWeakPtr(), request->render_process_id, + request->render_frame_id, std::move(devices_set_to_use), + is_devices_empty ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE + : blink::mojom::MediaStreamRequestResult::OK, + std::unique_ptr<MediaStreamUI>())); } void FakeMediaStreamUIProxy::OnStarted(
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.h b/content/browser/renderer_host/media/media_stream_ui_proxy.h index 0a261c7..f1e3bb17 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy.h +++ b/content/browser/renderer_host/media/media_stream_ui_proxy.h
@@ -29,9 +29,9 @@ // be created, used and destroyed on the IO thread. class CONTENT_EXPORT MediaStreamUIProxy { public: - using ResponseCallback = - base::OnceCallback<void(const blink::mojom::StreamDevices& devices, - blink::mojom::MediaStreamRequestResult result)>; + using ResponseCallback = base::OnceCallback<void( + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result)>; using WindowIdCallback = base::OnceCallback<void(gfx::NativeViewId window_id)>; @@ -117,7 +117,7 @@ friend class FakeMediaStreamUIProxy; void ProcessAccessRequestResponse( - const blink::mojom::StreamDevices& devices, + blink::mojom::StreamDevicesSetPtr stream_devices_set, blink::mojom::MediaStreamRequestResult result); void ProcessStopRequestFromUI(); void ProcessChangeSourceRequestFromUI(const DesktopMediaID& media_id);
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc index bd4ad22..ecee177e 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -39,7 +39,7 @@ class MockRenderFrameHostDelegate : public RenderFrameHostDelegate { public: void RequestMediaAccessPermission(const MediaStreamRequest& request, - MediaResponseCallback callback) { + MediaResponseCallback callback) override { return RequestMediaAccessPermission(request, &callback); } const blink::web_pref::WebPreferences& GetOrCreateWebPreferences() override { @@ -60,7 +60,7 @@ class MockResponseCallback { public: MOCK_METHOD2(OnAccessRequestResponse, - void(const blink::mojom::StreamDevices& devices, + void(const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result)); MOCK_METHOD1(OnCheckResponse, void(bool have_access)); }; @@ -153,19 +153,22 @@ base::RunLoop().RunUntilIdle(); ASSERT_FALSE(callback.is_null()); - std::move(callback).Run(blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::unique_ptr<MediaStreamUI>()); - blink::mojom::StreamDevices response; + blink::mojom::StreamDevicesSetPtr response; EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) - .WillOnce([&response](const blink::mojom::StreamDevices& arg0, + .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0, blink::mojom::MediaStreamRequestResult arg1) { - response = arg0; + response = arg0.Clone(); }); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); + EXPECT_TRUE(blink::ToMediaStreamDevicesList(*response).empty()); } TEST_F(MediaStreamUIProxyTest, AcceptAndStart) { @@ -189,28 +192,31 @@ base::RunLoop().RunUntilIdle(); ASSERT_FALSE(callback.is_null()); - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; devices.audio_device = blink::MediaStreamDevice( blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, "Mic", "Mic"); auto ui = std::make_unique<MockMediaStreamUI>(); EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce(Return(0)); - std::move(callback).Run(std::move(devices), + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); - blink::mojom::StreamDevices response; + blink::mojom::StreamDevicesSetPtr response; EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) - .WillOnce([&response](const blink::mojom::StreamDevices& arg0, + .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0, blink::mojom::MediaStreamRequestResult arg1) { - response = arg0; + response = arg0.Clone(); }); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); + EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty()); proxy_->OnStarted(base::OnceClosure(), MediaStreamUI::SourceCallback(), MediaStreamUIProxy::WindowIdCallback(), - /*label=*/std::string(), /*screen_capture_ids=*/{}, + /*label=*/std::string(), /*screen_share_ids=*/{}, MediaStreamUI::StateChangeCallback()); base::RunLoop().RunUntilIdle(); } @@ -240,7 +246,10 @@ proxy_.reset(); std::unique_ptr<MediaStreamUI> ui; - std::move(callback).Run(blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); } @@ -268,7 +277,10 @@ base::OnceClosure stop_callback; - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; devices.audio_device = blink::MediaStreamDevice( blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, "Mic", "Mic"); auto ui = std::make_unique<MockMediaStreamUI>(); @@ -278,26 +290,26 @@ return 0; }); - std::move(callback).Run(std::move(devices), + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); - blink::mojom::StreamDevices response; + blink::mojom::StreamDevicesSetPtr response; EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) - .WillOnce([&response](const blink::mojom::StreamDevices& arg0, + .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0, blink::mojom::MediaStreamRequestResult arg1) { - response = arg0; + response = arg0.Clone(); }); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); + EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty()); MockStopStreamHandler stop_handler; proxy_->OnStarted(base::BindOnce(&MockStopStreamHandler::OnStop, base::Unretained(&stop_handler)), MediaStreamUI::SourceCallback(), MediaStreamUIProxy::WindowIdCallback(), - /*label=*/std::string(), /*screen_capture_ids=*/{}, + /*label=*/std::string(), /*screen_share_ids=*/{}, MediaStreamUI::StateChangeCallback()); base::RunLoop().RunUntilIdle(); @@ -331,7 +343,10 @@ auto ui = std::make_unique<MockMediaStreamUI>(); EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce(Return(kWindowId)); - std::move(callback).Run(blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)); @@ -344,7 +359,7 @@ MediaStreamUI::SourceCallback(), base::BindOnce(&MockStopStreamHandler::OnWindowId, base::Unretained(&handler)), - /*label=*/std::string(), /*screen_capture_ids=*/{}, + /*label=*/std::string(), /*screen_share_ids=*/{}, MediaStreamUI::StateChangeCallback()); base::RunLoop().RunUntilIdle(); } @@ -372,29 +387,31 @@ MediaStreamUI::SourceCallback source_callback; - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; devices.video_device = blink::MediaStreamDevice( blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE, "fake_desktop_video_device", "Fake Desktop Video Device"); auto ui = std::make_unique<MockMediaStreamUI>(); - EXPECT_CALL(*ui, MockOnStarted(_, _)) - .WillOnce([&source_callback](auto, auto callback) { - source_callback = std::move(callback); - return 0; - }); - std::move(callback).Run(std::move(devices), + EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce([&](auto, auto callback) { + source_callback = std::move(callback); + return 0; + }); + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); - blink::mojom::StreamDevices response; + blink::mojom::StreamDevicesSetPtr response; EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) - .WillOnce([&response](const blink::mojom::StreamDevices& arg0, + .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0, blink::mojom::MediaStreamRequestResult arg1) { - response = arg0; + response = arg0.Clone(); }); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); + EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty()); MockStopStreamHandler stop_handler; MockChangeSourceStreamHandler source_handler; @@ -404,7 +421,7 @@ base::BindRepeating(&MockChangeSourceStreamHandler::OnChangeSource, base::Unretained(&source_handler)), MediaStreamUIProxy::WindowIdCallback(), /*label=*/std::string(), - /*screen_capture_ids=*/{}, MediaStreamUI::StateChangeCallback()); + /*screen_share_ids=*/{}, MediaStreamUI::StateChangeCallback()); base::RunLoop().RunUntilIdle(); ASSERT_FALSE(source_callback.is_null()); @@ -436,7 +453,10 @@ MediaStreamUI::SourceCallback source_callback; - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; devices.video_device = blink::MediaStreamDevice( blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE, "fake_tab_video_device", "Fake Tab Video Device"); @@ -448,20 +468,20 @@ stop_callback = std::move(stop); return 0; }); - std::move(callback).Run(std::move(devices), + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); - blink::mojom::StreamDevices response; + blink::mojom::StreamDevicesSetPtr response; EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) .Times(2) - .WillRepeatedly([&response](const blink::mojom::StreamDevices& arg0, - blink::mojom::MediaStreamRequestResult arg1) { - response = arg0; + .WillRepeatedly([&](const blink::mojom::StreamDevicesSet& arg0, + blink::mojom::MediaStreamRequestResult arg1) { + response = arg0.Clone(); }); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); + EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty()); MockStopStreamHandler stop_handler; // No stop event should be triggered. @@ -505,7 +525,7 @@ blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE, "fake_tab_video_device", "Fake Tab Video Device"); - std::move(callback).Run(std::move(devices), + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::make_unique<MockMediaStreamUI>()); @@ -571,7 +591,11 @@ public: void RequestMediaAccessPermission(const MediaStreamRequest& request, MediaResponseCallback callback) override { - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = + *stream_devices_set.stream_devices[0]; if (request.audio_type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { devices.audio_device = blink::MediaStreamDevice( @@ -584,7 +608,7 @@ "Camera"); } auto ui = std::make_unique<MockMediaStreamUI>(); - std::move(callback).Run(std::move(devices), + std::move(callback).Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); } @@ -610,7 +634,7 @@ } void FinishedGetResultOnIOThread( - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); proxy_.reset(); @@ -618,13 +642,13 @@ FROM_HERE, base::BindOnce( &MediaStreamUIProxyPermissionsPolicyTest::FinishedGetResult, - base::Unretained(this), devices, result)); + base::Unretained(this), stream_devices_set.Clone(), result)); } - void FinishedGetResult(const blink::mojom::StreamDevices& devices, + void FinishedGetResult(blink::mojom::StreamDevicesSetPtr stream_devices_set, blink::mojom::MediaStreamRequestResult result) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - devices_ = blink::StreamDevicesToMediaStreamDevicesList(devices); + devices_ = blink::ToMediaStreamDevicesList(*stream_devices_set); result_ = result; std::move(quit_closure_).Run(); }
diff --git a/content/browser/renderer_host/render_frame_host_delegate.cc b/content/browser/renderer_host/render_frame_host_delegate.cc index 6997170..36ccf06 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.cc +++ b/content/browser/renderer_host/render_frame_host_delegate.cc
@@ -44,7 +44,7 @@ MediaResponseCallback callback) { LOG(ERROR) << "RenderFrameHostDelegate::RequestMediaAccessPermission: " << "Not supported."; - std::move(callback).Run(blink::mojom::StreamDevices(), + std::move(callback).Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, std::unique_ptr<MediaStreamUI>()); }
diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc index 63f4c65..0728c7f 100644 --- a/content/browser/speech/speech_recognition_manager_impl.cc +++ b/content/browser/speech/speech_recognition_manager_impl.cc
@@ -307,9 +307,9 @@ // which is only supported in combination with the getDisplayMediaSet API. DCHECK_EQ(stream_devices_set.stream_devices.size(), 1u); DCHECK(stream_devices_set.stream_devices[0]); + blink::MediaStreamDevices devices_list = - blink::StreamDevicesToMediaStreamDevicesList( - *stream_devices_set.stream_devices[0]); + blink::ToMediaStreamDevicesList(stream_devices_set); const bool is_allowed = !devices_list.empty(); if (is_allowed) { // Copy the approved devices array to the context for UI indication.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 9655de6..33f6efe 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4285,7 +4285,7 @@ delegate_->RequestMediaAccessPermission(this, request, std::move(callback)); } else { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, std::unique_ptr<MediaStreamUI>()); }
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index 0f43a8a..19c46ce 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -3214,11 +3214,11 @@ contents()->RequestMediaAccessPermission( dummy_request, base::BindLambdaForTesting( - [&callback_run](const blink::mojom::StreamDevices& stream_devices, - blink::mojom::MediaStreamRequestResult result, - std::unique_ptr<MediaStreamUI> ui) { - EXPECT_FALSE(stream_devices.audio_device.has_value()); - EXPECT_FALSE(stream_devices.video_device.has_value()); + [&callback_run]( + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<MediaStreamUI> ui) { + EXPECT_TRUE(stream_devices_set.stream_devices.empty()); EXPECT_EQ( result, blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN);
diff --git a/content/public/browser/media_stream_request.h b/content/public/browser/media_stream_request.h index e246f363..a2aa228 100644 --- a/content/public/browser/media_stream_request.h +++ b/content/public/browser/media_stream_request.h
@@ -152,10 +152,10 @@ }; // Callback used return results of media access requests. -using MediaResponseCallback = - base::OnceCallback<void(const blink::mojom::StreamDevices& stream_devices, - blink::mojom::MediaStreamRequestResult result, - std::unique_ptr<MediaStreamUI> ui)>; +using MediaResponseCallback = base::OnceCallback<void( + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<MediaStreamUI> ui)>; } // namespace content #endif // CONTENT_PUBLIC_BROWSER_MEDIA_STREAM_REQUEST_H_
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc index daf9b45..ef388906 100644 --- a/content/public/browser/web_contents_delegate.cc +++ b/content/public/browser/web_contents_delegate.cc
@@ -220,7 +220,7 @@ content::MediaResponseCallback callback) { LOG(ERROR) << "WebContentsDelegate::RequestMediaAccessPermission: " << "Not supported."; - std::move(callback).Run(blink::mojom::StreamDevices(), + std::move(callback).Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>()); }
diff --git a/content/test/fuzzer/OWNERS b/content/test/fuzzer/OWNERS index 5d8a22f..8e42a55 100644 --- a/content/test/fuzzer/OWNERS +++ b/content/test/fuzzer/OWNERS
@@ -1,3 +1,2 @@ -ochang@chromium.org metzman@chromium.org bookholt@chromium.org
diff --git a/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc index 3338e86..5302c68 100644 --- a/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc +++ b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc
@@ -5,14 +5,8 @@ #include <stdint.h> #include <utility> -#include "base/at_exit.h" -#include "base/base_switches.h" -#include "base/command_line.h" #include "base/files/scoped_temp_dir.h" -#include "base/i18n/icu_util.h" #include "base/no_destructor.h" -#include "base/test/test_switches.h" -#include "base/test/test_timeouts.h" #include "base/threading/platform_thread.h" #include "base/threading/thread.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" // nogncheck @@ -25,7 +19,7 @@ #include "content/public/test/test_content_client_initializer.h" #include "content/test/fuzzer/file_system_manager_mojolpm_fuzzer.pb.h" #include "content/test/fuzzer/mojolpm_fuzzer_support.h" -#include "mojo/core/embedder/embedder.h" +#include "mojo/public/tools/fuzzers/mojolpm.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/special_storage_policy.h" #include "storage/browser/test/mock_special_storage_policy.h" @@ -69,35 +63,28 @@ // Since the Browser process will host one FileSystemManagerImpl per // RenderProcessHost, we emulate this by allowing the fuzzer to create (and // destroy) multiple FileSystemManagerImpl instances. -class FileSystemManagerTestcase { +class FileSystemManagerTestcase + : public ::mojolpm::Testcase< + content::fuzzing::file_system_manager::proto::Testcase, + content::fuzzing::file_system_manager::proto::Action> { public: + using ProtoTestcase = content::fuzzing::file_system_manager::proto::Testcase; + using ProtoAction = content::fuzzing::file_system_manager::proto::Action; + explicit FileSystemManagerTestcase( const content::fuzzing::file_system_manager::proto::Testcase& testcase); - // Returns true once either all of the actions in the testcase have been - // performed, or the per-testcase action limit has been exceeded. - // - // This should only be called from the fuzzer sequence. - bool IsFinished(); + void SetUp(base::OnceClosure done_closure) override; + void TearDown(base::OnceClosure done_closure) override; - // If there are still actions remaining in the testcase, this will perform the - // next sequence of actions before returning. - // - // If IsFinished() would return true, then calling this function is a no-op. - // - // This should only be called from the fuzzer sequence. - void NextAction(); - - void SetUp(); - void TearDown(); + void RunAction(const ProtoAction& action, + base::OnceClosure done_closure) override; private: - using Action = content::fuzzing::file_system_manager::proto::Action; - - void SetUpOnIOThread(); - void SetUpOnUIThread(); - void TearDownOnIOThread(); - void TearDownOnUIThread(); + void SetUpOnIOThread(base::OnceClosure done_closure); + void SetUpOnUIThread(base::OnceClosure done_closure); + void TearDownOnIOThread(base::OnceClosure done_closure); + void TearDownOnUIThread(base::OnceClosure done_closure); // Used by AddFileSystemManager to create and bind FileSystemManagerImpl on the // UI thread. @@ -115,19 +102,8 @@ uint32_t id, content::fuzzing::file_system_manager::proto::NewFileSystemManagerAction:: RenderProcessId render_process_id, - const storage_key_proto::StorageKey& storage_key); - - // The proto message describing the test actions to perform. - const content::fuzzing::file_system_manager::proto::Testcase& testcase_; - - // Apply a reasonable upper-bound on testcase complexity to avoid timeouts. - const int max_action_count_ = 512; - - // Count of total actions performed in this testcase. - int action_count_ = 0; - - // The index of the next sequence of actions to execute. - int next_sequence_idx_ = 0; + const storage_key_proto::StorageKey& storage_key, + base::OnceClosure done_closure); // Prerequisite state TestBrowserContext browser_context_; @@ -139,40 +115,28 @@ // Access only from UI thread. std::unique_ptr<FileSystemManagerImpl> file_system_manager_impls_[kNumRenderers]; - - SEQUENCE_CHECKER(sequence_checker_); }; FileSystemManagerTestcase::FileSystemManagerTestcase( const content::fuzzing::file_system_manager::proto::Testcase& testcase) - : testcase_(testcase), browser_context_() { + : Testcase<ProtoTestcase, ProtoAction>(testcase), browser_context_() { // FileSystemManagerTestcase is created on the main thread, but the actions // that we want to validate the sequencing of take place on the fuzzer // sequence. DETACH_FROM_SEQUENCE(sequence_checker_); } -void FileSystemManagerTestcase::SetUp() { +void FileSystemManagerTestcase::SetUp(base::OnceClosure done_closure) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - base::RunLoop io_run_loop(base::RunLoop::Type::kNestableTasksAllowed); - GetIOThreadTaskRunner({})->PostTaskAndReply( + GetIOThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&FileSystemManagerTestcase::SetUpOnIOThread, - base::Unretained(this)), - io_run_loop.QuitClosure()); - io_run_loop.Run(); - - base::RunLoop ui_run_loop(base::RunLoop::Type::kNestableTasksAllowed); - GetUIThreadTaskRunner({})->PostTaskAndReply( - FROM_HERE, - base::BindOnce(&FileSystemManagerTestcase::SetUpOnUIThread, - base::Unretained(this)), - ui_run_loop.QuitClosure()); - ui_run_loop.Run(); + base::Unretained(this), std::move(done_closure))); } -void FileSystemManagerTestcase::SetUpOnIOThread() { +void FileSystemManagerTestcase::SetUpOnIOThread( + base::OnceClosure done_closure) { CHECK(temp_dir_.CreateUniqueTempDir()); file_system_context_ = storage::CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath()); @@ -180,9 +144,15 @@ blob_storage_context_ = base::MakeRefCounted<ChromeBlobStorageContext>(); blob_storage_context_->InitializeOnIOThread( temp_dir_.GetPath(), temp_dir_.GetPath(), GetIOThreadTaskRunner({})); + + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&FileSystemManagerTestcase::SetUpOnUIThread, + base::Unretained(this), std::move(done_closure))); } -void FileSystemManagerTestcase::SetUpOnUIThread() { +void FileSystemManagerTestcase::SetUpOnUIThread( + base::OnceClosure done_closure) { ChildProcessSecurityPolicyImpl* p = ChildProcessSecurityPolicyImpl::GetInstance(); p->RegisterFileSystemPermissionPolicy(storage::kFileSystemTypeTest, @@ -198,96 +168,83 @@ i, file_system_context_, blob_storage_context_); p->Add(i, &browser_context_); } + + GetFuzzerTaskRunner()->PostTask(FROM_HERE, std::move(done_closure)); } -void FileSystemManagerTestcase::TearDown() { +void FileSystemManagerTestcase::TearDown(base::OnceClosure done_closure) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - base::RunLoop ui_run_loop(base::RunLoop::Type::kNestableTasksAllowed); - content::GetUIThreadTaskRunner({})->PostTaskAndReply( + GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&FileSystemManagerTestcase::TearDownOnUIThread, - base::Unretained(this)), - ui_run_loop.QuitClosure()); - ui_run_loop.Run(); - - base::RunLoop io_run_loop(base::RunLoop::Type::kNestableTasksAllowed); - content::GetIOThreadTaskRunner({})->PostTaskAndReply( - FROM_HERE, - base::BindOnce(&FileSystemManagerTestcase::TearDownOnIOThread, - base::Unretained(this)), - io_run_loop.QuitClosure()); - io_run_loop.Run(); + base::Unretained(this), std::move(done_closure))); } -void FileSystemManagerTestcase::TearDownOnIOThread() { +void FileSystemManagerTestcase::TearDownOnIOThread( + base::OnceClosure done_closure) { for (size_t i = 0; i < kNumRenderers; i++) { file_system_manager_impls_[i].reset(); } + + GetFuzzerTaskRunner()->PostTask(FROM_HERE, std::move(done_closure)); } -void FileSystemManagerTestcase::TearDownOnUIThread() { +void FileSystemManagerTestcase::TearDownOnUIThread( + base::OnceClosure done_closure) { ChildProcessSecurityPolicyImpl* p = ChildProcessSecurityPolicyImpl::GetInstance(); for (size_t i = 0; i < kNumRenderers; i++) { p->Remove(i); } + + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&FileSystemManagerTestcase::TearDownOnIOThread, + base::Unretained(this), std::move(done_closure))); } -bool FileSystemManagerTestcase::IsFinished() { +void FileSystemManagerTestcase::RunAction(const ProtoAction& action, + base::OnceClosure run_closure) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return next_sequence_idx_ >= testcase_.sequence_indexes_size(); -} -void FileSystemManagerTestcase::NextAction() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (next_sequence_idx_ < testcase_.sequence_indexes_size()) { - auto sequence_idx = testcase_.sequence_indexes(next_sequence_idx_++); - const auto& sequence = - testcase_.sequences(sequence_idx % testcase_.sequences_size()); - for (auto action_idx : sequence.action_indexes()) { - if (!testcase_.actions_size() || ++action_count_ > max_action_count_) { - return; + const auto ThreadId_UI = + content::fuzzing::file_system_manager::proto::RunThreadAction_ThreadId_UI; + const auto ThreadId_IO = + content::fuzzing::file_system_manager::proto::RunThreadAction_ThreadId_IO; + + switch (action.action_case()) { + case ProtoAction::kNewFileSystemManager: + AddFileSystemManager(action.new_file_system_manager().id(), + action.new_file_system_manager().render_process_id(), + action.new_file_system_manager().storage_key(), + std::move(run_closure)); + return; + + case ProtoAction::kRunThread: + if (action.run_thread().id() == ThreadId_UI) { + content::GetUIThreadTaskRunner({})->PostTaskAndReply( + FROM_HERE, base::DoNothing(), std::move(run_closure)); + } else if (action.run_thread().id() == ThreadId_IO) { + content::GetIOThreadTaskRunner({})->PostTaskAndReply( + FROM_HERE, base::DoNothing(), std::move(run_closure)); } - const auto& action = - testcase_.actions(action_idx % testcase_.actions_size()); - switch (action.action_case()) { - case Action::kNewFileSystemManager: - AddFileSystemManager( - action.new_file_system_manager().id(), - action.new_file_system_manager().render_process_id(), - action.new_file_system_manager().storage_key()); - break; + return; - case Action::kRunThread: - if (action.run_thread().id()) { - base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); - GetUIThreadTaskRunner({})->PostTask(FROM_HERE, - run_loop.QuitClosure()); - run_loop.Run(); - } else { - base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); - GetIOThreadTaskRunner({})->PostTask(FROM_HERE, - run_loop.QuitClosure()); - run_loop.Run(); - } - break; + case ProtoAction::kFileSystemManagerRemoteAction: + ::mojolpm::HandleRemoteAction(action.file_system_manager_remote_action()); + break; - case Action::kFileSystemManagerRemoteAction: - ::mojolpm::HandleRemoteAction( - action.file_system_manager_remote_action()); - break; + case ProtoAction::kFileSystemCancellableOperationRemoteAction: + ::mojolpm::HandleRemoteAction( + action.file_system_cancellable_operation_remote_action()); + break; - case Action::kFileSystemCancellableOperationRemoteAction: - ::mojolpm::HandleRemoteAction( - action.file_system_cancellable_operation_remote_action()); - break; - - case Action::ACTION_NOT_SET: - break; - } - } + case ProtoAction::ACTION_NOT_SET: + break; } + + GetFuzzerTaskRunner()->PostTask(FROM_HERE, std::move(run_closure)); } void FileSystemManagerTestcase::AddFileSystemManagerImpl( @@ -305,65 +262,35 @@ storage_key_proto::Convert(storage_key), std::move(receiver)); } +static void AddFileSystemManagerInstance( + uint32_t id, + mojo::Remote<::blink::mojom::FileSystemManager> remote, + base::OnceClosure run_closure) { + ::mojolpm::GetContext()->AddInstance(id, std::move(remote)); + + std::move(run_closure).Run(); +} + void FileSystemManagerTestcase::AddFileSystemManager( uint32_t id, content::fuzzing::file_system_manager::proto::NewFileSystemManagerAction:: RenderProcessId render_process_id, - const storage_key_proto::StorageKey& storage_key) { + const storage_key_proto::StorageKey& storage_key, + base::OnceClosure run_closure) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); mojo::Remote<::blink::mojom::FileSystemManager> remote; auto receiver = remote.BindNewPipeAndPassReceiver(); - base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); - content::GetIOThreadTaskRunner({})->PostTaskAndReply( + GetIOThreadTaskRunner({})->PostTaskAndReply( FROM_HERE, base::BindOnce(&FileSystemManagerTestcase::AddFileSystemManagerImpl, base::Unretained(this), id, render_process_id, storage_key, std::move(receiver)), - run_loop.QuitClosure()); - run_loop.Run(); - - ::mojolpm::GetContext()->AddInstance(id, std::move(remote)); + base::BindOnce(&AddFileSystemManagerInstance, id, std::move(remote), + std::move(run_closure))); } } // namespace content -// Helper function to keep scheduling fuzzer actions on the current runloop -// until the testcase has completed, and then quit the runloop. -void NextAction(content::FileSystemManagerTestcase* testcase, - base::RepeatingClosure quit_closure) { - if (!testcase->IsFinished()) { - testcase->NextAction(); - content::GetFuzzerTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(NextAction, base::Unretained(testcase), - std::move(quit_closure))); - } else { - content::GetFuzzerTaskRunner()->PostTask(FROM_HERE, - std::move(quit_closure)); - } -} - -// Helper function to setup and run the testcase, since we need to do that from -// the fuzzer sequence rather than the main thread. -void RunTestcase(content::FileSystemManagerTestcase* testcase) { - mojo::Message message; - auto dispatch_context = - std::make_unique<mojo::internal::MessageDispatchContext>(&message); - - testcase->SetUp(); - - ::mojolpm::GetContext()->StartTestcase(); - - base::RunLoop fuzzer_run_loop(base::RunLoop::Type::kNestableTasksAllowed); - content::GetFuzzerTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(NextAction, base::Unretained(testcase), - fuzzer_run_loop.QuitClosure())); - fuzzer_run_loop.Run(); - - ::mojolpm::GetContext()->EndTestcase(); - - testcase->TearDown(); -} - DEFINE_BINARY_PROTO_FUZZER( const content::fuzzing::file_system_manager::proto::Testcase& proto_testcase) { @@ -377,13 +304,16 @@ content::FileSystemManagerTestcase testcase(proto_testcase); - base::RunLoop ui_run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::RunLoop main_run_loop; - // Unretained is safe here, because ui_run_loop has to finish before testcase - // goes out of scope. - content::GetFuzzerTaskRunner()->PostTaskAndReply( - FROM_HERE, base::BindOnce(RunTestcase, base::Unretained(&testcase)), - ui_run_loop.QuitClosure()); + // Unretained is safe here, because `main_run_loop` has to finish before + // testcase goes out of scope. + content::GetFuzzerTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&mojolpm::RunTestcase<content::FileSystemManagerTestcase>, + base::Unretained(&testcase), + content::GetFuzzerTaskRunner(), + main_run_loop.QuitClosure())); - ui_run_loop.Run(); + main_run_loop.Run(); }
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc index a8902c04..5f4f2e3 100644 --- a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc +++ b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
@@ -214,7 +214,7 @@ const std::string& user_input) { if (!allow) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, std::unique_ptr<content::MediaStreamUI>()); return; @@ -222,7 +222,7 @@ if (!web_view_guest()->attached() || !web_view_guest()->embedder_web_contents()->GetDelegate()) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); return;
diff --git a/extensions/browser/media_capture_util.cc b/extensions/browser/media_capture_util.cc index df6b066..f25b3a0 100644 --- a/extensions/browser/media_capture_util.cc +++ b/extensions/browser/media_capture_util.cc
@@ -59,7 +59,11 @@ request.video_type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); - blink::mojom::StreamDevices devices; + // TOOD(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::StreamDevicesSet stream_devices_set; + stream_devices_set.stream_devices.emplace_back( + blink::mojom::StreamDevices::New()); + blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; if (request.audio_type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { @@ -84,8 +88,8 @@ // TODO(jamescook): Should we show a recording icon somewhere? If so, where? std::unique_ptr<MediaStreamUI> ui; std::move(callback).Run( - devices, - devices.audio_device.has_value() || devices.video_device.has_value() + stream_devices_set, + (devices.audio_device.has_value() || devices.video_device.has_value()) ? blink::mojom::MediaStreamRequestResult::OK : blink::mojom::MediaStreamRequestResult::INVALID_STATE, std::move(ui));
diff --git a/fuchsia_web/webengine/browser/frame_impl.cc b/fuchsia_web/webengine/browser/frame_impl.cc index b77eed7..bb3db27 100644 --- a/fuchsia_web/webengine/browser/frame_impl.cc +++ b/fuchsia_web/webengine/browser/frame_impl.cc
@@ -8,6 +8,7 @@ #include <lib/fpromise/result.h> #include <lib/sys/cpp/component_context.h> #include <lib/ui/scenic/cpp/view_ref_pair.h> +#include <algorithm> #include <limits> #include "base/bind.h" @@ -206,14 +207,15 @@ const content::MediaStreamRequest& request, content::MediaResponseCallback callback, const std::vector<blink::mojom::PermissionStatus>& result) { - blink::mojom::StreamDevices devices; + // TODO(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::StreamDevicesPtr devices = blink::mojom::StreamDevices::New(); int result_pos = 0; if (request.audio_type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) { - devices.audio_device = blink::MediaStreamDevice( + devices->audio_device = blink::MediaStreamDevice( request.audio_type, request.requested_audio_device_id, /*name=*/""); } @@ -223,15 +225,19 @@ if (request.video_type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) { if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) { - devices.video_device = blink::MediaStreamDevice( + devices->video_device = blink::MediaStreamDevice( request.video_type, request.requested_video_device_id, /*name=*/""); } } + blink::mojom::StreamDevicesSet stream_devices_set; + if (devices->audio_device.has_value() || devices->video_device.has_value()) { + stream_devices_set.stream_devices.emplace_back(std::move(devices)); + } std::move(callback).Run( - devices, - (!devices.audio_device.has_value() && !devices.video_device.has_value()) + stream_devices_set, + stream_devices_set.stream_devices.empty() ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE : blink::mojom::MediaStreamRequestResult::OK, nullptr); @@ -1245,7 +1251,7 @@ permissions.push_back(blink::PermissionType::AUDIO_CAPTURE); } else if (request.audio_type != blink::mojom::MediaStreamType::NO_SERVICE) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); return; } @@ -1255,7 +1261,7 @@ permissions.push_back(blink::PermissionType::VIDEO_CAPTURE); } else if (request.video_type != blink::mojom::MediaStreamType::NO_SERVICE) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); return; } @@ -1264,7 +1270,7 @@ request.render_process_id, request.render_frame_id); if (!render_frame_host) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_STATE, nullptr); return; } @@ -1272,7 +1278,7 @@ if (url::Origin::Create(request.security_origin) != render_frame_host->GetLastCommittedOrigin()) { std::move(callback).Run( - blink::mojom::StreamDevices(), + blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN, nullptr); return;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 59d9e02..a36b9901 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -10551,6 +10551,9 @@ Texture::ImageState old_image_state; gl::GLImage* image = texture->GetLevelImage(textarget, 0, &old_image_state); if (image && old_image_state == Texture::UNBOUND) { + UMA_HISTOGRAM_BOOLEAN( + "GPU.GLES2DecoderImplLazyBindingCheck.WasBindNecessary", true); + ScopedGLErrorSuppressor suppressor( "GLES2DecoderImpl::DoBindOrCopyTexImageIfNeeded", error_state_.get()); if (texture_unit) @@ -10569,8 +10572,17 @@ return false; } return true; + } else { + // If present, the image was already bound. + UMA_HISTOGRAM_BOOLEAN( + "GPU.GLES2DecoderImplLazyBindingCheck.WasBindNecessary", false); } + } else { + // If present, the image was already in use by the texture (i.e., bound). + UMA_HISTOGRAM_BOOLEAN( + "GPU.GLES2DecoderImplLazyBindingCheck.WasBindNecessary", false); } + return false; }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index a066195..1c3e3a6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -2044,8 +2044,12 @@ // It's possible that this texture was processed by some other decoder // while it was also bound here, or that it has been destroyed. In // either case, do nothing. - if (!texture || !texture->is_bind_pending()) + if (!texture || !texture->is_bind_pending()) { + UMA_HISTOGRAM_BOOLEAN( + "GPU.GLES2DecoderPassthroughImplLazyBindingCheck.WasBindNecessary", + false); return; + } // TODO(liberato): make this work for non-0 levels. gl::GLImage* image = texture->GetLevelImage(target, 0); @@ -2057,11 +2061,19 @@ // Similarly, we might not even get here if an image was bound to a // texture that requries bind/copy, but that texture was already bound // to a sampler in this decoder. - if (!image) + if (!image) { + UMA_HISTOGRAM_BOOLEAN( + "GPU.GLES2DecoderPassthroughImplLazyBindingCheck.WasBindNecessary", + false); return; + } // Because the binding is deferred, this texture may not be currently bound // any more. Bind it again. + + UMA_HISTOGRAM_BOOLEAN( + "GPU.GLES2DecoderPassthroughImplLazyBindingCheck.WasBindNecessary", true); + GLenum texture_type = TextureTargetToTextureType(target); api()->glBindTextureFn(texture_type, texture->service_id());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc index 51bc65f..fe05334b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
@@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/strings/string_number_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "components/viz/common/resources/resource_format_utils.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -3404,6 +3405,8 @@ SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_TRUE(group().texture_manager()->CanRender(texture_ref)); + base::HistogramTester histogram_tester; + InSequence s; EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1); cmds::DrawElements cmd; @@ -3413,6 +3416,11 @@ kValidIndexRangeStart * 2); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // As the image was already bound, the decoder should have recorded that lazy + // binding was not necessary. + histogram_tester.ExpectUniqueSample( + "GPU.GLES2DecoderImplLazyBindingCheck.WasBindNecessary", false, 1); } TEST_P(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES2) {
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 7bb415f..13bcdb0a 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -76153,7 +76153,6 @@ builders { name: "WebRTC Chromium Android Builder" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:WebRTC Chromium Android Builder" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" exe { @@ -76200,7 +76199,6 @@ builders { name: "WebRTC Chromium Android Tester" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:WebRTC Chromium Android Tester" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" exe { @@ -76247,7 +76245,6 @@ builders { name: "WebRTC Chromium Linux Builder" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:WebRTC Chromium Linux Builder" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" exe { @@ -76296,7 +76293,6 @@ swarming_host: "chromium-swarm.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" - dimensions: "pool:luci.chromium.webrtc.fyi" exe { cipd_package: "infra/chromium/bootstrapper/${platform}" cipd_version: "latest" @@ -76341,7 +76337,6 @@ builders { name: "WebRTC Chromium Mac Builder" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:WebRTC Chromium Mac Builder" dimensions: "cpu:x86-64" dimensions: "os:Mac" exe { @@ -76390,7 +76385,6 @@ swarming_host: "chromium-swarm.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" - dimensions: "pool:luci.chromium.webrtc.fyi" exe { cipd_package: "infra/chromium/bootstrapper/${platform}" cipd_version: "latest" @@ -76435,7 +76429,6 @@ builders { name: "WebRTC Chromium Win Builder" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:WebRTC Chromium Win Builder" dimensions: "cpu:x86-64" dimensions: "os:Windows" exe { @@ -76484,7 +76477,6 @@ swarming_host: "chromium-swarm.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" - dimensions: "pool:luci.chromium.webrtc.fyi" exe { cipd_package: "infra/chromium/bootstrapper/${platform}" cipd_version: "latest"
diff --git a/infra/config/subprojects/webrtc/webrtc.star b/infra/config/subprojects/webrtc/webrtc.star index a3daa8b..c94c40f8 100644 --- a/infra/config/subprojects/webrtc/webrtc.star +++ b/infra/config/subprojects/webrtc/webrtc.star
@@ -28,7 +28,7 @@ defaults.bucket.set("webrtc") defaults.builder_group.set("chromium.webrtc") -defaults.builderless.set(False) +defaults.builderless.set(None) defaults.build_numbers.set(True) defaults.cpu.set(cpu.X86_64) defaults.executable.set("recipe:chromium") @@ -61,8 +61,6 @@ builder( name = "WebRTC Chromium Linux Tester", triggered_by = ["WebRTC Chromium Linux Builder"], - pool = "luci.chromium.webrtc.fyi", - auto_builder_dimension = False, ) builder( @@ -74,8 +72,6 @@ builder( name = "WebRTC Chromium Mac Tester", triggered_by = ["WebRTC Chromium Mac Builder"], - pool = "luci.chromium.webrtc.fyi", - auto_builder_dimension = False, ) builder( @@ -88,6 +84,4 @@ builder( name = "WebRTC Chromium Win10 Tester", triggered_by = ["WebRTC Chromium Win Builder"], - pool = "luci.chromium.webrtc.fyi", - auto_builder_dimension = False, )
diff --git a/ios/build/tools/convert_gn_xcodeproj.py b/ios/build/tools/convert_gn_xcodeproj.py index 9b2f564..1f30bd9d 100755 --- a/ios/build/tools/convert_gn_xcodeproj.py +++ b/ios/build/tools/convert_gn_xcodeproj.py
@@ -218,7 +218,7 @@ # TODO(crbug.com/1334028) Disable code signing for Xcode 14. lines = check_output(['xcodebuild', '-version']).splitlines() - xcode_version_int = int(float(lines[0].split()[-1])) + xcode_version_int = int(lines[0].split()[-1].split('.')[0]) for key, obj in list(self.IterObjectsByIsa('XCConfigurationList')): # Use the first build configuration as template for creating all the
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index fd91c6b6..ba5ac39 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -11,8 +11,6 @@ "browser_view_controller+private.h", "browser_view_controller.h", "browser_view_controller.mm", - "browser_view_controller_dependency_factory.h", - "browser_view_controller_dependency_factory.mm", "browser_view_controller_helper.h", "browser_view_controller_helper.mm", "common_tab_helper_delegate.h",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index f3fd1f6..4e88289 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -43,7 +43,8 @@ #import "ios/chrome/browser/ui/browser_view/browser_view_controller+delegates.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller+private.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h" -#import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" +#import "ios/chrome/browser/ui/browser_view/browser_view_controller_helper.h" +#import "ios/chrome/browser/ui/browser_view/key_commands_provider.h" #import "ios/chrome/browser/ui/browser_view/tab_lifecycle_mediator.h" #import "ios/chrome/browser/ui/bubble/bubble_presenter.h" #import "ios/chrome/browser/ui/commands/activity_service_commands.h" @@ -314,6 +315,18 @@ if (self = [super initWithBaseViewController:viewController browser:browser]) { _dispatcher = browser->GetCommandDispatcher(); + + ChromeBrowserState* browserState = browser->GetBrowserState(); + + _prerenderService = + PrerenderServiceFactory::GetForBrowserState(browserState); + if (!browserState->IsOffTheRecord()) { + DCHECK(_prerenderService); + _prerenderService->SetDelegate(self); + } + + _bubblePresenter = + [[BubblePresenter alloc] initWithBrowserState:browserState]; } return self; } @@ -473,29 +486,22 @@ - (void)createViewController { DCHECK(self.browserContainerCoordinator.viewController); - BrowserViewControllerDependencyFactory* factory = - [[BrowserViewControllerDependencyFactory alloc] - initWithBrowser:self.browser]; + BrowserViewControllerHelper* browserViewControllerHelper = + [[BrowserViewControllerHelper alloc] init]; + KeyCommandsProvider* keyCommandsProvider = [[KeyCommandsProvider alloc] init]; - ChromeBrowserState* browserState = self.browser->GetBrowserState(); - _prerenderService = PrerenderServiceFactory::GetForBrowserState(browserState); - if (!browserState->IsOffTheRecord()) { - DCHECK(_prerenderService); - _prerenderService->SetDelegate(self); - } - - _bubblePresenter = - [[BubblePresenter alloc] initWithBrowserState:browserState]; + BrowserViewControllerDependencies dependencies = + [self createBrowserViewControllerDependencies]; _viewController = [[BrowserViewController alloc] initWithBrowser:self.browser - dependencyFactory:factory browserContainerViewController:self.browserContainerCoordinator .viewController + browserViewControllerHelper:browserViewControllerHelper dispatcher:self.dispatcher - prerenderService:_prerenderService - bubblePresenter:_bubblePresenter - downloadManagerCoordinator:self.downloadManagerCoordinator]; + keyCommandsProvider:keyCommandsProvider + dependencies:dependencies]; + WebNavigationBrowserAgent::FromBrowser(self.browser) ->SetDelegate(_viewController); @@ -795,6 +801,14 @@ } } +- (BrowserViewControllerDependencies)createBrowserViewControllerDependencies { + BrowserViewControllerDependencies dependencies; + dependencies.prerenderService = _prerenderService; + dependencies.bubblePresenter = _bubblePresenter; + dependencies.downloadManagerCoordinator = self.downloadManagerCoordinator; + + return dependencies; +} #pragma mark - ActivityServiceCommands - (void)sharePage {
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.h b/ios/chrome/browser/ui/browser_view/browser_view_controller.h index 72d5b30..7d0ee940 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.h +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.h
@@ -23,7 +23,7 @@ @protocol ActivityServicePositioner; class Browser; @class BrowserContainerViewController; -@class BrowserViewControllerDependencyFactory; +@class BrowserViewControllerHelper; @class BubblePresenter; @class CommandDispatcher; @protocol CRWResponderInputView; @@ -32,11 +32,21 @@ // TODO(crbug.com/1331229): Remove all use of the download manager coordinator // from BVC @class DownloadManagerCoordinator; +@class KeyCommandsProvider; // TODO(crbug.com/1328039): Remove all use of the prerender service from BVC class PrerenderService; @class ToolbarAccessoryPresenter; @protocol IncognitoReauthCommands; +// TODO(crbug.com/1328039): Remove all use of the prerender service from BVC +// TODO(crbug.com/1331229): Remove all use of the download manager coordinator +// from BVC +typedef struct { + PrerenderService* prerenderService; + BubblePresenter* bubblePresenter; + DownloadManagerCoordinator* downloadManagerCoordinator; +} BrowserViewControllerDependencies; + // The top-level view controller for the browser UI. Manages other controllers // which implement the interface. @interface BrowserViewController @@ -53,26 +63,21 @@ WebStateContainerViewProvider> // Initializes a new BVC. -// `browser` is the browser whose tabs this BVC will display. -// `factory` is the dependency factory created for this BVC instance. -// `browserContainerViewController` is the container object this BVC will exist +// |browser| is the browser whose tabs this BVC will display. +// |browserContainerViewController| is the container object this BVC will exist // inside. // `dispatcher` is the dispatcher instance this BVC will use. // TODO(crbug.com/992582): Remove references to model objects -- including -// `browser` and `dispatcher` -- from this class. -// TODO(crbug.com/1328039): Remove all use of the prerender service from BVC -// TODO(crbug.com/1331229): Remove all use of the download manager coordinator -// from BVC +// |browser| and |dispatcher| -- from this class. - (instancetype)initWithBrowser:(Browser*)browser - dependencyFactory: - (BrowserViewControllerDependencyFactory*)factory browserContainerViewController: (BrowserContainerViewController*)browserContainerViewController + browserViewControllerHelper: + (BrowserViewControllerHelper*)browserViewControllerHelper dispatcher:(CommandDispatcher*)dispatcher - prerenderService:(PrerenderService*)prerenderService - bubblePresenter:(BubblePresenter*)bubblePresenter - downloadManagerCoordinator: - (DownloadManagerCoordinator*)downloadManagerCoordinator + keyCommandsProvider:(KeyCommandsProvider*)keyCommandsProvider + dependencies: + (BrowserViewControllerDependencies)dependencies NS_DESIGNATED_INITIALIZER; - (instancetype)initWithNibName:(NSString*)nibNameOrNil
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index a52a449..daa2efeb 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -57,7 +57,6 @@ #import "ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h" #import "ios/chrome/browser/ui/browser_container/browser_container_view_controller.h" -#import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller_helper.h" #import "ios/chrome/browser/ui/browser_view/key_commands_provider.h" #import "ios/chrome/browser/ui/bubble/bubble_presenter.h" @@ -272,10 +271,6 @@ URLLoadingObserver, ViewRevealingAnimatee, WebStateListObserving> { - // The dependency factory passed on initialization. Used to vend objects used - // by the BVC. - BrowserViewControllerDependencyFactory* _dependencyFactory; - // Identifier for each animation of an NTP opening. NSInteger _NTPAnimationIdentifier; @@ -284,6 +279,10 @@ std::unique_ptr<LocationBarModelDelegateIOS> _locationBarModelDelegate; std::unique_ptr<LocationBarModel> _locationBarModel; + // Helper for the bvc. + // TODO(crbug.com/1329102): Remove this property. + BrowserViewControllerHelper* _browserViewControllerHelper; + // Controller for edge swipe gestures for page and tab navigation. SideSwipeController* _sideSwipeController; @@ -393,8 +392,6 @@ BrowserContainerViewController* browserContainerViewController; // Invisible button used to dismiss the keyboard. @property(nonatomic, strong) UIButton* typingShield; -// The object that manages keyboard commands on behalf of the BVC. -@property(nonatomic, strong, readonly) KeyCommandsProvider* keyCommandsProvider; // Whether the controller's view is currently available. // YES from viewWillAppear to viewWillDisappear. @property(nonatomic, assign, getter=isVisible) BOOL visible; @@ -432,10 +429,6 @@ // A snapshot of the tab strip used on the thumb strip reveal/hide animation. @property(nonatomic, strong) UIView* tabStripSnapshot; -// Helper for the bvc. -// TODO(crbug.com/1329102): Remove this property. -@property(nonatomic, strong) BrowserViewControllerHelper* helper; - // The user agent type used to load the currently visible page. User agent // type is NONE if there is no visible page. // TODO(crbug.com/1272534): Move BubblePresenter to BrowserCoordinator. @@ -530,29 +523,28 @@ #pragma mark - Object lifecycle - (instancetype)initWithBrowser:(Browser*)browser - dependencyFactory: - (BrowserViewControllerDependencyFactory*)factory browserContainerViewController: (BrowserContainerViewController*)browserContainerViewController + browserViewControllerHelper: + (BrowserViewControllerHelper*)browserViewControllerHelper dispatcher:(CommandDispatcher*)dispatcher - prerenderService:(PrerenderService*)prerenderService - bubblePresenter:(BubblePresenter*)bubblePresenter - downloadManagerCoordinator: - (DownloadManagerCoordinator*)downloadManagerCoordinator { + keyCommandsProvider:(KeyCommandsProvider*)keyCommandsProvider + dependencies: + (BrowserViewControllerDependencies)dependencies { self = [super initWithNibName:nil bundle:base::mac::FrameworkBundle()]; if (self) { - DCHECK(factory); - // TODO(crbug.com/1272524): DCHECK that `browser` is non-null. + // TODO(crbug.com/1272524): DCHECK that |browser| is non-null. - _commandDispatcher = dispatcher; _browserContainerViewController = browserContainerViewController; - _dependencyFactory = factory; + _browserViewControllerHelper = browserViewControllerHelper; + _commandDispatcher = dispatcher; + _keyCommandsProvider = keyCommandsProvider; // TODO(crbug.com/1328039): Remove all use of the prerender service from BVC - _prerenderService = prerenderService; - _bubblePresenter = bubblePresenter; + _prerenderService = dependencies.prerenderService; + _bubblePresenter = dependencies.bubblePresenter; // TODO(crbug.com/1331229): Remove all use of the download manager // coordinator from BVC - _downloadManagerCoordinator = downloadManagerCoordinator; + _downloadManagerCoordinator = dependencies.downloadManagerCoordinator; // TODO(crbug.com/1329089): Inject this handler. self.textZoomHandler = HandlerForProtocol(self.commandDispatcher, TextZoomCommands); @@ -681,13 +673,6 @@ #pragma mark - Private Properties -- (KeyCommandsProvider*)keyCommandsProvider { - if (!_keyCommandsProvider) { - _keyCommandsProvider = [_dependencyFactory newKeyCommandsProvider]; - } - return _keyCommandsProvider; -} - - (BOOL)canShowTabStrip { return IsRegularXRegularSizeClass(self); } @@ -1230,7 +1215,7 @@ // TODO(crbug.com/1329100): Inject the key commands provider. WebNavigationBrowserAgent* navigationAgent = WebNavigationBrowserAgent::FromBrowser(self.browser); - return [self.keyCommandsProvider + return [_keyCommandsProvider keyCommandsForConsumer:self baseViewController:self dispatcher:self.dispatcher @@ -1429,7 +1414,7 @@ _toolbarUIState = nil; _locationBarModelDelegate = nil; _locationBarModel = nil; - self.helper = nil; + _browserViewControllerHelper = nil; if (base::FeatureList::IsEnabled(kModernTabStrip)) { [self.tabStripCoordinator stop]; self.tabStripCoordinator = nil; @@ -1820,9 +1805,6 @@ _locationBarModel = std::make_unique<LocationBarModelImpl>( _locationBarModelDelegate.get(), kMaxURLDisplayChars); - // TODO(crbug.com/1329102): Remove `self.helper`. - self.helper = [_dependencyFactory newBrowserViewControllerHelper]; - // TODO(crbug.com/1329094): Move this coordinator to BrowserCoordinator self.popupMenuCoordinator = [[PopupMenuCoordinator alloc] initWithBaseViewController:self @@ -2378,7 +2360,7 @@ - (void)updateToolbar { // If the BVC has been partially torn down for low memory, wait for the // view rebuild to handle toolbar updates. - if (!(self.helper && self.browserState)) + if (!(_browserViewControllerHelper && self.browserState)) return; web::WebState* webState = self.currentWebState; @@ -2390,7 +2372,8 @@ (_prerenderService && _prerenderService->IsLoadingPrerender()); // TODO(crbug.com/1329102): Change -isToolbarLoading method to a free // function. - if (isPrerendered && ![self.helper isToolbarLoading:self.currentWebState]) + if (isPrerendered && + ![_browserViewControllerHelper isToolbarLoading:self.currentWebState]) [self.primaryToolbarCoordinator showPrerenderingAnimation]; [self.dispatcher showFindUIIfActive]; @@ -3813,11 +3796,11 @@ [self.primaryToolbarCoordinator transitionToLocationBarFocusedState:YES]; - self.keyCommandsProvider.canDismissModals = YES; + _keyCommandsProvider.canDismissModals = YES; } - (void)locationBarDidResignFirstResponder { - self.keyCommandsProvider.canDismissModals = NO; + _keyCommandsProvider.canDismissModals = NO; [self.sideSwipeController setEnabled:YES]; if (self.isNTPActiveForCurrentWebState || IsSingleNtpEnabled()) { @@ -3857,8 +3840,8 @@ GURL URL = self.currentWebState->GetLastCommittedURL(); // TODO(crbug.com/1329102): Change -isWebStateBookmarkedByUser method to a // free function. - BOOL alreadyBookmarked = - [self.helper isWebStateBookmarkedByUser:self.currentWebState]; + BOOL alreadyBookmarked = [_browserViewControllerHelper + isWebStateBookmarkedByUser:self.currentWebState]; if (alreadyBookmarked) { [_bookmarkInteractionController presentBookmarkEditorForURL:URL];
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h b/ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h deleted file mode 100644 index 13cba239..0000000 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_BROWSER_VIEW_BROWSER_VIEW_CONTROLLER_DEPENDENCY_FACTORY_H_ -#define IOS_CHROME_BROWSER_UI_BROWSER_VIEW_BROWSER_VIEW_CONTROLLER_DEPENDENCY_FACTORY_H_ - -#import <UIKit/UIKit.h> - - -@class AlertCoordinator; -class Browser; -@class BrowserViewControllerHelper; -@class KeyCommandsProvider; - -// Creates helper objects needed by BrowserViewController. -@interface BrowserViewControllerDependencyFactory : NSObject - -// Creates a new factory backed by `browser`. This must be the same browser -// provided to BrowserViewController (and like BVC, this is a weak reference). -- (instancetype)initWithBrowser:(Browser*)browser; - -- (BrowserViewControllerHelper*)newBrowserViewControllerHelper; - -// Returns a new keyboard commands coordinator to handle keyboard commands. -- (KeyCommandsProvider*)newKeyCommandsProvider; - -@end - -#endif // IOS_CHROME_BROWSER_UI_BROWSER_VIEW_BROWSER_VIEW_CONTROLLER_DEPENDENCY_FACTORY_H_
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.mm deleted file mode 100644 index 85ba188..0000000 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.mm +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" - -#include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/main/browser.h" -#import "ios/chrome/browser/ui/browser_view/browser_view_controller_helper.h" -#import "ios/chrome/browser/ui/browser_view/key_commands_provider.h" -#include "ui/base/l10n/l10n_util_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation BrowserViewControllerDependencyFactory { - Browser* _browser; - ChromeBrowserState* _browserState; - WebStateList* _webStateList; -} - -- (id)initWithBrowser:(Browser*)browser { - self = [super init]; - if (self) { - _browser = browser; - _browserState = browser->GetBrowserState(); - _webStateList = browser->GetWebStateList(); - } - return self; -} - -- (BrowserViewControllerHelper*)newBrowserViewControllerHelper { - return [[BrowserViewControllerHelper alloc] init]; -} - -- (KeyCommandsProvider*)newKeyCommandsProvider { - return [[KeyCommandsProvider alloc] init]; -} - -@end
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm index 58d9d47..f4ec2c8 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
@@ -25,7 +25,6 @@ #import "ios/chrome/browser/sessions/test_session_service.h" #import "ios/chrome/browser/tabs/tab_helper_util.h" #import "ios/chrome/browser/ui/browser_container/browser_container_view_controller.h" -#import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller_helper.h" #import "ios/chrome/browser/ui/browser_view/key_commands_provider.h" #import "ios/chrome/browser/ui/bubble/bubble_presenter.h" @@ -105,15 +104,6 @@ [OCMockObject niceMockForClass:[PKAddPassesViewController class]]; passKitViewController_ = passKitController; - bvcHelper_ = [[BrowserViewControllerHelper alloc] init]; - - // Set up a stub dependency factory. - id factory = [OCMockObject - mockForClass:[BrowserViewControllerDependencyFactory class]]; - [[[factory stub] andReturn:bvcHelper_] newBrowserViewControllerHelper]; - - dependencyFactory_ = factory; - browser_ = std::make_unique<TestBrowser>(chrome_browser_state_.get()); WebUsageEnablerBrowserAgent::CreateForBrowser(browser_.get()); UrlLoadingNotifierBrowserAgent::CreateForBrowser(browser_.get()); @@ -183,6 +173,10 @@ ClipboardRecentContent::SetInstance( std::make_unique<FakeClipboardRecentContent>()); + container_ = [[BrowserContainerViewController alloc] init]; + bvc_helper_ = [[BrowserViewControllerHelper alloc] init]; + key_commands_provider_ = [[KeyCommandsProvider alloc] init]; + fake_prerender_service_ = std::make_unique<FakePrerenderService>(); bubble_presenter_ = [[BubblePresenter alloc] @@ -192,15 +186,18 @@ initWithBaseViewController:[[UIViewController alloc] init] browser:browser_.get()]; - container_ = [[BrowserContainerViewController alloc] init]; + BrowserViewControllerDependencies dependencies; + dependencies.prerenderService = fake_prerender_service_.get(); + dependencies.bubblePresenter = bubble_presenter_; + dependencies.downloadManagerCoordinator = download_manager_coordinator_; + bvc_ = [[BrowserViewController alloc] initWithBrowser:browser_.get() - dependencyFactory:factory browserContainerViewController:container_ + browserViewControllerHelper:bvc_helper_ dispatcher:browser_->GetCommandDispatcher() - prerenderService:fake_prerender_service_.get() - bubblePresenter:bubble_presenter_ - downloadManagerCoordinator:download_manager_coordinator_]; + keyCommandsProvider:key_commands_provider_ + dependencies:dependencies]; // Force the view to load. UIWindow* window = [[UIWindow alloc] initWithFrame:CGRectZero]; @@ -228,7 +225,8 @@ std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<Browser> browser_; std::unique_ptr<PrerenderService> fake_prerender_service_; - BrowserViewControllerHelper* bvcHelper_; + BrowserViewControllerHelper* bvc_helper_; + KeyCommandsProvider* key_commands_provider_; PKAddPassesViewController* passKitViewController_; OCMockObject* dependencyFactory_; CommandDispatcher* command_dispatcher_;
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm index e7a60e61..a594685 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -21,7 +21,6 @@ #import "ios/chrome/browser/snapshots/snapshot_browser_agent.h" #import "ios/chrome/browser/ui/browser_view/browser_coordinator.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h" -#import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browsing_data_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 0cefa12..d6cdbba 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -6bf982611d5c4df13a2a694e07b182da931b7609 \ No newline at end of file +9ce45f67842397a076fd044b5d243d3a119b5255 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 6b986d0..b9f0626 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -0a2ee68f386929280534369f3858b2ec6497d6e4 \ No newline at end of file +b2567e8abc7cc9a1e9fd53ac627d974991c85b34 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index a911838..6c814b9 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -f597692672207e9c5fbc1f0435591aca9471a21d \ No newline at end of file +8d22b9f8e9d4e7adb9b54a539d7ff29ae686de76 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index 02f99a7..c74e73e 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -383e79d3130539196d27a4fbccec41dd7f6ab488 \ No newline at end of file +a0a7b1ee0222fa2abcb6a4b6b974c4a27fea32c3 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index d400f68..e2b3c406 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -35e93d58bb31865b013d3f32a6b3e8aaa9321cf5 \ No newline at end of file +3c33d89c13871558b0b5a3f82959c8b6ce61972f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index 7e7bc63c..aa76d9d2 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -b4e9292d84fc93cb2a16a05cb6f04b53a5d145cc \ No newline at end of file +23771a89ace4b4ed68698287c52ebfa2f261dd21 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 657c385..e5428225 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -06408c87551305288ac232f7bf2576926f78eabc \ No newline at end of file +85d2f7147c48870b56901987444a24d52b85f4d2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index d4304aa..b77fcb3 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -e7fe7e2eb02066dc5c52bdee3dd2190fc0e21c69 \ No newline at end of file +d4be0b8f87c7e037b240cd839d93428f41ab431d \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index 983c18b..2ab7b282 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -346f2fa38431c6da6d0a2280443f260df8f9810a \ No newline at end of file +928f0fcd1fe261376943f3fe87a6753661f45e70 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 2d2a5d88..e7d7919 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -0ee06675c5b8b389b607774ef0f62431b3e7c389 \ No newline at end of file +547adf26f778a432a8cfb783b3711a5461e03c75 \ No newline at end of file
diff --git a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc index ad614d1..7c7214d 100644 --- a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc
@@ -737,7 +737,6 @@ AV1VaapiVideoDecoderDelegate::~AV1VaapiVideoDecoderDelegate() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!picture_params_); - DCHECK(slice_params_.empty()); DCHECK(!crypto_params_); } @@ -834,17 +833,17 @@ if (!picture_params_) return DecodeStatus::kFail; } - if (slice_params_.size() != slice_params.size()) { - while (slice_params_.size() < slice_params.size()) { - slice_params_.push_back(vaapi_wrapper_->CreateVABuffer( - VASliceParameterBufferType, sizeof(VASliceParameterBufferAV1))); - if (!slice_params_.back()) { - slice_params_.clear(); - return DecodeStatus::kFail; - } - } - slice_params_.resize(slice_params.size()); - slice_params_.shrink_to_fit(); + + // TODO(b/235138734): Once the driver is fixed, re-use the + // VASliceParameterBufferAV1 buffers across frames instead of creating new + // ones every time. Alternatively, consider recreating these buffers only if + // |slice_params| changes from frame to frame. + std::vector<std::unique_ptr<ScopedVABuffer>> slice_params_va_buffers; + for (size_t i = 0; i < slice_params.size(); i++) { + slice_params_va_buffers.push_back(vaapi_wrapper_->CreateVABuffer( + VASliceParameterBufferType, sizeof(VASliceParameterBufferAV1))); + if (!slice_params_va_buffers.back()) + return DecodeStatus::kFail; } // TODO(hiroh): Don't submit the entire coded data to the buffer. Instead, @@ -864,9 +863,9 @@ {encoded_data->id(), {encoded_data->type(), encoded_data->size(), data.data()}}}; for (size_t i = 0; i < slice_params.size(); ++i) { - buffers.push_back({slice_params_[i]->id(), - {slice_params_[i]->type(), slice_params_[i]->size(), - &slice_params[i]}}); + buffers.push_back({slice_params_va_buffers[i]->id(), + {slice_params_va_buffers[i]->type(), + slice_params_va_buffers[i]->size(), &slice_params[i]}}); } #if BUILDFLAG(IS_CHROMEOS_ASH) if (uses_crypto) { @@ -892,7 +891,6 @@ // Destroy the member ScopedVABuffers below since they refer to a VAContextID // that will be destroyed soon. picture_params_.reset(); - slice_params_.clear(); crypto_params_.reset(); } } // namespace media
diff --git a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h index 301c488..31fd5a4 100644 --- a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h +++ b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h
@@ -43,7 +43,6 @@ private: std::unique_ptr<ScopedVABuffer> picture_params_; - std::vector<std::unique_ptr<ScopedVABuffer>> slice_params_; std::unique_ptr<ScopedVABuffer> crypto_params_; }; } // namespace media
diff --git a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc index 102d6b7..ffc25c1e 100644 --- a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc +++ b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc
@@ -226,22 +226,6 @@ DVLOGF(1) << "Spatial layer encoding is not supported"; return false; } - if (config.HasTemporalLayer() && !supports_temporal_layer_for_testing_) { - bool support_temporal_layer = false; -#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS) - VAImplementation implementation = VaapiWrapper::GetImplementationType(); - // TODO(b/199487660): Enable H.264 temporal layer encoding on AMD once their - // drivers support them. - support_temporal_layer = - base::FeatureList::IsEnabled(kVaapiH264TemporalLayerHWEncoding) && - (implementation == VAImplementation::kIntelI965 || - implementation == VAImplementation::kIntelIHD); -#endif - if (!support_temporal_layer) { - DVLOGF(1) << "Temporal layer encoding is not supported"; - return false; - } - } visible_size_ = config.input_visible_size; // For 4:2:0, the pixel sizes have to be even. @@ -290,15 +274,6 @@ << base::strict_cast<size_t>(num_temporal_layers_); return false; } - - // |ave_config.max_num_ref_frames| represents the maximum number of - // reference frames for both the reference picture list 0 (bottom 16 bits) - // and the reference picture list 1 (top 16 bits) in H264 encoding. - const size_t max_p_frame_slots = ave_config.max_num_ref_frames & 0xffff; - if (max_p_frame_slots < num_temporal_layers_ - 1) { - DVLOGF(1) << "P frame slots is too short: " << max_p_frame_slots; - return false; - } } curr_params_.max_ref_pic_list0_size =
diff --git a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.h b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.h index 49cd78c..c6f0bad 100644 --- a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.h +++ b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.h
@@ -152,10 +152,6 @@ // RefPicList0 per spec (spec section 8.2.4.2). base::circular_deque<scoped_refptr<H264Picture>> ref_pic_list0_; - // Sets true if and only if testing. - // TODO(b/199487660): Remove once all drivers support temporal layers. - bool supports_temporal_layer_for_testing_ = false; - uint8_t num_temporal_layers_ = 1; };
diff --git a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc index d557d30b..18b8a3e9 100644 --- a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc +++ b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc
@@ -188,8 +188,6 @@ base::BindRepeating(&H264VaapiVideoEncoderDelegateTest::OnError, base::Unretained(this))); EXPECT_CALL(*this, OnError()).Times(0); - - encoder_->supports_temporal_layer_for_testing_ = true; } bool H264VaapiVideoEncoderDelegateTest::InitializeEncoder(
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc index 2b49650..0c795665 100644 --- a/media/gpu/vaapi/vaapi_unittest.cc +++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -515,12 +515,7 @@ VaapiWrapper::GetSupportedScalabilityModes( H264PROFILE_BASELINE, VAProfileH264ConstrainedBaseline); #if BUILDFLAG(IS_CHROMEOS) - // TODO(b/199487660): Enable H.264 temporal layer encoding on AMD once their - // drivers support them. - const auto implementation = VaapiWrapper::GetImplementationType(); - if (base::FeatureList::IsEnabled(kVaapiH264TemporalLayerHWEncoding) && - (implementation == VAImplementation::kIntelI965 || - implementation == VAImplementation::kIntelIHD)) { + if (base::FeatureList::IsEnabled(kVaapiH264TemporalLayerHWEncoding)) { EXPECT_EQ(scalability_modes_h264_baseline, kSupportedTemporalSVC); } else { EXPECT_TRUE(scalability_modes_h264_baseline.empty());
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc index 074f00e..761fa1b 100644 --- a/media/gpu/vaapi/vaapi_wrapper.cc +++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -1518,12 +1518,7 @@ } if (media_profile >= H264PROFILE_MIN && media_profile <= H264PROFILE_MAX) { - // TODO(b/199487660): Enable H.264 temporal layer encoding on AMD once their - // drivers support them. - VAImplementation implementation = VaapiWrapper::GetImplementationType(); - if (base::FeatureList::IsEnabled(kVaapiH264TemporalLayerHWEncoding) && - (implementation == VAImplementation::kIntelI965 || - implementation == VAImplementation::kIntelIHD)) { + if (base::FeatureList::IsEnabled(kVaapiH264TemporalLayerHWEncoding)) { scalability_modes.push_back(SVCScalabilityMode::kL1T2); scalability_modes.push_back(SVCScalabilityMode::kL1T3); }
diff --git a/media/mojo/services/stable_video_decoder_service.cc b/media/mojo/services/stable_video_decoder_service.cc index 2cbdedf..9679202 100644 --- a/media/mojo/services/stable_video_decoder_service.cc +++ b/media/mojo/services/stable_video_decoder_service.cc
@@ -11,9 +11,12 @@ : video_decoder_client_receiver_(this), media_log_receiver_(this), stable_video_frame_handle_releaser_receiver_(this), - dst_video_decoder_(std::move(dst_video_decoder)) { + dst_video_decoder_(std::move(dst_video_decoder)), + dst_video_decoder_receiver_(dst_video_decoder_.get()) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CHECK(!!dst_video_decoder_); + dst_video_decoder_remote_.Bind( + dst_video_decoder_receiver_.BindNewPipeAndPassRemote()); } StableVideoDecoderService::~StableVideoDecoderService() { @@ -54,11 +57,11 @@ stable_video_frame_handle_releaser_receiver_.Bind( std::move(stable_video_frame_handle_releaser_receiver)); - dst_video_decoder_->Construct( + dst_video_decoder_remote_->Construct( video_decoder_client_receiver_.BindNewEndpointAndPassRemote(), media_log_receiver_.BindNewPipeAndPassRemote(), video_frame_handle_releaser_remote_.BindNewPipeAndPassReceiver(), - std::move(decoder_buffer_pipe), mojom::CommandBufferId::New(), + std::move(decoder_buffer_pipe), mojom::CommandBufferIdPtr(), target_color_space); } @@ -94,7 +97,10 @@ bool can_read_without_stalling, const absl::optional<base::UnguessableToken>& release_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - NOTIMPLEMENTED(); + DCHECK(stable_video_decoder_client_remote_.is_bound()); + DCHECK(release_token.has_value()); + stable_video_decoder_client_remote_->OnVideoFrameDecoded( + frame, can_read_without_stalling, *release_token); } void StableVideoDecoderService::OnWaiting(WaitingReason reason) {
diff --git a/media/mojo/services/stable_video_decoder_service.h b/media/mojo/services/stable_video_decoder_service.h index 4593d04..20ee73a 100644 --- a/media/mojo/services/stable_video_decoder_service.h +++ b/media/mojo/services/stable_video_decoder_service.h
@@ -110,9 +110,19 @@ video_frame_handle_releaser_remote_ GUARDED_BY_CONTEXT(sequence_checker_); // The incoming stable::mojom::StableVideoDecoder requests are forwarded to - // |dst_video_decoder_|. + // |dst_video_decoder_receiver_| through |dst_video_decoder_remote_|. + // + // Note: the implementation behind |dst_video_decoder_receiver_| (i.e., + // |dst_video_decoder_|) lives in-process. The reason we don't just make calls + // directly to that implementation is that when we call Construct(), we need + // to pass a mojo::PendingAssociatedRemote which needs to be sent over an + // existing pipe before using it to make calls. std::unique_ptr<mojom::VideoDecoder> dst_video_decoder_ GUARDED_BY_CONTEXT(sequence_checker_); + mojo::Receiver<mojom::VideoDecoder> dst_video_decoder_receiver_ + GUARDED_BY_CONTEXT(sequence_checker_); + mojo::Remote<mojom::VideoDecoder> dst_video_decoder_remote_ + GUARDED_BY_CONTEXT(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/media/mojo/services/stable_video_decoder_service_unittest.cc b/media/mojo/services/stable_video_decoder_service_unittest.cc index 3f24b23..009b0f23 100644 --- a/media/mojo/services/stable_video_decoder_service_unittest.cc +++ b/media/mojo/services/stable_video_decoder_service_unittest.cc
@@ -19,6 +19,7 @@ using testing::ByMove; using testing::Mock; using testing::Return; +using testing::SaveArg; using testing::StrictMock; namespace media { @@ -367,6 +368,36 @@ /*expect_construct_call=*/false)); } +TEST_F(StableVideoDecoderServiceTest, + StableVideoDecoderClientReceivesOnVideoFrameDecodedEvent) { + auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>(); + auto* mock_video_decoder_raw = mock_video_decoder.get(); + auto stable_video_decoder_remote = + CreateStableVideoDecoder(std::move(mock_video_decoder)); + ASSERT_TRUE(stable_video_decoder_remote.is_bound()); + ASSERT_TRUE(stable_video_decoder_remote.is_connected()); + auto auxiliary_endpoints = ConstructStableVideoDecoder( + stable_video_decoder_remote, *mock_video_decoder_raw, + /*expect_construct_call=*/true); + ASSERT_TRUE(auxiliary_endpoints); + ASSERT_TRUE(auxiliary_endpoints->video_decoder_client_remote); + ASSERT_TRUE(auxiliary_endpoints->mock_stable_video_decoder_client); + + const auto token_for_release = base::UnguessableToken::Create(); + scoped_refptr<VideoFrame> video_frame_to_send = VideoFrame::CreateEOSFrame(); + scoped_refptr<VideoFrame> video_frame_received; + constexpr bool kCanReadWithoutStalling = true; + EXPECT_CALL( + *auxiliary_endpoints->mock_stable_video_decoder_client, + OnVideoFrameDecoded(_, kCanReadWithoutStalling, token_for_release)) + .WillOnce(SaveArg<0>(&video_frame_received)); + auxiliary_endpoints->video_decoder_client_remote->OnVideoFrameDecoded( + video_frame_to_send, kCanReadWithoutStalling, token_for_release); + auxiliary_endpoints->video_decoder_client_remote.FlushForTesting(); + ASSERT_TRUE(video_frame_received); + EXPECT_TRUE(video_frame_received->metadata().end_of_stream); +} + } // namespace } // namespace media
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc index d5d84aa..0ae446df 100644 --- a/net/android/network_change_notifier_android.cc +++ b/net/android/network_change_notifier_android.cc
@@ -214,8 +214,7 @@ NetworkChangeNotifierDelegateAndroid* delegate) : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()), delegate_(delegate), - blocking_thread_objects_(nullptr, base::OnTaskRunnerDeleter(nullptr)), - force_network_handles_supported_for_testing_(false) { + blocking_thread_objects_(nullptr, base::OnTaskRunnerDeleter(nullptr)) { CHECK_EQ(NetId::INVALID, NetworkChangeNotifier::kInvalidNetworkHandle) << "kInvalidNetworkHandle doesn't match NetId::INVALID"; delegate_->RegisterObserver(this);
diff --git a/net/android/network_change_notifier_android.h b/net/android/network_change_notifier_android.h index 8cf8c1e4..1911af3 100644 --- a/net/android/network_change_notifier_android.h +++ b/net/android/network_change_notifier_android.h
@@ -117,7 +117,7 @@ // Also used for DnsConfigService which also must live on blocking sequences. std::unique_ptr<BlockingThreadObjects, base::OnTaskRunnerDeleter> blocking_thread_objects_; - bool force_network_handles_supported_for_testing_; + bool force_network_handles_supported_for_testing_ = false; }; } // namespace net
diff --git a/net/android/network_change_notifier_android_unittest.cc b/net/android/network_change_notifier_android_unittest.cc index 087a258b1..b3c5a8e0 100644 --- a/net/android/network_change_notifier_android_unittest.cc +++ b/net/android/network_change_notifier_android_unittest.cc
@@ -40,11 +40,7 @@ typedef NetworkChangeNotifier::NetworkHandle NetworkHandle; typedef NetworkChangeNotifier::NetworkList NetworkList; - NetworkChangeNotifierDelegateAndroidObserver() - : type_notifications_count_(0), - cost_notifications_count_(0), - max_bandwidth_notifications_count_(0), - default_network_active_notifications_count_(0) {} + NetworkChangeNotifierDelegateAndroidObserver() = default; // NetworkChangeNotifierDelegateAndroid::Observer: void OnConnectionTypeChanged() override { type_notifications_count_++; } @@ -79,16 +75,16 @@ } private: - int type_notifications_count_; - int cost_notifications_count_; - int max_bandwidth_notifications_count_; - int default_network_active_notifications_count_; + int type_notifications_count_ = 0; + int cost_notifications_count_ = 0; + int max_bandwidth_notifications_count_ = 0; + int default_network_active_notifications_count_ = 0; }; class NetworkChangeNotifierObserver : public NetworkChangeNotifier::ConnectionTypeObserver { public: - NetworkChangeNotifierObserver() : notifications_count_(0) {} + NetworkChangeNotifierObserver() = default; // NetworkChangeNotifier::ConnectionTypeObserver: void OnConnectionTypeChanged( @@ -101,7 +97,7 @@ } private: - int notifications_count_; + int notifications_count_ = 0; }; class NetworkChangeNotifierConnectionCostObserver
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc index 00925d0b..f971b575 100644 --- a/net/android/network_change_notifier_delegate_android.cc +++ b/net/android/network_change_notifier_delegate_android.cc
@@ -94,8 +94,7 @@ // TODO(crbug.com/1042122): Remove once Cronet drops Kitkat support. is_default_network_active_api_supported_( base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_LOLLIPOP), - default_network_active_observers_(0) { + base::android::SDK_VERSION_LOLLIPOP) { JNIEnv* env = base::android::AttachCurrentThread(); Java_NetworkChangeNotifier_addNativeObserver( env, java_network_change_notifier_, reinterpret_cast<intptr_t>(this));
diff --git a/net/android/network_change_notifier_delegate_android.h b/net/android/network_change_notifier_delegate_android.h index b03763b..228db92 100644 --- a/net/android/network_change_notifier_delegate_android.h +++ b/net/android/network_change_notifier_delegate_android.h
@@ -228,7 +228,7 @@ // Used to enable/disable default network active notifications on the Java // side. - std::atomic_int default_network_active_observers_; + std::atomic_int default_network_active_observers_ = 0; }; } // namespace net
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc index 44336cae..2b8d6fd 100644 --- a/net/base/address_tracker_linux.cc +++ b/net/base/address_tracker_linux.cc
@@ -155,11 +155,8 @@ link_callback_(base::DoNothing()), tunnel_callback_(base::DoNothing()), ignored_interfaces_(), - connection_type_initialized_(false), connection_type_initialized_cv_(&connection_type_lock_), - current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE), - tracking_(false), - threads_waiting_for_connection_type_initialization_(0) {} + tracking_(false) {} AddressTrackerLinux::AddressTrackerLinux( const base::RepeatingClosure& address_callback, @@ -171,11 +168,8 @@ link_callback_(link_callback), tunnel_callback_(tunnel_callback), ignored_interfaces_(ignored_interfaces), - connection_type_initialized_(false), connection_type_initialized_cv_(&connection_type_lock_), - current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE), - tracking_(true), - threads_waiting_for_connection_type_initialization_(0) { + tracking_(true) { DCHECK(!address_callback.is_null()); DCHECK(!link_callback.is_null()); }
diff --git a/net/base/address_tracker_linux.h b/net/base/address_tracker_linux.h index c993318..db564af 100644 --- a/net/base/address_tracker_linux.h +++ b/net/base/address_tracker_linux.h
@@ -180,11 +180,12 @@ const std::unordered_set<std::string> ignored_interfaces_; base::Lock connection_type_lock_; - bool connection_type_initialized_; + bool connection_type_initialized_ = false; base::ConditionVariable connection_type_initialized_cv_; - NetworkChangeNotifier::ConnectionType current_connection_type_; + NetworkChangeNotifier::ConnectionType current_connection_type_ = + NetworkChangeNotifier::CONNECTION_NONE; bool tracking_; - int threads_waiting_for_connection_type_initialization_; + int threads_waiting_for_connection_type_initialization_ = 0; // Used to verify single-threaded access in non-tracking mode. base::ThreadChecker thread_checker_;
diff --git a/net/base/datagram_buffer.cc b/net/base/datagram_buffer.cc index 7c4c2cfd..7f3798e 100644 --- a/net/base/datagram_buffer.cc +++ b/net/base/datagram_buffer.cc
@@ -38,7 +38,7 @@ } DatagramBuffer::DatagramBuffer(size_t max_buffer_size) - : data_(new char[max_buffer_size]), length_(0) {} + : data_(new char[max_buffer_size]) {} DatagramBuffer::~DatagramBuffer() {}
diff --git a/net/base/datagram_buffer.h b/net/base/datagram_buffer.h index a7622b8..bb45dd1 100644 --- a/net/base/datagram_buffer.h +++ b/net/base/datagram_buffer.h
@@ -94,7 +94,7 @@ void Set(const char* buffer, size_t buf_len); std::unique_ptr<char[]> data_; - size_t length_; + size_t length_ = 0; }; } // namespace net
diff --git a/net/base/directory_lister_unittest.cc b/net/base/directory_lister_unittest.cc index 3b6ac1c..d97dd7c 100644 --- a/net/base/directory_lister_unittest.cc +++ b/net/base/directory_lister_unittest.cc
@@ -35,8 +35,7 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { public: - explicit ListerDelegate(DirectoryLister::ListingType type) - : lister_(nullptr), type_(type) {} + explicit ListerDelegate(DirectoryLister::ListingType type) : type_(type) {} // When set to true, this signals that the directory list operation should be // cancelled (And the run loop quit) in the first call to OnListFile. @@ -113,7 +112,7 @@ bool cancel_lister_on_list_done_ = false; // This is owned by the individual tests, rather than the ListerDelegate. - raw_ptr<DirectoryLister> lister_; + raw_ptr<DirectoryLister> lister_ = nullptr; base::RunLoop run_loop;
diff --git a/net/base/io_buffer.cc b/net/base/io_buffer.cc index 78d4cf4..26e0e02 100644 --- a/net/base/io_buffer.cc +++ b/net/base/io_buffer.cc
@@ -68,12 +68,12 @@ } DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, int size) - : IOBuffer(base->data()), base_(std::move(base)), size_(size), used_(0) { + : IOBuffer(base->data()), base_(std::move(base)), size_(size) { AssertValidBufferSize(size); } DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size) - : IOBuffer(base->data()), base_(std::move(base)), size_(size), used_(0) { + : IOBuffer(base->data()), base_(std::move(base)), size_(size) { AssertValidBufferSize(size); }
diff --git a/net/base/io_buffer.h b/net/base/io_buffer.h index 2de7d9e..b8f9a8ab 100644 --- a/net/base/io_buffer.h +++ b/net/base/io_buffer.h
@@ -176,7 +176,7 @@ scoped_refptr<IOBuffer> base_; int size_; - int used_; + int used_ = 0; }; // This version provides a resizable buffer and a changeable offset.
diff --git a/net/base/mock_file_stream.cc b/net/base/mock_file_stream.cc index 4027a29c..97b1e519 100644 --- a/net/base/mock_file_stream.cc +++ b/net/base/mock_file_stream.cc
@@ -17,18 +17,12 @@ MockFileStream::MockFileStream( const scoped_refptr<base::TaskRunner>& task_runner) - : FileStream(task_runner), - forced_error_(OK), - async_error_(false), - throttled_(false) {} + : FileStream(task_runner) {} MockFileStream::MockFileStream( base::File file, const scoped_refptr<base::TaskRunner>& task_runner) - : FileStream(std::move(file), task_runner), - forced_error_(OK), - async_error_(false), - throttled_(false) {} + : FileStream(std::move(file), task_runner) {} MockFileStream::~MockFileStream() = default;
diff --git a/net/base/mock_file_stream.h b/net/base/mock_file_stream.h index fba7843..2811810 100644 --- a/net/base/mock_file_stream.h +++ b/net/base/mock_file_stream.h
@@ -92,9 +92,9 @@ int ErrorCallback(CompletionOnceCallback callback); int64_t ErrorCallback64(Int64CompletionOnceCallback callback); - int forced_error_; - bool async_error_; - bool throttled_; + int forced_error_ = OK; + bool async_error_ = false; + bool throttled_ = false; base::OnceClosure throttled_task_; base::FilePath path_;
diff --git a/net/base/net_error_details.h b/net/base/net_error_details.h index 728770c..0406760 100644 --- a/net/base/net_error_details.h +++ b/net/base/net_error_details.h
@@ -15,16 +15,11 @@ // net stack. struct NET_EXPORT NetErrorDetails { NetErrorDetails() - : quic_broken(false), - quic_connection_error(quic::QUIC_NO_ERROR), - connection_info(HttpResponseInfo::CONNECTION_INFO_UNKNOWN), - quic_port_migration_detected(false) {} + : quic_broken(false), quic_connection_error(quic::QUIC_NO_ERROR) {} NetErrorDetails(bool quic_broken, quic::QuicErrorCode quic_connection_error) : quic_broken(quic_broken), - quic_connection_error(quic_connection_error), - connection_info(HttpResponseInfo::CONNECTION_INFO_UNKNOWN), - quic_port_migration_detected(false) {} + quic_connection_error(quic_connection_error) {} // True if all QUIC alternative services are marked broken for the origin. bool quic_broken; @@ -33,10 +28,11 @@ // Early prediction of the connection type that this request attempts to use. // Will be discarded by upper layers if the connection type can be fetched // from response header from the server. - HttpResponseInfo::ConnectionInfo connection_info; + HttpResponseInfo::ConnectionInfo connection_info = + HttpResponseInfo::CONNECTION_INFO_UNKNOWN; // True if receives a GoAway frame from the server due to connection // migration with port change. - bool quic_port_migration_detected; + bool quic_port_migration_detected = false; }; } // namespace net
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 1dd4055..387c8343 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc
@@ -219,8 +219,7 @@ base::ObserverListPolicy::EXISTING_ONLY)), default_network_active_observer_list_( new base::ObserverListThreadSafe<DefaultNetworkActiveObserver>( - base::ObserverListPolicy::EXISTING_ONLY)), - connection_cost_observers_added_(false) {} + base::ObserverListPolicy::EXISTING_ONLY)) {} ObserverList(const ObserverList&) = delete; ObserverList& operator=(const ObserverList&) = delete; @@ -254,7 +253,7 @@ // Indicates if connection cost observer was added before // network_change_notifier was initialized, if so ConnectionCostObserverAdded // is invoked from constructor. - std::atomic_bool connection_cost_observers_added_; + std::atomic_bool connection_cost_observers_added_ = false; }; class NetworkChangeNotifier::SystemDnsConfigObserver
diff --git a/net/base/network_change_notifier_mac.h b/net/base/network_change_notifier_mac.h index e76bf881..117f771 100644 --- a/net/base/network_change_notifier_mac.h +++ b/net/base/network_change_notifier_mac.h
@@ -68,8 +68,8 @@ // These must be constructed before config_watcher_ to ensure // the lock is in a valid state when Forwarder::Init is called. - ConnectionType connection_type_; - bool connection_type_initialized_; + ConnectionType connection_type_ = CONNECTION_UNKNOWN; + bool connection_type_initialized_ = false; mutable base::Lock connection_type_lock_; mutable base::ConditionVariable initial_connection_type_cv_; base::ScopedCFTypeRef<SCNetworkReachabilityRef> reachability_;
diff --git a/net/base/network_change_notifier_mac.mm b/net/base/network_change_notifier_mac.mm index 0acd8008..20baff33f 100644 --- a/net/base/network_change_notifier_mac.mm +++ b/net/base/network_change_notifier_mac.mm
@@ -35,8 +35,6 @@ NetworkChangeNotifierMac::NetworkChangeNotifierMac() : NetworkChangeNotifier(NetworkChangeCalculatorParamsMac()), - connection_type_(CONNECTION_UNKNOWN), - connection_type_initialized_(false), initial_connection_type_cv_(&connection_type_lock_), forwarder_(this) { // Must be initialized after the rest of this object, as it may call back into
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc index b6eab1f..d84e6e1d 100644 --- a/net/base/network_change_notifier_win.cc +++ b/net/base/network_change_notifier_win.cc
@@ -119,7 +119,6 @@ blocking_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})), last_computed_connection_type_(RecomputeCurrentConnectionType()), - last_computed_connection_cost_(ConnectionCost::CONNECTION_COST_UNKNOWN), last_announced_offline_(last_computed_connection_type_ == CONNECTION_NONE), sequence_runner_for_registration_(
diff --git a/net/base/network_change_notifier_win.h b/net/base/network_change_notifier_win.h index e3fced1d..f1989cb7 100644 --- a/net/base/network_change_notifier_win.h +++ b/net/base/network_change_notifier_win.h
@@ -141,7 +141,8 @@ mutable base::Lock last_computed_connection_type_lock_; ConnectionType last_computed_connection_type_; - std::atomic<ConnectionCost> last_computed_connection_cost_; + std::atomic<ConnectionCost> last_computed_connection_cost_ = + ConnectionCost::CONNECTION_COST_UNKNOWN; // Result of IsOffline() when NotifyObserversOfConnectionTypeChange() // was last called.
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc index 06fbb27d9..fbaf0eda 100644 --- a/net/base/network_config_watcher_mac.cc +++ b/net/base/network_config_watcher_mac.cc
@@ -142,7 +142,7 @@ base::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_; NetworkConfigWatcherMac::Delegate* const delegate_; #if !BUILDFLAG(IS_IOS) - int num_retry_; + int num_retry_ = 0; #endif // !BUILDFLAG(IS_IOS) base::WeakPtrFactory<NetworkConfigWatcherMacThread> weak_factory_; }; @@ -151,11 +151,7 @@ NetworkConfigWatcherMac::Delegate* delegate) : base::Thread("NetworkConfigWatcher"), delegate_(delegate), -#if !BUILDFLAG(IS_IOS) - num_retry_(0), -#endif // !BUILDFLAG(IS_IOS) - weak_factory_(this) { -} + weak_factory_(this) {} NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() { // This is expected to be invoked during shutdown.
diff --git a/net/base/upload_file_element_reader.cc b/net/base/upload_file_element_reader.cc index e26398c..b7a9400 100644 --- a/net/base/upload_file_element_reader.cc +++ b/net/base/upload_file_element_reader.cc
@@ -36,11 +36,7 @@ path_(path), range_offset_(range_offset), range_length_(range_length), - expected_modification_time_(expected_modification_time), - content_length_(0), - bytes_remaining_(0), - next_state_(State::IDLE), - init_called_while_operation_pending_(false) { + expected_modification_time_(expected_modification_time) { DCHECK(file.IsValid()); DCHECK(task_runner_.get()); file_stream_ = std::make_unique<FileStream>(std::move(file), task_runner); @@ -56,11 +52,7 @@ path_(path), range_offset_(range_offset), range_length_(range_length), - expected_modification_time_(expected_modification_time), - content_length_(0), - bytes_remaining_(0), - next_state_(State::IDLE), - init_called_while_operation_pending_(false) { + expected_modification_time_(expected_modification_time) { DCHECK(task_runner_.get()); }
diff --git a/net/base/upload_file_element_reader.h b/net/base/upload_file_element_reader.h index cfb2b94..89e108a 100644 --- a/net/base/upload_file_element_reader.h +++ b/net/base/upload_file_element_reader.h
@@ -119,16 +119,16 @@ const uint64_t range_length_; const base::Time expected_modification_time_; std::unique_ptr<FileStream> file_stream_; - uint64_t content_length_; - uint64_t bytes_remaining_; + uint64_t content_length_ = 0; + uint64_t bytes_remaining_ = 0; // File information. Only valid during GET_FILE_INFO_COMPLETE state. base::File::Info file_info_; - State next_state_; + State next_state_ = State::IDLE; CompletionOnceCallback pending_callback_; // True if Init() was called while an async operation was in progress. - bool init_called_while_operation_pending_; + bool init_called_while_operation_pending_ = false; base::WeakPtrFactory<UploadFileElementReader> weak_ptr_factory_{this}; };
diff --git a/net/cert/cert_database_mac.cc b/net/cert/cert_database_mac.cc index 7ca7e08..1cd7809c 100644 --- a/net/cert/cert_database_mac.cc +++ b/net/cert/cert_database_mac.cc
@@ -31,10 +31,7 @@ // TYPE_UI thread. Events will be dispatched from this message loop. Notifier(CertDatabase* cert_db, scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : cert_db_(cert_db), - task_runner_(std::move(task_runner)), - registered_(false), - called_shutdown_(false) { + : cert_db_(cert_db), task_runner_(std::move(task_runner)) { // Ensure an associated CFRunLoop. DCHECK(base::CurrentUIThread::IsSet()); DCHECK(task_runner_->BelongsToCurrentThread()); @@ -79,8 +76,8 @@ CertDatabase* const cert_db_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - bool registered_; - bool called_shutdown_; + bool registered_ = false; + bool called_shutdown_ = false; }; // static
diff --git a/net/cert/cert_verify_proc_builtin_unittest.cc b/net/cert/cert_verify_proc_builtin_unittest.cc index e09dbe1..c864606 100644 --- a/net/cert/cert_verify_proc_builtin_unittest.cc +++ b/net/cert/cert_verify_proc_builtin_unittest.cc
@@ -189,7 +189,7 @@ CertVerifier::Config config_; std::unique_ptr<net::URLRequestContext> context_; - raw_ptr<MockSystemTrustStore> mock_system_trust_store_; + raw_ptr<MockSystemTrustStore> mock_system_trust_store_ = nullptr; scoped_refptr<CertVerifyProc> verify_proc_; scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher_; };
diff --git a/net/cert/ct_log_verifier.cc b/net/cert/ct_log_verifier.cc index 56b41a54..7d6fcca 100644 --- a/net/cert/ct_log_verifier.cc +++ b/net/cert/ct_log_verifier.cc
@@ -67,7 +67,7 @@ } CTLogVerifier::CTLogVerifier(std::string description) - : description_(std::move(description)), public_key_(nullptr) {} + : description_(std::move(description)) {} bool CTLogVerifier::Verify(const ct::SignedEntryData& entry, const ct::SignedCertificateTimestamp& sct) const {
diff --git a/net/cert/ct_log_verifier.h b/net/cert/ct_log_verifier.h index 69ea252..09a69a90 100644 --- a/net/cert/ct_log_verifier.h +++ b/net/cert/ct_log_verifier.h
@@ -96,7 +96,7 @@ ct::DigitallySigned::SignatureAlgorithm signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ANONYMOUS; - raw_ptr<EVP_PKEY> public_key_; + raw_ptr<EVP_PKEY> public_key_ = nullptr; }; } // namespace net
diff --git a/net/cert/nss_cert_database_chromeos_unittest.cc b/net/cert/nss_cert_database_chromeos_unittest.cc index e7891f8b..2ecd13b 100644 --- a/net/cert/nss_cert_database_chromeos_unittest.cc +++ b/net/cert/nss_cert_database_chromeos_unittest.cc
@@ -53,11 +53,7 @@ class NSSCertDatabaseChromeOSTest : public TestWithTaskEnvironment, public CertDatabase::Observer { public: - NSSCertDatabaseChromeOSTest() - : observer_added_(false), - db_changed_count_(0), - user_1_("user1"), - user_2_("user2") {} + NSSCertDatabaseChromeOSTest() : user_1_("user1"), user_2_("user2") {} void SetUp() override { // Initialize nss_util slots. @@ -95,8 +91,8 @@ void OnCertDBChanged() override { db_changed_count_++; } protected: - bool observer_added_; - int db_changed_count_; + bool observer_added_ = false; + int db_changed_count_ = 0; crypto::ScopedTestNSSChromeOSUser user_1_; crypto::ScopedTestNSSChromeOSUser user_2_;
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index c9b6a7a..4a85634 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -364,18 +364,11 @@ base::TimeDelta last_access_threshold, NetLog* net_log, bool first_party_sets_enabled) - : num_keys_(0u), - num_partitioned_cookies_(0u), - change_dispatcher_(this, first_party_sets_enabled), - initialized_(false), - started_fetching_all_cookies_(false), - finished_fetching_all_cookies_(false), - seen_global_task_(false), + : change_dispatcher_(this, first_party_sets_enabled), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::COOKIE_STORE)), store_(std::move(store)), last_access_threshold_(last_access_threshold), last_statistic_record_time_(base::Time::Now()), - persist_session_cookies_(false), first_party_sets_enabled_(first_party_sets_enabled) { cookieable_schemes_.insert( cookieable_schemes_.begin(), kDefaultCookieableSchemes,
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h index 659a346d..d2cfebf 100644 --- a/net/cookies/cookie_monster.h +++ b/net/cookies/cookie_monster.h
@@ -730,7 +730,7 @@ // The number of distinct keys (eTLD+1's) currently present in the |cookies_| // multimap. This is histogrammed periodically. - size_t num_keys_; + size_t num_keys_ = 0u; CookieMap cookies_; @@ -738,17 +738,17 @@ // Number of distinct partitioned cookies globally. This is used to enforce a // global maximum on the number of partitioned cookies. - size_t num_partitioned_cookies_; + size_t num_partitioned_cookies_ = 0u; CookieMonsterChangeDispatcher change_dispatcher_; // Indicates whether the cookie store has been initialized. - bool initialized_; + bool initialized_ = false; // Indicates whether the cookie store has started fetching all cookies. - bool started_fetching_all_cookies_; + bool started_fetching_all_cookies_ = false; // Indicates whether the cookie store has finished fetching all cookies. - bool finished_fetching_all_cookies_; + bool finished_fetching_all_cookies_ = false; // List of domain keys that have been loaded from the DB. std::set<std::string> keys_loaded_; @@ -768,7 +768,7 @@ // view of the cookie store. This is more to ensure fancy cookie export/import // code has a consistent view of the CookieStore, rather than out of concern // for typical use. - bool seen_global_task_; + bool seen_global_task_ = false; NetLogWithSource net_log_; @@ -793,7 +793,7 @@ base::Time last_statistic_record_time_; - bool persist_session_cookies_; + bool persist_session_cookies_ = false; bool first_party_sets_enabled_;
diff --git a/net/cookies/cookie_store_test_callbacks.cc b/net/cookies/cookie_store_test_callbacks.cc index af88e4da..1a8465a 100644 --- a/net/cookies/cookie_store_test_callbacks.cc +++ b/net/cookies/cookie_store_test_callbacks.cc
@@ -14,12 +14,11 @@ namespace net { CookieCallback::CookieCallback(base::Thread* run_in_thread) - : run_in_thread_(run_in_thread), was_run_(false) {} + : run_in_thread_(run_in_thread) {} CookieCallback::CookieCallback() : run_in_thread_(nullptr), - run_in_task_runner_(base::ThreadTaskRunnerHandle::Get()), - was_run_(false) {} + run_in_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} CookieCallback::~CookieCallback() = default;
diff --git a/net/cookies/cookie_store_test_callbacks.h b/net/cookies/cookie_store_test_callbacks.h index e1dcf6b1..ee319423 100644 --- a/net/cookies/cookie_store_test_callbacks.h +++ b/net/cookies/cookie_store_test_callbacks.h
@@ -54,7 +54,7 @@ raw_ptr<base::Thread> run_in_thread_; scoped_refptr<base::SingleThreadTaskRunner> run_in_task_runner_; base::RunLoop loop_to_quit_; - bool was_run_; + bool was_run_ = false; }; // Callback implementations for the asynchronous CookieStore methods.
diff --git a/net/der/parse_values.h b/net/der/parse_values.h index a80a4d7d..51307c8 100644 --- a/net/der/parse_values.h +++ b/net/der/parse_values.h
@@ -53,7 +53,7 @@ // * There may be at most 7 unused bits. class NET_EXPORT BitString { public: - BitString() : unused_bits_(0) {} + BitString() = default; // |unused_bits| represents the number of bits in the last octet of |bytes|, // starting from the least significant bit, that are unused. It MUST be < 8. @@ -73,7 +73,7 @@ private: Input bytes_; - uint8_t unused_bits_; + uint8_t unused_bits_ = 0; // Default assignment and copy constructor are OK. };
diff --git a/net/der/parser.cc b/net/der/parser.cc index c59eaa95f..94c36000 100644 --- a/net/der/parser.cc +++ b/net/der/parser.cc
@@ -11,11 +11,11 @@ namespace der { -Parser::Parser() : advance_len_(0) { +Parser::Parser() { CBS_init(&cbs_, nullptr, 0); } -Parser::Parser(const Input& input) : advance_len_(0) { +Parser::Parser(const Input& input) { CBS_init(&cbs_, input.UnsafeData(), input.Length()); }
diff --git a/net/der/parser.h b/net/der/parser.h index 09ea1eb..c5deaa6eee 100644 --- a/net/der/parser.h +++ b/net/der/parser.h
@@ -205,7 +205,7 @@ private: CBS cbs_; - size_t advance_len_; + size_t advance_len_ = 0; }; } // namespace der
diff --git a/net/disk_cache/blockfile/eviction.cc b/net/disk_cache/blockfile/eviction.cc index e3236dc..3e16efe 100644 --- a/net/disk_cache/blockfile/eviction.cc +++ b/net/disk_cache/blockfile/eviction.cc
@@ -79,7 +79,7 @@ // The real initialization happens during Init(), init_ is the only member that // has to be initialized here. -Eviction::Eviction() : backend_(nullptr) {} +Eviction::Eviction() = default; Eviction::~Eviction() = default;
diff --git a/net/disk_cache/blockfile/eviction.h b/net/disk_cache/blockfile/eviction.h index 92e60c6..8946b6f 100644 --- a/net/disk_cache/blockfile/eviction.h +++ b/net/disk_cache/blockfile/eviction.h
@@ -73,7 +73,7 @@ int SelectListByLength(Rankings::ScopedRankingsBlock* next); void ReportListStats(); - raw_ptr<BackendImpl> backend_; + raw_ptr<BackendImpl> backend_ = nullptr; raw_ptr<Rankings> rankings_; raw_ptr<IndexHeader> header_; int max_size_;
diff --git a/net/disk_cache/blockfile/in_flight_backend_io.cc b/net/disk_cache/blockfile/in_flight_backend_io.cc index c9371bb..0f18911 100644 --- a/net/disk_cache/blockfile/in_flight_backend_io.cc +++ b/net/disk_cache/blockfile/in_flight_backend_io.cc
@@ -57,18 +57,7 @@ } BackendIO::BackendIO(InFlightIO* controller, BackendImpl* backend) - : BackgroundIO(controller), - backend_(backend), - operation_(OP_NONE), - out_entry_(nullptr), - out_entry_opened_(false), - iterator_(nullptr), - entry_(nullptr), - index_(0), - offset_(0), - buf_len_(0), - truncate_(false), - offset64_(0) { + : BackgroundIO(controller), backend_(backend) { start_time_ = base::TimeTicks::Now(); }
diff --git a/net/disk_cache/blockfile/in_flight_backend_io.h b/net/disk_cache/blockfile/in_flight_backend_io.h index c5abe9e..7c67dc98 100644 --- a/net/disk_cache/blockfile/in_flight_backend_io.h +++ b/net/disk_cache/blockfile/in_flight_backend_io.h
@@ -156,12 +156,13 @@ raw_ptr<BackendImpl> backend_; net::CompletionOnceCallback callback_; - Operation operation_; + Operation operation_ = OP_NONE; // Used for ops that open or create entries. EntryResultCallback entry_result_callback_; - raw_ptr<Entry> out_entry_; // if set, already has the user's ref added. - bool out_entry_opened_; + // if set, already has the user's ref added. + raw_ptr<Entry> out_entry_ = nullptr; + bool out_entry_opened_ = false; // For GetAvailableRange RangeResultCallback range_result_callback_; @@ -171,15 +172,15 @@ std::string key_; base::Time initial_time_; base::Time end_time_; - raw_ptr<Rankings::Iterator> iterator_; + raw_ptr<Rankings::Iterator> iterator_ = nullptr; std::unique_ptr<Rankings::Iterator> scoped_iterator_; - raw_ptr<EntryImpl> entry_; - int index_; - int offset_; + raw_ptr<EntryImpl> entry_ = nullptr; + int index_ = 0; + int offset_ = 0; scoped_refptr<net::IOBuffer> buf_; - int buf_len_; - bool truncate_; - int64_t offset64_; + int buf_len_ = 0; + bool truncate_ = false; + int64_t offset64_ = 0; base::TimeTicks start_time_; base::OnceClosure task_; };
diff --git a/net/disk_cache/blockfile/sparse_control.cc b/net/disk_cache/blockfile/sparse_control.cc index f797e63..96cb03c 100644 --- a/net/disk_cache/blockfile/sparse_control.cc +++ b/net/disk_cache/blockfile/sparse_control.cc
@@ -202,7 +202,6 @@ SparseControl::SparseControl(EntryImpl* entry) : entry_(entry), - child_(nullptr), child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32) { memset(&sparse_header_, 0, sizeof(sparse_header_)); memset(&child_data_, 0, sizeof(child_data_));
diff --git a/net/disk_cache/blockfile/storage_block-inl.h b/net/disk_cache/blockfile/storage_block-inl.h index bb1ba39..b1c0a89 100644 --- a/net/disk_cache/blockfile/storage_block-inl.h +++ b/net/disk_cache/blockfile/storage_block-inl.h
@@ -18,7 +18,7 @@ template <typename T> StorageBlock<T>::StorageBlock(MappedFile* file, Addr address) - : data_(nullptr), file_(file), address_(address) { + : file_(file), address_(address) { if (address.num_blocks() > 1) extended_ = true; DCHECK(!address.is_initialized() || sizeof(*data_) == address.BlockSize())
diff --git a/net/disk_cache/blockfile/storage_block.h b/net/disk_cache/blockfile/storage_block.h index e1e3acf..f0bb68c 100644 --- a/net/disk_cache/blockfile/storage_block.h +++ b/net/disk_cache/blockfile/storage_block.h
@@ -94,12 +94,12 @@ void DeleteData(); uint32_t CalculateHash() const; - raw_ptr<T> data_; + raw_ptr<T> data_ = nullptr; raw_ptr<MappedFile> file_; Addr address_; bool modified_ = false; - bool own_data_ = - false; // Is data_ owned by this object or shared with someone else. + // Is data_ owned by this object or shared with someone else. + bool own_data_ = false; bool extended_ = false; // Used to store an entry of more than one block. };
diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc index 9d18ab21..792e751 100644 --- a/net/disk_cache/disk_cache_test_base.cc +++ b/net/disk_cache/disk_cache_test_base.cc
@@ -80,8 +80,7 @@ return rv; } -DiskCacheTestWithCache::DiskCacheTestWithCache() - : cache_impl_(nullptr), simple_cache_impl_(nullptr), mem_cache_(nullptr) {} +DiskCacheTestWithCache::DiskCacheTestWithCache() = default; DiskCacheTestWithCache::~DiskCacheTestWithCache() = default;
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h index 1b8ec71c..3659a1a 100644 --- a/net/disk_cache/disk_cache_test_base.h +++ b/net/disk_cache/disk_cache_test_base.h
@@ -197,10 +197,10 @@ // cache_ will always have a valid object, regardless of how the cache was // initialized. The implementation pointers can be NULL. std::unique_ptr<disk_cache::Backend> cache_; - raw_ptr<disk_cache::BackendImpl> cache_impl_; + raw_ptr<disk_cache::BackendImpl> cache_impl_ = nullptr; std::unique_ptr<disk_cache::SimpleFileTracker> simple_file_tracker_; - raw_ptr<disk_cache::SimpleBackendImpl> simple_cache_impl_; - raw_ptr<disk_cache::MemBackendImpl> mem_cache_; + raw_ptr<disk_cache::SimpleBackendImpl> simple_cache_impl_ = nullptr; + raw_ptr<disk_cache::MemBackendImpl> mem_cache_ = nullptr; uint32_t mask_ = 0; int64_t size_ = 0;
diff --git a/net/disk_cache/memory/mem_backend_impl.cc b/net/disk_cache/memory/mem_backend_impl.cc index f59f772..993792e4 100644 --- a/net/disk_cache/memory/mem_backend_impl.cc +++ b/net/disk_cache/memory/mem_backend_impl.cc
@@ -44,7 +44,6 @@ MemBackendImpl::MemBackendImpl(net::NetLog* net_log) : Backend(net::MEMORY_CACHE), - custom_clock_for_testing_(nullptr), net_log_(net_log), memory_pressure_listener_( FROM_HERE,
diff --git a/net/disk_cache/memory/mem_backend_impl.h b/net/disk_cache/memory/mem_backend_impl.h index b0cebfb3..b3994ed 100644 --- a/net/disk_cache/memory/mem_backend_impl.h +++ b/net/disk_cache/memory/mem_backend_impl.h
@@ -140,7 +140,7 @@ void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); - raw_ptr<base::Clock> custom_clock_for_testing_; // usually nullptr. + raw_ptr<base::Clock> custom_clock_for_testing_ = nullptr; // usually nullptr. EntryMap entries_;
diff --git a/net/disk_cache/memory/mem_entry_impl.cc b/net/disk_cache/memory/mem_entry_impl.cc index 6193646..a045f72 100644 --- a/net/disk_cache/memory/mem_entry_impl.cc +++ b/net/disk_cache/memory/mem_entry_impl.cc
@@ -289,14 +289,11 @@ MemEntryImpl* parent, net::NetLog* net_log) : key_(key), - ref_count_(0), child_id_(child_id), - child_first_pos_(0), parent_(parent), last_modified_(MemBackendImpl::Now(backend)), last_used_(last_modified_), - backend_(backend), - doomed_(false) { + backend_(backend) { backend_->OnEntryInserted(this); net_log_ = net::NetLogWithSource::Make( net_log, net::NetLogSourceType::MEMORY_CACHE_ENTRY);
diff --git a/net/disk_cache/memory/mem_entry_impl.h b/net/disk_cache/memory/mem_entry_impl.h index 0f68062b..4dcf339 100644 --- a/net/disk_cache/memory/mem_entry_impl.h +++ b/net/disk_cache/memory/mem_entry_impl.h
@@ -182,12 +182,12 @@ std::string key_; std::vector<char> data_[kNumStreams]; // User data. - uint32_t ref_count_; + uint32_t ref_count_ = 0; int64_t child_id_; // The ID of a child entry. - int child_first_pos_; // The position of the first byte in a child - // entry. 0 here is beginning of child, not of - // the entire file. + int child_first_pos_ = 0; // The position of the first byte in a child + // entry. 0 here is beginning of child, not of + // the entire file. // Pointer to the parent entry, or nullptr if this entry is a parent entry. raw_ptr<MemEntryImpl> parent_; std::unique_ptr<EntryMap> children_; @@ -195,7 +195,7 @@ base::Time last_modified_; base::Time last_used_; base::WeakPtr<MemBackendImpl> backend_; // Back pointer to the cache. - bool doomed_; // True if this entry was removed from the cache. + bool doomed_ = false; // True if this entry was removed from the cache. net::NetLogWithSource net_log_; };
diff --git a/net/dns/address_sorter_win.cc b/net/dns/address_sorter_win.cc index 5220047..1f3fdc7f 100644 --- a/net/dns/address_sorter_win.cc +++ b/net/dns/address_sorter_win.cc
@@ -71,8 +71,7 @@ input_buffer_( reinterpret_cast<SOCKET_ADDRESS_LIST*>(malloc(buffer_size_))), output_buffer_( - reinterpret_cast<SOCKET_ADDRESS_LIST*>(malloc(buffer_size_))), - success_(false) { + reinterpret_cast<SOCKET_ADDRESS_LIST*>(malloc(buffer_size_))) { input_buffer_->iAddressCount = base::checked_cast<INT>(endpoints.size()); SOCKADDR_STORAGE* storage = reinterpret_cast<SOCKADDR_STORAGE*>( input_buffer_->Address + input_buffer_->iAddressCount); @@ -140,7 +139,7 @@ const DWORD buffer_size_; std::unique_ptr<SOCKET_ADDRESS_LIST, base::FreeDeleter> input_buffer_; std::unique_ptr<SOCKET_ADDRESS_LIST, base::FreeDeleter> output_buffer_; - bool success_; + bool success_ = false; }; };
diff --git a/net/dns/dns_config.cc b/net/dns/dns_config.cc index 2d0cea2..2a24a13 100644 --- a/net/dns/dns_config.cc +++ b/net/dns/dns_config.cc
@@ -21,18 +21,7 @@ DnsConfig::DnsConfig(DnsConfig&& other) = default; DnsConfig::DnsConfig(std::vector<IPEndPoint> nameservers) - : nameservers(std::move(nameservers)), - dns_over_tls_active(false), - unhandled_options(false), - append_to_multi_label_name(true), - ndots(1), - fallback_period(kDnsDefaultFallbackPeriod), - attempts(2), - doh_attempts(1), - rotate(false), - use_local_ipv6(false), - secure_dns_mode(SecureDnsMode::kOff), - allow_dns_over_https_upgrade(false) {} + : nameservers(std::move(nameservers)) {} DnsConfig::~DnsConfig() = default;
diff --git a/net/dns/dns_config.h b/net/dns/dns_config.h index 601ddc3..19fbd97 100644 --- a/net/dns/dns_config.h +++ b/net/dns/dns_config.h
@@ -55,7 +55,7 @@ std::vector<IPEndPoint> nameservers; // Status of system DNS-over-TLS (DoT). - bool dns_over_tls_active; + bool dns_over_tls_active = false; std::string dns_over_tls_hostname; // Suffix search list; used on first lookup when number of dots in given name @@ -66,33 +66,33 @@ // True if there are options set in the system configuration that are not yet // supported by DnsClient. - bool unhandled_options; + bool unhandled_options = false; // AppendToMultiLabelName: is suffix search performed for multi-label names? // True, except on Windows where it can be configured. - bool append_to_multi_label_name; + bool append_to_multi_label_name = true; // Resolver options; see man resolv.conf. // Minimum number of dots before global resolution precedes |search|. - int ndots; + int ndots = 1; // Time between retransmissions, see res_state.retrans. // Used by Chrome as the initial transaction attempt fallback period (before // exponential backoff and dynamic period determination based on previous // attempts.) - base::TimeDelta fallback_period; + base::TimeDelta fallback_period = kDnsDefaultFallbackPeriod; // Maximum number of attempts, see res_state.retry. - int attempts; + int attempts = 2; // Maximum number of times a DoH server is attempted per attempted per DNS // transaction. This is separate from the global failure limit. - int doh_attempts; + int doh_attempts = 1; // Round robin entries in |nameservers| for subsequent requests. - bool rotate; + bool rotate = false; // Indicates system configuration uses local IPv6 connectivity, e.g., // DirectAccess. This is exposed for HostResolver to skip IPv6 probes, // as it may cause them to return incorrect results. - bool use_local_ipv6; + bool use_local_ipv6 = false; // DNS over HTTPS server configuration. DnsOverHttpsConfig doh_config; @@ -101,12 +101,12 @@ // overridden for individual requests (such as requests to resolve a DoH // server hostname) using |HostResolver::ResolveHostParameters:: // secure_dns_mode_override|. - SecureDnsMode secure_dns_mode; + SecureDnsMode secure_dns_mode = SecureDnsMode::kOff; // If set to |true|, we will attempt to upgrade the user's DNS configuration // to use DoH server(s) operated by the same provider(s) when the user is // in AUTOMATIC mode and has not pre-specified DoH servers. - bool allow_dns_over_https_upgrade; + bool allow_dns_over_https_upgrade = false; }; } // namespace net
diff --git a/net/dns/dns_config_watcher_mac.cc b/net/dns/dns_config_watcher_mac.cc index f48dc70..9d5398a 100644 --- a/net/dns/dns_config_watcher_mac.cc +++ b/net/dns/dns_config_watcher_mac.cc
@@ -20,10 +20,7 @@ typedef dns_config_t* (*dns_configuration_copy_t)(); typedef void (*dns_configuration_free_t)(dns_config_t*); - DnsInfoApi() - : dns_configuration_notify_key(NULL), - dns_configuration_copy(NULL), - dns_configuration_free(NULL) { + DnsInfoApi() { handle_ = dlopen("/usr/lib/libSystem.dylib", RTLD_LAZY | RTLD_NOLOAD); if (!handle_) @@ -44,9 +41,9 @@ dlclose(handle_); } - dns_configuration_notify_key_t dns_configuration_notify_key; - dns_configuration_copy_t dns_configuration_copy; - dns_configuration_free_t dns_configuration_free; + dns_configuration_notify_key_t dns_configuration_notify_key = nullptr; + dns_configuration_copy_t dns_configuration_copy = nullptr; + dns_configuration_free_t dns_configuration_free = nullptr; private: void* handle_;
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc index 0f07bb3..4827aab 100644 --- a/net/dns/dns_test_util.cc +++ b/net/dns/dns_test_util.cc
@@ -410,9 +410,7 @@ SecureDnsMode secure_dns_mode, ResolveContext* resolve_context, bool fast_timeout) - : result_(MockDnsClientRule::ResultType::kFail), - hostname_(std::move(hostname)), - qtype_(qtype) { + : hostname_(std::move(hostname)), qtype_(qtype) { // Do not allow matching any rules if transaction is secure and no DoH // servers are available. if (!secure || force_doh_server_available || @@ -581,7 +579,7 @@ void SetRequestPriority(RequestPriority priority) override {} - MockDnsClientRule::Result result_; + MockDnsClientRule::Result result_{MockDnsClientRule::ResultType::kFail}; const std::string hostname_; const uint16_t qtype_; ResponseCallback callback_;
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index 3c4ca83..4e8d6ee 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -630,7 +630,6 @@ HostCache::HostCache(size_t max_entries) : max_entries_(max_entries), - delegate_(nullptr), tick_clock_(base::DefaultTickClock::GetInstance()) {} HostCache::~HostCache() {
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index 70d453ef..bcbc1654 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -531,7 +531,7 @@ // RestoreFromListValue(). Used in histograms. size_t restore_size_ = 0; - raw_ptr<PersistenceDelegate> delegate_; + raw_ptr<PersistenceDelegate> delegate_ = nullptr; // Shared tick clock, overridden for testing. raw_ptr<const base::TickClock> tick_clock_;
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index 95aec2d..9f6b33a 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -3120,17 +3120,12 @@ SystemDnsConfigChangeNotifier* system_dns_config_notifier, NetworkChangeNotifier::NetworkHandle target_network, NetLog* net_log) - : max_queued_jobs_(0), - proc_params_(nullptr, options.max_system_retry_attempts), + : proc_params_(nullptr, options.max_system_retry_attempts), net_log_(net_log), system_dns_config_notifier_(system_dns_config_notifier), target_network_(target_network), check_ipv6_on_wifi_(options.check_ipv6_on_wifi), - last_ipv6_probe_result_(true), - additional_resolver_flags_(0), - allow_fallback_to_proctask_(true), - tick_clock_(base::DefaultTickClock::GetInstance()), - invalidation_in_progress_(false) { + tick_clock_(base::DefaultTickClock::GetInstance()) { PrioritizedDispatcher::Limits job_limits = GetDispatcherLimits(options); dispatcher_ = std::make_unique<PrioritizedDispatcher>(job_limits); max_queued_jobs_ = job_limits.total_jobs * 100u;
diff --git a/net/dns/host_resolver_manager.h b/net/dns/host_resolver_manager.h index 9a20bf8..602a18b2 100644 --- a/net/dns/host_resolver_manager.h +++ b/net/dns/host_resolver_manager.h
@@ -498,7 +498,7 @@ std::unique_ptr<PrioritizedDispatcher> dispatcher_; // Limit on the maximum number of jobs queued in |dispatcher_|. - size_t max_queued_jobs_; + size_t max_queued_jobs_ = 0; // Parameters for ProcTask. ProcTaskParams proc_params_; @@ -517,13 +517,13 @@ bool check_ipv6_on_wifi_; base::TimeTicks last_ipv6_probe_time_; - bool last_ipv6_probe_result_; + bool last_ipv6_probe_result_ = true; // Any resolver flags that should be added to a request by default. - HostResolverFlags additional_resolver_flags_; + HostResolverFlags additional_resolver_flags_ = 0; // Allow fallback to ProcTask if DnsTask fails. - bool allow_fallback_to_proctask_; + bool allow_fallback_to_proctask_ = true; // Task runner used for DNS lookups using the system resolver. Normally a // ThreadPool task runner, but can be overridden for tests. @@ -540,7 +540,7 @@ true /* check_empty */, false /* allow_reentrancy */> registered_contexts_; - bool invalidation_in_progress_; + bool invalidation_in_progress_ = false; // Helper for metrics associated with `features::kDnsHttpssvc`. HttpssvcExperimentDomainCache httpssvc_domain_cache_;
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index de7c47e..9b62694 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -4183,8 +4183,7 @@ base::test::TaskEnvironment::TimeSource::MOCK_TIME) : HostResolverManagerTest(time_source), notifier_task_runner_( - base::MakeRefCounted<base::TestMockTimeTaskRunner>()), - dns_client_(nullptr) { + base::MakeRefCounted<base::TestMockTimeTaskRunner>()) { auto config_service = std::make_unique<TestDnsConfigService>(); config_service_ = config_service.get(); notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>( @@ -4467,7 +4466,7 @@ std::unique_ptr<SystemDnsConfigChangeNotifier> notifier_; // Owned by |resolver_|. - raw_ptr<MockDnsClient> dns_client_; + raw_ptr<MockDnsClient> dns_client_ = nullptr; }; TEST_F(HostResolverManagerDnsTest, FlushCacheOnDnsConfigChange) {
diff --git a/net/dns/host_resolver_proc.cc b/net/dns/host_resolver_proc.cc index a98cbf2..d43d82ef 100644 --- a/net/dns/host_resolver_proc.cc +++ b/net/dns/host_resolver_proc.cc
@@ -251,9 +251,6 @@ SystemHostResolverProc::~SystemHostResolverProc() = default; -const base::TimeDelta ProcTaskParams::kDnsDefaultUnresponsiveDelay = - base::Seconds(6); - ProcTaskParams::ProcTaskParams(HostResolverProc* resolver_proc, size_t in_max_retry_attempts) : resolver_proc(resolver_proc),
diff --git a/net/dns/host_resolver_proc.h b/net/dns/host_resolver_proc.h index 2d7fd449..9d33547 100644 --- a/net/dns/host_resolver_proc.h +++ b/net/dns/host_resolver_proc.h
@@ -154,7 +154,8 @@ struct NET_EXPORT_PRIVATE ProcTaskParams { // Default delay between calls to the system resolver for the same hostname. // (Can be overridden by field trial.) - static const base::TimeDelta kDnsDefaultUnresponsiveDelay; + static constexpr base::TimeDelta kDnsDefaultUnresponsiveDelay = + base::Seconds(6); // Sets up defaults. ProcTaskParams(HostResolverProc* resolver_proc, size_t max_retry_attempts); @@ -174,7 +175,7 @@ // This is the limit after which we make another attempt to resolve the host // if the worker thread has not responded yet. - base::TimeDelta unresponsive_delay; + base::TimeDelta unresponsive_delay = kDnsDefaultUnresponsiveDelay; // Factor to grow |unresponsive_delay| when we re-re-try. uint32_t retry_factor = 2;
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index 6d33a9c..03500cf 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -421,10 +421,7 @@ MdnsListenerImpl(const HostPortPair& host, DnsQueryType query_type, base::WeakPtr<MockHostResolverBase> resolver) - : host_(host), - query_type_(query_type), - delegate_(nullptr), - resolver_(resolver) { + : host_(host), query_type_(query_type), resolver_(resolver) { DCHECK_NE(DnsQueryType::UNSPECIFIED, query_type_); DCHECK(resolver_); } @@ -471,7 +468,7 @@ const HostPortPair host_; const DnsQueryType query_type_; - raw_ptr<Delegate> delegate_; + raw_ptr<Delegate> delegate_ = nullptr; // Use a WeakPtr as the resolver may be destroyed while there are still // outstanding listener objects.
diff --git a/net/filter/fuzzed_source_stream.cc b/net/filter/fuzzed_source_stream.cc index 81e5cc5..67e61f4 100644 --- a/net/filter/fuzzed_source_stream.cc +++ b/net/filter/fuzzed_source_stream.cc
@@ -25,10 +25,7 @@ } // namespace FuzzedSourceStream::FuzzedSourceStream(FuzzedDataProvider* data_provider) - : SourceStream(SourceStream::TYPE_NONE), - data_provider_(data_provider), - read_pending_(false), - end_returned_(false) {} + : SourceStream(SourceStream::TYPE_NONE), data_provider_(data_provider) {} FuzzedSourceStream::~FuzzedSourceStream() { DCHECK(!read_pending_);
diff --git a/net/filter/fuzzed_source_stream.h b/net/filter/fuzzed_source_stream.h index 5e575200..c12cf4fa 100644 --- a/net/filter/fuzzed_source_stream.h +++ b/net/filter/fuzzed_source_stream.h
@@ -46,10 +46,10 @@ FuzzedDataProvider* data_provider_; // Whether there is a pending Read(). - bool read_pending_; + bool read_pending_ = false; // Last result returned by Read() is an error or 0. - bool end_returned_; + bool end_returned_ = false; }; } // namespace net
diff --git a/net/http/bidirectional_stream.cc b/net/http/bidirectional_stream.cc index 3d7f3b5..13faebf 100644 --- a/net/http/bidirectional_stream.cc +++ b/net/http/bidirectional_stream.cc
@@ -85,7 +85,6 @@ NetLogSourceType::BIDIRECTIONAL_STREAM)), session_(session), send_request_headers_automatically_(send_request_headers_automatically), - request_headers_sent_(false), delegate_(delegate), timer_(std::move(timer)) { DCHECK(delegate_);
diff --git a/net/http/bidirectional_stream.h b/net/http/bidirectional_stream.h index 1741344..debf81b 100644 --- a/net/http/bidirectional_stream.h +++ b/net/http/bidirectional_stream.h
@@ -234,7 +234,7 @@ bool send_request_headers_automatically_; // Whether request headers have been sent, as indicated in OnStreamReady() // callback. - bool request_headers_sent_; + bool request_headers_sent_ = false; const raw_ptr<Delegate> delegate_;
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc index 60c45dd4..d39ee35 100644 --- a/net/http/bidirectional_stream_unittest.cc +++ b/net/http/bidirectional_stream_unittest.cc
@@ -104,16 +104,7 @@ std::unique_ptr<base::OneShotTimer> timer) : read_buf_(read_buf), read_buf_len_(read_buf_len), - timer_(std::move(timer)), - loop_(nullptr), - received_bytes_(0), - sent_bytes_(0), - error_(OK), - on_data_read_count_(0), - on_data_sent_count_(0), - do_not_start_read_(false), - run_until_completion_(false), - not_expect_callback_(false) {} + timer_(std::move(timer)) {} TestDelegateBase(const TestDelegateBase&) = delete; TestDelegateBase& operator=(const TestDelegateBase&) = delete; @@ -298,17 +289,17 @@ spdy::Http2HeaderBlock response_headers_; spdy::Http2HeaderBlock trailers_; NextProto next_proto_; - int64_t received_bytes_; - int64_t sent_bytes_; + int64_t received_bytes_ = 0; + int64_t sent_bytes_ = 0; LoadTimingInfo load_timing_info_; - int error_; - int on_data_read_count_; - int on_data_sent_count_; - bool do_not_start_read_; - bool run_until_completion_; + int error_ = OK; + int on_data_read_count_ = 0; + int on_data_sent_count_ = 0; + bool do_not_start_read_ = false; + bool run_until_completion_ = false; // This is to ensure that delegate callback is not invoked synchronously when // calling into |stream_|. - bool not_expect_callback_; + bool not_expect_callback_ = false; CompletionOnceCallback callback_; };
diff --git a/net/http/http_auth_handler_factory.h b/net/http/http_auth_handler_factory.h index 683b63f..d9b9138 100644 --- a/net/http/http_auth_handler_factory.h +++ b/net/http/http_auth_handler_factory.h
@@ -45,7 +45,7 @@ CREATE_PREEMPTIVE, // Create a handler preemptively. }; - HttpAuthHandlerFactory() : http_auth_preferences_(nullptr) {} + HttpAuthHandlerFactory() = default; HttpAuthHandlerFactory(const HttpAuthHandlerFactory&) = delete; HttpAuthHandlerFactory& operator=(const HttpAuthHandlerFactory&) = delete; @@ -163,7 +163,7 @@ private: // The preferences for HTTP authentication. - raw_ptr<const HttpAuthPreferences> http_auth_preferences_; + raw_ptr<const HttpAuthPreferences> http_auth_preferences_ = nullptr; }; // The HttpAuthHandlerRegistryFactory dispatches create requests out
diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc index df30c4f0..bab8b1b 100644 --- a/net/http/http_auth_handler_negotiate.cc +++ b/net/http/http_auth_handler_negotiate.cc
@@ -150,7 +150,6 @@ HostResolver* resolver) : auth_system_(std::move(auth_system)), resolver_(resolver), - auth_token_(nullptr), http_auth_preferences_(prefs) {} HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() = default;
diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h index 687f4c97..73f2c22 100644 --- a/net/http/http_auth_handler_negotiate.h +++ b/net/http/http_auth_handler_negotiate.h
@@ -149,7 +149,7 @@ // Things which vary each round. CompletionOnceCallback callback_; - raw_ptr<std::string> auth_token_; + raw_ptr<std::string> auth_token_ = nullptr; State next_state_ = STATE_NONE;
diff --git a/net/http/http_cache_lookup_manager.cc b/net/http/http_cache_lookup_manager.cc index 3f71c65..6ed9cd0 100644 --- a/net/http/http_cache_lookup_manager.cc +++ b/net/http/http_cache_lookup_manager.cc
@@ -30,7 +30,6 @@ NetLog* net_log) : push_helper_(std::move(server_push_helper)), request_(new HttpRequestInfo()), - transaction_(nullptr), net_log_(NetLogWithSource::Make( net_log, NetLogSourceType::SERVER_PUSH_LOOKUP_TRANSACTION)) {}
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index f5a72b8d..764fd4d6 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc
@@ -161,13 +161,7 @@ //----------------------------------------------------------------------------- HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache) - : initial_request_(nullptr), - request_(nullptr), - priority_(priority), - cache_(cache->GetWeakPtr()), - entry_(nullptr), - new_response_(nullptr), - websocket_handshake_stream_base_create_helper_(nullptr) { + : priority_(priority), cache_(cache->GetWeakPtr()) { TRACE_EVENT1("net", "HttpCacheTransaction::Transaction", "priority", RequestPriorityToString(priority)); static_assert(HttpCache::Transaction::kNumValidationHeaders ==
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h index 647f265..88ed8087 100644 --- a/net/http/http_cache_transaction.h +++ b/net/http/http_cache_transaction.h
@@ -611,9 +611,9 @@ State next_state_{STATE_NONE}; // Initial request with which Start() was invoked. - raw_ptr<const HttpRequestInfo> initial_request_; + raw_ptr<const HttpRequestInfo> initial_request_ = nullptr; - raw_ptr<const HttpRequestInfo> request_; + raw_ptr<const HttpRequestInfo> request_ = nullptr; std::string method_; RequestPriority priority_; @@ -624,7 +624,7 @@ // |external_validation_| contains the value of those headers. ValidationHeaders external_validation_; base::WeakPtr<HttpCache> cache_; - raw_ptr<HttpCache::ActiveEntry> entry_; + raw_ptr<HttpCache::ActiveEntry> entry_ = nullptr; HttpCache::ActiveEntry* new_entry_ = nullptr; std::unique_ptr<HttpTransaction> network_trans_; CompletionOnceCallback callback_; // Consumer's callback. @@ -640,7 +640,7 @@ // WriteResponseInfoToEntry() resets this to absl::nullopt. std::unique_ptr<HttpResponseInfo> updated_prefetch_response_; - raw_ptr<const HttpResponseInfo> new_response_; + raw_ptr<const HttpResponseInfo> new_response_ = nullptr; std::string cache_key_; Mode mode_ = NONE; bool reading_ = false; // We are already reading. Never reverts to @@ -715,7 +715,7 @@ // This is passed to the underlying network transaction. It is stored here in // case the transaction does not exist yet. raw_ptr<WebSocketHandshakeStreamBase::CreateHelper> - websocket_handshake_stream_base_create_helper_; + websocket_handshake_stream_base_create_helper_ = nullptr; // Set if we are currently calculating a checksum of the resource to validate // it against the expected checksum for the single-keyed cache. Accumulates a
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 6eb6d36..457bb67 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -142,7 +142,6 @@ context.ct_policy_enforcer, &ssl_client_session_cache_, context.sct_auditing_delegate), - push_delegate_(nullptr), quic_stream_factory_(context.net_log, context.host_resolver, context.ssl_config_service,
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index edd979a2..5f530c8 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc
@@ -116,7 +116,6 @@ : io_callback_(base::BindRepeating(&HttpNetworkTransaction::OnIOComplete, base::Unretained(this))), session_(session), - request_(nullptr), priority_(priority) {} HttpNetworkTransaction::~HttpNetworkTransaction() {
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index e10a7d7..525a4b1 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h
@@ -328,7 +328,7 @@ NetLogWithSource net_log_; // Reset to null at the start of the Read state machine. - raw_ptr<const HttpRequestInfo> request_; + raw_ptr<const HttpRequestInfo> request_ = nullptr; // The requested URL. GURL url_;
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index e048ecb..7a0e8f0e4 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -181,11 +181,8 @@ GrowableIOBuffer* read_buffer, const NetLogWithSource& net_log) : request_(request), - request_headers_(nullptr), read_buf_(read_buffer), response_header_start_offset_(std::string::npos), - response_(nullptr), - user_read_buf_(nullptr), stream_socket_(stream_socket), connection_is_reused_(connection_is_reused), net_log_(net_log) {
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h index 84df5c1..73a4bc56 100644 --- a/net/http/http_stream_parser.h +++ b/net/http/http_stream_parser.h
@@ -246,7 +246,7 @@ // cannot be safely accessed after reading the final set of headers, as the // caller of SendRequest may have been destroyed - this happens in the case an // HttpResponseBodyDrainer is used. - raw_ptr<HttpResponseInfo> response_; + raw_ptr<HttpResponseInfo> response_ = nullptr; // Time at which the first bytes of the first header response including // informational responses (1xx) are about to be parsed. This corresponds to
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc index 1053681..254263ab 100644 --- a/net/http/http_transaction_test_util.cc +++ b/net/http/http_transaction_test_util.cc
@@ -32,7 +32,6 @@ #include "net/http/http_transaction.h" #include "net/log/net_log.h" #include "net/log/net_log_source.h" -#include "net/log/net_log_with_source.h" #include "net/ssl/ssl_private_key.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -285,9 +284,7 @@ MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority, MockNetworkLayer* factory) - : priority_(priority), - transaction_factory_(factory->AsWeakPtr()), - socket_log_id_(NetLogSource::kInvalidId) {} + : priority_(priority), transaction_factory_(factory->AsWeakPtr()) {} MockNetworkTransaction::~MockNetworkTransaction() { // Use request_ as in ~HttpNetworkTransaction to make sure its valid and not
diff --git a/net/http/http_transaction_test_util.h b/net/http/http_transaction_test_util.h index 67f57e22..71541b55 100644 --- a/net/http/http_transaction_test_util.h +++ b/net/http/http_transaction_test_util.h
@@ -33,6 +33,7 @@ #include "net/http/http_request_info.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" +#include "net/log/net_log_source.h" #include "net/socket/connection_attempts.h" namespace net { @@ -295,7 +296,7 @@ // connection. Requires Start() be passed a NetLogWithSource with a real // NetLog to // be initialized. - unsigned int socket_log_id_; + unsigned int socket_log_id_ = NetLogSource::kInvalidId; bool done_reading_called_ = false; bool reading_ = false;
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index 3029855..96a6e29 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc
@@ -917,12 +917,10 @@ Values optional_values, Quotes strict_quotes) : props_(begin, end, delimiter), - valid_(true), name_begin_(end), name_end_(end), value_begin_(end), value_end_(end), - value_is_quoted_(false), values_optional_(optional_values == Values::NOT_REQUIRED), strict_quotes_(strict_quotes == Quotes::STRICT_QUOTES) {}
diff --git a/net/http/http_util.h b/net/http/http_util.h index 65f64279..7733270 100644 --- a/net/http/http_util.h +++ b/net/http/http_util.h
@@ -450,7 +450,7 @@ private: HttpUtil::ValuesIterator props_; - bool valid_; + bool valid_ = true; std::string::const_iterator name_begin_; std::string::const_iterator name_end_; @@ -463,7 +463,7 @@ // into the original's unquoted_value_ member. std::string unquoted_value_; - bool value_is_quoted_; + bool value_is_quoted_ = false; // True if values are required for each name/value pair; false if a // name is permitted to appear without a corresponding value.
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc index f5217b3..25c3764df 100644 --- a/net/http/transport_security_state.cc +++ b/net/http/transport_security_state.cc
@@ -404,10 +404,7 @@ TransportSecurityState::TransportSecurityState( std::vector<std::string> hsts_host_bypass_list) - : enable_static_pins_(true), - enable_static_expect_ct_(true), - enable_pkp_bypass_for_local_trust_anchors_(true), - sent_hpkp_reports_cache_(kMaxReportCacheEntries), + : sent_hpkp_reports_cache_(kMaxReportCacheEntries), sent_expect_ct_reports_cache_(kMaxReportCacheEntries), key_expect_ct_by_nik_(base::FeatureList::IsEnabled( features::kPartitionExpectCTStateByNetworkIsolationKey)) {
diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h index 0e003911..f8b6882 100644 --- a/net/http/transport_security_state.h +++ b/net/http/transport_security_state.h
@@ -779,13 +779,13 @@ raw_ptr<ReportSenderInterface> report_sender_ = nullptr; // True if static pins should be used. - bool enable_static_pins_; + bool enable_static_pins_ = true; // True if static expect-CT state should be used. - bool enable_static_expect_ct_; + bool enable_static_expect_ct_ = true; // True if public key pinning bypass is enabled for local trust anchors. - bool enable_pkp_bypass_for_local_trust_anchors_; + bool enable_pkp_bypass_for_local_trust_anchors_ = true; raw_ptr<ExpectCTReporter> expect_ct_reporter_ = nullptr;
diff --git a/net/log/net_log.cc b/net/log/net_log.cc index 2bb696e..6ea23415 100644 --- a/net/log/net_log.cc +++ b/net/log/net_log.cc
@@ -14,7 +14,7 @@ namespace net { -NetLog::ThreadSafeObserver::ThreadSafeObserver() : net_log_(nullptr) {} +NetLog::ThreadSafeObserver::ThreadSafeObserver() = default; NetLog::ThreadSafeObserver::~ThreadSafeObserver() { // Make sure we aren't watching a NetLog on destruction. Because the NetLog
diff --git a/net/log/net_log.h b/net/log/net_log.h index a89dbc56..d041ab8 100644 --- a/net/log/net_log.h +++ b/net/log/net_log.h
@@ -137,7 +137,7 @@ // Both of these values are only modified by the NetLog. NetLogCaptureMode capture_mode_ = NetLogCaptureMode::kDefault; - raw_ptr<NetLog> net_log_; + raw_ptr<NetLog> net_log_ = nullptr; }; // An observer that is notified of changes in the capture mode set, and has
diff --git a/net/log/net_log_unittest.cc b/net/log/net_log_unittest.cc index b0de08e..5083cf6 100644 --- a/net/log/net_log_unittest.cc +++ b/net/log/net_log_unittest.cc
@@ -235,10 +235,7 @@ // RunTestThread. class NetLogTestThread : public base::SimpleThread { public: - NetLogTestThread() - : base::SimpleThread("NetLogTest"), - net_log_(nullptr), - start_event_(nullptr) {} + NetLogTestThread() : base::SimpleThread("NetLogTest") {} NetLogTestThread(const NetLogTestThread&) = delete; NetLogTestThread& operator=(const NetLogTestThread&) = delete; @@ -260,12 +257,12 @@ virtual void RunTestThread() = 0; protected: - raw_ptr<NetLog> net_log_; + raw_ptr<NetLog> net_log_ = nullptr; private: // Only triggered once all threads have been created, to make it less likely // each thread completes before the next one starts. - raw_ptr<base::WaitableEvent> start_event_; + raw_ptr<base::WaitableEvent> start_event_ = nullptr; }; // A thread that adds a bunch of events to the NetLog.
diff --git a/net/log/trace_net_log_observer.cc b/net/log/trace_net_log_observer.cc index b2998b25..77c3d25 100644 --- a/net/log/trace_net_log_observer.cc +++ b/net/log/trace_net_log_observer.cc
@@ -47,7 +47,7 @@ } // namespace -TraceNetLogObserver::TraceNetLogObserver() : net_log_to_watch_(nullptr) {} +TraceNetLogObserver::TraceNetLogObserver() = default; TraceNetLogObserver::~TraceNetLogObserver() { DCHECK(!net_log_to_watch_);
diff --git a/net/log/trace_net_log_observer.h b/net/log/trace_net_log_observer.h index 2c5dde4..568f533 100644 --- a/net/log/trace_net_log_observer.h +++ b/net/log/trace_net_log_observer.h
@@ -44,7 +44,7 @@ void OnTraceLogDisabled() override; private: - raw_ptr<NetLog> net_log_to_watch_; + raw_ptr<NetLog> net_log_to_watch_ = nullptr; base::WeakPtrFactory<TraceNetLogObserver> weak_factory_{this}; };
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc index 37b4dee..bedaca3e 100644 --- a/net/network_error_logging/network_error_logging_service.cc +++ b/net/network_error_logging/network_error_logging_service.cc
@@ -1043,6 +1043,6 @@ } NetworkErrorLoggingService::NetworkErrorLoggingService() - : clock_(base::DefaultClock::GetInstance()), reporting_service_(nullptr) {} + : clock_(base::DefaultClock::GetInstance()) {} } // namespace net
diff --git a/net/network_error_logging/network_error_logging_service.h b/net/network_error_logging/network_error_logging_service.h index fa56764..90fd2a8 100644 --- a/net/network_error_logging/network_error_logging_service.h +++ b/net/network_error_logging/network_error_logging_service.h
@@ -292,7 +292,7 @@ // Unowned: raw_ptr<const base::Clock> clock_; - raw_ptr<ReportingService> reporting_service_; + raw_ptr<ReportingService> reporting_service_ = nullptr; bool shut_down_ = false; };
diff --git a/net/nqe/network_qualities_prefs_manager.cc b/net/nqe/network_qualities_prefs_manager.cc index 59f41a6..1bf9bb5 100644 --- a/net/nqe/network_qualities_prefs_manager.cc +++ b/net/nqe/network_qualities_prefs_manager.cc
@@ -57,8 +57,7 @@ NetworkQualitiesPrefsManager::NetworkQualitiesPrefsManager( std::unique_ptr<PrefDelegate> pref_delegate) : pref_delegate_(std::move(pref_delegate)), - prefs_(pref_delegate_->GetDictionaryValue()), - network_quality_estimator_(nullptr) { + prefs_(pref_delegate_->GetDictionaryValue()) { DCHECK(pref_delegate_); DCHECK_GE(kMaxCacheSize, prefs_.size()); }
diff --git a/net/nqe/network_qualities_prefs_manager.h b/net/nqe/network_qualities_prefs_manager.h index 7dbd0ef8..aceab05d 100644 --- a/net/nqe/network_qualities_prefs_manager.h +++ b/net/nqe/network_qualities_prefs_manager.h
@@ -81,7 +81,7 @@ const nqe::internal::CachedNetworkQuality& cached_network_quality) override; - raw_ptr<NetworkQualityEstimator> network_quality_estimator_; + raw_ptr<NetworkQualityEstimator> network_quality_estimator_ = nullptr; // Network quality prefs read from the disk at the time of startup. ParsedPrefs read_prefs_startup_;
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index 376fccd..2895c5b 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -120,7 +120,6 @@ tick_clock_, params_->weight_multiplier_per_second(), 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/)}, - effective_connection_type_recomputation_interval_(base::Seconds(10)), net_log_(NetLogWithSource::Make( net_log, net::NetLogSourceType::NETWORK_QUALITY_ESTIMATOR)),
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h index d0f263c..cda6fac5 100644 --- a/net/nqe/network_quality_estimator.h +++ b/net/nqe/network_quality_estimator.h
@@ -593,7 +593,8 @@ // Minimum duration between two consecutive computations of effective // connection type. Set to non-zero value as a performance optimization. - const base::TimeDelta effective_connection_type_recomputation_interval_; + const base::TimeDelta effective_connection_type_recomputation_interval_ = + base::Seconds(10); // Time when the effective connection type was last computed. base::TimeTicks last_effective_connection_type_computation_;
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc index 2cb3bfa..0b81b9f 100644 --- a/net/nqe/network_quality_estimator_params.cc +++ b/net/nqe/network_quality_estimator_params.cc
@@ -446,7 +446,6 @@ params_, "hanging_request_http_rtt_upper_bound_http_rtt_multiplier", 6)), - hanging_request_upper_bound_min_http_rtt_(base::Milliseconds(500)), http_rtt_transport_rtt_min_count_( GetValueForVariationParam(params_, "http_rtt_transport_rtt_min_count", @@ -470,7 +469,6 @@ params_, "hanging_request_duration_http_rtt_multiplier", 5)), - hanging_request_min_duration_(base::Milliseconds(3000)), add_default_platform_observations_( GetStringValueForVariationParamWithDefaultValue( params_,
diff --git a/net/nqe/network_quality_estimator_params.h b/net/nqe/network_quality_estimator_params.h index 3a34c0b..b71ccc72 100644 --- a/net/nqe/network_quality_estimator_params.h +++ b/net/nqe/network_quality_estimator_params.h
@@ -276,13 +276,15 @@ const double upper_bound_http_rtt_endtoend_rtt_multiplier_; const int hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_; const int hanging_request_http_rtt_upper_bound_http_rtt_multiplier_; - const base::TimeDelta hanging_request_upper_bound_min_http_rtt_; + const base::TimeDelta hanging_request_upper_bound_min_http_rtt_ = + base::Milliseconds(500); const size_t http_rtt_transport_rtt_min_count_; const base::TimeDelta increase_in_transport_rtt_logging_interval_; const base::TimeDelta recent_time_threshold_; const base::TimeDelta historical_time_threshold_; const int hanging_request_duration_http_rtt_multiplier_; - const base::TimeDelta hanging_request_min_duration_; + const base::TimeDelta hanging_request_min_duration_ = + base::Milliseconds(3000); const bool add_default_platform_observations_; const base::TimeDelta socket_watchers_min_notification_interval_; const bool use_end_to_end_rtt_ = true;
diff --git a/net/nqe/network_quality_estimator_test_util.cc b/net/nqe/network_quality_estimator_test_util.cc index fb387206..92b9964c 100644 --- a/net/nqe/network_quality_estimator_test_util.cc +++ b/net/nqe/network_quality_estimator_test_util.cc
@@ -51,7 +51,6 @@ : NetworkQualityEstimator( std::make_unique<NetworkQualityEstimatorParams>(variation_params), NetLog::Get()), - current_network_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), embedded_test_server_(base::FilePath(kTestFilePath)), suppress_notifications_for_testing_(suppress_notifications_for_testing) { SetUseLocalHostRequestsForTesting(allow_local_host_requests_for_tests); @@ -61,7 +60,6 @@ TestNetworkQualityEstimator::TestNetworkQualityEstimator( std::unique_ptr<NetworkQualityEstimatorParams> params) : NetworkQualityEstimator(std::move(params), NetLog::Get()), - current_network_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), embedded_test_server_(base::FilePath(kTestFilePath)), suppress_notifications_for_testing_(false) {}
diff --git a/net/nqe/network_quality_estimator_test_util.h b/net/nqe/network_quality_estimator_test_util.h index 283b4b90..5a1b9aa 100644 --- a/net/nqe/network_quality_estimator_test_util.h +++ b/net/nqe/network_quality_estimator_test_util.h
@@ -247,7 +247,8 @@ absl::optional<EffectiveConnectionType> effective_connection_type_; absl::optional<EffectiveConnectionType> recent_effective_connection_type_; - NetworkChangeNotifier::ConnectionType current_network_type_; + NetworkChangeNotifier::ConnectionType current_network_type_ = + NetworkChangeNotifier::CONNECTION_UNKNOWN; std::string current_network_id_; // If set, GetRecentHttpRTT() would return one of the set values.
diff --git a/net/proxy_resolution/configured_proxy_resolution_request.cc b/net/proxy_resolution/configured_proxy_resolution_request.cc index 88b06c4..c2c8975 100644 --- a/net/proxy_resolution/configured_proxy_resolution_request.cc +++ b/net/proxy_resolution/configured_proxy_resolution_request.cc
@@ -29,7 +29,6 @@ url_(url), method_(method), network_isolation_key_(network_isolation_key), - resolve_job_(nullptr), net_log_(net_log), creation_time_(base::TimeTicks::Now()) { DCHECK(!user_callback_.is_null());
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.cc b/net/proxy_resolution/configured_proxy_resolution_service.cc index f1cab35..30072447 100644 --- a/net/proxy_resolution/configured_proxy_resolution_service.cc +++ b/net/proxy_resolution/configured_proxy_resolution_service.cc
@@ -418,8 +418,7 @@ class ConfiguredProxyResolutionService::InitProxyResolver { public: - InitProxyResolver() - : proxy_resolver_factory_(nullptr), proxy_resolver_(nullptr) {} + InitProxyResolver() = default; InitProxyResolver(const InitProxyResolver&) = delete; InitProxyResolver& operator=(const InitProxyResolver&) = delete; @@ -600,9 +599,9 @@ PacFileDataWithSource script_data_; base::TimeDelta wait_delay_; std::unique_ptr<PacFileDecider> decider_; - raw_ptr<ProxyResolverFactory> proxy_resolver_factory_; + raw_ptr<ProxyResolverFactory> proxy_resolver_factory_ = nullptr; std::unique_ptr<ProxyResolverFactory::Request> create_resolver_request_; - raw_ptr<std::unique_ptr<ProxyResolver>> proxy_resolver_; + raw_ptr<std::unique_ptr<ProxyResolver>> proxy_resolver_ = nullptr; CompletionOnceCallback callback_; State next_state_ = State::kNone; bool quick_check_enabled_ = true;
diff --git a/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc b/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc index fe1e4d7..cdd6bc8b 100644 --- a/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc +++ b/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc
@@ -161,13 +161,11 @@ class MockProxyConfigService : public ProxyConfigService { public: explicit MockProxyConfigService(const ProxyConfig& config) - : availability_(CONFIG_VALID), - config_( + : config_( ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS)) {} explicit MockProxyConfigService(const std::string& pac_url) - : availability_(CONFIG_VALID), - config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url)), + : config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url)), TRAFFIC_ANNOTATION_FOR_TESTS) {} void AddObserver(Observer* observer) override { @@ -199,7 +197,7 @@ } private: - ConfigAvailability availability_; + ConfigAvailability availability_ = CONFIG_VALID; ProxyConfigWithAnnotation config_; base::ObserverList<Observer, true>::Unchecked observers_; };
diff --git a/net/proxy_resolution/mock_pac_file_fetcher.cc b/net/proxy_resolution/mock_pac_file_fetcher.cc index 3aebe8bb..aa950804 100644 --- a/net/proxy_resolution/mock_pac_file_fetcher.cc +++ b/net/proxy_resolution/mock_pac_file_fetcher.cc
@@ -14,7 +14,7 @@ namespace net { -MockPacFileFetcher::MockPacFileFetcher() : pending_request_text_(nullptr) {} +MockPacFileFetcher::MockPacFileFetcher() = default; MockPacFileFetcher::~MockPacFileFetcher() = default;
diff --git a/net/proxy_resolution/mock_pac_file_fetcher.h b/net/proxy_resolution/mock_pac_file_fetcher.h index c3142a187..2947259 100644 --- a/net/proxy_resolution/mock_pac_file_fetcher.h +++ b/net/proxy_resolution/mock_pac_file_fetcher.h
@@ -44,7 +44,7 @@ private: GURL pending_request_url_; CompletionOnceCallback pending_request_callback_; - raw_ptr<std::u16string> pending_request_text_; + raw_ptr<std::u16string> pending_request_text_ = nullptr; base::OnceClosure on_fetch_complete_; bool is_shutdown_ = false; };
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver.cc b/net/proxy_resolution/multi_threaded_proxy_resolver.cc index 8ff6ab4..7a587a0 100644 --- a/net/proxy_resolution/multi_threaded_proxy_resolver.cc +++ b/net/proxy_resolution/multi_threaded_proxy_resolver.cc
@@ -162,7 +162,7 @@ class Job : public base::RefCountedThreadSafe<Job> { public: - Job() : executor_(nullptr) {} + Job() = default; void set_executor(Executor* executor) { executor_ = executor; @@ -208,7 +208,7 @@ virtual ~Job() = default; private: - raw_ptr<Executor> executor_; + raw_ptr<Executor> executor_ = nullptr; bool was_cancelled_ = false; };
diff --git a/net/proxy_resolution/pac_file_decider_unittest.cc b/net/proxy_resolution/pac_file_decider_unittest.cc index 6e568b8..fa086e0 100644 --- a/net/proxy_resolution/pac_file_decider_unittest.cc +++ b/net/proxy_resolution/pac_file_decider_unittest.cc
@@ -103,8 +103,7 @@ class RuleBasedPacFileFetcher : public PacFileFetcher { public: - explicit RuleBasedPacFileFetcher(const Rules* rules) - : rules_(rules), request_context_(nullptr) {} + explicit RuleBasedPacFileFetcher(const Rules* rules) : rules_(rules) {} virtual void SetRequestContext(URLRequestContext* context) { request_context_ = context; @@ -133,7 +132,7 @@ private: raw_ptr<const Rules> rules_; - raw_ptr<URLRequestContext> request_context_; + raw_ptr<URLRequestContext> request_context_ = nullptr; }; // A mock retriever, returns asynchronously when CompleteRequests() is called.
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.cc b/net/proxy_resolution/pac_file_fetcher_impl.cc index e2a9114f..313f686 100644 --- a/net/proxy_resolution/pac_file_fetcher_impl.cc +++ b/net/proxy_resolution/pac_file_fetcher_impl.cc
@@ -318,7 +318,6 @@ PacFileFetcherImpl::PacFileFetcherImpl(URLRequestContext* url_request_context) : url_request_context_(url_request_context), buf_(base::MakeRefCounted<IOBuffer>(kBufSize)), - result_text_(nullptr), max_response_bytes_(kDefaultMaxResponseBytes), max_duration_(kDefaultMaxDuration) { DCHECK(url_request_context);
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.h b/net/proxy_resolution/pac_file_fetcher_impl.h index 32ef8e61..185554dc 100644 --- a/net/proxy_resolution/pac_file_fetcher_impl.h +++ b/net/proxy_resolution/pac_file_fetcher_impl.h
@@ -137,7 +137,7 @@ // This buffer is owned by the owner of |callback|, and will be filled with // UTF16 response on completion. - raw_ptr<std::u16string> result_text_; + raw_ptr<std::u16string> result_text_ = nullptr; // The maximum number of bytes to allow in responses. size_t max_response_bytes_;
diff --git a/net/proxy_resolution/proxy_config_service_android.cc b/net/proxy_resolution/proxy_config_service_android.cc index 3287205e9..9dc7a7b3 100644 --- a/net/proxy_resolution/proxy_config_service_android.cc +++ b/net/proxy_resolution/proxy_config_service_android.cc
@@ -282,9 +282,7 @@ : jni_delegate_(this), main_task_runner_(main_task_runner), jni_task_runner_(jni_task_runner), - get_property_callback_(get_property_callback), - exclude_pac_url_(false), - has_proxy_override_(false) {} + get_property_callback_(get_property_callback) {} Delegate(const Delegate&) = delete; Delegate& operator=(const Delegate&) = delete; @@ -489,9 +487,9 @@ scoped_refptr<base::SequencedTaskRunner> jni_task_runner_; GetPropertyCallback get_property_callback_; ProxyConfigWithAnnotation proxy_config_; - bool exclude_pac_url_; + bool exclude_pac_url_ = false; // This may only be accessed or modified on the JNI thread - bool has_proxy_override_; + bool has_proxy_override_ = false; }; ProxyConfigServiceAndroid::ProxyConfigServiceAndroid(
diff --git a/net/proxy_resolution/proxy_config_service_android_unittest.cc b/net/proxy_resolution/proxy_config_service_android_unittest.cc index 7e6a2a0..8e47290 100644 --- a/net/proxy_resolution/proxy_config_service_android_unittest.cc +++ b/net/proxy_resolution/proxy_config_service_android_unittest.cc
@@ -214,13 +214,12 @@ struct ProxyCallback { ProxyCallback() - : called(false), - callback(base::BindOnce(&ProxyCallback::Call, base::Unretained(this))) { + : callback(base::BindOnce(&ProxyCallback::Call, base::Unretained(this))) { } void Call() { called = true; } - bool called; + bool called = false; base::OnceClosure callback; };
diff --git a/net/proxy_resolution/proxy_config_service_linux.cc b/net/proxy_resolution/proxy_config_service_linux.cc index e2448a7..0ec473e 100644 --- a/net/proxy_resolution/proxy_config_service_linux.cc +++ b/net/proxy_resolution/proxy_config_service_linux.cc
@@ -516,8 +516,7 @@ public: explicit SettingGetterImplKDE(base::Environment* env_var_getter) : debounce_timer_(new base::OneShotTimer()), - env_var_getter_(env_var_getter), - file_task_runner_(nullptr) { + env_var_getter_(env_var_getter) { // This has to be called on the UI thread (http://crbug.com/69057). base::ThreadRestrictions::ScopedAllowIO allow_io;
diff --git a/net/proxy_resolution/proxy_config_service_mac.cc b/net/proxy_resolution/proxy_config_service_mac.cc index a7d7037..645b2cfa 100644 --- a/net/proxy_resolution/proxy_config_service_mac.cc +++ b/net/proxy_resolution/proxy_config_service_mac.cc
@@ -199,7 +199,6 @@ const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, const NetworkTrafficAnnotationTag& traffic_annotation) : forwarder_(this), - has_fetched_config_(false), helper_(new Helper(this)), sequenced_task_runner_(sequenced_task_runner), traffic_annotation_(traffic_annotation) {
diff --git a/net/proxy_resolution/proxy_config_service_mac.h b/net/proxy_resolution/proxy_config_service_mac.h index e8d5a0b0..3773e53 100644 --- a/net/proxy_resolution/proxy_config_service_mac.h +++ b/net/proxy_resolution/proxy_config_service_mac.h
@@ -76,7 +76,7 @@ base::ObserverList<Observer>::Unchecked observers_; // Holds the last system proxy settings that we fetched. - bool has_fetched_config_; + bool has_fetched_config_ = false; ProxyConfigWithAnnotation last_config_fetched_; scoped_refptr<Helper> helper_;
diff --git a/net/proxy_resolution/proxy_resolver_mac.cc b/net/proxy_resolution/proxy_resolver_mac.cc index 3fc3f65..50bebc0a 100644 --- a/net/proxy_resolution/proxy_resolver_mac.cc +++ b/net/proxy_resolution/proxy_resolver_mac.cc
@@ -124,7 +124,7 @@ base::Lock& lock_; // Indicates whether the current observer holds the lock. It is used to // avoid double locking and releasing. - bool lock_acquired_; + bool lock_acquired_ = false; // The underlying CFRunLoopObserverRef structure wrapped by this instance. base::ScopedCFTypeRef<CFRunLoopObserverRef> observer_; // Validates that all methods of this class are executed on the same thread. @@ -132,7 +132,7 @@ }; SynchronizedRunLoopObserver::SynchronizedRunLoopObserver(base::Lock& lock) - : lock_(lock), lock_acquired_(false) { + : lock_(lock) { CFRunLoopObserverContext observer_context = {0, this, NULL, NULL, NULL}; observer_.reset(CFRunLoopObserverCreate( kCFAllocatorDefault,
diff --git a/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc b/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc index b95e619..52041a0 100644 --- a/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc +++ b/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc
@@ -14,7 +14,6 @@ #include "base/task/task_runner.h" #include "base/threading/scoped_blocking_call.h" #include "base/time/time.h" -#include "net/base/net_errors.h" #include "net/proxy_resolution/pac_file_fetcher_impl.h" #include "net/proxy_resolution/win/dhcpcsvc_init_win.h" #include "net/url_request/url_request_context.h" @@ -35,10 +34,7 @@ DhcpPacFileAdapterFetcher::DhcpPacFileAdapterFetcher( URLRequestContext* url_request_context, scoped_refptr<base::TaskRunner> task_runner) - : task_runner_(task_runner), - state_(STATE_START), - result_(ERR_IO_PENDING), - url_request_context_(url_request_context) { + : task_runner_(task_runner), url_request_context_(url_request_context) { DCHECK(url_request_context_); }
diff --git a/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h b/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h index e87dd26c..2ecf2250 100644 --- a/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h +++ b/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h
@@ -16,6 +16,7 @@ #include "base/threading/thread_checker.h" #include "base/timer/timer.h" #include "net/base/completion_once_callback.h" +#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h" @@ -171,10 +172,10 @@ scoped_refptr<base::TaskRunner> task_runner_; // Current state of this state machine. - State state_; + State state_ = STATE_START; // A network error indicating result of operation. - int result_; + int result_ = ERR_IO_PENDING; // Empty string or the PAC script downloaded. std::u16string pac_script_;
diff --git a/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win_unittest.cc b/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win_unittest.cc index afd1d6a6..b6d642f 100644 --- a/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win_unittest.cc +++ b/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win_unittest.cc
@@ -52,11 +52,7 @@ URLRequestContext* context, scoped_refptr<base::TaskRunner> task_runner) : DhcpPacFileAdapterFetcher(context, task_runner), - dhcp_delay_(base::Milliseconds(1)), timeout_(TestTimeouts::action_timeout()), - configured_url_(kPacUrl), - fetcher_delay_ms_(1), - fetcher_result_(OK), pac_script_("bingo") {} void Cancel() override { @@ -139,11 +135,11 @@ dhcp_query_->test_finished_event_.Signal(); } - base::TimeDelta dhcp_delay_; + base::TimeDelta dhcp_delay_ = base::Milliseconds(1); base::TimeDelta timeout_; - std::string configured_url_; - int fetcher_delay_ms_; - int fetcher_result_; + std::string configured_url_{kPacUrl}; + int fetcher_delay_ms_ = 1; + int fetcher_result_ = OK; std::string pac_script_; raw_ptr<MockPacFileFetcher> fetcher_; base::OneShotTimer fetcher_timer_;
diff --git a/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc b/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc index af1d3ad5..b5b6803d 100644 --- a/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc +++ b/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc
@@ -255,10 +255,7 @@ DhcpPacFileFetcherWin::DhcpPacFileFetcherWin( URLRequestContext* url_request_context) - : state_(STATE_START), - num_pending_fetchers_(0), - destination_string_(nullptr), - url_request_context_(url_request_context), + : url_request_context_(url_request_context), task_runner_(base::MakeRefCounted<TaskRunnerWithCap>()) { DCHECK(url_request_context_); }
diff --git a/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h b/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h index 1a8e9a6..b25285d7 100644 --- a/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h +++ b/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h
@@ -167,12 +167,12 @@ FetcherVector fetchers_; // Current state of this state machine. - State state_; + State state_ = STATE_START; // The following members are associated with the latest call to Fetch(). // Number of fetchers we are waiting for. - int num_pending_fetchers_; + int num_pending_fetchers_ = 0; // Lets our client know we're done. Not valid in states START or DONE. CompletionOnceCallback callback_; @@ -182,7 +182,7 @@ // Pointer to string we will write results to. Not valid in states // START and DONE. - raw_ptr<std::u16string> destination_string_; + raw_ptr<std::u16string> destination_string_ = nullptr; // PAC URL retrieved from DHCP, if any. Valid only in state STATE_DONE. GURL pac_url_;
diff --git a/net/proxy_resolution/win/dhcp_pac_file_fetcher_win_unittest.cc b/net/proxy_resolution/win/dhcp_pac_file_fetcher_win_unittest.cc index 9657fe1..a4bb2d82 100644 --- a/net/proxy_resolution/win/dhcp_pac_file_fetcher_win_unittest.cc +++ b/net/proxy_resolution/win/dhcp_pac_file_fetcher_win_unittest.cc
@@ -53,9 +53,7 @@ public: RealFetchTester() : context_(CreateTestURLRequestContextBuilder()->Build()), - fetcher_(new DhcpPacFileFetcherWin(context_.get())), - finished_(false), - on_completion_is_error_(false) { + fetcher_(new DhcpPacFileFetcherWin(context_.get())) { // Make sure the test ends. timeout_.Start(FROM_HERE, base::Seconds(5), this, &RealFetchTester::OnTimeout); @@ -119,11 +117,11 @@ std::unique_ptr<URLRequestContext> context_; std::unique_ptr<DhcpPacFileFetcherWin> fetcher_; - bool finished_; + bool finished_ = false; std::u16string pac_text_; base::OneShotTimer timeout_; base::OneShotTimer cancel_timer_; - bool on_completion_is_error_; + bool on_completion_is_error_ = false; }; TEST(DhcpPacFileFetcherWin, RealFetch) { @@ -218,11 +216,7 @@ public: DummyDhcpPacFileAdapterFetcher(URLRequestContext* context, scoped_refptr<base::TaskRunner> runner) - : DhcpPacFileAdapterFetcher(context, runner), - did_finish_(false), - result_(OK), - pac_script_(u"bingo"), - fetch_delay_ms_(1) {} + : DhcpPacFileAdapterFetcher(context, runner), pac_script_(u"bingo") {} void Fetch(const std::string& adapter_name, CompletionOnceCallback callback, @@ -259,10 +253,10 @@ } private: - bool did_finish_; - int result_; + bool did_finish_ = false; + int result_ = OK; std::u16string pac_script_; - int fetch_delay_ms_; + int fetch_delay_ms_ = 1; CompletionOnceCallback callback_; base::OneShotTimer timer_; }; @@ -290,7 +284,6 @@ MockDhcpPacFileFetcherWin(URLRequestContext* context) : DhcpPacFileFetcherWin(context), - num_fetchers_created_(0), worker_finished_event_( base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED) { @@ -372,7 +365,7 @@ scoped_refptr<MockAdapterQuery> adapter_query_; base::TimeDelta max_wait_; - int num_fetchers_created_; + int num_fetchers_created_ = 0; base::WaitableEvent worker_finished_event_; }; @@ -380,9 +373,7 @@ public: FetcherClient() : context_(CreateTestURLRequestContextBuilder()->Build()), - fetcher_(context_.get()), - finished_(false), - result_(ERR_UNEXPECTED) {} + fetcher_(context_.get()) {} void RunTest() { int result = fetcher_.Fetch( @@ -434,8 +425,8 @@ std::unique_ptr<URLRequestContext> context_; MockDhcpPacFileFetcherWin fetcher_; - bool finished_; - int result_; + bool finished_ = false; + int result_ = ERR_UNEXPECTED; std::u16string pac_text_; };
diff --git a/net/proxy_resolution/win/proxy_resolver_winhttp.cc b/net/proxy_resolution/win/proxy_resolver_winhttp.cc index 2fed37a..ae5fa94 100644 --- a/net/proxy_resolution/win/proxy_resolver_winhttp.cc +++ b/net/proxy_resolution/win/proxy_resolver_winhttp.cc
@@ -72,15 +72,14 @@ void CloseWinHttpSession(); // Proxy configuration is cached on the session handle. - HINTERNET session_handle_; + HINTERNET session_handle_ = nullptr; const GURL pac_url_; }; ProxyResolverWinHttp::ProxyResolverWinHttp( const scoped_refptr<PacFileData>& script_data) - : session_handle_(nullptr), - pac_url_(script_data->type() == PacFileData::TYPE_AUTO_DETECT + : pac_url_(script_data->type() == PacFileData::TYPE_AUTO_DETECT ? GURL("http://wpad/wpad.dat") : script_data->url()) {}
diff --git a/net/quic/bidirectional_stream_quic_impl.cc b/net/quic/bidirectional_stream_quic_impl.cc index befaf5538..3f90770 100644 --- a/net/quic/bidirectional_stream_quic_impl.cc +++ b/net/quic/bidirectional_stream_quic_impl.cc
@@ -40,10 +40,7 @@ BidirectionalStreamQuicImpl::BidirectionalStreamQuicImpl( std::unique_ptr<QuicChromiumClientSession::Handle> session) - : session_(std::move(session)), - stream_(nullptr), - request_info_(nullptr), - delegate_(nullptr) {} + : session_(std::move(session)) {} BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() { if (stream_) {
diff --git a/net/quic/bidirectional_stream_quic_impl.h b/net/quic/bidirectional_stream_quic_impl.h index eb54b1f6..3a4442b 100644 --- a/net/quic/bidirectional_stream_quic_impl.h +++ b/net/quic/bidirectional_stream_quic_impl.h
@@ -86,8 +86,8 @@ const std::unique_ptr<QuicChromiumClientSession::Handle> session_; std::unique_ptr<QuicChromiumClientStream::Handle> stream_; - raw_ptr<const BidirectionalStreamRequestInfo> request_info_; - raw_ptr<BidirectionalStreamImpl::Delegate> delegate_; + raw_ptr<const BidirectionalStreamRequestInfo> request_info_ = nullptr; + raw_ptr<BidirectionalStreamImpl::Delegate> delegate_ = nullptr; // Saves the response status if the stream is explicitly closed via OnError // or OnClose with an error. Once all buffered data has been returned, this // will be used as the final response.
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc index e7132c61..42a8428 100644 --- a/net/quic/bidirectional_stream_quic_impl_unittest.cc +++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -123,21 +123,7 @@ std::unique_ptr<base::OneShotTimer> timer) : read_buf_(read_buf), read_buf_len_(read_buf_len), - timer_(std::move(timer)), - loop_(nullptr), - next_proto_(kProtoUnknown), - received_bytes_(0), - sent_bytes_(0), - has_load_timing_info_(false), - error_(OK), - on_data_read_count_(0), - on_data_sent_count_(0), - not_expect_callback_(false), - on_failed_called_(false), - send_request_headers_automatically_(true), - is_ready_(false), - trailers_expected_(false), - trailers_received_(false) { + timer_(std::move(timer)) { loop_ = std::make_unique<base::RunLoop>(); } @@ -338,23 +324,23 @@ std::unique_ptr<base::RunLoop> loop_; spdy::Http2HeaderBlock response_headers_; spdy::Http2HeaderBlock trailers_; - NextProto next_proto_; - int64_t received_bytes_; - int64_t sent_bytes_; - bool has_load_timing_info_; + NextProto next_proto_ = kProtoUnknown; + int64_t received_bytes_ = 0; + int64_t sent_bytes_ = 0; + bool has_load_timing_info_ = false; LoadTimingInfo load_timing_info_; - int error_; - int on_data_read_count_; - int on_data_sent_count_; + int error_ = OK; + int on_data_read_count_ = 0; + int on_data_sent_count_ = 0; // This is to ensure that delegate callback is not invoked synchronously when // calling into |stream_|. - bool not_expect_callback_; - bool on_failed_called_; + bool not_expect_callback_ = false; + bool on_failed_called_ = false; CompletionOnceCallback callback_; - bool send_request_headers_automatically_; - bool is_ready_; - bool trailers_expected_; - bool trailers_received_; + bool send_request_headers_automatically_ = true; + bool is_ready_ = false; + bool trailers_expected_ = false; + bool trailers_received_ = false; }; // A delegate that deletes the stream in a particular callback. @@ -466,7 +452,6 @@ kDefaultServerHostName, quic::Perspective::IS_SERVER, false), - random_generator_(0), printer_(version_), destination_(url::kHttpsScheme, kDefaultServerHostName, @@ -855,7 +840,7 @@ QuicTestPacketMaker server_maker_; IPEndPoint self_addr_; IPEndPoint peer_addr_; - quic::test::MockRandom random_generator_; + quic::test::MockRandom random_generator_{0}; QuicPacketPrinter printer_; MockCryptoClientStreamFactory crypto_client_stream_factory_; std::unique_ptr<StaticSocketDataProvider> socket_data_;
diff --git a/net/quic/mock_crypto_client_stream_factory.cc b/net/quic/mock_crypto_client_stream_factory.cc index 3b50b76..49a9935 100644 --- a/net/quic/mock_crypto_client_stream_factory.cc +++ b/net/quic/mock_crypto_client_stream_factory.cc
@@ -15,7 +15,7 @@ MockCryptoClientStreamFactory::~MockCryptoClientStreamFactory() {} MockCryptoClientStreamFactory::MockCryptoClientStreamFactory() - : last_stream_(nullptr), config_(new quic::QuicConfig()) {} + : config_(new quic::QuicConfig()) {} void MockCryptoClientStreamFactory::SetConfig(const quic::QuicConfig& config) { config_ = std::make_unique<quic::QuicConfig>(config);
diff --git a/net/quic/mock_crypto_client_stream_factory.h b/net/quic/mock_crypto_client_stream_factory.h index 540660cc..2a703b8 100644 --- a/net/quic/mock_crypto_client_stream_factory.h +++ b/net/quic/mock_crypto_client_stream_factory.h
@@ -58,7 +58,7 @@ private: MockCryptoClientStream::HandshakeMode handshake_mode_ = MockCryptoClientStream::CONFIRM_HANDSHAKE; - raw_ptr<MockCryptoClientStream> last_stream_; + raw_ptr<MockCryptoClientStream> last_stream_ = nullptr; base::queue<const ProofVerifyDetailsChromium*> proof_verify_details_queue_; std::unique_ptr<quic::QuicConfig> config_; bool use_mock_crypter_ = false;
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 918f5e05..b84d03f 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -628,7 +628,6 @@ const NetworkTrafficAnnotationTag& traffic_annotation) : session_(session), requires_confirmation_(requires_confirmation), - stream_(nullptr), traffic_annotation_(traffic_annotation) {} QuicChromiumClientSession::StreamRequest::~StreamRequest() {
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc index ffba0e1..ca0e1ea3 100644 --- a/net/quic/quic_chromium_client_session_test.cc +++ b/net/quic/quic_chromium_client_session_test.cc
@@ -138,7 +138,6 @@ socket_data_( new SequencedSocketData(base::make_span(default_read_.get(), 1), base::span<MockWrite>())), - random_(0), helper_(&clock_, &random_), transport_security_state_(std::make_unique<TransportSecurityState>()), session_key_(kServerHostname, @@ -297,7 +296,7 @@ std::unique_ptr<MockRead> default_read_; std::unique_ptr<SequencedSocketData> socket_data_; quic::MockClock clock_; - quic::test::MockRandom random_; + quic::test::MockRandom random_{0}; QuicChromiumConnectionHelper helper_; quic::test::MockAlarmFactory alarm_factory_; std::unique_ptr<TransportSecurityState> transport_security_state_;
diff --git a/net/quic/quic_chromium_client_stream.cc b/net/quic/quic_chromium_client_stream.cc index 9767668..11a2dd5 100644 --- a/net/quic/quic_chromium_client_stream.cc +++ b/net/quic/quic_chromium_client_stream.cc
@@ -45,9 +45,7 @@ } // namespace QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream) - : stream_(stream), - read_headers_buffer_(nullptr), - net_log_(stream->net_log()) { + : stream_(stream), net_log_(stream->net_log()) { SaveState(); } @@ -446,15 +444,8 @@ const NetworkTrafficAnnotationTag& traffic_annotation) : quic::QuicSpdyStream(id, session, type), net_log_(net_log), - handle_(nullptr), - initial_headers_sent_(false), session_(session), - quic_version_(session->connection()->transport_version()), - can_migrate_to_cellular_network_(true), - initial_headers_arrived_(false), - headers_delivered_(false), - initial_headers_frame_len_(0), - trailing_headers_frame_len_(0) {} + quic_version_(session->connection()->transport_version()) {} QuicChromiumClientStream::QuicChromiumClientStream( quic::PendingStream* pending, @@ -463,15 +454,8 @@ const NetworkTrafficAnnotationTag& traffic_annotation) : quic::QuicSpdyStream(pending, session), net_log_(net_log), - handle_(nullptr), - initial_headers_sent_(false), session_(session), - quic_version_(session->connection()->transport_version()), - can_migrate_to_cellular_network_(true), - initial_headers_arrived_(false), - headers_delivered_(false), - initial_headers_frame_len_(0), - trailing_headers_frame_len_(0) {} + quic_version_(session->connection()->transport_version()) {} QuicChromiumClientStream::~QuicChromiumClientStream() { if (handle_)
diff --git a/net/quic/quic_chromium_client_stream.h b/net/quic/quic_chromium_client_stream.h index fbf9299..b254848f 100644 --- a/net/quic/quic_chromium_client_stream.h +++ b/net/quic/quic_chromium_client_stream.h
@@ -183,7 +183,7 @@ // Callback to be invoked when ReadInitialHeaders completes asynchronously. CompletionOnceCallback read_headers_callback_; // Provided by the owner of this handle when ReadInitialHeaders is called. - raw_ptr<spdy::Http2HeaderBlock> read_headers_buffer_; + raw_ptr<spdy::Http2HeaderBlock> read_headers_buffer_ = nullptr; // Callback to be invoked when ReadBody completes asynchronously. CompletionOnceCallback read_body_callback_; @@ -312,30 +312,30 @@ void NotifyHandleOfDataAvailable(); NetLogWithSource net_log_; - raw_ptr<Handle> handle_; + raw_ptr<Handle> handle_ = nullptr; // True when initial headers have been sent. - bool initial_headers_sent_; + bool initial_headers_sent_ = false; raw_ptr<quic::QuicSpdyClientSessionBase> session_; quic::QuicTransportVersion quic_version_; // Set to false if this stream should not be migrated to a cellular network // during connection migration. - bool can_migrate_to_cellular_network_; + bool can_migrate_to_cellular_network_ = true; // True if non-informational (non-1xx) initial headers have arrived. - bool initial_headers_arrived_; + bool initial_headers_arrived_ = false; // True if non-informational (non-1xx) initial headers have been delivered to // the handle. - bool headers_delivered_; + bool headers_delivered_ = false; // Stores the initial header until they are delivered to the handle. spdy::Http2HeaderBlock initial_headers_; // Length of the HEADERS frame containing initial headers. - size_t initial_headers_frame_len_; + size_t initial_headers_frame_len_ = 0; // Length of the HEADERS frame containing trailing headers. - size_t trailing_headers_frame_len_; + size_t trailing_headers_frame_len_ = 0; struct EarlyHints { EarlyHints(spdy::Http2HeaderBlock headers, size_t frame_len)
diff --git a/net/quic/quic_chromium_packet_writer.cc b/net/quic/quic_chromium_packet_writer.cc index a9c070cd..f1fcd2c 100644 --- a/net/quic/quic_chromium_packet_writer.cc +++ b/net/quic/quic_chromium_packet_writer.cc
@@ -81,18 +81,12 @@ std::memcpy(data(), buffer, buf_len); } -QuicChromiumPacketWriter::QuicChromiumPacketWriter() {} - QuicChromiumPacketWriter::QuicChromiumPacketWriter( DatagramClientSocket* socket, base::SequencedTaskRunner* task_runner) : socket_(socket), - delegate_(nullptr), - packet_( - base::MakeRefCounted<ReusableIOBuffer>(quic::kMaxOutgoingPacketSize)), - write_in_progress_(false), - force_write_blocked_(false), - retry_count_(0) { + packet_(base::MakeRefCounted<ReusableIOBuffer>( + quic::kMaxOutgoingPacketSize)) { retry_timer_.SetTaskRunner(task_runner); write_callback_ = base::BindRepeating( &QuicChromiumPacketWriter::OnWriteComplete, weak_factory_.GetWeakPtr());
diff --git a/net/quic/quic_chromium_packet_writer.h b/net/quic/quic_chromium_packet_writer.h index 1781d34..5535eef 100644 --- a/net/quic/quic_chromium_packet_writer.h +++ b/net/quic/quic_chromium_packet_writer.h
@@ -65,7 +65,6 @@ virtual void OnWriteUnblocked() = 0; }; - QuicChromiumPacketWriter(); // |socket| and |task_runner| must outlive writer. QuicChromiumPacketWriter(DatagramClientSocket* socket, base::SequencedTaskRunner* task_runner); @@ -112,7 +111,7 @@ void RetryPacketAfterNoBuffers(); quic::WriteResult WritePacketToSocketImpl(); raw_ptr<DatagramClientSocket> socket_; // Unowned. - raw_ptr<Delegate> delegate_; // Unowned. + raw_ptr<Delegate> delegate_ = nullptr; // Unowned. // Reused for every packet write for the lifetime of the writer. Is // moved to the delegate in the case of a write error. scoped_refptr<ReusableIOBuffer> packet_; @@ -120,13 +119,13 @@ // Whether a write is currently in progress: true if an asynchronous write is // in flight, or a retry of a previous write is in progress, or session is // handling write error of a previous write. - bool write_in_progress_; + bool write_in_progress_ = false; // If ture, IsWriteBlocked() will return true regardless of // |write_in_progress_|. - bool force_write_blocked_; + bool force_write_blocked_ = false; - int retry_count_; + int retry_count_ = 0; // Timer set when a packet should be retried after ENOBUFS. base::OneShotTimer retry_timer_;
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index f3ba9a4..dcbcaef 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -62,10 +62,6 @@ std::unique_ptr<QuicChromiumClientSession::Handle> session, std::set<std::string> dns_aliases) : MultiplexedHttpStream(std::move(session)), - stream_(nullptr), - request_info_(nullptr), - request_body_stream_(nullptr), - response_info_(nullptr), dns_aliases_(std::move(dns_aliases)) {} QuicHttpStream::~QuicHttpStream() {
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h index e4dfa0d0..d19f78d 100644 --- a/net/quic/quic_http_stream.h +++ b/net/quic/quic_http_stream.h
@@ -160,20 +160,20 @@ // The request to send. // Only valid before the response body is read. - raw_ptr<const HttpRequestInfo> request_info_; + raw_ptr<const HttpRequestInfo> request_info_ = nullptr; // Whether this request can be sent without confirmation. bool can_send_early_ = false; // The request body to send, if any, owned by the caller. - raw_ptr<UploadDataStream> request_body_stream_; + raw_ptr<UploadDataStream> request_body_stream_ = nullptr; // Time the request was issued. base::Time request_time_; // The priority of the request. RequestPriority priority_ = MINIMUM_PRIORITY; // |response_info_| is the HTTP response data object which is filled in // when a the response headers are read. It is not owned by this stream. - raw_ptr<HttpResponseInfo> response_info_; + raw_ptr<HttpResponseInfo> response_info_ = nullptr; bool has_response_status_ = false; // true if response_status_ as been set. // Because response data is buffered, also buffer the response status if the // stream is explicitly closed via OnError or OnClose with an error.
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc index 8f0471f..84e6718 100644 --- a/net/quic/quic_http_stream_test.cc +++ b/net/quic/quic_http_stream_test.cc
@@ -288,7 +288,6 @@ kDefaultServerHostName, quic::Perspective::IS_SERVER, false), - random_generator_(0), printer_(version_) { FLAGS_quic_enable_http3_grease_randomness = false; quic::QuicEnableVersion(version_); @@ -702,7 +701,7 @@ QuicTestPacketMaker server_maker_; IPEndPoint self_addr_; IPEndPoint peer_addr_; - quic::test::MockRandom random_generator_; + quic::test::MockRandom random_generator_{0}; ProofVerifyDetailsChromium verify_details_; MockCryptoClientStreamFactory crypto_client_stream_factory_; std::unique_ptr<StaticSocketDataProvider> socket_data_;
diff --git a/net/quic/quic_proxy_client_socket.cc b/net/quic/quic_proxy_client_socket.cc index 512e9879..3daf0ced 100644 --- a/net/quic/quic_proxy_client_socket.cc +++ b/net/quic/quic_proxy_client_socket.cc
@@ -33,7 +33,6 @@ ProxyDelegate* proxy_delegate) : stream_(std::move(stream)), session_(std::move(session)), - read_buf_(nullptr), endpoint_(endpoint), auth_(auth_controller), proxy_server_(proxy_server),
diff --git a/net/quic/quic_proxy_client_socket.h b/net/quic/quic_proxy_client_socket.h index 4a31834f..1bbf40d 100644 --- a/net/quic/quic_proxy_client_socket.h +++ b/net/quic/quic_proxy_client_socket.h
@@ -120,7 +120,7 @@ // Stores the callback for Read(). CompletionOnceCallback read_callback_; // Stores the read buffer pointer for Read(). - raw_ptr<IOBuffer> read_buf_; + raw_ptr<IOBuffer> read_buf_ = nullptr; // Stores the callback for Write(). CompletionOnceCallback write_callback_; // Stores the write buffer length for Write().
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc index fbad904c..49aeb05 100644 --- a/net/quic/quic_proxy_client_socket_unittest.cc +++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -184,7 +184,6 @@ kProxyHost, quic::Perspective::IS_SERVER, false), - random_generator_(0), user_agent_(kUserAgent), proxy_endpoint_(url::kHttpsScheme, kProxyHost, kProxyPort), destination_endpoint_(url::kHttpsScheme, kOriginHost, kOriginPort), @@ -637,7 +636,7 @@ QuicTestPacketMaker client_maker_; QuicTestPacketMaker server_maker_; IPEndPoint peer_addr_; - quic::test::MockRandom random_generator_; + quic::test::MockRandom random_generator_{0}; ProofVerifyDetailsChromium verify_details_; MockCryptoClientStreamFactory crypto_client_stream_factory_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 2ed3c62..0c2ed48 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -1171,7 +1171,6 @@ host_resolver_(host_resolver), client_socket_factory_(client_socket_factory), http_server_properties_(http_server_properties), - push_delegate_(nullptr), cert_verifier_(cert_verifier), ct_policy_enforcer_(ct_policy_enforcer), transport_security_state_(transport_security_state), @@ -1197,8 +1196,6 @@ kQuicYieldAfterDurationMilliseconds)), default_network_(NetworkChangeNotifier::kInvalidNetworkHandle), connectivity_monitor_(default_network_), - tick_clock_(nullptr), - task_runner_(nullptr), ssl_config_service_(ssl_config_service), use_network_isolation_key_for_crypto_configs_( base::FeatureList::IsEnabled(
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index 7151d302..c509693 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -521,7 +521,7 @@ raw_ptr<HostResolver> host_resolver_; raw_ptr<ClientSocketFactory> client_socket_factory_; raw_ptr<HttpServerProperties> http_server_properties_; - raw_ptr<ServerPushDelegate> push_delegate_; + raw_ptr<ServerPushDelegate> push_delegate_ = nullptr; const raw_ptr<CertVerifier> cert_verifier_; const raw_ptr<CTPolicyEnforcer> ct_policy_enforcer_; const raw_ptr<TransportSecurityState> transport_security_state_; @@ -608,9 +608,9 @@ QuicConnectivityMonitor connectivity_monitor_; - raw_ptr<const base::TickClock> tick_clock_; + raw_ptr<const base::TickClock> tick_clock_ = nullptr; - raw_ptr<base::SequencedTaskRunner> task_runner_; + raw_ptr<base::SequencedTaskRunner> task_runner_ = nullptr; const raw_ptr<SSLConfigService> ssl_config_service_;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 32370cf..79c9947 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -229,8 +229,6 @@ false), http_server_properties_(std::make_unique<HttpServerProperties>()), cert_verifier_(std::make_unique<MockCertVerifier>()), - scoped_mock_network_change_notifier_(nullptr), - factory_(nullptr), scheme_host_port_(url::kHttpsScheme, kDefaultServerHostName, kDefaultServerPort),
diff --git a/net/reporting/reporting_policy.cc b/net/reporting/reporting_policy.cc index 956db4137..bb895c5 100644 --- a/net/reporting/reporting_policy.cc +++ b/net/reporting/reporting_policy.cc
@@ -30,12 +30,7 @@ *owned_policy = policy; } -ReportingPolicy::ReportingPolicy() - : delivery_interval(base::Minutes(1)), - persistence_interval(base::Minutes(1)), - garbage_collection_interval(base::Minutes(5)), - max_report_age(base::Minutes(15)), - max_group_staleness(base::Days(7)) { +ReportingPolicy::ReportingPolicy() { endpoint_backoff_policy.num_errors_to_ignore = 0; endpoint_backoff_policy.initial_delay_ms = 60 * 1000; // 1 minute endpoint_backoff_policy.multiply_factor = 2.0;
diff --git a/net/reporting/reporting_policy.h b/net/reporting/reporting_policy.h index edecae7..4edf5781 100644 --- a/net/reporting/reporting_policy.h +++ b/net/reporting/reporting_policy.h
@@ -39,14 +39,14 @@ size_t max_endpoints_per_origin = 40u; // Minimum interval at which to attempt delivery of queued reports. - base::TimeDelta delivery_interval; + base::TimeDelta delivery_interval = base::Minutes(1); // Backoff policy for failing endpoints. BackoffEntry::Policy endpoint_backoff_policy; // Minimum interval at which Reporting will persist state to (relatively) // stable storage to be restored if the embedder restarts. - base::TimeDelta persistence_interval; + base::TimeDelta persistence_interval = base::Minutes(1); // Whether to persist undelivered reports across embedder restarts. bool persist_reports_across_restarts = false; @@ -56,13 +56,13 @@ bool persist_clients_across_restarts = true; // Minimum interval at which to garbage-collect the cache. - base::TimeDelta garbage_collection_interval; + base::TimeDelta garbage_collection_interval = base::Minutes(5); // Maximum age a report can be queued for before being discarded as expired. - base::TimeDelta max_report_age; + base::TimeDelta max_report_age = base::Minutes(15); // Maximum time an endpoint group can go unused before being deleted. - base::TimeDelta max_group_staleness; + base::TimeDelta max_group_staleness = base::Days(7); // Maximum number of delivery attempts a report can have before being // discarded as failed.
diff --git a/net/reporting/reporting_test_util.cc b/net/reporting/reporting_test_util.cc index d12ccf0..08cf7192 100644 --- a/net/reporting/reporting_test_util.cc +++ b/net/reporting/reporting_test_util.cc
@@ -191,7 +191,7 @@ garbage_collection_timer_ = nullptr; } -ReportingTestBase::ReportingTestBase() : store_(nullptr) { +ReportingTestBase::ReportingTestBase() { // For tests, disable jitter. ReportingPolicy policy; policy.endpoint_backoff_policy.jitter_factor = 0.0;
diff --git a/net/reporting/reporting_test_util.h b/net/reporting/reporting_test_util.h index 6c1353c..f25577d 100644 --- a/net/reporting/reporting_test_util.h +++ b/net/reporting/reporting_test_util.h
@@ -290,7 +290,7 @@ base::SimpleTestClock clock_; base::SimpleTestTickClock tick_clock_; std::unique_ptr<TestReportingContext> context_; - raw_ptr<ReportingCache::PersistentReportingStore> store_; + raw_ptr<ReportingCache::PersistentReportingStore> store_ = nullptr; }; class TestReportingService : public ReportingService {
diff --git a/net/server/http_connection.cc b/net/server/http_connection.cc index 73f4fe1bd..180e0a4 100644 --- a/net/server/http_connection.cc +++ b/net/server/http_connection.cc
@@ -13,8 +13,7 @@ namespace net { HttpConnection::ReadIOBuffer::ReadIOBuffer() - : base_(base::MakeRefCounted<GrowableIOBuffer>()), - max_buffer_size_(kDefaultMaxBufferSize) { + : base_(base::MakeRefCounted<GrowableIOBuffer>()) { SetCapacity(kInitialBufSize); } @@ -91,8 +90,7 @@ } } -HttpConnection::QueuedWriteIOBuffer::QueuedWriteIOBuffer() - : max_buffer_size_(kDefaultMaxBufferSize) {} +HttpConnection::QueuedWriteIOBuffer::QueuedWriteIOBuffer() = default; HttpConnection::QueuedWriteIOBuffer::~QueuedWriteIOBuffer() { data_ = nullptr; // pending_data_ owns data_.
diff --git a/net/server/http_connection.h b/net/server/http_connection.h index b59d1b8..9167f82 100644 --- a/net/server/http_connection.h +++ b/net/server/http_connection.h
@@ -64,7 +64,7 @@ ~ReadIOBuffer() override; scoped_refptr<GrowableIOBuffer> base_; - int max_buffer_size_; + int max_buffer_size_ = kDefaultMaxBufferSize; }; // IOBuffer of pending data to write which has a queue of pending data. Each @@ -110,7 +110,7 @@ // chunks, as they may be handed out via net::IOBuffer::data(). base::queue<std::unique_ptr<std::string>> pending_data_; int total_size_ = 0; - int max_buffer_size_; + int max_buffer_size_ = kDefaultMaxBufferSize; }; HttpConnection(int id, std::unique_ptr<StreamSocket> socket);
diff --git a/net/server/http_server_fuzzer.cc b/net/server/http_server_fuzzer.cc index f9c9c5e4..b091cc7 100644 --- a/net/server/http_server_fuzzer.cc +++ b/net/server/http_server_fuzzer.cc
@@ -19,8 +19,7 @@ public: WaitTillHttpCloseDelegate(FuzzedDataProvider* data_provider, base::OnceClosure done_closure) - : server_(nullptr), - data_provider_(data_provider), + : data_provider_(data_provider), done_closure_(std::move(done_closure)), action_flags_(data_provider_->ConsumeIntegral<uint8_t>()) {} @@ -89,7 +88,7 @@ CLOSE_WEBSOCKET_RATHER_THAN_ACCEPT = 16 }; - net::HttpServer* server_; + net::HttpServer* server_ = nullptr; FuzzedDataProvider* const data_provider_; base::OnceClosure done_closure_; const uint8_t action_flags_;
diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc index ea67618e..a48b18a0 100644 --- a/net/server/http_server_unittest.cc +++ b/net/server/http_server_unittest.cc
@@ -943,7 +943,7 @@ class MockStreamSocket : public StreamSocket { public: - MockStreamSocket() : read_buf_(nullptr) {} + MockStreamSocket() = default; MockStreamSocket(const MockStreamSocket&) = delete; MockStreamSocket& operator=(const MockStreamSocket&) = delete;
diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc index a51fea51..3204f6e 100644 --- a/net/socket/client_socket_handle.cc +++ b/net/socket/client_socket_handle.cc
@@ -21,9 +21,7 @@ namespace net { ClientSocketHandle::ClientSocketHandle() - : pool_(nullptr), - higher_pool_(nullptr), - resolve_error_info_(ResolveErrorInfo(OK)) {} + : resolve_error_info_(ResolveErrorInfo(OK)) {} ClientSocketHandle::~ClientSocketHandle() { Reset();
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h index 6f68a98..eeb9692 100644 --- a/net/socket/client_socket_handle.h +++ b/net/socket/client_socket_handle.h
@@ -229,8 +229,8 @@ void ResetErrorState(); bool is_initialized_ = false; - raw_ptr<ClientSocketPool> pool_; - raw_ptr<HigherLayeredPool> higher_pool_; + raw_ptr<ClientSocketPool> pool_ = nullptr; + raw_ptr<HigherLayeredPool> higher_pool_ = nullptr; std::unique_ptr<StreamSocket> socket_; ClientSocketPool::GroupId group_id_; SocketReuseType reuse_type_ = ClientSocketHandle::UNUSED;
diff --git a/net/socket/fuzzed_server_socket.cc b/net/socket/fuzzed_server_socket.cc index a5fc9dbe..82f4147 100644 --- a/net/socket/fuzzed_server_socket.cc +++ b/net/socket/fuzzed_server_socket.cc
@@ -15,10 +15,7 @@ FuzzedServerSocket::FuzzedServerSocket(FuzzedDataProvider* data_provider, net::NetLog* net_log) - : data_provider_(data_provider), - net_log_(net_log), - first_accept_(true), - listen_called_(false) {} + : data_provider_(data_provider), net_log_(net_log) {} FuzzedServerSocket::~FuzzedServerSocket() = default;
diff --git a/net/socket/fuzzed_server_socket.h b/net/socket/fuzzed_server_socket.h index 36249c3..e4ef3214 100644 --- a/net/socket/fuzzed_server_socket.h +++ b/net/socket/fuzzed_server_socket.h
@@ -51,8 +51,8 @@ net::NetLog* net_log_; IPEndPoint listening_on_; - bool first_accept_; - bool listen_called_; + bool first_accept_ = true; + bool listen_called_ = false; base::WeakPtrFactory<FuzzedServerSocket> weak_factory_{this}; };
diff --git a/net/socket/fuzzed_socket_factory.cc b/net/socket/fuzzed_socket_factory.cc index 65c749af..ec213e1 100644 --- a/net/socket/fuzzed_socket_factory.cc +++ b/net/socket/fuzzed_socket_factory.cc
@@ -107,7 +107,7 @@ } // namespace FuzzedSocketFactory::FuzzedSocketFactory(FuzzedDataProvider* data_provider) - : data_provider_(data_provider), fuzz_connect_result_(true) {} + : data_provider_(data_provider) {} FuzzedSocketFactory::~FuzzedSocketFactory() = default;
diff --git a/net/socket/fuzzed_socket_factory.h b/net/socket/fuzzed_socket_factory.h index 2dd91c5..25526d6 100644 --- a/net/socket/fuzzed_socket_factory.h +++ b/net/socket/fuzzed_socket_factory.h
@@ -61,7 +61,7 @@ private: FuzzedDataProvider* data_provider_; - bool fuzz_connect_result_; + bool fuzz_connect_result_ = true; }; } // namespace net
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index f9f41402..0bc5665c 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -353,11 +353,7 @@ SequencedSocketData::SequencedSocketData(base::span<const MockRead> reads, base::span<const MockWrite> writes) - : helper_(reads, writes), - sequence_number_(0), - read_state_(IoState::kIdle), - write_state_(IoState::kIdle), - busy_before_sync_reads_(false) { + : helper_(reads, writes) { // Check that reads and writes have a contiguous set of sequence numbers // starting from 0 and working their way up, with no repeats and skipping // no values. @@ -939,8 +935,7 @@ : MockClientSocket(NetLogWithSource::Make(net_log, NetLogSourceType::NONE)), addresses_(addresses), data_(data), - read_data_(SYNCHRONOUS, ERR_UNEXPECTED), - pending_read_buf_(nullptr) { + read_data_(SYNCHRONOUS, ERR_UNEXPECTED) { DCHECK(data_); peer_addr_ = data->connect_data().peer_addr; data_->Initialize(this); @@ -1504,8 +1499,6 @@ : data_(data), read_data_(SYNCHRONOUS, ERR_UNEXPECTED), source_host_(IPAddress(192, 0, 2, 33)), - network_(NetworkChangeNotifier::kInvalidNetworkHandle), - pending_read_buf_(nullptr), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::NONE)) { if (data_) { data_->Initialize(this);
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 788df9d..bacfd83c 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -592,11 +592,11 @@ StaticSocketDataHelper helper_; raw_ptr<SocketDataPrinter> printer_ = nullptr; - int sequence_number_; - IoState read_state_; - IoState write_state_; + int sequence_number_ = 0; + IoState read_state_ = IoState::kIdle; + IoState write_state_ = IoState::kIdle; - bool busy_before_sync_reads_; + bool busy_before_sync_reads_ = false; // Used by RunUntilPaused. NULL at all other times. std::unique_ptr<base::RunLoop> run_until_paused_run_loop_; @@ -847,7 +847,7 @@ bool peer_closed_connection_ = false; // While an asynchronous read is pending, we save our user-buffer state. - scoped_refptr<IOBuffer> pending_read_buf_; + scoped_refptr<IOBuffer> pending_read_buf_ = nullptr; int pending_read_buf_len_ = 0; CompletionOnceCallback pending_read_callback_; @@ -1045,10 +1045,11 @@ IPEndPoint peer_addr_; // Network that the socket is bound to. - NetworkChangeNotifier::NetworkHandle network_; + NetworkChangeNotifier::NetworkHandle network_ = + NetworkChangeNotifier::kInvalidNetworkHandle; // While an asynchronous IO is pending, we save our user-buffer state. - scoped_refptr<IOBuffer> pending_read_buf_; + scoped_refptr<IOBuffer> pending_read_buf_ = nullptr; int pending_read_buf_len_ = 0; CompletionOnceCallback pending_read_callback_; CompletionOnceCallback pending_write_callback_;
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc index 037fc4f3..6b25b06 100644 --- a/net/socket/tcp_client_socket.cc +++ b/net/socket/tcp_client_socket.cc
@@ -155,11 +155,6 @@ bind_address_(std::move(bind_address)), addresses_(addresses), current_address_index_(current_address_index), - next_connect_state_(CONNECT_STATE_NONE), - previously_disconnected_(false), - total_received_bytes_(0), - was_ever_used_(false), - was_disconnected_on_suspend_(false), network_quality_estimator_(network_quality_estimator), network_(network) { DCHECK(socket_);
diff --git a/net/socket/tcp_client_socket.h b/net/socket/tcp_client_socket.h index c28c797..891f36b2 100644 --- a/net/socket/tcp_client_socket.h +++ b/net/socket/tcp_client_socket.h
@@ -210,22 +210,22 @@ CompletionOnceCallback write_callback_; // The next state for the Connect() state machine. - ConnectState next_connect_state_; + ConnectState next_connect_state_ = CONNECT_STATE_NONE; // This socket was previously disconnected and has not been re-connected. - bool previously_disconnected_; + bool previously_disconnected_ = false; // Total number of bytes received by the socket. - int64_t total_received_bytes_; + int64_t total_received_bytes_ = 0; BeforeConnectCallback before_connect_callback_; - bool was_ever_used_; + bool was_ever_used_ = false; // Set to true if the socket was disconnected due to entering suspend mode. // Once set, read/write operations return ERR_NETWORK_IO_SUSPENDED, until // Connect() or Disconnect() is called. - bool was_disconnected_on_suspend_; + bool was_disconnected_on_suspend_ = false; // The time when the latest connect attempt was started. absl::optional<base::TimeTicks> start_connect_attempt_;
diff --git a/net/socket/tcp_server_socket.cc b/net/socket/tcp_server_socket.cc index 29929fc2..ea14a44 100644 --- a/net/socket/tcp_server_socket.cc +++ b/net/socket/tcp_server_socket.cc
@@ -24,7 +24,7 @@ source)) {} TCPServerSocket::TCPServerSocket(std::unique_ptr<TCPSocket> socket) - : socket_(std::move(socket)), pending_accept_(false) {} + : socket_(std::move(socket)) {} int TCPServerSocket::AdoptSocket(SocketDescriptor socket) { return socket_->AdoptUnconnectedSocket(socket);
diff --git a/net/socket/tcp_server_socket.h b/net/socket/tcp_server_socket.h index 3a6cf15..ae883b3 100644 --- a/net/socket/tcp_server_socket.h +++ b/net/socket/tcp_server_socket.h
@@ -71,7 +71,7 @@ std::unique_ptr<TCPSocket> accepted_socket_; IPEndPoint accepted_address_; - bool pending_accept_; + bool pending_accept_ = false; }; } // namespace net
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc index b400332..ad38540 100644 --- a/net/socket/tcp_socket_win.cc +++ b/net/socket/tcp_socket_win.cc
@@ -133,10 +133,10 @@ // The buffers used in Read() and Write(). scoped_refptr<IOBuffer> read_iobuffer_; scoped_refptr<IOBuffer> write_iobuffer_; - int read_buffer_length_; - int write_buffer_length_; + int read_buffer_length_ = 0; + int write_buffer_length_ = 0; - bool non_blocking_reads_initialized_; + bool non_blocking_reads_initialized_ = false; private: friend class base::RefCounted<Core>; @@ -183,9 +183,6 @@ TCPSocketWin::Core::Core(TCPSocketWin* socket) : read_event_(WSACreateEvent()), - read_buffer_length_(0), - write_buffer_length_(0), - non_blocking_reads_initialized_(false), socket_(socket), reader_(this), writer_(this) { @@ -263,13 +260,6 @@ : socket_(INVALID_SOCKET), socket_performance_watcher_(std::move(socket_performance_watcher)), accept_event_(WSA_INVALID_EVENT), - accept_socket_(nullptr), - accept_address_(nullptr), - waiting_connect_(false), - waiting_read_(false), - waiting_write_(false), - connect_os_error_(0), - logging_multiple_connect_attempts_(false), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) { net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source); EnsureWinsockInit();
diff --git a/net/socket/tcp_socket_win.h b/net/socket/tcp_socket_win.h index 8217c318..1b2ad4eb 100644 --- a/net/socket/tcp_socket_win.h +++ b/net/socket/tcp_socket_win.h
@@ -176,14 +176,14 @@ HANDLE accept_event_; base::win::ObjectWatcher accept_watcher_; - raw_ptr<std::unique_ptr<TCPSocketWin>> accept_socket_; - raw_ptr<IPEndPoint> accept_address_; + raw_ptr<std::unique_ptr<TCPSocketWin>> accept_socket_ = nullptr; + raw_ptr<IPEndPoint> accept_address_ = nullptr; CompletionOnceCallback accept_callback_; // The various states that the socket could be in. - bool waiting_connect_; - bool waiting_read_; - bool waiting_write_; + bool waiting_connect_ = false; + bool waiting_read_ = false; + bool waiting_write_ = false; // The core of the socket that can live longer than the socket itself. We pass // resources to the Windows async IO functions and we have to make sure that @@ -203,9 +203,9 @@ std::unique_ptr<IPEndPoint> peer_address_; // The OS error that a connect attempt last completed with. - int connect_os_error_; + int connect_os_error_ = 0; - bool logging_multiple_connect_attempts_; + bool logging_multiple_connect_attempts_ = false; NetLogWithSource net_log_;
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc index 0d57f2cb..8c11056 100644 --- a/net/socket/transport_client_socket_pool.cc +++ b/net/socket/transport_client_socket_pool.cc
@@ -92,8 +92,7 @@ socket_params_(std::move(socket_params)), proxy_annotation_tag_(proxy_annotation_tag), net_log_(net_log), - socket_tag_(socket_tag), - job_(nullptr) { + socket_tag_(socket_tag) { if (respect_limits_ == ClientSocketPool::RespectLimits::DISABLED) DCHECK_EQ(priority_, MAXIMUM_PRIORITY); } @@ -782,9 +781,6 @@ : ClientSocketPool(is_for_websockets, common_connect_job_params, std::move(connect_job_factory)), - idle_socket_count_(0), - connecting_socket_count_(0), - handed_out_socket_count_(0), max_sockets_(max_sockets), max_sockets_per_group_(max_sockets_per_group), unused_idle_socket_timeout_(unused_idle_socket_timeout),
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h index 60de4755..e215025 100644 --- a/net/socket/transport_client_socket_pool.h +++ b/net/socket/transport_client_socket_pool.h
@@ -143,7 +143,7 @@ const absl::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag_; const NetLogWithSource net_log_; const SocketTag socket_tag_; - raw_ptr<ConnectJob> job_; + raw_ptr<ConnectJob> job_ = nullptr; }; TransportClientSocketPool( @@ -764,13 +764,13 @@ PendingCallbackMap pending_callback_map_; // The total number of idle sockets in the system. - int idle_socket_count_; + int idle_socket_count_ = 0; // Number of connecting sockets across all groups. - int connecting_socket_count_; + int connecting_socket_count_ = 0; // Number of connected sockets we handed out across all groups. - int handed_out_socket_count_; + int handed_out_socket_count_ = 0; // The maximum total number of sockets. See ReachedMaxSocketsLimit. const int max_sockets_;
diff --git a/net/socket/udp_socket_global_limits.cc b/net/socket/udp_socket_global_limits.cc index 0163a7b..419d6a0 100644 --- a/net/socket/udp_socket_global_limits.cc +++ b/net/socket/udp_socket_global_limits.cc
@@ -16,7 +16,7 @@ // Threadsafe singleton for tracking the process-wide count of UDP sockets. class GlobalUDPSocketCounts { public: - GlobalUDPSocketCounts() : count_(0) {} + GlobalUDPSocketCounts() = default; ~GlobalUDPSocketCounts() = delete; @@ -47,7 +47,7 @@ int GetCountForTesting() { return count_.SubtleRefCountForDebug(); } private: - base::AtomicRefCount count_; + base::AtomicRefCount count_{0}; }; } // namespace
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc index 8dfabde..01fe429 100644 --- a/net/socket/udp_socket_posix.cc +++ b/net/socket/udp_socket_posix.cc
@@ -138,7 +138,6 @@ write_socket_watcher_(FROM_HERE), read_watcher_(this), write_watcher_(this), - recv_from_address_(nullptr), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)), bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle), always_update_bytes_received_(base::FeatureList::IsEnabled(
diff --git a/net/socket/udp_socket_posix.h b/net/socket/udp_socket_posix.h index 351c305..a19e304 100644 --- a/net/socket/udp_socket_posix.h +++ b/net/socket/udp_socket_posix.h
@@ -598,7 +598,7 @@ // The buffer used by InternalRead() to retry Read requests scoped_refptr<IOBuffer> read_buf_; int read_buf_len_ = 0; - raw_ptr<IPEndPoint> recv_from_address_; + raw_ptr<IPEndPoint> recv_from_address_ = nullptr; // The buffer used by InternalWrite() to retry Write requests scoped_refptr<IOBuffer> write_buf_;
diff --git a/net/socket/udp_socket_win.cc b/net/socket/udp_socket_win.cc index 53364dd..dec07ce8 100644 --- a/net/socket/udp_socket_win.cc +++ b/net/socket/udp_socket_win.cc
@@ -166,7 +166,7 @@ } //----------------------------------------------------------------------------- -QwaveApi::QwaveApi() : qwave_supported_(false) { +QwaveApi::QwaveApi() { HMODULE qwave = LoadLibrary(L"qwave.dll"); if (!qwave) return; @@ -243,15 +243,7 @@ net::NetLog* net_log, const net::NetLogSource& source) : socket_(INVALID_SOCKET), - addr_family_(0), - is_connected_(false), socket_options_(SOCKET_OPTION_MULTICAST_LOOP), - multicast_interface_(0), - multicast_time_to_live_(1), - use_non_blocking_io_(false), - read_iobuffer_len_(0), - write_iobuffer_len_(0), - recv_from_address_(nullptr), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)) { EnsureWinsockInit(); net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source);
diff --git a/net/socket/udp_socket_win.h b/net/socket/udp_socket_win.h index 0a50ac9..880f710 100644 --- a/net/socket/udp_socket_win.h +++ b/net/socket/udp_socket_win.h
@@ -99,7 +99,7 @@ LPOVERLAPPED overlapped); private: - std::atomic<bool> qwave_supported_; + std::atomic<bool> qwave_supported_{false}; CreateHandleFn create_handle_func_; CloseHandleFn close_handle_func_; @@ -430,19 +430,19 @@ virtual QwaveApi* GetQwaveApi() const; SOCKET socket_; - int addr_family_; - bool is_connected_; + int addr_family_ = 0; + bool is_connected_ = false; // Bitwise-or'd combination of SocketOptions. Specifies the set of // options that should be applied to |socket_| before Bind(). int socket_options_; // Multicast interface. - uint32_t multicast_interface_; + uint32_t multicast_interface_ = 0; // Multicast socket options cached for SetMulticastOption. // Cannot be used after Bind(). - int multicast_time_to_live_; + int multicast_time_to_live_ = 1; // These are mutable since they're just cached copies to make // GetPeerAddress/GetLocalAddress smarter. @@ -455,7 +455,7 @@ scoped_refptr<Core> core_; // True if non-blocking IO is used. - bool use_non_blocking_io_; + bool use_non_blocking_io_ = false; // Watches |read_write_event_|. base::win::ObjectWatcher read_write_watcher_; @@ -467,10 +467,10 @@ scoped_refptr<IOBuffer> read_iobuffer_; scoped_refptr<IOBuffer> write_iobuffer_; - int read_iobuffer_len_; - int write_iobuffer_len_; + int read_iobuffer_len_ = 0; + int write_iobuffer_len_ = 0; - raw_ptr<IPEndPoint> recv_from_address_; + raw_ptr<IPEndPoint> recv_from_address_ = nullptr; // Cached copy of the current address we're sending to, if any. Used for // logging.
diff --git a/net/spdy/bidirectional_stream_spdy_impl.cc b/net/spdy/bidirectional_stream_spdy_impl.cc index 4b443a4b..bb16279 100644 --- a/net/spdy/bidirectional_stream_spdy_impl.cc +++ b/net/spdy/bidirectional_stream_spdy_impl.cc
@@ -32,10 +32,7 @@ BidirectionalStreamSpdyImpl::BidirectionalStreamSpdyImpl( const base::WeakPtr<SpdySession>& spdy_session, NetLogSource source_dependency) - : spdy_session_(spdy_session), - request_info_(nullptr), - delegate_(nullptr), - source_dependency_(source_dependency) {} + : spdy_session_(spdy_session), source_dependency_(source_dependency) {} BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() { // Sends a RST to the remote if the stream is destroyed before it completes.
diff --git a/net/spdy/bidirectional_stream_spdy_impl.h b/net/spdy/bidirectional_stream_spdy_impl.h index 41ef997..a5e2dcc 100644 --- a/net/spdy/bidirectional_stream_spdy_impl.h +++ b/net/spdy/bidirectional_stream_spdy_impl.h
@@ -91,8 +91,8 @@ bool MaybeHandleStreamClosedInSendData(); const base::WeakPtr<SpdySession> spdy_session_; - raw_ptr<const BidirectionalStreamRequestInfo> request_info_; - raw_ptr<BidirectionalStreamImpl::Delegate> delegate_; + raw_ptr<const BidirectionalStreamRequestInfo> request_info_ = nullptr; + raw_ptr<BidirectionalStreamImpl::Delegate> delegate_ = nullptr; std::unique_ptr<base::OneShotTimer> timer_; SpdyStreamRequest stream_request_; base::WeakPtr<SpdyStream> stream_;
diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc index 94d6338..eb6c340 100644 --- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc +++ b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
@@ -75,8 +75,7 @@ : stream_(std::make_unique<BidirectionalStreamSpdyImpl>(session, NetLogSource())), read_buf_(read_buf), - read_buf_len_(read_buf_len), - loop_(nullptr) {} + read_buf_len_(read_buf_len) {} TestDelegateBase(const TestDelegateBase&) = delete; TestDelegateBase& operator=(const TestDelegateBase&) = delete;
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc index 913efea..d0502c2c 100644 --- a/net/spdy/buffered_spdy_framer.cc +++ b/net/spdy/buffered_spdy_framer.cc
@@ -25,7 +25,6 @@ const NetLogWithSource& net_log, TimeFunc time_func) : spdy_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION), - visitor_(nullptr), max_header_list_size_(max_header_list_size), net_log_(net_log), time_func_(time_func) {
diff --git a/net/spdy/buffered_spdy_framer.h b/net/spdy/buffered_spdy_framer.h index 7679ca6..08ca82b42 100644 --- a/net/spdy/buffered_spdy_framer.h +++ b/net/spdy/buffered_spdy_framer.h
@@ -250,7 +250,7 @@ private: spdy::SpdyFramer spdy_framer_; http2::Http2DecoderAdapter deframer_; - raw_ptr<BufferedSpdyFramerVisitorInterface> visitor_; + raw_ptr<BufferedSpdyFramerVisitorInterface> visitor_ = nullptr; int frames_received_ = 0;
diff --git a/net/spdy/spdy_buffer.cc b/net/spdy/spdy_buffer.cc index e8148c9..aaf447e 100644 --- a/net/spdy/spdy_buffer.cc +++ b/net/spdy/spdy_buffer.cc
@@ -60,13 +60,12 @@ }; SpdyBuffer::SpdyBuffer(std::unique_ptr<spdy::SpdySerializedFrame> frame) - : shared_frame_(new SharedFrame(std::move(frame))), offset_(0) {} + : shared_frame_(new SharedFrame(std::move(frame))) {} // The given data may not be strictly a SPDY frame; we (ab)use // |frame_| just as a container. -SpdyBuffer::SpdyBuffer(const char* data, size_t size) : - shared_frame_(new SharedFrame()), - offset_(0) { +SpdyBuffer::SpdyBuffer(const char* data, size_t size) + : shared_frame_(new SharedFrame()) { CHECK_GT(size, 0u); CHECK_LE(size, kMaxSpdyFrameSize); shared_frame_->data = MakeSpdySerializedFrame(data, size);
diff --git a/net/spdy/spdy_buffer.h b/net/spdy/spdy_buffer.h index 4abe9d9..4b8337c4 100644 --- a/net/spdy/spdy_buffer.h +++ b/net/spdy/spdy_buffer.h
@@ -100,7 +100,7 @@ const scoped_refptr<SharedFrame> shared_frame_; std::vector<ConsumeCallback> consume_callbacks_; - size_t offset_; + size_t offset_ = 0; }; } // namespace net
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index dd9588c..be3c2d7 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc
@@ -110,8 +110,6 @@ pushed_stream_id_(pushed_stream_id), is_reused_(spdy_session_->IsReused()), source_dependency_(source_dependency), - request_info_(nullptr), - response_info_(nullptr), dns_aliases_(std::move(dns_aliases)) { DCHECK(spdy_session_.get()); }
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h index 513b3d6..761271b 100644 --- a/net/spdy/spdy_http_stream.h +++ b/net/spdy/spdy_http_stream.h
@@ -189,12 +189,12 @@ // |this| to be shared for reading and to possibly outlive request_info_'s // owner. Setting to null happens after headers are completely read or upload // data stream is uploaded, whichever is later. - raw_ptr<const HttpRequestInfo> request_info_; + raw_ptr<const HttpRequestInfo> request_info_ = nullptr; // |response_info_| is the HTTP response data object which is filled in // when a response HEADERS comes in for the stream. // It is not owned by this stream object, or point to |push_response_info_|. - raw_ptr<HttpResponseInfo> response_info_; + raw_ptr<HttpResponseInfo> response_info_ = nullptr; std::unique_ptr<HttpResponseInfo> push_response_info_;
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index 5ac00e8..9aa415b 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -219,8 +219,7 @@ }; SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() - : read_buf_(nullptr), - connect_data_(SYNCHRONOUS, OK), + : connect_data_(SYNCHRONOUS, OK), user_agent_(kUserAgent), url_(kRequestUrl), proxy_host_port_(kProxyHost, kProxyPort),
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index fe41ff9..05ff79b123 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -936,11 +936,9 @@ NetworkQualityEstimator* network_quality_estimator, NetLog* net_log) : spdy_session_key_(spdy_session_key), - pool_(nullptr), http_server_properties_(http_server_properties), transport_security_state_(transport_security_state), ssl_config_service_(ssl_config_service), - socket_(nullptr), stream_hi_water_mark_(kFirstStreamId), push_delegate_(push_delegate), initial_settings_(initial_settings),
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index e3437454..8bd21fe 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -1086,7 +1086,7 @@ std::set<SpdySessionKey> pooled_aliases_; // |pool_| owns us, therefore its lifetime must exceed ours. - raw_ptr<SpdySessionPool> pool_; + raw_ptr<SpdySessionPool> pool_ = nullptr; raw_ptr<HttpServerProperties> http_server_properties_; raw_ptr<TransportSecurityState> transport_security_state_; @@ -1103,7 +1103,7 @@ std::unique_ptr<LoadTimingInfo::ConnectTiming> connect_timing_; // The socket for this session. - raw_ptr<StreamSocket> socket_; + raw_ptr<StreamSocket> socket_ = nullptr; // The read buffer used to read data from the socket. // Non-null if there is a Read() pending.
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index 46766de..d2a243c 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc
@@ -112,7 +112,6 @@ enable_priority_update_(enable_priority_update), go_away_on_ip_change_(go_away_on_ip_change), time_func_(time_func), - push_delegate_(nullptr), network_quality_estimator_(network_quality_estimator), cleanup_sessions_on_ip_address_changed_( cleanup_sessions_on_ip_address_changed) {
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 2ba3a0f..1778261 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h
@@ -493,7 +493,7 @@ SpdySessionRequestMap spdy_session_request_map_; TimeFunc time_func_; - raw_ptr<ServerPushDelegate> push_delegate_; + raw_ptr<ServerPushDelegate> push_delegate_ = nullptr; raw_ptr<NetworkQualityEstimator> network_quality_estimator_;
diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc index ccf9fab..6c039ec 100644 --- a/net/spdy/spdy_session_pool_unittest.cc +++ b/net/spdy/spdy_session_pool_unittest.cc
@@ -62,7 +62,7 @@ SPDY_POOL_CLOSE_IDLE_SESSIONS, }; - SpdySessionPoolTest() : spdy_session_pool_(nullptr) {} + SpdySessionPoolTest() = default; void CreateNetworkSession() { http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); @@ -91,7 +91,7 @@ SpdySessionDependencies session_deps_; std::unique_ptr<HttpNetworkSession> http_session_; - raw_ptr<SpdySessionPool> spdy_session_pool_; + raw_ptr<SpdySessionPool> spdy_session_pool_ = nullptr; std::vector<std::unique_ptr<SSLSocketDataProvider>> ssl_data_vector_; };
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index 54a53a5..47e91154 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -176,8 +176,6 @@ HttpNetworkSession::NORMAL_SOCKET_POOL)), old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( HttpNetworkSession::NORMAL_SOCKET_POOL)), - test_push_delegate_(nullptr), - spdy_session_pool_(nullptr), test_url_(kDefaultUrl), test_server_(test_url_), key_(HostPortPair::FromURL(test_url_), @@ -391,8 +389,8 @@ SpdySessionDependencies session_deps_; std::unique_ptr<HttpNetworkSession> http_session_; base::WeakPtr<SpdySession> session_; - raw_ptr<TestServerPushDelegate> test_push_delegate_; - raw_ptr<SpdySessionPool> spdy_session_pool_; + raw_ptr<TestServerPushDelegate> test_push_delegate_ = nullptr; + raw_ptr<SpdySessionPool> spdy_session_pool_ = nullptr; const GURL test_url_; const url::SchemeHostPort test_server_; SpdySessionKey key_;
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index 160439cc..c437d83 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc
@@ -107,7 +107,6 @@ recv_window_size_(max_recv_window_size), last_recv_window_update_(base::TimeTicks::Now()), session_(session), - delegate_(nullptr), request_time_(base::Time::Now()), net_log_(net_log), traffic_annotation_(traffic_annotation),
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 4cc771a..fb69c4b 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h
@@ -504,7 +504,7 @@ const base::WeakPtr<SpdySession> session_; // The transaction should own the delegate. - raw_ptr<SpdyStream::Delegate> delegate_; + raw_ptr<SpdyStream::Delegate> delegate_ = nullptr; // The headers for the request to send. bool request_headers_valid_ = false;
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index f7f3305..578ebbf 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -308,28 +308,7 @@ http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()), http_server_properties(std::make_unique<HttpServerProperties>()), quic_context(std::make_unique<QuicContext>()), - enable_ip_pooling(true), - enable_ping(false), - enable_user_alternate_protocol_ports(false), - enable_quic(false), - enable_server_push_cancellation(false), - session_max_recv_window_size(kDefaultInitialWindowSize), - session_max_queued_capped_frames(kSpdySessionMaxQueuedCappedFrames), - time_func(&base::TimeTicks::Now), - enable_http2_alternative_service(false), - enable_http2_settings_grease(false), - http2_end_stream_with_data_frame(false), - net_log(nullptr), - disable_idle_sockets_close_on_memory_pressure(false), - enable_early_data(false), - key_auth_cache_server_entries_by_network_isolation_key(false), - enable_priority_update(false), -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS) - go_away_on_ip_change(true), -#else - go_away_on_ip_change(false), -#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS) - ignore_ip_address_changes(false) { + time_func(&base::TimeTicks::Now) { http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = kDefaultInitialWindowSize; }
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index 5c9f9df..8b3af77 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -195,26 +195,30 @@ std::unique_ptr<ReportingService> reporting_service; std::unique_ptr<NetworkErrorLoggingService> network_error_logging_service; #endif - bool enable_ip_pooling; - bool enable_ping; - bool enable_user_alternate_protocol_ports; - bool enable_quic; - bool enable_server_push_cancellation; - size_t session_max_recv_window_size; - int session_max_queued_capped_frames; + bool enable_ip_pooling = true; + bool enable_ping = false; + bool enable_user_alternate_protocol_ports = false; + bool enable_quic = false; + bool enable_server_push_cancellation = false; + size_t session_max_recv_window_size = kDefaultInitialWindowSize; + int session_max_queued_capped_frames = kSpdySessionMaxQueuedCappedFrames; spdy::SettingsMap http2_settings; SpdySession::TimeFunc time_func; - bool enable_http2_alternative_service; - bool enable_http2_settings_grease; + bool enable_http2_alternative_service = false; + bool enable_http2_settings_grease = false; absl::optional<SpdySessionPool::GreasedHttp2Frame> greased_http2_frame; - bool http2_end_stream_with_data_frame; - raw_ptr<NetLog> net_log; - bool disable_idle_sockets_close_on_memory_pressure; - bool enable_early_data; - bool key_auth_cache_server_entries_by_network_isolation_key; - bool enable_priority_update; - bool go_away_on_ip_change; - bool ignore_ip_address_changes; + bool http2_end_stream_with_data_frame = false; + raw_ptr<NetLog> net_log = nullptr; + bool disable_idle_sockets_close_on_memory_pressure = false; + bool enable_early_data = false; + bool key_auth_cache_server_entries_by_network_isolation_key = false; + bool enable_priority_update = false; +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS) + bool go_away_on_ip_change = true; +#else + bool go_away_on_ip_change = false; +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS) + bool ignore_ip_address_changes = false; }; std::unique_ptr<URLRequestContextBuilder>
diff --git a/net/ssl/ssl_server_config.cc b/net/ssl/ssl_server_config.cc index 425d326b..b712c0fd 100644 --- a/net/ssl/ssl_server_config.cc +++ b/net/ssl/ssl_server_config.cc
@@ -10,10 +10,7 @@ namespace net { -SSLServerConfig::SSLServerConfig() - : version_min(kDefaultSSLVersionMin), - version_max(kDefaultSSLVersionMax), - client_cert_verifier(nullptr) {} +SSLServerConfig::SSLServerConfig() = default; SSLServerConfig::SSLServerConfig(const SSLServerConfig& other) = default;
diff --git a/net/ssl/ssl_server_config.h b/net/ssl/ssl_server_config.h index 520a8642..8ffc9d9 100644 --- a/net/ssl/ssl_server_config.h +++ b/net/ssl/ssl_server_config.h
@@ -40,8 +40,8 @@ // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined in ssl_config.h) // SSL 2.0 and SSL 3.0 are not supported. If version_max < version_min, it // means no protocol versions are enabled. - uint16_t version_min; - uint16_t version_max; + uint16_t version_min = kDefaultSSLVersionMin; + uint16_t version_max = kDefaultSSLVersionMax; // Whether early data is enabled on this connection. The caller is obligated // to reject early data that is non-safe to be replayed. @@ -101,7 +101,7 @@ // and must outlive any sockets spawned from this SSLServerContext. // This field is meaningful only if client certificates are requested. // If a verifier is not provided then all certificates are accepted. - raw_ptr<ClientCertVerifier> client_cert_verifier; + raw_ptr<ClientCertVerifier> client_cert_verifier = nullptr; // The list of application level protocols supported with ALPN (Application // Layer Protocol Negotiation), in decreasing order of preference. Protocols
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc index c259a58..9a278a8 100644 --- a/net/test/embedded_test_server/embedded_test_server.cc +++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -277,11 +277,7 @@ EmbeddedTestServer::EmbeddedTestServer(Type type, HttpConnection::Protocol protocol) - : is_using_ssl_(type == TYPE_HTTPS), - protocol_(protocol), - connection_listener_(nullptr), - port_(0), - cert_(CERT_OK) { + : is_using_ssl_(type == TYPE_HTTPS), protocol_(protocol) { DCHECK(thread_checker_.CalledOnValidThread()); // HTTP/2 is only valid by negotiation via TLS ALPN DCHECK(protocol_ != HttpConnection::Protocol::kHttp2 || type == TYPE_HTTPS);
diff --git a/net/test/embedded_test_server/embedded_test_server.h b/net/test/embedded_test_server/embedded_test_server.h index 7c5fa125..711d0e9 100644 --- a/net/test/embedded_test_server/embedded_test_server.h +++ b/net/test/embedded_test_server/embedded_test_server.h
@@ -571,8 +571,8 @@ std::unique_ptr<TCPServerSocket> listen_socket_; std::unique_ptr<StreamSocket> accepted_socket_; - raw_ptr<EmbeddedTestServerConnectionListener> connection_listener_; - uint16_t port_; + raw_ptr<EmbeddedTestServerConnectionListener> connection_listener_ = nullptr; + uint16_t port_ = 0; GURL base_url_; IPEndPoint local_endpoint_; @@ -586,7 +586,7 @@ base::ThreadChecker thread_checker_; net::SSLServerConfig ssl_config_; - ServerCertificate cert_; + ServerCertificate cert_ = CERT_OK; ServerCertificateConfig cert_config_; scoped_refptr<X509Certificate> x509_cert_; bssl::UniquePtr<EVP_PKEY> private_key_;
diff --git a/net/test/url_request/url_request_failed_job.cc b/net/test/url_request/url_request_failed_job.cc index b249abe..ec93428 100644 --- a/net/test/url_request/url_request_failed_job.cc +++ b/net/test/url_request/url_request_failed_job.cc
@@ -79,10 +79,7 @@ URLRequestFailedJob::URLRequestFailedJob(URLRequest* request, FailurePhase phase, int net_error) - : URLRequestJob(request), - phase_(phase), - net_error_(net_error), - total_received_bytes_(0) { + : URLRequestJob(request), phase_(phase), net_error_(net_error) { CHECK_GE(phase, URLRequestFailedJob::FailurePhase::START); CHECK_LE(phase, URLRequestFailedJob::FailurePhase::READ_ASYNC); CHECK_LT(net_error, OK);
diff --git a/net/test/url_request/url_request_failed_job.h b/net/test/url_request/url_request_failed_job.h index 86606e68..82f91ba0 100644 --- a/net/test/url_request/url_request_failed_job.h +++ b/net/test/url_request/url_request_failed_job.h
@@ -80,7 +80,7 @@ HttpResponseInfo response_info_; const FailurePhase phase_; const int net_error_; - int64_t total_received_bytes_; + int64_t total_received_bytes_ = 0; base::WeakPtrFactory<URLRequestFailedJob> weak_factory_{this}; };
diff --git a/net/url_request/test_url_fetcher_factory.cc b/net/url_request/test_url_fetcher_factory.cc index 321e1013..76af817 100644 --- a/net/url_request/test_url_fetcher_factory.cc +++ b/net/url_request/test_url_fetcher_factory.cc
@@ -42,7 +42,7 @@ } TestURLFetcher::TestURLFetcher(int id, const GURL& url, URLFetcherDelegate* d) - : id_(id), original_url_(url), delegate_(d), delegate_for_tests_(nullptr) { + : id_(id), original_url_(url), delegate_(d) { CHECK(original_url_.is_valid()); }
diff --git a/net/url_request/test_url_fetcher_factory.h b/net/url_request/test_url_fetcher_factory.h index c75f208..412c151 100644 --- a/net/url_request/test_url_fetcher_factory.h +++ b/net/url_request/test_url_fetcher_factory.h
@@ -213,7 +213,7 @@ const int id_; const GURL original_url_; raw_ptr<URLFetcherDelegate> delegate_; - raw_ptr<DelegateForTests> delegate_for_tests_; + raw_ptr<DelegateForTests> delegate_for_tests_ = nullptr; std::string upload_content_type_; std::string upload_data_; base::FilePath upload_file_path_;
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc index 22b58be..05fd10c 100644 --- a/net/url_request/url_fetcher_core.cc +++ b/net/url_request/url_fetcher_core.cc
@@ -84,7 +84,6 @@ delegate_(d), delegate_task_runner_(base::SequencedTaskRunnerHandle::Get()), allow_credentials_(absl::nullopt), - url_request_data_key_(nullptr), traffic_annotation_(traffic_annotation) { CHECK(original_url_.is_valid()); }
diff --git a/net/url_request/url_fetcher_core.h b/net/url_request/url_fetcher_core.h index 3d37e01..e0305399 100644 --- a/net/url_request/url_fetcher_core.h +++ b/net/url_request/url_fetcher_core.h
@@ -265,7 +265,7 @@ // Cookie/cache info for the request absl::optional<url::Origin> initiator_; // The request's initiator // The user data to add to each newly-created URLRequest. - raw_ptr<const void> url_request_data_key_; + raw_ptr<const void> url_request_data_key_ = nullptr; URLFetcher::CreateDataCallback url_request_create_data_callback_; HttpRequestHeaders extra_request_headers_; scoped_refptr<HttpResponseHeaders> response_headers_;
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index 0c0847c..f14a84e 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc
@@ -31,32 +31,8 @@ URLRequestContext::URLRequestContext( base::PassKey<URLRequestContextBuilder> pass_key) - : net_log_(nullptr), - host_resolver_(nullptr), - cert_verifier_(nullptr), - http_auth_handler_factory_(nullptr), - proxy_resolution_service_(nullptr), - proxy_delegate_(nullptr), - ssl_config_service_(nullptr), - network_delegate_(nullptr), - http_server_properties_(nullptr), - http_user_agent_settings_(nullptr), - cookie_store_(nullptr), - transport_security_state_(nullptr), - ct_policy_enforcer_(nullptr), - sct_auditing_delegate_(nullptr), - http_transaction_factory_(nullptr), - job_factory_(nullptr), - throttler_manager_(nullptr), - quic_context_(nullptr), - network_quality_estimator_(nullptr), -#if BUILDFLAG(ENABLE_REPORTING) - reporting_service_(nullptr), - network_error_logging_service_(nullptr), -#endif // BUILDFLAG(ENABLE_REPORTING) - url_requests_(std::make_unique<std::set<const URLRequest*>>()), - bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle) { -} + : url_requests_(std::make_unique<std::set<const URLRequest*>>()), + bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle) {} URLRequestContext::~URLRequestContext() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index 9da6d7e..7795b871 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h
@@ -325,28 +325,28 @@ // Ownership for these members are not defined here. Clients should either // provide storage elsewhere or have a subclass take ownership. - raw_ptr<NetLog> net_log_; - raw_ptr<HostResolver> host_resolver_; - raw_ptr<CertVerifier> cert_verifier_; - raw_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_; - raw_ptr<ProxyResolutionService> proxy_resolution_service_; - raw_ptr<ProxyDelegate> proxy_delegate_; - raw_ptr<SSLConfigService> ssl_config_service_; - raw_ptr<NetworkDelegate> network_delegate_; - raw_ptr<HttpServerProperties> http_server_properties_; - raw_ptr<const HttpUserAgentSettings> http_user_agent_settings_; - raw_ptr<CookieStore> cookie_store_; - raw_ptr<TransportSecurityState> transport_security_state_; - raw_ptr<CTPolicyEnforcer> ct_policy_enforcer_; - raw_ptr<SCTAuditingDelegate> sct_auditing_delegate_; - raw_ptr<HttpTransactionFactory> http_transaction_factory_; - raw_ptr<const URLRequestJobFactory> job_factory_; - raw_ptr<URLRequestThrottlerManager> throttler_manager_; - raw_ptr<QuicContext> quic_context_; - raw_ptr<NetworkQualityEstimator> network_quality_estimator_; + raw_ptr<NetLog> net_log_ = nullptr; + raw_ptr<HostResolver> host_resolver_ = nullptr; + raw_ptr<CertVerifier> cert_verifier_ = nullptr; + raw_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_ = nullptr; + raw_ptr<ProxyResolutionService> proxy_resolution_service_ = nullptr; + raw_ptr<ProxyDelegate> proxy_delegate_ = nullptr; + raw_ptr<SSLConfigService> ssl_config_service_ = nullptr; + raw_ptr<NetworkDelegate> network_delegate_ = nullptr; + raw_ptr<HttpServerProperties> http_server_properties_ = nullptr; + raw_ptr<const HttpUserAgentSettings> http_user_agent_settings_ = nullptr; + raw_ptr<CookieStore> cookie_store_ = nullptr; + raw_ptr<TransportSecurityState> transport_security_state_ = nullptr; + raw_ptr<CTPolicyEnforcer> ct_policy_enforcer_ = nullptr; + raw_ptr<SCTAuditingDelegate> sct_auditing_delegate_ = nullptr; + raw_ptr<HttpTransactionFactory> http_transaction_factory_ = nullptr; + raw_ptr<const URLRequestJobFactory> job_factory_ = nullptr; + raw_ptr<URLRequestThrottlerManager> throttler_manager_ = nullptr; + raw_ptr<QuicContext> quic_context_ = nullptr; + raw_ptr<NetworkQualityEstimator> network_quality_estimator_ = nullptr; #if BUILDFLAG(ENABLE_REPORTING) - raw_ptr<ReportingService> reporting_service_; - raw_ptr<NetworkErrorLoggingService> network_error_logging_service_; + raw_ptr<ReportingService> reporting_service_ = nullptr; + raw_ptr<NetworkErrorLoggingService> network_error_logging_service_ = nullptr; #endif // BUILDFLAG(ENABLE_REPORTING) std::unique_ptr<std::set<const URLRequest*>> url_requests_;
diff --git a/net/url_request/url_request_filter_unittest.cc b/net/url_request/url_request_filter_unittest.cc index 2f653dc..c330f61 100644 --- a/net/url_request/url_request_filter_unittest.cc +++ b/net/url_request/url_request_filter_unittest.cc
@@ -26,7 +26,7 @@ class TestURLRequestInterceptor : public URLRequestInterceptor { public: - TestURLRequestInterceptor() : job_(nullptr) {} + TestURLRequestInterceptor() = default; TestURLRequestInterceptor(const TestURLRequestInterceptor&) = delete; TestURLRequestInterceptor& operator=(const TestURLRequestInterceptor&) = @@ -47,7 +47,7 @@ } private: - mutable raw_ptr<URLRequestTestJob> job_; + mutable raw_ptr<URLRequestTestJob> job_ = nullptr; }; TEST(URLRequestFilter, BasicMatching) {
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index d170e20..1975492c 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -229,8 +229,6 @@ URLRequest* request, const HttpUserAgentSettings* http_user_agent_settings) : URLRequestJob(request), - response_info_(nullptr), - throttling_entry_(nullptr), http_user_agent_settings_(http_user_agent_settings) { URLRequestThrottlerManager* manager = request->context()->throttler_manager(); if (manager)
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 7bc5cf5..10516a902 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -232,7 +232,7 @@ RequestPriority priority_ = DEFAULT_PRIORITY; HttpRequestInfo request_info_; - raw_ptr<const HttpResponseInfo> response_info_; + raw_ptr<const HttpResponseInfo> response_info_ = nullptr; // Used for any logic, e.g. DNS-based scheme upgrade, that needs to synthesize // response info to override the real response info. Transaction should be
diff --git a/net/url_request/url_request_test_job.cc b/net/url_request/url_request_test_job.cc index d4105a4c..f2578e40 100644 --- a/net/url_request/url_request_test_job.cc +++ b/net/url_request/url_request_test_job.cc
@@ -130,13 +130,7 @@ URLRequestTestJob::URLRequestTestJob(URLRequest* request, bool auto_advance) : URLRequestJob(request), auto_advance_(auto_advance), - stage_(WAITING), - priority_(DEFAULT_PRIORITY), - offset_(0), - async_buf_(nullptr), - async_buf_size_(0), - response_headers_length_(0), - async_reads_(false) {} + response_headers_length_(0) {} URLRequestTestJob::URLRequestTestJob(URLRequest* request, const std::string& response_headers, @@ -144,16 +138,10 @@ bool auto_advance) : URLRequestJob(request), auto_advance_(auto_advance), - stage_(WAITING), - priority_(DEFAULT_PRIORITY), response_data_(response_data), - offset_(0), - async_buf_(nullptr), - async_buf_size_(0), response_headers_(base::MakeRefCounted<net::HttpResponseHeaders>( net::HttpUtil::AssembleRawHeaders(response_headers))), - response_headers_length_(response_headers.size()), - async_reads_(false) {} + response_headers_length_(response_headers.size()) {} URLRequestTestJob::~URLRequestTestJob() { base::Erase(g_pending_jobs.Get(), this);
diff --git a/net/url_request/url_request_test_job.h b/net/url_request/url_request_test_job.h index 6969cb8..d405ed7 100644 --- a/net/url_request/url_request_test_job.h +++ b/net/url_request/url_request_test_job.h
@@ -161,20 +161,20 @@ bool auto_advance_; - Stage stage_; + Stage stage_ = WAITING; - RequestPriority priority_; + RequestPriority priority_ = DEFAULT_PRIORITY; // The data to send, will be set in Start() if not provided in the explicit // ctor. std::string response_data_; // current offset within response_data_ - int offset_; + int offset_ = 0; // Holds the buffer for an asynchronous ReadRawData call - raw_ptr<IOBuffer> async_buf_; - int async_buf_size_; + raw_ptr<IOBuffer> async_buf_ = nullptr; + int async_buf_size_ = 0; LoadTimingInfo load_timing_info_; @@ -186,7 +186,7 @@ // Original size in bytes of the response headers before decoding. int response_headers_length_; - bool async_reads_; + bool async_reads_ = false; base::WeakPtrFactory<URLRequestTestJob> weak_factory_{this}; };
diff --git a/net/url_request/url_request_throttler_entry.cc b/net/url_request/url_request_throttler_entry.cc index ea55370..c7f4469 100644 --- a/net/url_request/url_request_throttler_entry.cc +++ b/net/url_request/url_request_throttler_entry.cc
@@ -67,7 +67,6 @@ const std::string& url_id) : sliding_window_period_(base::Milliseconds(kDefaultSlidingWindowPeriodMs)), max_send_threshold_(kDefaultMaxSendThreshold), - is_backoff_disabled_(false), backoff_entry_(&backoff_policy_), manager_(manager), url_id_(url_id), @@ -89,7 +88,6 @@ int maximum_backoff_ms) : sliding_window_period_(base::Milliseconds(sliding_window_period_ms)), max_send_threshold_(max_send_threshold), - is_backoff_disabled_(false), backoff_entry_(&backoff_policy_), manager_(manager), url_id_(url_id) {
diff --git a/net/url_request/url_request_throttler_entry.h b/net/url_request/url_request_throttler_entry.h index 7f7a9314..48d41f0 100644 --- a/net/url_request/url_request_throttler_entry.h +++ b/net/url_request/url_request_throttler_entry.h
@@ -141,7 +141,7 @@ const int max_send_threshold_; // True if DisableBackoffThrottling() has been called on this object. - bool is_backoff_disabled_; + bool is_backoff_disabled_ = false; // Access it through GetBackoffEntry() to allow a unit test seam. BackoffEntry backoff_entry_;
diff --git a/net/url_request/url_request_throttler_manager.cc b/net/url_request/url_request_throttler_manager.cc index 9fb5ca1..5927ee91 100644 --- a/net/url_request/url_request_throttler_manager.cc +++ b/net/url_request/url_request_throttler_manager.cc
@@ -16,8 +16,7 @@ const unsigned int URLRequestThrottlerManager::kMaximumNumberOfEntries = 1500; const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200; -URLRequestThrottlerManager::URLRequestThrottlerManager() - : registered_from_thread_(base::kInvalidThreadId) { +URLRequestThrottlerManager::URLRequestThrottlerManager() { url_id_replacements_.ClearPassword(); url_id_replacements_.ClearUsername(); url_id_replacements_.ClearQuery();
diff --git a/net/url_request/url_request_throttler_manager.h b/net/url_request/url_request_throttler_manager.h index 5b6a98a6..8bc39d1 100644 --- a/net/url_request/url_request_throttler_manager.h +++ b/net/url_request/url_request_throttler_manager.h
@@ -141,7 +141,7 @@ NetLogWithSource net_log_; // Valid once we've registered for network notifications. - base::PlatformThreadId registered_from_thread_; + base::PlatformThreadId registered_from_thread_ = base::kInvalidThreadId; THREAD_CHECKER(thread_checker_); };
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc index d66b4b9..0c33580 100644 --- a/net/websockets/websocket_basic_handshake_stream.cc +++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -179,7 +179,6 @@ WebSocketEndpointLockManager* websocket_endpoint_lock_manager) : state_(std::move(connection), using_proxy), connect_delegate_(connect_delegate), - http_response_info_(nullptr), requested_sub_protocols_(std::move(requested_sub_protocols)), requested_extensions_(std::move(requested_extensions)), stream_request_(request),
diff --git a/net/websockets/websocket_basic_handshake_stream.h b/net/websockets/websocket_basic_handshake_stream.h index 8b84684..f50cabb 100644 --- a/net/websockets/websocket_basic_handshake_stream.h +++ b/net/websockets/websocket_basic_handshake_stream.h
@@ -128,7 +128,7 @@ const raw_ptr<WebSocketStream::ConnectDelegate> connect_delegate_; // This is stored in SendRequest() for use by ReadResponseHeaders(). - raw_ptr<HttpResponseInfo> http_response_info_; + raw_ptr<HttpResponseInfo> http_response_info_ = nullptr; // The key to be sent in the next Sec-WebSocket-Key header. Usually NULL (the // key is generated on the fly).
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc index 7ac0456..0f9462e 100644 --- a/net/websockets/websocket_channel_test.cc +++ b/net/websockets/websocket_channel_test.cc
@@ -593,7 +593,7 @@ // otherwise the ReadFrames() callback will never be called. class EchoeyFakeWebSocketStream : public FakeWebSocketStream { public: - EchoeyFakeWebSocketStream() : read_frames_(nullptr) {} + EchoeyFakeWebSocketStream() = default; int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames, CompletionOnceCallback callback) override { @@ -658,7 +658,7 @@ std::vector<std::unique_ptr<WebSocketFrame>> stored_frames_; CompletionOnceCallback read_callback_; // Owned by the caller of ReadFrames(). - raw_ptr<std::vector<std::unique_ptr<WebSocketFrame>>> read_frames_; + raw_ptr<std::vector<std::unique_ptr<WebSocketFrame>>> read_frames_ = nullptr; std::vector<scoped_refptr<IOBuffer>> buffers_; // True if we should close the connection. bool done_ = false;
diff --git a/net/websockets/websocket_deflate_stream_test.cc b/net/websockets/websocket_deflate_stream_test.cc index 45736233..f98f0928 100644 --- a/net/websockets/websocket_deflate_stream_test.cc +++ b/net/websockets/websocket_deflate_stream_test.cc
@@ -198,7 +198,7 @@ class WebSocketDeflateStreamTest : public ::testing::Test { public: - WebSocketDeflateStreamTest() : mock_stream_(nullptr), predictor_(nullptr) {} + WebSocketDeflateStreamTest() = default; ~WebSocketDeflateStreamTest() override = default; void SetUp() override { @@ -247,9 +247,9 @@ std::unique_ptr<WebSocketDeflateStream> deflate_stream_; // Owned by |deflate_stream_|. - raw_ptr<MockWebSocketStream> mock_stream_; + raw_ptr<MockWebSocketStream> mock_stream_ = nullptr; // Owned by |deflate_stream_|. - raw_ptr<WebSocketDeflatePredictorMock> predictor_; + raw_ptr<WebSocketDeflatePredictorMock> predictor_ = nullptr; // TODO(yoichio): Make this type std::vector<std::string>. std::vector<std::unique_ptr<const char[]>> data_buffers;
diff --git a/net/websockets/websocket_http2_handshake_stream.cc b/net/websockets/websocket_http2_handshake_stream.cc index 0f3e465..dfbe503 100644 --- a/net/websockets/websocket_http2_handshake_stream.cc +++ b/net/websockets/websocket_http2_handshake_stream.cc
@@ -48,11 +48,9 @@ std::set<std::string> dns_aliases) : session_(session), connect_delegate_(connect_delegate), - http_response_info_(nullptr), requested_sub_protocols_(requested_sub_protocols), requested_extensions_(requested_extensions), stream_request_(request), - request_info_(nullptr), dns_aliases_(std::move(dns_aliases)) { DCHECK(connect_delegate); DCHECK(request);
diff --git a/net/websockets/websocket_http2_handshake_stream.h b/net/websockets/websocket_http2_handshake_stream.h index d9ed31cf..f04e76d 100644 --- a/net/websockets/websocket_http2_handshake_stream.h +++ b/net/websockets/websocket_http2_handshake_stream.h
@@ -136,7 +136,7 @@ // |connect_delegate| will live during the lifetime of this object. const raw_ptr<WebSocketStream::ConnectDelegate> connect_delegate_; - raw_ptr<HttpResponseInfo> http_response_info_; + raw_ptr<HttpResponseInfo> http_response_info_ = nullptr; spdy::Http2HeaderBlock http2_request_headers_; @@ -148,7 +148,7 @@ const raw_ptr<WebSocketStreamRequestAPI> stream_request_; - raw_ptr<const HttpRequestInfo> request_info_; + raw_ptr<const HttpRequestInfo> request_info_ = nullptr; RequestPriority priority_;
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc index ee54346..2c60fdfdc 100644 --- a/net/websockets/websocket_stream_create_test_base.cc +++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -92,8 +92,7 @@ base::OnceClosure done_callback_; }; -WebSocketStreamCreateTestBase::WebSocketStreamCreateTestBase() - : url_request_(nullptr) {} +WebSocketStreamCreateTestBase::WebSocketStreamCreateTestBase() = default; WebSocketStreamCreateTestBase::~WebSocketStreamCreateTestBase() = default;
diff --git a/net/websockets/websocket_stream_create_test_base.h b/net/websockets/websocket_stream_create_test_base.h index a57c6f26..8e36af7 100644 --- a/net/websockets/websocket_stream_create_test_base.h +++ b/net/websockets/websocket_stream_create_test_base.h
@@ -90,7 +90,7 @@ ssl_error_callbacks_; SSLInfo ssl_info_; bool ssl_fatal_ = false; - raw_ptr<URLRequest> url_request_; + raw_ptr<URLRequest> url_request_ = nullptr; AuthChallengeInfo auth_challenge_info_; base::OnceCallback<void(const AuthCredentials*)> on_auth_required_callback_;
diff --git a/services/network/public/cpp/corb/README.md b/services/network/public/cpp/corb/README.md index c13b204..97994c0fd 100644 --- a/services/network/public/cpp/corb/README.md +++ b/services/network/public/cpp/corb/README.md
@@ -1,16 +1,176 @@ -# Cross-Origin Read Blocking (CORB) +# Cross-Origin Read Blocking / Opaque Resource Blocking (CORB/ORB) -Cross-Origin Read Blocking (CORB) and Opaque Response Blocking (ORB) are -security features that prevent disclosing the body of cross-origin "no-cors" -responses outside of a limited set of legacy scenarios (images, scripts, -etc.). Outside of these legacy scenarios, the body of a cross-origin, -"no-cors" response doesn't ever need to (and shouldn't) reach the renderer process -(e.g. `fetch` returns an opaque response body for "no-cors" requests). -Robust Site Isolation requires either CORB or ORB to prevent a renderer -process from reading opaque responses from other sites (e.g. reading the -opaque responses via Spectre, or after compromising the renderer process). +tl;dr: -Good starting points for learning more: +* CORB and ORB are related solutions to the same problem. +* One can consider CORB to be v1, and ORB to be v2. +* This directory implements both. +* Implementation and rollout will be in stages. +* For websites that correctly label the MIME types of their responses none of + this matters. -- https://www.chromium.org/Home/chromium-security/corb-for-developers -- https://github.com/annevk/orb +# The Problem CORB/ORB Are Solving + +Browsers enforce the [same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) +for many website-initiated fetches. However, in some contexts, the same origin +policy does not apply. For example, a page may load images from other origins. +The specification refers to these as requests with a ["no-cors" request mode](https://fetch.spec.whatwg.org/#concept-request-mode). + +Meanwhile, the ["Spectre" family of attacks](https://chromium.googlesource.com/chromium/src/+/master/docs/security/side-channel-threat-model.md) +allow a website to read memory within an operating system process. +(Caveats apply and it's more complicated that that; but that's the gist.) + +These, at its extreme, allow a near-complete circumvention of the "same-origin +policy": By first loading any resource one wishes to read via e.g. an `<img>` +tag, and then reading the result from its own memory via a "Spectre" gadget. +In this scenario, the image loading will fail and the site does not get +any programmatic access to the image content. (That is, to the bytes of the +resource, that the attacker pretended to be an image.) But because the +"image" has been brought into the renderer process (in order to parse it), and +because "Spectre" allows access to memory within the process, an attacking +page might get its contents after all. + +Additionally, CORB/ORB serve as a "defense in depth" measure: They help +to improve [isolation](https://chromium.googlesource.com/chromium/src/+/master/docs/process_model_and_site_isolation.md) between origins and thus make it +harder [to exploit a compromised renderer](https://chromium.googlesource.com/chromium/src/+/main/docs/security/compromised-renderers.md). + +## Security Properties + +In brief, the security property we want from CORB/ORB is this: For any +"no-cors" request we want positive evidence that the response received +is of the intended data type. + +Note: +* CORB/ORB has nothing to add for non-"no-cors" requests. +* We require this evidence before handing the resource data off to the renderer. +* For "positive evidence" we accept a conservative approximation. + It's not okay to block a valid resource; but it might well be okay to + occasionally let an inappropriate resource pass. +* A "correct" MIME type is good enough evidence. +* A "wrong" MIME type is good enough counter evidence. +* For historic reasons, browsers accept a number of resources with + inappropriate MIME types. For these historically accepted MIME types, + we require "content sniffing" to provide us with the desired evidence. + +## A Note on Deprecations + +Both CORB and ORB are [deprecations](https://developer.chrome.com/blog/deps-rems-101/) +at heart. That is: Formerly allowed behaviour would be newly disallowed and +blocked. This invariably causes issues for some well-meaning websites that, +often inadvertently, rely on the behaviour to be deprecated. +Any deprecation requires great care when deploying in order to minimize +unintended side-effects on the web ecosystem. + +# The Solution(s) + +## Cross-Origin Read Blocking (CORB) + +[Cross-Origin Read Blocking](https://www.chromium.org/Home/chromium-security/corb-for-developers/) +identifies a number of resource types that should be protected, namely +HTML, XML (except SVG), and JSON, and blocks them from being loaded in +"no-cors" responses. None of the intended usages for these resource types +issue "no-cors" requests. In addition to MIME type checks, it also employs +"sniffers" for these formats. + +The full details are more complicated. Here, we'll skip over details of +sniffing, error handling, and partial content responses (HTTP 206 responses). +Additional details can be found +[here](https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md) and [here](https://www.chromium.org/Home/chromium-security/corb-for-developers/). + +Note that this is a partial mismatch for our security requirements: Instead +of requiring positive evidence for the intended format, we instead picked a +handful of known-bad cases. Essentially, we look for negative evidence +for a request type mismatch, and ignore all the cases for which we don't have +such evidence. + +## Opaque Resource Blocking (ORB) + +[ORB](https://github.com/annevk/orb) is an alternative proposal to solve the +same problem. In Chromium we intend to replace CORB with ORB, so that in +the context of Chromium ORB could be considered as a "version 2" of CORB. + +The fundamental difference between CORB and ORB is that CORB picked +specific type mismatches to disallow, while ORB enumerates the data formats +that we expect to occur in "no-cors" requests and blocks the rest. +This makes ORB a better fit for our security requirements. It also makes ORB +a much bigger risk for web compatibility. + +## "ORB v0.1" + +Since CORB/ORB are deprecations, great care must be taken to not +break legitimate web sites. Since no implementation of ORB exists +(as of 2022-05), we have no existing web compatibiltiy data and must thus +be careful in deploying ORB. + +As a first step we are implementing a subset, dubbed "ORB v0.1". This differs +from ORB as proposed: + +- It is more permissive with several resource types: `audio/*`, `video/*`, + and some XML MIME types. +- It does not implement the JavaScript parsing steps. Instead it + re-uses several sniffers from CORB: + [HTML](https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md#protecting-html), + [XML](https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md#protecting-xml), and + [JSON and "XSSI-defeating prefixes"](https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md#protecting-json). +- It will accept any response for which these heuristics do not deliver a + verdict. +- CORB error handling is re-used: If a response is blocked, an empty response + will be injected in its stead. (ORB proposes an error response.) + +One unfortunate effect of postponing JSON and JavaScript sniffing is that +"ORB v0.1" does not yet achieve our goal of blocking any resource for which +we do not have positive evidence. + +## ORB post v0.1 + +These plans are not settled. We will iterate towards a more complete ORB +implementation. Note that some ORB details are also not finalized yet. + +# Appendix: Implementation and Spec Status + +## CORB + +* Implemented & shipped: Chrome M67 +* Spec: Formerly https://fetch.spec.whatwg.org/#corb (removed [here](https://github.com/whatwg/fetch/commit/78f9bdd73e8c6893d629c2ce4a3bde7eb01cac59)) + +## "ORB v0.1" + +* Spec: n/a. Follows the [ORB](https://github.com/annevk/orb) proposal, but + with several differences, noted below. +* Implemented & shipped: [Intent here](https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/ScjhKz3Z6U4/m/kW5RjWamAQAJ) + +## ORB + +* Draft Spec: https://github.com/annevk/orb +* Implementation: Under discussion. + +# Appendix: Differences between "ORB v0.1" and ORB + +The main difference is that "ORB v0.1" is more permissive, to reduce web +compatibility risks. A more detailed write-up may be found +[here](https://docs.google.com/document/d/1qUbE2ySi6av3arUEw5DNdFJIKKBbWGRGsXz_ew3S7HQ/edit#heading=h.mptmm5bpjtdn). + +Below are the tabulated differences between "ORB v0.1" and the ORB proposal. +Decisions are based on four factors: + +* The response's MIME type, +* the response's "nosniff" header, +* several "sniffers" that heuristically examine the first 1KiB of data, +* and parsers for the full resource (ORB only). + +| | "ORB v0.1" | ORB | Comment | +| --- | --- | --- | --- | +| MIME type: JavaScript, text/css, image/svg+xml | n/a (allow, unless it "sniffs" wrong. This follows from the rules below.) | **allow** (without sniffing) | Known-good "no-cors" MIME types. +| MIME type: HTML, JSON, XML, text/plain | **block** (if nosniff) | **block** (if nosniff) | MIME types that have historically been accepted in "no-cors" requests. We hope developers set the "nosniff" header. +| MIME type: zip + gzip, various MS office types; protobuf, text/csv | **block** | **block** | "Never sniff" MIME types. Not allowed in any "no-cors" requests. +| MIME type: audio/* or video/* | **allow** | **block** (unless it "sniffs" okay. This follows from the rules below. I'd expect most resources to "sniff" okay, though, so in practice these would likely be mostly allowed.) | "ORB v0.1" relaxes audio + video handling, and just lets all audio + video MIME types pass. +| MIME type: n/a (invalid/missing MIME type) | n/a (rules below apply. Would probably mostly allow.) | **allow** | | +| sniffs as audio/*, video/*, image/* | **allow** | **allow** | | +| JSON / JS handling | **block** if first 1KiB bytes sniff as <ul><li>HTML (but not MIME type: CSS),</li><li>XML (but not MIME type: SVG),</li><li>JS parser breaker,</li><li>or JSON.</li></ul> | **block** if "nosniff", **allow** if parses (!!) as JavaScript, **block** otherwise. (E.g. JSON or HTML or PDF won’t parse as JS.) | "ORB v0.1" makes a very deliberate decision to not parse a full response. +| default | **allow** | **block** | Because "ORB v0.1" can only "sniff" certain JS anti-patterns, it has to make the unfortunate decision to allow unknown content. We'd very much like to fix this, without the cost of a full parse. + +The table omits: + +* Blocked response handling: "ORB v0.1" injects empty responses instead of + returning an error. +* Handling of range requests / partial content responses (HTTP 206 responses).
diff --git a/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc b/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc index ea12da0e..db1f90f 100644 --- a/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc +++ b/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc
@@ -25,6 +25,8 @@ return viz::mojom::SynchronizationType::kSyncToken; case viz::TransferableResource::SynchronizationType::kGpuCommandsCompleted: return viz::mojom::SynchronizationType::kGpuCommandsCompleted; + case viz::TransferableResource::SynchronizationType::kReleaseFence: + return viz::mojom::SynchronizationType::kReleaseFence; } NOTREACHED(); return viz::mojom::SynchronizationType::kSyncToken; @@ -43,6 +45,9 @@ *out = viz::TransferableResource::SynchronizationType::kGpuCommandsCompleted; return true; + case viz::mojom::SynchronizationType::kReleaseFence: + *out = viz::TransferableResource::SynchronizationType::kReleaseFence; + return true; } return false; }
diff --git a/services/viz/public/mojom/compositing/transferable_resource.mojom b/services/viz/public/mojom/compositing/transferable_resource.mojom index b4c970b08..e169be2 100644 --- a/services/viz/public/mojom/compositing/transferable_resource.mojom +++ b/services/viz/public/mojom/compositing/transferable_resource.mojom
@@ -18,6 +18,7 @@ enum SynchronizationType { kSyncToken, kGpuCommandsCompleted, + kReleaseFence, }; // See components/viz/common/resources/transferable_resource.h.
diff --git a/skia/tools/fuzzers/OWNERS b/skia/tools/fuzzers/OWNERS index f2369a3..b85a0c9b 100644 --- a/skia/tools/fuzzers/OWNERS +++ b/skia/tools/fuzzers/OWNERS
@@ -1,3 +1,2 @@ metzman@chromium.org -inferno@chromium.org kjlubick@chromium.org
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index 66f7be38..1614959c9 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -2311,7 +2311,7 @@ "dimension_sets": [ { "os": "Ubuntu-18.04", - "pool": "chrome.tests" + "pool": "chrome.tests.finch" } ], "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -4267,7 +4267,7 @@ "dimension_sets": [ { "os": "Windows-10-19042", - "pool": "chrome.tests" + "pool": "chrome.tests.finch" } ], "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 3b91be2..2cdb879b 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -8240,15 +8240,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8325,15 +8325,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8359,7 +8359,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -8750,15 +8750,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8835,15 +8835,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8869,7 +8869,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 2a1f7649..3030792 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -46215,15 +46215,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46300,15 +46300,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46334,7 +46334,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -46725,15 +46725,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46810,15 +46810,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46844,7 +46844,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47239,15 +47239,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47324,15 +47324,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47358,7 +47358,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47749,15 +47749,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47834,15 +47834,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47868,7 +47868,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48331,15 +48331,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48416,15 +48416,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48450,7 +48450,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48841,15 +48841,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48926,15 +48926,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48960,7 +48960,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49423,15 +49423,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49508,15 +49508,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49542,7 +49542,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49933,15 +49933,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -50018,15 +50018,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -50052,7 +50052,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.42" + "revision": "version:103.0.5060.45" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 0d293619..1be0d5bd 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -103967,7 +103967,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ], @@ -103990,7 +103992,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ], @@ -104012,7 +104016,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ], @@ -104034,7 +104040,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ], @@ -104056,7 +104064,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ], @@ -104078,7 +104088,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ], @@ -104108,7 +104120,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ], @@ -104136,7 +104150,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Windows-10-19042", + "os": "Windows-10-19042" + }, + { "pool": "chromium.tests.finch" } ],
diff --git a/testing/buildbot/chromium.webrtc.json b/testing/buildbot/chromium.webrtc.json index 75764ec..25e917c 100644 --- a/testing/buildbot/chromium.webrtc.json +++ b/testing/buildbot/chromium.webrtc.json
@@ -205,9 +205,8 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "builder": "WebRTC Chromium Linux Tester", "os": "Ubuntu-18.04", - "pool": "luci.chromium.webrtc" + "pool": "WebRTC-chromium" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -361,7 +360,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -386,7 +385,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -410,7 +409,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -434,10 +433,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "builder": "WebRTC Chromium Mac Tester", "cpu": "x86-64", "os": "Mac-11|Mac-10.16|Mac-12", - "pool": "luci.chromium.webrtc" + "pool": "WebRTC-chromium" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -459,7 +457,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -484,7 +482,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -510,7 +508,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -532,7 +530,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -554,7 +552,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Mac-10.15" + "os": "Mac-11|Mac-10.16|Mac-12" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -593,6 +591,9 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "browser_tests", @@ -612,6 +613,9 @@ "perf_builder_name_alias": "chromium-webrtc-rel-win10", "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "browser_tests", @@ -630,6 +634,9 @@ "perf_builder_name_alias": "chromium-webrtc-rel-win10", "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "browser_tests_apprtc", @@ -651,10 +658,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "builder": "WebRTC Chromium Win10 Tester", - "pool": "luci.chromium.webrtc" + "pool": "WebRTC-chromium" } ], + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", @@ -671,6 +680,9 @@ "perf_builder_name_alias": "chromium-webrtc-rel-win10", "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_browsertests", @@ -690,6 +702,9 @@ "perf_builder_name_alias": "chromium-webrtc-rel-win10", "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_browsertests", @@ -710,6 +725,9 @@ "perf_builder_name_alias": "chromium-webrtc-rel-win10", "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_browsertests", @@ -726,6 +744,9 @@ "perf_builder_name_alias": "chromium-webrtc-rel-win10", "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_unittests", @@ -742,6 +763,9 @@ "perf_builder_name_alias": "chromium-webrtc-rel-win10", "swarming": { "can_use_on_swarming_builders": true, + "dimensions": { + "os": "Windows-10" + }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "remoting_unittests",
diff --git a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter index 4a30567..55efcc1 100644 --- a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter +++ b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter
@@ -26,9 +26,6 @@ -WidgetInputMethodInteractiveTest.OneWindow -WidgetInputMethodInteractiveTest.TwoWindows -# TODO(https://crbug.com/1331307): Started failing consistently on Lacros --FullscreenOnScreensChangeFullscreenControllerInteractiveTest.FullscreenOnScreensChange/1 - # TODO(https://crbug.com/991596): Setup guest profiles correctly for tests. # Lacros has restrictions on the main profile (it must match the device account # profile) so this test doesn't pass.
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 4e49fbb..860e31e 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -430,6 +430,15 @@ ], }, }, + 'finch-chromium-swarming-pool': { + 'swarming': { + 'dimension_sets': [ + { + 'pool': 'chromium.tests.finch', + }, + ], + }, + }, 'flame': { # Pixel 4 'swarming': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 24ee6408..fb03e6ce 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3054,8 +3054,24 @@ }, 'variations_smoke_tests': { 'modifications': { + 'linux-chrome': { + 'swarming': { + 'dimension_sets': [ + { + 'pool': 'chrome.tests.finch', + }, + ], + }, + }, 'win-chrome': { 'experiment_percentage': 100, + 'swarming': { + 'dimension_sets': [ + { + 'pool': 'chrome.tests.finch', + }, + ], + }, }, }, },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index dc2e9be..fb277e4 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -5177,7 +5177,7 @@ }, }, - 'webrtc_chromium_baremetal_browser_gtests': { + 'webrtc_chromium_baremetal_gtests': { 'browser_tests': { 'args': [ '--gtest_filter=WebRtcStatsPerfBrowserTest.*:' @@ -5198,9 +5198,6 @@ 'r_webrtc_git': '${webrtc_got_rev}' }, }, - }, - - 'webrtc_chromium_baremetal_capture_gtests_linux': { # Run capture unittests as well since our bots have real webcams. 'capture_unittests': { 'args': ['--enable-logging', '--v=1', '--test-launcher-jobs=1', @@ -5208,42 +5205,7 @@ 'swarming': { 'dimension_sets': [ { - 'builder': 'WebRTC Chromium Linux Tester', - 'pool': 'luci.chromium.webrtc', - } - ], - }, - }, - }, - - 'webrtc_chromium_baremetal_capture_gtests_mac': { - # Run capture unittests as well since our bots have real webcams. - 'capture_unittests': { - 'remove_mixins': ['mac_x64'], - 'mixins': ['mac_11_or_12_x64'], - 'args': ['--enable-logging', '--v=1', '--test-launcher-jobs=1', - '--test-launcher-print-test-stdio=always'], - 'swarming': { - 'dimension_sets': [ - { - 'builder': 'WebRTC Chromium Mac Tester', - 'pool': 'luci.chromium.webrtc', - } - ], - }, - }, - }, - - 'webrtc_chromium_baremetal_capture_gtests_win': { - # Run capture unittests as well since our bots have real webcams. - 'capture_unittests': { - 'args': ['--enable-logging', '--v=1', '--test-launcher-jobs=1', - '--test-launcher-print-test-stdio=always'], - 'swarming': { - 'dimension_sets': [ - { - 'builder': 'WebRTC Chromium Win10 Tester', - 'pool': 'luci.chromium.webrtc', + 'pool': 'WebRTC-chromium', } ], }, @@ -6668,25 +6630,8 @@ 'webrtc_chromium_simple_gtests', ], - 'webrtc_chromium_tests_with_baremetal_tests_linux': [ - 'webrtc_chromium_baremetal_capture_gtests_linux', - 'webrtc_chromium_baremetal_browser_gtests', - 'webrtc_chromium_gtests', - 'webrtc_chromium_simple_baremetal_gtests', - 'webrtc_chromium_simple_gtests', - ], - - 'webrtc_chromium_tests_with_baremetal_tests_mac': [ - 'webrtc_chromium_baremetal_capture_gtests_mac', - 'webrtc_chromium_baremetal_browser_gtests', - 'webrtc_chromium_gtests', - 'webrtc_chromium_simple_baremetal_gtests', - 'webrtc_chromium_simple_gtests', - ], - - 'webrtc_chromium_tests_with_baremetal_tests_win': [ - 'webrtc_chromium_baremetal_capture_gtests_win', - 'webrtc_chromium_baremetal_browser_gtests', + 'webrtc_chromium_tests_with_baremetal_tests': [ + 'webrtc_chromium_baremetal_gtests', 'webrtc_chromium_gtests', 'webrtc_chromium_simple_baremetal_gtests', 'webrtc_chromium_simple_gtests',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index bd0b870..207fa8e 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -474,16 +474,16 @@ }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': { 'args': [ - '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M103/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=103', + '--webview-apk-path=apks/AOSP_SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M103/out/Release', + '--impl-version=103' ], 'identifier': 'with_impl_from_103', 'swarming': { @@ -491,23 +491,23 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.42', + 'revision': 'version:103.0.5060.45' } - ], - }, + ] + } }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ - '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M102/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=102', + '--webview-apk-path=apks/AOSP_SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M102/out/Release', + '--impl-version=102' ], 'identifier': 'with_impl_from_102', 'swarming': { @@ -515,10 +515,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.124', + 'revision': 'version:102.0.5005.124' } - ], - }, + ] + } }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -618,16 +618,16 @@ }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M103/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=103', + '--webview-apk-path=apks/SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M103/out/Release', + '--impl-version=103' ], 'identifier': 'with_impl_from_103', 'swarming': { @@ -635,23 +635,23 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.42', + 'revision': 'version:103.0.5060.45' } - ], - }, + ] + } }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M102/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=102', + '--webview-apk-path=apks/SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M102/out/Release', + '--impl-version=102' ], 'identifier': 'with_impl_from_102', 'swarming': { @@ -659,10 +659,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.124', + 'revision': 'version:102.0.5005.124' } - ], - }, + ] + } }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -762,16 +762,16 @@ }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', - '--client-outdir', - '../../weblayer_instrumentation_test_M103/out/Release', '--implementation-outdir', '.', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--client-version=103', + '--webview-apk-path=apks/SystemWebView.apk', + '--client-outdir', + '../../weblayer_instrumentation_test_M103/out/Release', + '--client-version=103' ], 'identifier': 'with_client_from_103', 'swarming': { @@ -779,23 +779,23 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.42', + 'revision': 'version:103.0.5060.45' } - ], - }, + ] + } }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', - '--client-outdir', - '../../weblayer_instrumentation_test_M102/out/Release', '--implementation-outdir', '.', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--client-version=102', + '--webview-apk-path=apks/SystemWebView.apk', + '--client-outdir', + '../../weblayer_instrumentation_test_M102/out/Release', + '--client-version=102' ], 'identifier': 'with_client_from_102', 'swarming': { @@ -803,10 +803,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.124', + 'revision': 'version:102.0.5005.124' } - ], - }, + ] + } }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 2ef0ebf2..408b146 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2986,18 +2986,12 @@ 'android-fieldtrial-rel': { 'mixins': [ 'has_native_resultdb_integration', + 'finch-chromium-swarming-pool', 'pie-x86-emulator', 'linux-bionic', 'x86-64', ], 'os_type': 'android', - 'swarming': { - 'dimension_sets': [ - { - 'pool': 'chromium.tests.finch', - }, - ], - }, 'test_suites': { 'gtest_tests': 'fieldtrial_android_tests', }, @@ -3760,14 +3754,8 @@ 'win-fieldtrial-rel': { 'mixins': [ 'win10', + 'finch-chromium-swarming-pool', ], - 'swarming': { - 'dimension_sets': [ - { - 'pool': 'chromium.tests.finch', - }, - ], - }, 'test_suites': { 'gtest_tests': 'fieldtrial_browser_tests', 'isolated_scripts': 'fieldtrial_isolated_scripts', @@ -5741,7 +5729,7 @@ 'chromium-webrtc-rel-linux', ], 'test_suites': { - 'gtest_tests': 'webrtc_chromium_tests_with_baremetal_tests_linux', + 'gtest_tests': 'webrtc_chromium_tests_with_baremetal_tests', }, }, 'WebRTC Chromium Mac Builder': { @@ -5752,10 +5740,10 @@ 'WebRTC Chromium Mac Tester': { 'mixins': [ 'chromium-webrtc-rel-mac', - 'mac_x64', + 'mac_11_or_12_x64', ], 'test_suites': { - 'gtest_tests': 'webrtc_chromium_tests_with_baremetal_tests_mac', + 'gtest_tests': 'webrtc_chromium_tests_with_baremetal_tests', }, }, 'WebRTC Chromium Win Builder': { @@ -5764,11 +5752,16 @@ ], }, 'WebRTC Chromium Win10 Tester': { + 'swarming': { + 'dimensions': { + 'os': 'Windows-10', + }, + }, 'mixins': [ 'chromium-webrtc-rel-win10', ], 'test_suites': { - 'gtest_tests': 'webrtc_chromium_tests_with_baremetal_tests_win', + 'gtest_tests': 'webrtc_chromium_tests_with_baremetal_tests', }, }, },
diff --git a/testing/clusterfuzz/OWNERS b/testing/clusterfuzz/OWNERS index 9685177..47caed48 100644 --- a/testing/clusterfuzz/OWNERS +++ b/testing/clusterfuzz/OWNERS
@@ -1,2 +1,2 @@ -inferno@chromium.org -ochang@chromium.org +bookholt@chromium.org +tiszka@chromium.org
diff --git a/testing/libfuzzer/OWNERS b/testing/libfuzzer/OWNERS index c1cc0d6..4422eda 100644 --- a/testing/libfuzzer/OWNERS +++ b/testing/libfuzzer/OWNERS
@@ -1,4 +1,2 @@ -inferno@chromium.org kcc@chromium.org metzman@chromium.org -ochang@chromium.org
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 6e5b285..cc2a29d6 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -902,21 +902,6 @@ ] } ], - "AutofillEnableManualFallbackForVirtualCards": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "AutofillEnableManualFallbackForVirtualCards" - ] - } - ] - } - ], "AutofillEnableProfileDeduplication": [ { "platforms": [ @@ -1058,26 +1043,6 @@ ] } ], - "AutofillEnableVirtualCardEnrollment": [ - { - "platforms": [ - "android", - "chromeos", - "chromeos_lacros", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "AutofillEnableUpdateVirtualCardEnrollment" - ] - } - ] - } - ], "AutofillFixServerQueriesIfPasswordManagerIsEnabled": [ { "platforms": [
diff --git a/third_party/afl/OWNERS b/third_party/afl/OWNERS index c1cc0d6..4422eda 100644 --- a/third_party/afl/OWNERS +++ b/third_party/afl/OWNERS
@@ -1,4 +1,2 @@ -inferno@chromium.org kcc@chromium.org metzman@chromium.org -ochang@chromium.org
diff --git a/third_party/blink/common/mediastream/media_stream_request.cc b/third_party/blink/common/mediastream/media_stream_request.cc index 6f4537e..786acc43 100644 --- a/third_party/blink/common/mediastream/media_stream_request.cc +++ b/third_party/blink/common/mediastream/media_stream_request.cc
@@ -144,16 +144,31 @@ session_id_ == other_device.session_id_; } -// TODO(crbug.com/1313021): Remove this function and use -// blink::mojom::StreaDevices directly everywhere. -blink::MediaStreamDevices StreamDevicesToMediaStreamDevicesList( - const blink::mojom::StreamDevices& devices) { - blink::MediaStreamDevices all_devices; - if (devices.audio_device.has_value()) - all_devices.push_back(devices.audio_device.value()); - if (devices.video_device.has_value()) - all_devices.push_back(devices.video_device.value()); - return all_devices; +BLINK_COMMON_EXPORT MediaStreamDevices +ToMediaStreamDevicesList(const mojom::StreamDevices& stream_devices) { + blink::MediaStreamDevices devices; + if (stream_devices.audio_device.has_value()) { + devices.push_back(stream_devices.audio_device.value()); + } + if (stream_devices.video_device.has_value()) { + devices.push_back(stream_devices.video_device.value()); + } + return devices; +} + +blink::MediaStreamDevices ToMediaStreamDevicesList( + const blink::mojom::StreamDevicesSet& stream_devices_set) { + blink::MediaStreamDevices devices; + for (const blink::mojom::StreamDevicesPtr& devices_to_insert : + stream_devices_set.stream_devices) { + if (devices_to_insert->audio_device.has_value()) { + devices.push_back(devices_to_insert->audio_device.value()); + } + if (devices_to_insert->video_device.has_value()) { + devices.push_back(devices_to_insert->video_device.value()); + } + } + return devices; } size_t CountDevices(const blink::mojom::StreamDevices& devices) {
diff --git a/third_party/blink/public/common/mediastream/media_stream_request.h b/third_party/blink/public/common/mediastream/media_stream_request.h index 5debf97..d377966 100644 --- a/third_party/blink/public/common/mediastream/media_stream_request.h +++ b/third_party/blink/public/common/mediastream/media_stream_request.h
@@ -125,8 +125,15 @@ using MediaStreamDevices = std::vector<MediaStreamDevice>; +// Takes a mojom::StreamDevices and returns all contained MediaStreamDevices. BLINK_COMMON_EXPORT MediaStreamDevices -StreamDevicesToMediaStreamDevicesList(const mojom::StreamDevices& devices); +ToMediaStreamDevicesList(const mojom::StreamDevices& stream_devices); + +// TODO(crbug.com/1313021): Remove this function and use +// blink::mojom::StreamDevicesSet directly everywhere. +// Takes a mojom::StreamDevicesSet and returns all contained MediaStreamDevices. +BLINK_COMMON_EXPORT MediaStreamDevices +ToMediaStreamDevicesList(const mojom::StreamDevicesSet& stream_devices_set); BLINK_COMMON_EXPORT size_t CountDevices(const mojom::StreamDevices& devices);
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md index df51bc3..99bfc83 100644 --- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md +++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
@@ -1150,6 +1150,8 @@ Non-empty string value specified by `[ReflectEmpty]` must be added to `core/html/keywords.json5`. +When no value is specified by `[ReflectEmpty]`, the value will be IDL null if the attribute type is nullable, otherwise the empty string. + ### [ReflectInvalid] _(a)_ Specification: [Limited value attributes](http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values) - _defined in spec prose, not as an IDL extended attribute._ @@ -1171,6 +1173,8 @@ Non-empty string value specified by `[ReflectInvalid]` must be added to `core/html/keywords.json5`. +When no value is specified by `[ReflectEmpty]`, the value will be IDL null if the attribute type is nullable, otherwise the empty string. + ### [ReflectMissing] _(a)_ Specification: [Limited value attributes](http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values) - _defined in spec prose, not as an IDL extended attribute._ @@ -1192,6 +1196,8 @@ Non-empty string value specified by `[ReflectMissing]` must be added to `core/html/keywords.json5`. +When no value is specified by `[ReflectEmpty]`, the value will be IDL null if the attribute type is nullable, otherwise the empty string. + ### [ReflectOnly] _(a)_ Specification: [Limited value attributes](http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values) - _defined in spec prose, not as an IDL extended attribute._
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index 4a1b9917..675d1f6 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -613,13 +613,12 @@ if not cg_context.attribute_get: return None + is_nullable = cg_context.return_type.unwrap(nullable=False).is_nullable ext_attrs = cg_context.attribute.extended_attributes - keywords = ext_attrs.values_of("ReflectOnly") - missing_default = ext_attrs.value_of("ReflectMissing") - empty_default = ext_attrs.value_of("ReflectEmpty") - invalid_default = ext_attrs.value_of("ReflectInvalid") def constant(keyword): + if keyword is None and is_nullable: + return "g_null_atom" if not keyword: return "g_empty_atom" return "keywords::{}".format(name_style.constant(keyword)) @@ -634,32 +633,36 @@ branches, ] - if missing_default is not None: + if "ReflectMissing" in ext_attrs: + missing_default = ext_attrs.value_of("ReflectMissing") branches.append( cond="reflect_value.IsNull()", body=F("${return_value} = {};", constant(missing_default))) - elif cg_context.return_type.unwrap(nullable=False).is_nullable: + elif is_nullable: branches.append( cond="reflect_value.IsNull()", body=T("// Null string to IDL null.")) - if empty_default is not None: + if "ReflectEmpty" in ext_attrs: + empty_default = ext_attrs.value_of("ReflectEmpty") branches.append( cond="reflect_value.IsEmpty()", body=F("${return_value} = {};", constant(empty_default))) + keywords = ext_attrs.values_of("ReflectOnly") expr = " || ".join( map(lambda keyword: "reflect_value == {}".format(constant(keyword)), keywords)) branches.append(cond=expr, body=T("${return_value} = reflect_value;")) - if invalid_default is not None: + if "ReflectInvalid" in ext_attrs: + invalid_default = ext_attrs.value_of("ReflectInvalid") branches.append( cond=True, body=F("${return_value} = {};", constant(invalid_default))) else: - branches.append( - cond=True, body=F("${return_value} = {};", constant(""))) + branches.append(cond=True, + body=F("${return_value} = {};", constant(None))) return SequenceNode(nodes)
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 3d34a790..f03bf26 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1273,12 +1273,6 @@ "editing/finder/text_finder_test.cc", "editing/keyboard_test.cc", "editing/link_selection_test.cc", - "events/message_event_test.cc", - "events/mouse_event_test.cc", - "events/pointer_event_factory_test.cc", - "events/pointer_event_util_test.cc", - "events/touch_event_test.cc", - "events/web_input_event_conversion_test.cc", "execution_context/execution_context_lifecycle_state_observer_test.cc", "exported/web_document_subresource_filter_test.cc", "exported/web_document_test.cc", @@ -1306,101 +1300,15 @@ "fragment_directive/text_fragment_handler_test.cc", "fragment_directive/text_fragment_selector_generator_test.cc", "fragment_directive/text_fragment_selector_test.cc", - "frame/ad_tracker_test.cc", - "frame/attribution_response_parsing_test.cc", - "frame/attribution_src_loader_test.cc", - "frame/browser_controls_test.cc", - "frame/child_frame_compositing_helper_test.cc", - "frame/csp/content_security_policy_test.cc", - "frame/csp/conversion_util_test.cc", - "frame/csp/csp_directive_list_test.cc", - "frame/csp/csp_source_test.cc", - "frame/csp/source_list_directive_test.cc", - "frame/csp/trusted_types_directive_test.cc", - "frame/deprecation/deprecation_report_body_test.cc", - "frame/document_loading_rendering_test.cc", - "frame/document_policy_violation_report_body_test.cc", - "frame/dom_timer_test.cc", - "frame/find_in_page_test.cc", - "frame/frame_content_as_text_test.cc", - "frame/frame_overlay_test.cc", - "frame/frame_serializer_test.cc", - "frame/frame_test.cc", - "frame/history_util_test.cc", - "frame/local_dom_window_test.cc", - "frame/local_frame_back_forward_cache_test.cc", - "frame/local_frame_client_impl_test.cc", - "frame/local_frame_test.cc", - "frame/local_frame_ukm_aggregator_test.cc", - "frame/local_frame_view_test.cc", - "frame/location_report_body_test.cc", - "frame/mhtml_archive_test.cc", - "frame/mhtml_loading_test.cc", - "frame/performance_monitor_test.cc", - "frame/policy_container_test.cc", - "frame/report_test.cc", - "frame/reporting_context_test.cc", - "frame/root_frame_viewport_test.cc", - "frame/rotation_viewport_anchor_test.cc", - "frame/use_counter_impl_test.cc", - "frame/visual_viewport_test.cc", - "frame/web_frame_test.cc", - "frame/web_frame_widget_test.cc", - "frame/web_local_frame_client_test.cc", "fullscreen/scoped_allow_fullscreen_test.cc", "geometry/dom_matrix_test.cc", "imagebitmap/image_bitmap_test.cc", - "input/event_handler_test.cc", - "input/ime_on_focus_test.cc", - "input/mouse_event_manager_test.cc", - "input/overscroll_behavior_test.cc", - "input/pointer_event_manager_test.cc", - "input/scroll_snap_test.cc", - "input/touch_action_test.cc", - "input/touch_event_manager_test.cc", - "inspector/agent_registry_test.cc", - "inspector/inspector_contrast_test.cc", - "inspector/inspector_emulation_agent_test.cc", - "inspector/inspector_highlight_test.cc", - "inspector/inspector_history_test.cc", - "inspector/inspector_media_context_impl_unittest.cc", - "inspector/inspector_session_state_test.cc", - "inspector/inspector_style_resolver_test.cc", - "inspector/main_thread_debugger_test.cc", - "inspector/protocol_parser_test.cc", - "inspector/protocol_unittest.cc", "intersection_observer/intersection_observer_test.cc", "messaging/blink_transferable_message_mojom_traits_test.cc", "messaging/message_port_descriptor_mojom_traits_test.cc", "mobile_metrics/mobile_friendliness_checker_test.cc", "navigation_api/navigation_api_test.cc", "origin_trials/origin_trial_context_test.cc", - "page/autoscroll_controller_test.cc", - "page/chrome_client_impl_test.cc", - "page/chrome_client_test.cc", - "page/context_menu_controller_test.cc", - "page/drag_controller_test.cc", - "page/drag_image_test.cc", - "page/focus_controller_test.cc", - "page/focusgroup_controller_test.cc", - "page/named_pages_mapper_test.cc", - "page/page_popup_client_test.cc", - "page/plugin_data_test.cc", - "page/print_context_test.cc", - "page/scrolling/element_fragment_anchor_test.cc", - "page/scrolling/main_thread_scrolling_reasons_test.cc", - "page/scrolling/root_scroller_test.cc", - "page/scrolling/scroll_into_view_test.cc", - "page/scrolling/scroll_metrics_test.cc", - "page/scrolling/scroll_state_test.cc", - "page/scrolling/scrolling_test.cc", - "page/scrolling/snap_coordinator_test.cc", - "page/slot_scoped_traversal_test.cc", - "page/spatial_navigation_test.cc", - "page/touch_adjustment_test.cc", - "page/validation_message_overlay_delegate_test.cc", - "page/viewport_test.cc", - "page/window_features_test.cc", "permissions_policy/document_policy_parser_test.cc", "permissions_policy/document_policy_sim_test.cc", "permissions_policy/permissions_policy_devtools_support_test.cc", @@ -1458,11 +1366,16 @@ sources += rebase_path(blink_core_tests_css, "", "css") sources += rebase_path(blink_core_tests_dom, "", "dom") sources += rebase_path(blink_core_tests_editing, "", "editing") + sources += rebase_path(blink_core_tests_events, "", "events") sources += rebase_path(blink_core_tests_fetch, "", "fetch") sources += rebase_path(blink_core_tests_fileapi, "", "fileapi") + sources += rebase_path(blink_core_tests_frame, "", "frame") sources += rebase_path(blink_core_tests_html, "", "html") + sources += rebase_path(blink_core_tests_input, "", "input") + sources += rebase_path(blink_core_tests_inspector, "", "inspector") sources += rebase_path(blink_core_tests_layout, "", "layout") sources += rebase_path(blink_core_tests_loader, "", "loader") + sources += rebase_path(blink_core_tests_page, "", "page") sources += rebase_path(blink_core_tests_paint, "", "paint") sources += rebase_path(blink_core_tests_scroll, "", "scroll") sources += rebase_path(blink_core_tests_streams, "", "streams")
diff --git a/third_party/blink/renderer/core/css/css_custom_font_data.h b/third_party/blink/renderer/core/css/css_custom_font_data.h index 37d259a..56ea0ae 100644 --- a/third_party/blink/renderer/core/css/css_custom_font_data.h +++ b/third_party/blink/renderer/core/css/css_custom_font_data.h
@@ -71,9 +71,15 @@ // TODO(Oilpan): consider moving (Custom)FontFace hierarchy to the heap, // thereby making this reference a Member<>. +#if defined(USE_PARALLEL_TEXT_SHAPING) + CrossThreadWeakPersistent<CSSFontFaceSource> font_face_source_; + std::atomic<FallbackVisibility> fallback_visibility_; + mutable std::atomic<bool> is_loading_; +#else WeakPersistent<CSSFontFaceSource> font_face_source_; FallbackVisibility fallback_visibility_; mutable bool is_loading_; +#endif }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_font_face.cc b/third_party/blink/renderer/core/css/css_font_face.cc index 91a3bdb..8df72fd2d 100644 --- a/third_party/blink/renderer/core/css/css_font_face.cc +++ b/third_party/blink/renderer/core/css/css_font_face.cc
@@ -36,63 +36,93 @@ #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/platform/fonts/font_description.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" +#include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" +#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" namespace blink { +CSSFontFace::CSSFontFace(FontFace* font_face, Vector<UnicodeRange>& ranges) + : ranges_(base::AdoptRef(new UnicodeRangeSet(ranges))), + font_face_(font_face) +#if defined(USE_PARALLEL_TEXT_SHAPING) + , + task_runner_(font_face->GetExecutionContext()->GetTaskRunner( + TaskType::kFontLoading)) +#endif +{ + DCHECK(font_face_); +} + void CSSFontFace::AddSource(CSSFontFaceSource* source) { + AutoLockForParallelTextShaping guard(sources_lock_); sources_.push_back(source); } void CSSFontFace::AddSegmentedFontFace( CSSSegmentedFontFace* segmented_font_face) { + DCHECK(IsContextThread()); DCHECK(!segmented_font_faces_.Contains(segmented_font_face)); segmented_font_faces_.insert(segmented_font_face); } void CSSFontFace::RemoveSegmentedFontFace( CSSSegmentedFontFace* segmented_font_face) { + DCHECK(IsContextThread()); DCHECK(segmented_font_faces_.Contains(segmented_font_face)); segmented_font_faces_.erase(segmented_font_face); } void CSSFontFace::DidBeginLoad() { + DCHECK(IsContextThread()); if (LoadStatus() == FontFace::kUnloaded) SetLoadStatus(FontFace::kLoading); } bool CSSFontFace::FontLoaded(CSSFontFaceSource* source) { - if (!IsValid() || source != sources_.front()) + DCHECK(IsContextThread()); + if (source != FrontSource()) return false; if (LoadStatus() == FontFace::kLoading) { if (source->IsValid()) { SetLoadStatus(FontFace::kLoaded); } else if (source->IsInFailurePeriod()) { - sources_.clear(); + { + AutoLockForParallelTextShaping guard(sources_lock_); + sources_.clear(); + } SetLoadStatus(FontFace::kError); } else { - sources_.pop_front(); + { + AutoLockForParallelTextShaping guard(sources_lock_); + if (!sources_.IsEmpty() && source == sources_.front()) + sources_.pop_front(); + } Load(); } } - for (CSSSegmentedFontFace* segmented_font_face : segmented_font_faces_) + for (const auto& segmented_font_face : segmented_font_faces_) segmented_font_face->FontFaceInvalidated(); return true; } void CSSFontFace::SetDisplay(FontDisplay value) { - for (auto& source : sources_) { + for (auto& source : GetSources()) { source->SetDisplay(value); } } size_t CSSFontFace::ApproximateBlankCharacterCount() const { - if (sources_.IsEmpty() || !sources_.front()->IsInBlockPeriod()) + auto* const source = FrontSource(); + if (!source || !source->IsInBlockPeriod()) return 0; size_t approximate_character_count_ = 0; - for (CSSSegmentedFontFace* segmented_font_face : segmented_font_faces_) { + for (const auto& segmented_font_face : segmented_font_faces_) { approximate_character_count_ += segmented_font_face->ApproximateCharacterCount(); } @@ -100,16 +130,18 @@ } bool CSSFontFace::FallbackVisibilityChanged(RemoteFontFaceSource* source) { - if (!IsValid() || source != sources_.front()) + if (source != FrontSource()) return false; - for (CSSSegmentedFontFace* segmented_font_face : segmented_font_faces_) + for (const auto& segmented_font_face : segmented_font_faces_) segmented_font_face->FontFaceInvalidated(); return true; } scoped_refptr<SimpleFontData> CSSFontFace::GetFontData( const FontDescription& font_description) { - if (!IsValid()) + AutoLockForParallelTextShaping guard(sources_lock_); + + if (sources_.IsEmpty()) return nullptr; // Apply the 'size-adjust' descriptor before font selection. @@ -142,63 +174,107 @@ } // The active source may already be loading or loaded. Adjust our // FontFace status accordingly. - if (LoadStatus() == FontFace::kUnloaded && - (source->IsLoading() || source->IsLoaded())) - SetLoadStatus(FontFace::kLoading); - if (LoadStatus() == FontFace::kLoading && source->IsLoaded()) - SetLoadStatus(FontFace::kLoaded); + UpdateLoadStatusForActiveSource(source); return result; } sources_.pop_front(); } // We ran out of source. Set the FontFace status to "error" and return. + UpdateLoadStatusForNoSource(); + return nullptr; +} + +void CSSFontFace::UpdateLoadStatusForActiveSource(CSSFontFaceSource* source) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (auto task_runner = GetCrossThreadTaskRunner()) { + PostCrossThreadTask( + *task_runner, FROM_HERE, + CrossThreadBindOnce(&CSSFontFace::UpdateLoadStatusForActiveSource, + WrapCrossThreadPersistent(this), + WrapCrossThreadPersistent(source))); + return; + } + if (!font_face_->GetExecutionContext()) + return; + DCHECK(IsContextThread()); +#endif + if (LoadStatus() == FontFace::kUnloaded && + (source->IsLoading() || source->IsLoaded())) + SetLoadStatus(FontFace::kLoading); + if (LoadStatus() == FontFace::kLoading && source->IsLoaded()) + SetLoadStatus(FontFace::kLoaded); +} + +void CSSFontFace::UpdateLoadStatusForNoSource() { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (auto task_runner = GetCrossThreadTaskRunner()) { + PostCrossThreadTask( + *task_runner, FROM_HERE, + CrossThreadBindOnce(&CSSFontFace::UpdateLoadStatusForNoSource, + WrapCrossThreadPersistent(this))); + return; + } + if (!font_face_->GetExecutionContext()) + return; + DCHECK(IsContextThread()); +#endif if (LoadStatus() == FontFace::kUnloaded) SetLoadStatus(FontFace::kLoading); if (LoadStatus() == FontFace::kLoading) SetLoadStatus(FontFace::kError); - return nullptr; } bool CSSFontFace::MaybeLoadFont(const FontDescription& font_description, - const String& text) { + const StringView& text) { + DCHECK(IsContextThread()); // This is a fast path of loading web font in style phase. For speed, this // only checks if the first character of the text is included in the font's // unicode range. If this font is needed by subsequent characters, load is // kicked off in layout phase. - UChar32 character = text.CharacterStartingAt(0); - if (ranges_->Contains(character)) { - if (LoadStatus() == FontFace::kUnloaded) - Load(font_description); + const UChar32 character = text.length() ? text.CodepointAt(0) : 0; + if (!ranges_->Contains(character)) + return false; + if (LoadStatus() != FontFace::kUnloaded) return true; - } - return false; + LoadInternal(font_description); + return true; } bool CSSFontFace::MaybeLoadFont(const FontDescription& font_description, const FontDataForRangeSet& range_set) { - if (ranges_ == range_set.Ranges()) { - if (LoadStatus() == FontFace::kUnloaded) { - Load(font_description); - } + if (ranges_ != range_set.Ranges()) + return false; + if (LoadStatus() != FontFace::kUnloaded) return true; - } - return false; + LoadInternal(font_description); + return true; } void CSSFontFace::Load() { + DCHECK(IsContextThread()); FontDescription font_description; FontFamily font_family; font_family.SetFamily(font_face_->family(), FontFamily::Type::kFamilyName); font_description.SetFamily(font_family); - Load(font_description); + LoadInternal(font_description); } -void CSSFontFace::Load(const FontDescription& font_description) { +void CSSFontFace::LoadInternal(const FontDescription& font_description) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (auto task_runner = GetCrossThreadTaskRunner()) { + PostCrossThreadTask( + *task_runner, FROM_HERE, + CrossThreadBindOnce(&CSSFontFace::LoadInternal, + WrapCrossThreadPersistent(this), font_description)); + return; + } +#endif if (LoadStatus() == FontFace::kUnloaded) SetLoadStatus(FontFace::kLoading); DCHECK_EQ(LoadStatus(), FontFace::kLoading); + AutoLockForParallelTextShaping guard(sources_lock_); while (!sources_.IsEmpty()) { Member<CSSFontFaceSource>& source = sources_.front(); if (source->IsValid()) { @@ -221,6 +297,7 @@ } void CSSFontFace::SetLoadStatus(FontFace::LoadStatusType new_status) { + DCHECK(IsContextThread()); DCHECK(font_face_); if (new_status == FontFace::kError) font_face_->SetError(); @@ -247,7 +324,7 @@ if (LoadStatus() == FontFace::kLoaded) return false; bool changed = false; - for (CSSFontFaceSource* source : sources_) { + for (CSSFontFaceSource* source : GetSources()) { if (source->UpdatePeriod()) changed = true; } @@ -255,9 +332,36 @@ } void CSSFontFace::Trace(Visitor* visitor) const { - visitor->Trace(segmented_font_faces_); - visitor->Trace(sources_); + { + AutoLockForParallelTextShaping guard(sources_lock_); + visitor->Trace(sources_); + } visitor->Trace(font_face_); } +bool CSSFontFace::IsContextThread() const { +#if defined(USE_PARALLEL_TEXT_SHAPING) + return font_face_->GetExecutionContext()->IsContextThread(); +#else + return true; +#endif +} + +#if defined(USE_PARALLEL_TEXT_SHAPING) +scoped_refptr<base::SequencedTaskRunner> CSSFontFace::GetCrossThreadTaskRunner() + const { + auto* const context = font_face_->GetExecutionContext(); + if (!context || context->IsContextThread()) + return nullptr; + return task_runner_; +} +#endif + +HeapVector<Member<CSSFontFaceSource>> CSSFontFace::GetSources() const { + AutoLockForParallelTextShaping guard(sources_lock_); + HeapVector<Member<CSSFontFaceSource>> sources; + CopyToVector(sources_, sources); + return sources; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_font_face.h b/third_party/blink/renderer/core/css/css_font_face.h index 97924a85..cf9bd7d1 100644 --- a/third_party/blink/renderer/core/css/css_font_face.h +++ b/third_party/blink/renderer/core/css/css_font_face.h
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/css/css_segmented_font_face.h" #include "third_party/blink/renderer/core/css/font_face.h" #include "third_party/blink/renderer/core/css/font_face_source.h" +#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h" #include "third_party/blink/renderer/platform/fonts/unicode_range_set.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h" @@ -48,16 +49,17 @@ class CORE_EXPORT CSSFontFace final : public GarbageCollected<CSSFontFace> { public: - CSSFontFace(FontFace* font_face, Vector<UnicodeRange>& ranges) - : ranges_(base::AdoptRef(new UnicodeRangeSet(ranges))), - font_face_(font_face) { - DCHECK(font_face_); - } + CSSFontFace(FontFace* font_face, Vector<UnicodeRange>& ranges); CSSFontFace(const CSSFontFace&) = delete; CSSFontFace& operator=(const CSSFontFace&) = delete; // Front source is the first successfully loaded source. - const CSSFontFaceSource* FrontSource() const { + const CSSFontFaceSource* FrontSource() const LOCKS_EXCLUDED(sources_lock_) { + AutoLockForParallelTextShaping guard(sources_lock_); + return sources_.IsEmpty() ? nullptr : sources_.front(); + } + CSSFontFaceSource* FrontSource() LOCKS_EXCLUDED(sources_lock_) { + AutoLockForParallelTextShaping guard(sources_lock_); return sources_.IsEmpty() ? nullptr : sources_.front(); } FontFace* GetFontFace() const { return font_face_; } @@ -67,42 +69,57 @@ void AddSegmentedFontFace(CSSSegmentedFontFace*); void RemoveSegmentedFontFace(CSSSegmentedFontFace*); - bool IsValid() const { return !sources_.IsEmpty(); } + bool IsValid() const { return FrontSource(); } size_t ApproximateBlankCharacterCount() const; - void AddSource(CSSFontFaceSource*); + void AddSource(CSSFontFaceSource*) LOCKS_EXCLUDED(sources_lock_); void SetDisplay(FontDisplay); void DidBeginLoad(); bool FontLoaded(CSSFontFaceSource*); bool FallbackVisibilityChanged(RemoteFontFaceSource*); - scoped_refptr<SimpleFontData> GetFontData(const FontDescription&); + scoped_refptr<SimpleFontData> GetFontData(const FontDescription&) + LOCKS_EXCLUDED(sources_lock_); FontFace::LoadStatusType LoadStatus() const { return font_face_->LoadStatus(); } - bool MaybeLoadFont(const FontDescription&, const String&); + bool MaybeLoadFont(const FontDescription&, const StringView&); bool MaybeLoadFont(const FontDescription&, const FontDataForRangeSet&); void Load(); - void Load(const FontDescription&); // Recalculate the font loading timeline period for the font face. // https://drafts.csswg.org/css-fonts-4/#font-display-timeline // Returns true if the display period is changed. bool UpdatePeriod(); - bool HadBlankText() { return IsValid() && sources_.front()->HadBlankText(); } + bool HadBlankText() { + if (auto* source = FrontSource()) + return source->HadBlankText(); + return false; + } void Trace(Visitor*) const; private: + HeapVector<Member<CSSFontFaceSource>> GetSources() const + LOCKS_EXCLUDED(sources_lock_); + bool IsContextThread() const; + void LoadInternal(const FontDescription&) LOCKS_EXCLUDED(sources_lock_); void SetLoadStatus(FontFace::LoadStatusType); + void UpdateLoadStatusForActiveSource(CSSFontFaceSource*); + void UpdateLoadStatusForNoSource(); scoped_refptr<UnicodeRangeSet> ranges_; - HeapHashSet<Member<CSSSegmentedFontFace>> segmented_font_faces_; - HeapDeque<Member<CSSFontFaceSource>> sources_; - Member<FontFace> font_face_; + HashSet<scoped_refptr<CSSSegmentedFontFace>> segmented_font_faces_; + mutable LockForParallelTextShaping sources_lock_; + HeapDeque<Member<CSSFontFaceSource>> sources_ GUARDED_BY(sources_lock_); + const Member<FontFace> font_face_; +#if defined(USE_PARALLEL_TEXT_SHAPING) + scoped_refptr<base::SequencedTaskRunner> GetCrossThreadTaskRunner() const; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; +#endif }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_font_selector.cc b/third_party/blink/renderer/core/css/css_font_selector.cc index c4cb3ff3f..fb149ec 100644 --- a/third_party/blink/renderer/core/css/css_font_selector.cc +++ b/third_party/blink/renderer/core/css/css_font_selector.cc
@@ -40,7 +40,11 @@ namespace blink { CSSFontSelector::CSSFontSelector(const TreeScope& tree_scope) - : tree_scope_(&tree_scope) { + : CSSFontSelectorBase( + tree_scope.GetDocument().GetExecutionContext()->GetTaskRunner( + TaskType::kInternalDefault)), + tree_scope_(&tree_scope) { + DCHECK(tree_scope.GetDocument().GetExecutionContext()->IsContextThread()); DCHECK(tree_scope.GetDocument().GetFrame()); generic_font_family_settings_ = tree_scope.GetDocument() .GetFrame() @@ -57,7 +61,8 @@ CSSFontSelector::~CSSFontSelector() = default; UseCounter* CSSFontSelector::GetUseCounter() const { - return GetExecutionContext(); + auto* const context = GetExecutionContext(); + return context && context->IsContextThread() ? context : nullptr; } void CSSFontSelector::RegisterForInvalidationCallbacks( @@ -124,8 +129,7 @@ } if (!font_family.FamilyIsGeneric()) { - if (CSSSegmentedFontFace* face = - font_face_cache_->Get(request_description, family_name)) { + if (auto face = font_face_cache_->Get(request_description, family_name)) { ReportWebFontFamily(family_name); return face->GetFontData(request_description); } @@ -148,7 +152,7 @@ FontCache::Get().GetFontData(request_description, settings_family_name); ReportFontLookupByUniqueOrFamilyName(settings_family_name, - request_description, font_data.get()); + request_description, font_data); return font_data; } @@ -165,6 +169,10 @@ return GetDocument().GetFontMatchingMetrics(); } +bool CSSFontSelector::IsAlive() const { + return tree_scope_; +} + void CSSFontSelector::Trace(Visitor* visitor) const { visitor->Trace(tree_scope_); visitor->Trace(clients_);
diff --git a/third_party/blink/renderer/core/css/css_font_selector.h b/third_party/blink/renderer/core/css/css_font_selector.h index 74b7ee2..c568a0e 100644 --- a/third_party/blink/renderer/core/css/css_font_selector.h +++ b/third_party/blink/renderer/core/css/css_font_selector.h
@@ -82,6 +82,7 @@ void DispatchInvalidationCallbacks(FontInvalidationReason); // `CSSFontSelectorBase` overrides + bool IsAlive() const override; FontMatchingMetrics* GetFontMatchingMetrics() const override; UseCounter* GetUseCounter() const override;
diff --git a/third_party/blink/renderer/core/css/css_font_selector_base.cc b/third_party/blink/renderer/core/css/css_font_selector_base.cc index aeec9b2..2fa1fe9 100644 --- a/third_party/blink/renderer/core/css/css_font_selector_base.cc +++ b/third_party/blink/renderer/core/css/css_font_selector_base.cc
@@ -16,17 +16,58 @@ namespace blink { +CSSFontSelectorBase::CSSFontSelectorBase( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) +#if defined(USE_PARALLEL_TEXT_SHAPING) + : task_runner_(task_runner) +#endif +{ + DCHECK(IsContextThread()); +} + void CSSFontSelectorBase::CountUse(WebFeature feature) const { - return UseCounter::Count(GetUseCounter(), feature); +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (IsContextThread()) + return UseCounter::Count(GetUseCounter(), feature); + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&CSSFontSelectorBase::CountUse, + WrapCrossThreadPersistent(this), feature)); +#endif } AtomicString CSSFontSelectorBase::FamilyNameFromSettings( const FontDescription& font_description, const FontFamily& generic_family_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsContextThread()) { + if (IsWebkitBodyFamily(font_description)) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::CountUse, WrapCrossThreadPersistent(this), + WebFeature::kFontSelectorCSSFontFamilyWebKitPrefixBody)); + } + return FontSelector::FamilyNameFromSettings(generic_font_family_settings_, + font_description, + generic_family_name, nullptr); + } +#endif return FontSelector::FamilyNameFromSettings( generic_font_family_settings_, font_description, generic_family_name, GetUseCounter()); } + +bool CSSFontSelectorBase::IsContextThread() const { +#if defined(USE_PARALLEL_TEXT_SHAPING) + return task_runner_->RunsTasksInCurrentSequence(); +#else + return true; +#endif +} + bool CSSFontSelectorBase::IsPlatformFamilyMatchAvailable( const FontDescription& font_description, const FontFamily& passed_family) { @@ -40,6 +81,19 @@ void CSSFontSelectorBase::ReportEmojiSegmentGlyphCoverage( unsigned num_clusters, unsigned num_broken_clusters) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::ReportEmojiSegmentGlyphCoverage, + WrapCrossThreadPersistent(this), num_clusters, + num_broken_clusters)); + return; + } +#endif GetFontMatchingMetrics()->ReportEmojiSegmentGlyphCoverage( num_clusters, num_broken_clusters); } @@ -49,6 +103,19 @@ UScriptCode script, FontDescription::GenericFamilyType generic_family_type, const AtomicString& resulting_font_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::ReportFontFamilyLookupByGenericFamily, + WrapCrossThreadPersistent(this), generic_font_family_name, script, + generic_family_type, resulting_font_name)); + return; + } +#endif GetFontMatchingMetrics()->ReportFontFamilyLookupByGenericFamily( generic_font_family_name, script, generic_family_type, resulting_font_name); @@ -56,56 +123,153 @@ void CSSFontSelectorBase::ReportSuccessfulFontFamilyMatch( const AtomicString& font_family_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&CSSFontSelectorBase::ReportFailedFontFamilyMatch, + WrapCrossThreadPersistent(this), font_family_name)); + return; + } +#endif GetFontMatchingMetrics()->ReportSuccessfulFontFamilyMatch(font_family_name); } void CSSFontSelectorBase::ReportFailedFontFamilyMatch( const AtomicString& font_family_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&CSSFontSelectorBase::ReportFailedFontFamilyMatch, + WrapCrossThreadPersistent(this), font_family_name)); + return; + } +#endif GetFontMatchingMetrics()->ReportFailedFontFamilyMatch(font_family_name); } void CSSFontSelectorBase::ReportSuccessfulLocalFontMatch( const AtomicString& font_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::ReportSuccessfulLocalFontMatch, + WrapCrossThreadPersistent(this), font_name)); + return; + } +#endif GetFontMatchingMetrics()->ReportSuccessfulLocalFontMatch(font_name); } void CSSFontSelectorBase::ReportFailedLocalFontMatch( const AtomicString& font_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&CSSFontSelectorBase::ReportFailedLocalFontMatch, + WrapCrossThreadPersistent(this), font_name)); + return; + } +#endif GetFontMatchingMetrics()->ReportFailedLocalFontMatch(font_name); } void CSSFontSelectorBase::ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data) { + scoped_refptr<SimpleFontData> resulting_font_data) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::ReportFontLookupByUniqueOrFamilyName, + WrapCrossThreadPersistent(this), name, font_description, + resulting_font_data)); + return; + } +#endif GetFontMatchingMetrics()->ReportFontLookupByUniqueOrFamilyName( - name, font_description, resulting_font_data); + name, font_description, resulting_font_data.get()); } void CSSFontSelectorBase::ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data, + scoped_refptr<SimpleFontData> resulting_font_data, bool is_loading_fallback) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::ReportFontLookupByUniqueNameOnly, + WrapCrossThreadPersistent(this), name, font_description, + resulting_font_data, is_loading_fallback)); + return; + } +#endif GetFontMatchingMetrics()->ReportFontLookupByUniqueNameOnly( - name, font_description, resulting_font_data, is_loading_fallback); + name, font_description, resulting_font_data.get(), is_loading_fallback); } void CSSFontSelectorBase::ReportFontLookupByFallbackCharacter( UChar32 fallback_character, FontFallbackPriority fallback_priority, const FontDescription& font_description, - SimpleFontData* resulting_font_data) { + scoped_refptr<SimpleFontData> resulting_font_data) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::ReportFontLookupByFallbackCharacter, + WrapCrossThreadPersistent(this), fallback_character, + fallback_priority, font_description, resulting_font_data)); + return; + } +#endif GetFontMatchingMetrics()->ReportFontLookupByFallbackCharacter( fallback_character, fallback_priority, font_description, - resulting_font_data); + resulting_font_data.get()); } void CSSFontSelectorBase::ReportLastResortFallbackFontLookup( const FontDescription& font_description, - SimpleFontData* resulting_font_data) { + scoped_refptr<SimpleFontData> resulting_font_data) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce( + &CSSFontSelectorBase::ReportLastResortFallbackFontLookup, + WrapCrossThreadPersistent(this), font_description, + resulting_font_data)); + return; + } +#endif GetFontMatchingMetrics()->ReportLastResortFallbackFontLookup( - font_description, resulting_font_data); + font_description, resulting_font_data.get()); } void CSSFontSelectorBase::ReportNotDefGlyph() const { @@ -114,11 +278,33 @@ void CSSFontSelectorBase::ReportSystemFontFamily( const AtomicString& font_family_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&CSSFontSelectorBase::ReportSystemFontFamily, + WrapCrossThreadPersistent(this), font_family_name)); + return; + } +#endif GetFontMatchingMetrics()->ReportSystemFontFamily(font_family_name); } void CSSFontSelectorBase::ReportWebFontFamily( const AtomicString& font_family_name) { +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!IsAlive()) + return; + if (!IsContextThread()) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&CSSFontSelectorBase::ReportWebFontFamily, + WrapCrossThreadPersistent(this), font_family_name)); + return; + } +#endif GetFontMatchingMetrics()->ReportWebFontFamily(font_family_name); } @@ -127,7 +313,7 @@ const FontFamily& family, const String& text) { if (family.FamilyIsGeneric()) { - if (family.IsPrewarmed()) + if (family.IsPrewarmed() || UNLIKELY(family.FamilyName().IsEmpty())) return; family.SetIsPrewarmed(); // |FamilyNameFromSettings| has a visible impact on the load performance. @@ -135,9 +321,13 @@ // only when the |Font| is shared across elements, and therefore it can't // help when e.g., the font size is different, check once more if this // generic family is already prewarmed. - const auto result = prewarmed_generic_families_.insert(family.FamilyName()); - if (!result.is_new_entry) - return; + { + AutoLockForParallelTextShaping guard(prewarmed_generic_families_lock_); + const auto result = + prewarmed_generic_families_.insert(family.FamilyName()); + if (!result.is_new_entry) + return; + } const AtomicString& family_name = FamilyNameFromSettings(font_description, family); if (!family_name.IsEmpty()) @@ -145,13 +335,13 @@ return; } - if (CSSSegmentedFontFace* face = + if (auto face = font_face_cache_->Get(font_description, family.FamilyName())) { face->WillUseFontData(font_description, text); return; } - if (family.IsPrewarmed()) + if (family.IsPrewarmed() || UNLIKELY(family.FamilyName().IsEmpty())) return; family.SetIsPrewarmed(); FontCache::PrewarmFamily(family.FamilyName()); @@ -160,8 +350,7 @@ void CSSFontSelectorBase::WillUseRange(const FontDescription& font_description, const AtomicString& family, const FontDataForRangeSet& range_set) { - if (CSSSegmentedFontFace* face = - font_face_cache_->Get(font_description, family)) + if (auto face = font_face_cache_->Get(font_description, family)) face->WillUseRange(font_description, range_set); }
diff --git a/third_party/blink/renderer/core/css/css_font_selector_base.h b/third_party/blink/renderer/core/css/css_font_selector_base.h index 00eea28..5c4047d0 100644 --- a/third_party/blink/renderer/core/css/css_font_selector_base.h +++ b/third_party/blink/renderer/core/css/css_font_selector_base.h
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/css/font_face_cache.h" #include "third_party/blink/renderer/platform/fonts/font_selector.h" #include "third_party/blink/renderer/platform/fonts/generic_font_family_settings.h" +#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/wtf/forward.h" namespace blink { @@ -46,23 +47,23 @@ void ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data) override; + scoped_refptr<SimpleFontData> resulting_font_data) override; void ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data, + scoped_refptr<SimpleFontData> resulting_font_data, bool is_loading_fallback = false) override; void ReportFontLookupByFallbackCharacter( UChar32 fallback_character, FontFallbackPriority fallback_priority, const FontDescription& font_description, - SimpleFontData* resulting_font_data) override; + scoped_refptr<SimpleFontData> resulting_font_data) override; void ReportLastResortFallbackFontLookup( const FontDescription& font_description, - SimpleFontData* resulting_font_data) override; + scoped_refptr<SimpleFontData> resulting_font_data) override; void ReportFontFamilyLookupByGenericFamily( const AtomicString& generic_font_family_name, @@ -75,9 +76,18 @@ void ReportEmojiSegmentGlyphCoverage(unsigned num_clusters, unsigned num_broken_clusters) override; + bool IsContextThread() const override; + void Trace(Visitor*) const override; protected: + explicit CSSFontSelectorBase( + scoped_refptr<base::SingleThreadTaskRunner> task_runner); + + // TODO(crbug.com/383860): We should get rid of `IsAlive()` once lifetime + // issue of `CSSFontSelector` is solved. It will be alive after `TreeScope` + // is dead. + virtual bool IsAlive() const { return true; } virtual FontMatchingMetrics* GetFontMatchingMetrics() const = 0; virtual UseCounter* GetUseCounter() const = 0; @@ -89,7 +99,12 @@ Member<FontFaceCache> font_face_cache_; GenericFontFamilySettings generic_font_family_settings_; - HashSet<AtomicString> prewarmed_generic_families_; + LockForParallelTextShaping prewarmed_generic_families_lock_; + HashSet<AtomicString> prewarmed_generic_families_ + GUARDED_BY(prewarmed_generic_families_lock_); +#if defined(USE_PARALLEL_TEXT_SHAPING) + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; +#endif }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_segmented_font_face.cc b/third_party/blink/renderer/core/css/css_segmented_font_face.cc index eec016f9..b859dbe 100644 --- a/third_party/blink/renderer/core/css/css_segmented_font_face.cc +++ b/third_party/blink/renderer/core/css/css_segmented_font_face.cc
@@ -37,6 +37,7 @@ #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h" #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" +#include "third_party/blink/renderer/platform/heap/thread_state.h" // See comment below in CSSSegmentedFontFace::GetFontData - the cache from // CSSSegmentedFontFace (which represents a group of @font-face declarations @@ -51,21 +52,23 @@ namespace blink { // static -CSSSegmentedFontFace* CSSSegmentedFontFace::Create( +scoped_refptr<CSSSegmentedFontFace> CSSSegmentedFontFace::Create( FontSelectionCapabilities capabilities) { - return MakeGarbageCollected<CSSSegmentedFontFace>(capabilities); + return base::AdoptRef(new CSSSegmentedFontFace(capabilities)); } CSSSegmentedFontFace::CSSSegmentedFontFace( FontSelectionCapabilities font_selection_capabilities) : font_selection_capabilities_(font_selection_capabilities), font_data_table_(kFontDataTableMaxSize), - font_faces_(MakeGarbageCollected<FontFaceList>()), - approximate_character_count_(0) {} + approximate_character_count_(0) { + DCHECK(ThreadState::Current()->GetIsolate()); +} CSSSegmentedFontFace::~CSSSegmentedFontFace() = default; void CSSSegmentedFontFace::PruneTable() { + lock_.AssertAcquired(); // Make sure the glyph page tree prunes out all uses of this custom font. if (!font_data_table_.size()) return; @@ -74,8 +77,9 @@ } bool CSSSegmentedFontFace::IsValid() const { + lock_.AssertAcquired(); // Valid if at least one font face is valid. - return font_faces_->ForEachUntilTrue( + return font_faces_.ForEachUntilTrue( WTF::BindRepeating([](Member<FontFace> font_face) -> bool { if (font_face->CssFontFace()->IsValid()) return true; @@ -84,18 +88,21 @@ } void CSSSegmentedFontFace::FontFaceInvalidated() { + AutoLockForParallelTextShaping guard(lock_); PruneTable(); } void CSSSegmentedFontFace::AddFontFace(FontFace* font_face, bool css_connected) { + AutoLockForParallelTextShaping guard(lock_); PruneTable(); font_face->CssFontFace()->AddSegmentedFontFace(this); - font_faces_->Insert(font_face, css_connected); + font_faces_.Insert(font_face, css_connected); } void CSSSegmentedFontFace::RemoveFontFace(FontFace* font_face) { - if (!font_faces_->Erase(font_face)) + AutoLockForParallelTextShaping guard(lock_); + if (!font_faces_.Erase(font_face)) return; PruneTable(); @@ -104,6 +111,7 @@ scoped_refptr<FontData> CSSSegmentedFontFace::GetFontData( const FontDescription& font_description) { + AutoLockForParallelTextShaping guard(lock_); if (!IsValid()) return nullptr; @@ -144,7 +152,7 @@ font_selection_request.slope >= ItalicSlopeValue() && font_description.SyntheticItalicAllowed()); - font_faces_->ForEachReverse(WTF::BindRepeating( + font_faces_.ForEachReverse(WTF::BindRepeating( [](const FontDescription& requested_font_description, scoped_refptr<SegmentedFontData> created_font_data, Member<FontFace> font_face) { @@ -181,10 +189,12 @@ void CSSSegmentedFontFace::WillUseFontData( const FontDescription& font_description, - const String& text) { + const StringView& text) { + // This function is called from main thread or worker thread. + AutoLockForParallelTextShaping guard(lock_); approximate_character_count_ += text.length(); - font_faces_->ForEachReverseUntilTrue(WTF::BindRepeating( - [](const FontDescription& font_description, const String& text, + font_faces_.ForEachReverseUntilTrue(WTF::BindRepeating( + [](const FontDescription& font_description, const StringView& text, Member<FontFace> font_face) -> bool { if (font_face->LoadStatus() != FontFace::kUnloaded) return true; @@ -198,10 +208,11 @@ void CSSSegmentedFontFace::WillUseRange( const blink::FontDescription& font_description, const blink::FontDataForRangeSet& range_set) { + AutoLockForParallelTextShaping guard(lock_); // Iterating backwards since later defined unicode-range faces override // previously defined ones, according to the CSS3 fonts module. // https://drafts.csswg.org/css-fonts/#composite-fonts - font_faces_->ForEachReverseUntilTrue(WTF::BindRepeating( + font_faces_.ForEachReverseUntilTrue(WTF::BindRepeating( [](const blink::FontDescription& font_description, const blink::FontDataForRangeSet& range_set, Member<FontFace> font_face) -> bool { @@ -214,7 +225,8 @@ } bool CSSSegmentedFontFace::CheckFont(const String& text) const { - return font_faces_->ForEachUntilFalse(WTF::BindRepeating( + AutoLockForParallelTextShaping guard(lock_); + return font_faces_.ForEachUntilFalse(WTF::BindRepeating( [](const String& text, Member<FontFace> font_face) -> bool { if (font_face->LoadStatus() != FontFace::kLoaded && font_face->CssFontFace()->Ranges()->IntersectsWith(text)) @@ -226,9 +238,10 @@ void CSSSegmentedFontFace::Match(const String& text, HeapVector<Member<FontFace>>* faces) const { + AutoLockForParallelTextShaping guard(lock_); // WTF::BindRepeating requires WrapPersistent around |faces|, which is fine, // because the wrap's lifetime is contained to this function. - font_faces_->ForEach(WTF::BindRepeating( + font_faces_.ForEach(WTF::BindRepeating( [](const String& text, HeapVector<Member<FontFace>>* faces, Member<FontFace> font_face) { if (font_face->CssFontFace()->Ranges()->IntersectsWith(text)) @@ -238,6 +251,7 @@ } void CSSSegmentedFontFace::Trace(Visitor* visitor) const { + AutoLockForParallelTextShaping guard(lock_); visitor->Trace(font_faces_); }
diff --git a/third_party/blink/renderer/core/css/css_segmented_font_face.h b/third_party/blink/renderer/core/css/css_segmented_font_face.h index f74aad11..019ef6f 100644 --- a/third_party/blink/renderer/core/css/css_segmented_font_face.h +++ b/third_party/blink/renderer/core/css/css_segmented_font_face.h
@@ -27,8 +27,10 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_SEGMENTED_FONT_FACE_H_ #include "base/callback.h" +#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/fonts/font_cache_key.h" #include "third_party/blink/renderer/platform/fonts/font_selection_types.h" +#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" @@ -36,6 +38,7 @@ #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/lru_cache.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -51,8 +54,18 @@ // Note however, |Insert| has to be instructed which sub-list to insert it to. // Iterating over the combined set, behaves as if all non-CSS-connected // FontFaces were stored after the CSS-connected ones. -class FontFaceList : public GarbageCollected<FontFaceList> { - using FontFaceListPart = HeapLinkedHashSet<Member<FontFace>>; +class FontFaceList final { + DISALLOW_NEW(); + + // TODO(yosin): Once Oilpan allowed mixed thread heap, we should make + // |FontFaceList| as |HeapLinkedHashSet<T>|. + class FontFaceListPart : public LinkedHashSet<Member<FontFace>> { + public: + void Trace(Visitor* visitor) const { + for (auto& entry : *this) + visitor->Trace(*entry); + } + }; public: bool IsEmpty() const; @@ -86,12 +99,13 @@ FontFaceListPart non_css_connected_face_; }; -class CSSSegmentedFontFace final - : public GarbageCollected<CSSSegmentedFontFace> { +// TODO(yosin): Once Oilpan allowed mixed thread heap, we should make +// |CSSSegmentedFontFace| as |GarbageCollected<T>|. +class CORE_EXPORT CSSSegmentedFontFace final + : public RefCountedWillBeThreadSafeForParallelTextShaping< + CSSSegmentedFontFace> { public: - static CSSSegmentedFontFace* Create(FontSelectionCapabilities); - - explicit CSSSegmentedFontFace(FontSelectionCapabilities); + static scoped_refptr<CSSSegmentedFontFace> Create(FontSelectionCapabilities); ~CSSSegmentedFontFace(); FontSelectionCapabilities GetFontSelectionCapabilities() const { @@ -100,18 +114,25 @@ // Called when status of a FontFace has changed (e.g. loaded or timed out) // so cached FontData must be discarded. - void FontFaceInvalidated(); + void FontFaceInvalidated() LOCKS_EXCLUDED(lock_); - void AddFontFace(FontFace*, bool css_connected); - void RemoveFontFace(FontFace*); - bool IsEmpty() const { return font_faces_->IsEmpty(); } + void AddFontFace(FontFace*, bool css_connected) LOCKS_EXCLUDED(lock_); + void RemoveFontFace(FontFace*) LOCKS_EXCLUDED(lock_); + bool IsEmpty() const LOCKS_EXCLUDED(lock_) { + AutoLockForParallelTextShaping guard(lock_); + return font_faces_.IsEmpty(); + } - scoped_refptr<FontData> GetFontData(const FontDescription&); + scoped_refptr<FontData> GetFontData(const FontDescription&) + LOCKS_EXCLUDED(lock_); - bool CheckFont(const String&) const; - void Match(const String&, HeapVector<Member<FontFace>>*) const; - void WillUseFontData(const FontDescription&, const String& text); - void WillUseRange(const FontDescription&, const blink::FontDataForRangeSet&); + bool CheckFont(const String&) const LOCKS_EXCLUDED(lock_); + void Match(const String&, HeapVector<Member<FontFace>>*) const + LOCKS_EXCLUDED(lock_); + void WillUseFontData(const FontDescription&, const StringView& text) + LOCKS_EXCLUDED(lock_); + void WillUseRange(const FontDescription&, const blink::FontDataForRangeSet&) + LOCKS_EXCLUDED(lock_); size_t ApproximateCharacterCount() const { return approximate_character_count_; } @@ -119,16 +140,19 @@ void Trace(Visitor*) const; private: - void PruneTable(); - bool IsValid() const; + explicit CSSSegmentedFontFace(FontSelectionCapabilities); + + void PruneTable() EXCLUSIVE_LOCKS_REQUIRED(lock_); + bool IsValid() const EXCLUSIVE_LOCKS_REQUIRED(lock_); FontSelectionCapabilities font_selection_capabilities_; - WTF::LruCache<FontCacheKey, scoped_refptr<SegmentedFontData>> - font_data_table_; + mutable LockForParallelTextShaping lock_; + WTF::LruCache<FontCacheKey, scoped_refptr<SegmentedFontData>> font_data_table_ + GUARDED_BY(lock_); // All non-CSS-connected FontFaces are stored after the CSS-connected ones. - Member<FontFaceList> font_faces_; + FontFaceList font_faces_ GUARDED_BY(lock_); // Approximate number of characters styled with this CSSSegmentedFontFace. // LayoutText::StyleDidChange() increments this on the first
diff --git a/third_party/blink/renderer/core/css/font_face.cc b/third_party/blink/renderer/core/css/font_face.cc index b4a0cc4b..a8c4763 100644 --- a/third_party/blink/renderer/core/css/font_face.cc +++ b/third_party/blink/renderer/core/css/font_face.cc
@@ -872,7 +872,8 @@ RemoteFontFaceSource* source = MakeGarbageCollected<RemoteFontFaceSource>( css_font_face_, font_selector, - CSSValueToFontDisplay(display_.Get())); + CSSValueToFontDisplay(display_.Get()), + GetExecutionContext()->GetTaskRunner(TaskType::kFontLoading)); item.Fetch(context, source); css_font_face_->AddSource(source); }
diff --git a/third_party/blink/renderer/core/css/font_face_cache.cc b/third_party/blink/renderer/core/css/font_face_cache.cc index 068c9b0..435fd72 100644 --- a/third_party/blink/renderer/core/css/font_face_cache.cc +++ b/third_party/blink/renderer/core/css/font_face_cache.cc
@@ -52,9 +52,9 @@ bool css_connected) { const auto result = map_.insert(font_face->family(), nullptr); if (result.is_new_entry) - result.stored_value->value = MakeGarbageCollected<CapabilitiesSet>(); + result.stored_value->value = base::MakeRefCounted<CapabilitiesSet>(); - CapabilitiesSet* family_faces = result.stored_value->value; + scoped_refptr<CapabilitiesSet> family_faces = result.stored_value->value; family_faces->AddFontFace(font_face, css_connected); } @@ -73,6 +73,7 @@ void FontFaceCache::FontSelectionQueryCache::Remove( const AtomicString& family) { + AutoLockForParallelTextShaping guard(lock_); map_.erase(family); } @@ -103,7 +104,7 @@ if (it == map_.end()) return false; - CapabilitiesSet* family_segmented_faces = it->value; + scoped_refptr<CapabilitiesSet> family_segmented_faces = it->value; if (family_segmented_faces->RemoveFontFace(font_face)) map_.erase(it); return true; @@ -126,7 +127,7 @@ if (it == map_.end()) return false; - CSSSegmentedFontFace* segmented_font_face = it->value; + scoped_refptr<CSSSegmentedFontFace> segmented_font_face = it->value; segmented_font_face->RemoveFontFace(font_face); if (!segmented_font_face->IsEmpty()) return false; @@ -155,6 +156,7 @@ } void FontFaceCache::FontSelectionQueryCache::Clear() { + AutoLockForParallelTextShaping guard(lock_); map_.clear(); } @@ -165,21 +167,21 @@ version_ = g_version.GetNext(); } -FontFaceCache::CapabilitiesSet* FontFaceCache::SegmentedFacesByFamily::Find( - const AtomicString& family) const { +scoped_refptr<FontFaceCache::CapabilitiesSet> +FontFaceCache::SegmentedFacesByFamily::Find(const AtomicString& family) const { const auto it = map_.find(family); if (it == map_.end() || it->value->IsEmpty()) return nullptr; return it->value; } -CSSSegmentedFontFace* FontFaceCache::Get( +scoped_refptr<CSSSegmentedFontFace> FontFaceCache::Get( const FontDescription& font_description, const AtomicString& family) { if (family.IsEmpty()) return nullptr; - CapabilitiesSet* family_faces = segmented_faces_.Find(family); + scoped_refptr<CapabilitiesSet> family_faces = segmented_faces_.Find(family); if (!family_faces) return nullptr; @@ -187,19 +189,22 @@ font_description.GetFontSelectionRequest(), family, family_faces); } -CSSSegmentedFontFace* FontFaceCache::FontSelectionQueryCache::GetOrCreate( +scoped_refptr<CSSSegmentedFontFace> +FontFaceCache::FontSelectionQueryCache::GetOrCreate( const FontSelectionRequest& request, const AtomicString& family, - CapabilitiesSet* family_faces) { + scoped_refptr<CapabilitiesSet> family_faces) { + AutoLockForParallelTextShaping guard(lock_); const auto result = map_.insert(family, nullptr); if (result.is_new_entry) { result.stored_value->value = - MakeGarbageCollected<FontSelectionQueryResult>(); + base::MakeRefCounted<FontSelectionQueryResult>(); } return result.stored_value->value->GetOrCreate(request, *family_faces); } -CSSSegmentedFontFace* FontFaceCache::FontSelectionQueryResult::GetOrCreate( +scoped_refptr<CSSSegmentedFontFace> +FontFaceCache::FontSelectionQueryResult::GetOrCreate( const FontSelectionRequest& request, const CapabilitiesSet& family_faces) { const auto face_entry = map_.insert(request, nullptr); @@ -222,7 +227,7 @@ all_faces_boundaries); for (const auto& item : family_faces) { const FontSelectionCapabilities& candidate_key = item.key; - CSSSegmentedFontFace* candidate_value = item.value; + scoped_refptr<CSSSegmentedFontFace> candidate_value = item.value; if (!face_entry.stored_value->value || font_selection_algorithm.IsBetterMatchForRequest( candidate_key, @@ -252,19 +257,24 @@ } void FontFaceCache::CapabilitiesSet::Trace(Visitor* visitor) const { - visitor->Trace(map_); + for (auto& entry : map_) + visitor->Trace(*entry.value); } void FontFaceCache::FontSelectionQueryCache::Trace(Visitor* visitor) const { - visitor->Trace(map_); + AutoLockForParallelTextShaping guard(lock_); + for (auto& entry : map_) + visitor->Trace(*entry.value); } void FontFaceCache::FontSelectionQueryResult::Trace(Visitor* visitor) const { - visitor->Trace(map_); + for (auto& entry : map_) + visitor->Trace(*entry.value); } void FontFaceCache::SegmentedFacesByFamily::Trace(Visitor* visitor) const { - visitor->Trace(map_); + for (auto& entry : map_) + visitor->Trace(*entry.value); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/font_face_cache.h b/third_party/blink/renderer/core/css/font_face_cache.h index 927a5da..f7f381a 100644 --- a/third_party/blink/renderer/core/css/font_face_cache.h +++ b/third_party/blink/renderer/core/css/font_face_cache.h
@@ -32,11 +32,13 @@ #include "third_party/blink/renderer/core/css/font_face.h" #include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/platform/fonts/font_selection_types.h" +#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" #include "third_party/blink/renderer/platform/wtf/text/string_hash.h" +#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" namespace blink { @@ -58,7 +60,8 @@ // FIXME: It's sort of weird that add/remove uses StyleRuleFontFace* as key, // but this function uses FontDescription/family pair. - CSSSegmentedFontFace* Get(const FontDescription&, const AtomicString& family); + scoped_refptr<CSSSegmentedFontFace> Get(const FontDescription&, + const AtomicString& family); const HeapLinkedHashSet<Member<FontFace>>& CssConnectedFontFaces() const { return css_connected_font_faces_; @@ -80,9 +83,11 @@ // A second lookup table caches the previously received FontSelectionRequest // queries, which is: HeapHashMap <String, HeapHashMap<FontSelectionRequest, // CSSSegmentedFontFace>> - class CapabilitiesSet final : public GarbageCollected<CapabilitiesSet> { + class CapabilitiesSet final + : public RefCountedWillBeThreadSafeForParallelTextShaping< + CapabilitiesSet> { using Map = - HeapHashMap<FontSelectionCapabilities, Member<CSSSegmentedFontFace>>; + HashMap<FontSelectionCapabilities, scoped_refptr<CSSSegmentedFontFace>>; public: Map::const_iterator begin() const { return map_.begin(); } @@ -92,7 +97,7 @@ void AddFontFace(FontFace* font_face, bool css_connected); bool IsEmpty() const { return map_.IsEmpty(); } - // Returns true if associated |CSSSegmentedFontFace| is empty. + // Returns true if associated `CSSSegmentedFontFace` is empty. bool RemoveFontFace(FontFace* font_face); void Trace(Visitor*) const; @@ -101,18 +106,19 @@ Map map_; }; - // The map from |FontSelectionRequestKey| to |CSSSegmentedFontFace|. + // The map from `FontSelectionRequestKey` to `CSSSegmentedFontFace`. class FontSelectionQueryResult final - : public GarbageCollected<FontSelectionQueryResult> { - using Map = - HeapHashMap<FontSelectionRequestKey, - Member<CSSSegmentedFontFace>, - FontSelectionRequestKeyHash, - WTF::SimpleClassHashTraits<FontSelectionRequestKey>>; + : public RefCountedWillBeThreadSafeForParallelTextShaping< + FontSelectionQueryResult> { + using Map = HashMap<FontSelectionRequestKey, + scoped_refptr<CSSSegmentedFontFace>, + FontSelectionRequestKeyHash, + WTF::SimpleClassHashTraits<FontSelectionRequestKey>>; public: - CSSSegmentedFontFace* GetOrCreate(const FontSelectionRequest& request, - const CapabilitiesSet& family_faces); + scoped_refptr<CSSSegmentedFontFace> GetOrCreate( + const FontSelectionRequest& request, + const CapabilitiesSet& family_faces); void Trace(Visitor*) const; @@ -120,36 +126,38 @@ Map map_; }; - // The map from font family name to |FontSelectionQueryResult|. + // The map from font family name to `FontSelectionQueryResult`. class FontSelectionQueryCache final { - DISALLOW_NEW(); - - using Map = - HeapHashMap<String, Member<FontSelectionQueryResult>, CaseFoldingHash>; + using Map = HashMap<String, + scoped_refptr<FontSelectionQueryResult>, + CaseFoldingHash>; public: - void Clear(); - CSSSegmentedFontFace* GetOrCreate(const FontSelectionRequest& request, - const AtomicString& family, - CapabilitiesSet* family_faces); - void Remove(const AtomicString& family); + void Clear() LOCKS_EXCLUDED(lock_); + scoped_refptr<CSSSegmentedFontFace> GetOrCreate( + const FontSelectionRequest& request, + const AtomicString& family, + scoped_refptr<CapabilitiesSet> family_faces) LOCKS_EXCLUDED(lock_); + void Remove(const AtomicString& family) LOCKS_EXCLUDED(lock_); - void Trace(Visitor*) const; + void Trace(Visitor*) const LOCKS_EXCLUDED(lock_); private: - Map map_; + mutable LockForParallelTextShaping lock_; + Map map_ GUARDED_BY(lock_); }; - // The map from font family name to |CapabilitiesSet|. + // The map from font family name to `CapabilitiesSet`. class SegmentedFacesByFamily final { - DISALLOW_NEW(); + using Map = + HashMap<String, scoped_refptr<CapabilitiesSet>, CaseFoldingHash>; public: void AddFontFace(FontFace* font_face, bool css_connected); void Clear() { map_.clear(); } - CapabilitiesSet* Find(const AtomicString& family) const; + scoped_refptr<CapabilitiesSet> Find(const AtomicString& family) const; bool IsEmpty() const { return map_.IsEmpty(); } - // Returns true if |font_face| is removed from |map_|. + // Returns true if `font_face` is removed from `map_`. bool RemoveFontFace(FontFace* font_face); size_t GetNumSegmentedFacesForTesting() const; @@ -157,8 +165,6 @@ void Trace(Visitor*) const; private: - using Map = HeapHashMap<String, Member<CapabilitiesSet>, CaseFoldingHash>; - Map map_; };
diff --git a/third_party/blink/renderer/core/css/font_face_cache_test.cc b/third_party/blink/renderer/core/css/font_face_cache_test.cc index 35b59b13..fec64cae 100644 --- a/third_party/blink/renderer/core/css/font_face_cache_test.cc +++ b/third_party/blink/renderer/core/css/font_face_cache_test.cc
@@ -146,7 +146,7 @@ const FontDescription& description_condensed = FontDescriptionForRequest( CondensedWidthValue(), NormalSlopeValue(), NormalWeightValue()); - CSSSegmentedFontFace* result = + scoped_refptr<CSSSegmentedFontFace> result = cache_->Get(description_condensed, kFontNameForTesting); ASSERT_TRUE(result); @@ -177,7 +177,7 @@ const FontDescription& description_bold = FontDescriptionForRequest( NormalWidthValue(), NormalSlopeValue(), BoldWeightValue()); - CSSSegmentedFontFace* result = + scoped_refptr<CSSSegmentedFontFace> result = cache_->Get(description_bold, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -272,7 +272,7 @@ } } for (FontDescription& test_description : test_descriptions) { - CSSSegmentedFontFace* result = + scoped_refptr<CSSSegmentedFontFace> result = cache_->Get(test_description, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -320,7 +320,7 @@ const FontDescription& description_bold = FontDescriptionForRequest( NormalWidthValue(), NormalSlopeValue(), BoldWeightValue()); - CSSSegmentedFontFace* result = + scoped_refptr<CSSSegmentedFontFace> result = cache_->Get(description_bold, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -372,7 +372,7 @@ const FontDescription& description_expanded = FontDescriptionForRequest( NormalWidthValue(), NormalSlopeValue(), test_weight); - CSSSegmentedFontFace* result = + scoped_refptr<CSSSegmentedFontFace> result = cache_->Get(description_expanded, kFontNameForTesting); ASSERT_TRUE(result); ASSERT_EQ(result->GetFontSelectionCapabilities().weight.minimum, @@ -429,7 +429,7 @@ const FontDescription& description_expanded = FontDescriptionForRequest( FontSelectionValue(105), NormalSlopeValue(), NormalWeightValue()); - CSSSegmentedFontFace* result = + scoped_refptr<CSSSegmentedFontFace> result = cache_->Get(description_expanded, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -482,7 +482,7 @@ const FontDescription& description_italic = FontDescriptionForRequest( NormalWidthValue(), ItalicSlopeValue(), NormalWeightValue()); - CSSSegmentedFontFace* result = + scoped_refptr<CSSSegmentedFontFace> result = cache_->Get(description_italic, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities =
diff --git a/third_party/blink/renderer/core/css/font_face_set.cc b/third_party/blink/renderer/core/css/font_face_set.cc index f4e144d..49d5433 100644 --- a/third_party/blink/renderer/core/css/font_face_set.cc +++ b/third_party/blink/renderer/core/css/font_face_set.cc
@@ -184,7 +184,7 @@ f = f->Next()) { if (f->FamilyIsGeneric()) continue; - CSSSegmentedFontFace* segmented_font_face = + auto segmented_font_face = font_face_cache->Get(font.GetFontDescription(), f->FamilyName()); if (segmented_font_face) segmented_font_face->Match(text, faces); @@ -220,7 +220,7 @@ f = f->Next()) { if (f->FamilyIsGeneric()) continue; - CSSSegmentedFontFace* face = + auto face = font_face_cache->Get(font.GetFontDescription(), f->FamilyName()); if (face) { if (!face->CheckFont(text))
diff --git a/third_party/blink/renderer/core/css/offscreen_font_selector.cc b/third_party/blink/renderer/core/css/offscreen_font_selector.cc index fa1b592f..7b7d462 100644 --- a/third_party/blink/renderer/core/css/offscreen_font_selector.cc +++ b/third_party/blink/renderer/core/css/offscreen_font_selector.cc
@@ -12,7 +12,8 @@ namespace blink { OffscreenFontSelector::OffscreenFontSelector(WorkerGlobalScope* worker) - : worker_(worker) { + : CSSFontSelectorBase(worker->GetTaskRunner(TaskType::kInternalDefault)), + worker_(worker) { DCHECK(worker); font_face_cache_ = MakeGarbageCollected<FontFaceCache>(); FontCache::Get().AddClient(this); @@ -43,8 +44,7 @@ const FontDescription& font_description, const FontFamily& font_family) { const auto& family_name = font_family.FamilyName(); - if (CSSSegmentedFontFace* face = - font_face_cache_->Get(font_description, family_name)) { + if (auto face = font_face_cache_->Get(font_description, family_name)) { ReportWebFontFamily(family_name); return face->GetFontData(font_description); }
diff --git a/third_party/blink/renderer/core/css/remote_font_face_source.cc b/third_party/blink/renderer/core/css/remote_font_face_source.cc index 11d1ef1..cf944c61 100644 --- a/third_party/blink/renderer/core/css/remote_font_face_source.cc +++ b/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -28,6 +28,10 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h" #include "third_party/blink/renderer/platform/network/network_state_notifier.h" +#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" namespace blink { @@ -133,11 +137,16 @@ return kSwapPeriod; } -RemoteFontFaceSource::RemoteFontFaceSource(CSSFontFace* css_font_face, - FontSelector* font_selector, - FontDisplay display) +RemoteFontFaceSource::RemoteFontFaceSource( + CSSFontFace* css_font_face, + FontSelector* font_selector, + FontDisplay display, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) : face_(css_font_face), font_selector_(font_selector), +#if defined(USE_PARALLEL_TEXT_SHAPING) + task_runner_(task_runner), +#endif // No need to report the violation here since the font is not loaded yet display_( GetFontDisplayWithDocumentPolicyCheck(display, @@ -176,6 +185,7 @@ ExecutionContext* execution_context = font_selector_->GetExecutionContext(); if (!execution_context) return; + DCHECK(execution_context->IsContextThread()); // Prevent promise rejection while shutting down the document. // See crbug.com/960290 auto* window = DynamicTo<LocalDOMWindow>(execution_context); @@ -372,8 +382,29 @@ } void RemoteFontFaceSource::BeginLoadIfNeeded() { - if (IsLoaded() || !font_selector_->GetExecutionContext()) + if (IsLoaded()) return; + ExecutionContext* const execution_context = + font_selector_->GetExecutionContext(); + if (!execution_context) + return; +#if defined(USE_PARALLEL_TEXT_SHAPING) + if (!execution_context->IsContextThread()) { + // Following tests reache here. + // * fast/css3-text/css3-text-decoration/text-decoration-skip-ink-links.html + // * fast/css3-text/css3-word-break/word-break-break-all-in-span.html + // * virtual/text-antialias/justify-vertical.html + // * virtual/text-antialias/line-break-8bit-after-16bit.html + // Note: |ExecutionContext::GetTaskRunner()| works only for context + // thread, so we ask main thread to handle |BeginLoadIfNeeded()|. + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&RemoteFontFaceSource::BeginLoadIfNeeded, + WrapCrossThreadPersistent(this))); + return; + } +#endif + DCHECK(GetResource()); SetDisplay(face_->GetFontFace()->GetFontDisplay()); @@ -381,20 +412,19 @@ auto* font = To<FontResource>(GetResource()); if (font->StillNeedsLoad()) { if (font->IsLowPriorityLoadingAllowedForRemoteFont()) { - font_selector_->GetExecutionContext()->AddConsoleMessage( - MakeGarbageCollected<ConsoleMessage>( - mojom::ConsoleMessageSource::kIntervention, - mojom::ConsoleMessageLevel::kInfo, - "Slow network is detected. See " - "https://www.chromestatus.com/feature/5636954674692096 for more " - "details. Fallback font will be used while loading: " + - font->Url().ElidedString())); + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kIntervention, + mojom::blink::ConsoleMessageLevel::kInfo, + "Slow network is detected. See " + "https://www.chromestatus.com/feature/5636954674692096 for more " + "details. Fallback font will be used while loading: " + + font->Url().ElidedString())); // Set the loading priority to VeryLow only when all other clients agreed // that this font is not required for painting the text. font->DidChangePriority(ResourceLoadPriority::kVeryLow, 0); } - if (font_selector_->GetExecutionContext()->Fetcher()->StartLoad(font)) + if (execution_context->Fetcher()->StartLoad(font)) histograms_.LoadStarted(); } @@ -402,9 +432,7 @@ // Note that <link rel=preload> may have initiated loading without kicking // off the timers. font->StartLoadLimitTimersIfNecessary( - font_selector_->GetExecutionContext() - ->GetTaskRunner(TaskType::kInternalLoading) - .get()); + execution_context->GetTaskRunner(TaskType::kInternalLoading).get()); face_->DidBeginLoad(); }
diff --git a/third_party/blink/renderer/core/css/remote_font_face_source.h b/third_party/blink/renderer/core/css/remote_font_face_source.h index 7744db3..6fe503d 100644 --- a/third_party/blink/renderer/core/css/remote_font_face_source.h +++ b/third_party/blink/renderer/core/css/remote_font_face_source.h
@@ -23,7 +23,10 @@ public: enum Phase { kNoLimitExceeded, kShortLimitExceeded, kLongLimitExceeded }; - RemoteFontFaceSource(CSSFontFace*, FontSelector*, FontDisplay); + RemoteFontFaceSource(CSSFontFace*, + FontSelector*, + FontDisplay, + scoped_refptr<base::SingleThreadTaskRunner>); ~RemoteFontFaceSource() override; bool IsLoading() const override; @@ -148,6 +151,11 @@ Member<CSSFontFace> face_; Member<FontSelector> font_selector_; +#if defined(USE_PARALLEL_TEXT_SHAPING) + // Post `BeginLoadIfNeeded()` unless context thread. + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; +#endif + // |nullptr| if font is not loaded or failed to decode. scoped_refptr<FontCustomPlatformData> custom_font_data_; // |nullptr| if font is not loaded or failed to decode.
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 3c569934..7e24486 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -343,10 +343,10 @@ // There's only one font and it's bold and normal. EXPECT_EQ(1u, GetStyleEngine().GetFontSelector()->GetFontFaceCache() ->GetNumSegmentedFacesForTesting()); - CSSSegmentedFontFace* font_face = - GetStyleEngine().GetFontSelector()->GetFontFaceCache() - ->Get(t4->GetComputedStyle()->GetFontDescription(), - AtomicString("Cool Font")); + scoped_refptr<CSSSegmentedFontFace> font_face = + GetStyleEngine().GetFontSelector()->GetFontFaceCache()->Get( + t4->GetComputedStyle()->GetFontDescription(), + AtomicString("Cool Font")); EXPECT_TRUE(font_face); FontSelectionCapabilities capabilities = font_face->GetFontSelectionCapabilities();
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc index 5f0a6d0..ebf9336 100644 --- a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc +++ b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc
@@ -17,6 +17,8 @@ #include "third_party/blink/renderer/core/dom/pseudo_element.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/layout/layout_view.h" +#include "third_party/blink/renderer/core/page/page.h" +#include "third_party/blink/renderer/core/page/page_animator.h" #include "third_party/blink/renderer/core/paint/clip_path_clipper.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" @@ -467,6 +469,8 @@ // new elements in the DOM. InvalidateStyle(); + if (auto* page = document_->GetPage()) + page->Animator().SetHasSharedElementTransition(true); return true; } @@ -491,6 +495,8 @@ pending_shared_element_tags_.clear(); set_element_sequence_id_ = 0; document_->GetStyleEngine().SetDocumentTransitionTags({}); + if (auto* page = document_->GetPage()) + page->Animator().SetHasSharedElementTransition(false); } void DocumentTransitionStyleTracker::UpdateElementIndicesAndSnapshotId(
diff --git a/third_party/blink/renderer/core/events/build.gni b/third_party/blink/renderer/core/events/build.gni index 1009f6e..c8cf6ba 100644 --- a/third_party/blink/renderer/core/events/build.gni +++ b/third_party/blink/renderer/core/events/build.gni
@@ -89,3 +89,12 @@ "wheel_event.cc", "wheel_event.h", ] + +blink_core_tests_events = [ + "message_event_test.cc", + "mouse_event_test.cc", + "pointer_event_factory_test.cc", + "pointer_event_util_test.cc", + "touch_event_test.cc", + "web_input_event_conversion_test.cc", +]
diff --git a/third_party/blink/renderer/core/frame/build.gni b/third_party/blink/renderer/core/frame/build.gni index ead22ca..60c1df8 100644 --- a/third_party/blink/renderer/core/frame/build.gni +++ b/third_party/blink/renderer/core/frame/build.gni
@@ -245,3 +245,47 @@ "window_controls_overlay_changed_delegate.h", ] } + +blink_core_tests_frame = [ + "ad_tracker_test.cc", + "attribution_response_parsing_test.cc", + "attribution_src_loader_test.cc", + "browser_controls_test.cc", + "child_frame_compositing_helper_test.cc", + "csp/content_security_policy_test.cc", + "csp/conversion_util_test.cc", + "csp/csp_directive_list_test.cc", + "csp/csp_source_test.cc", + "csp/source_list_directive_test.cc", + "csp/trusted_types_directive_test.cc", + "deprecation/deprecation_report_body_test.cc", + "document_loading_rendering_test.cc", + "document_policy_violation_report_body_test.cc", + "dom_timer_test.cc", + "find_in_page_test.cc", + "frame_content_as_text_test.cc", + "frame_overlay_test.cc", + "frame_serializer_test.cc", + "frame_test.cc", + "history_util_test.cc", + "local_dom_window_test.cc", + "local_frame_back_forward_cache_test.cc", + "local_frame_client_impl_test.cc", + "local_frame_test.cc", + "local_frame_ukm_aggregator_test.cc", + "local_frame_view_test.cc", + "location_report_body_test.cc", + "mhtml_archive_test.cc", + "mhtml_loading_test.cc", + "performance_monitor_test.cc", + "policy_container_test.cc", + "report_test.cc", + "reporting_context_test.cc", + "root_frame_viewport_test.cc", + "rotation_viewport_anchor_test.cc", + "use_counter_impl_test.cc", + "visual_viewport_test.cc", + "web_frame_test.cc", + "web_frame_widget_test.cc", + "web_local_frame_client_test.cc", +]
diff --git a/third_party/blink/renderer/core/input/build.gni b/third_party/blink/renderer/core/input/build.gni index 151d49a95..4cc9464a 100644 --- a/third_party/blink/renderer/core/input/build.gni +++ b/third_party/blink/renderer/core/input/build.gni
@@ -36,3 +36,14 @@ "widget_event_handler.cc", "widget_event_handler.h", ] + +blink_core_tests_input = [ + "event_handler_test.cc", + "ime_on_focus_test.cc", + "mouse_event_manager_test.cc", + "overscroll_behavior_test.cc", + "pointer_event_manager_test.cc", + "scroll_snap_test.cc", + "touch_action_test.cc", + "touch_event_manager_test.cc", +]
diff --git a/third_party/blink/renderer/core/inspector/build.gni b/third_party/blink/renderer/core/inspector/build.gni index 10566582..2e50b1a 100644 --- a/third_party/blink/renderer/core/inspector/build.gni +++ b/third_party/blink/renderer/core/inspector/build.gni
@@ -123,3 +123,17 @@ "worker_thread_debugger.cc", "worker_thread_debugger.h", ] + +blink_core_tests_inspector = [ + "agent_registry_test.cc", + "inspector_contrast_test.cc", + "inspector_emulation_agent_test.cc", + "inspector_highlight_test.cc", + "inspector_history_test.cc", + "inspector_media_context_impl_unittest.cc", + "inspector_session_state_test.cc", + "inspector_style_resolver_test.cc", + "main_thread_debugger_test.cc", + "protocol_parser_test.cc", + "protocol_unittest.cc", +]
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc index 61916ac2..ebbd4250 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc
@@ -751,8 +751,6 @@ // tcy PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)), PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)), - PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)), - PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)), // "X" PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100)), PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100)))); @@ -776,8 +774,6 @@ // "a" PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)), PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)), - PhysicalRect(PhysicalOffset(25, 0), PhysicalSize(100, 100)), - PhysicalRect(PhysicalOffset(20, 0), PhysicalSize(110, 100)), // "X" PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100)), PhysicalRect(PhysicalOffset(25, 100), PhysicalSize(100, 100))));
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index 879c1b9d..6d01cdd 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -1313,15 +1313,15 @@ // additional_offset to be an offset from containing_block. // Since containing_block is our layout object, offset must be 0,0. // https://crbug.com/968019 - Vector<PhysicalRect> children_rects; + const wtf_size_t size_before = outline_rects->size(); AddOutlineRectsForNormalChildren( - &children_rects, PhysicalOffset(), outline_type, + outline_rects, PhysicalOffset(), outline_type, To<LayoutBoxModelObject>(GetLayoutObject())); if (!additional_offset.IsZero()) { - for (auto& rect : children_rects) + for (PhysicalRect& rect : + base::make_span(*outline_rects).subspan(size_before)) rect.offset += additional_offset; } - outline_rects->AppendVector(children_rects); for (const auto& child : PostLayoutChildren()) { if (child->IsOutOfFlowPositioned()) { AddOutlineRectsForDescendant(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc index c303bad..17840150 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -794,11 +794,13 @@ NGInlineCursor* cursor) const { const auto* const text_combine = DynamicTo<LayoutNGTextCombine>(containing_block); - for (; *cursor; cursor->MoveToNext()) { + while (*cursor) { DCHECK(cursor->Current().Item()); const NGFragmentItem& item = *cursor->Current().Item(); - if (UNLIKELY(item.IsLayoutObjectDestroyedOrMoved())) + if (UNLIKELY(item.IsLayoutObjectDestroyedOrMoved())) { + cursor->MoveToNext(); continue; + } switch (item.Type()) { case NGFragmentItem::kLine: { AddOutlineRectsForDescendant( @@ -832,10 +834,16 @@ AddOutlineRectsForDescendant( {child_box, item.OffsetInContainerFragment()}, outline_rects, additional_offset, outline_type, containing_block); + if (child_box->IsInlineBox()) { + // Inline boxes have their children in the flat list. Skip them. + cursor->MoveToNextSkippingChildren(); + continue; + } } break; } } + cursor->MoveToNext(); } }
diff --git a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc index 9d5c546b..031717d 100644 --- a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc +++ b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
@@ -117,9 +117,6 @@ ResourceLoaderOptions resource_loader_options( execution_context->GetCurrentWorld()); - if (execution_context->IsWorkerGlobalScope()) - resource_loader_options.request_initiator_context = kWorkerContext; - threadable_loader_ = MakeGarbageCollected<ThreadableLoader>( *execution_context, this, resource_loader_options); threadable_loader_->SetTimeout(resource_request.TimeoutInterval());
diff --git a/third_party/blink/renderer/core/page/build.gni b/third_party/blink/renderer/core/page/build.gni index ab63ce6d..c13851d 100644 --- a/third_party/blink/renderer/core/page/build.gni +++ b/third_party/blink/renderer/core/page/build.gni
@@ -108,3 +108,32 @@ "viewport_description.cc", "viewport_description.h", ] + +blink_core_tests_page = [ + "autoscroll_controller_test.cc", + "chrome_client_impl_test.cc", + "chrome_client_test.cc", + "context_menu_controller_test.cc", + "drag_controller_test.cc", + "drag_image_test.cc", + "focus_controller_test.cc", + "focusgroup_controller_test.cc", + "named_pages_mapper_test.cc", + "page_popup_client_test.cc", + "plugin_data_test.cc", + "print_context_test.cc", + "scrolling/element_fragment_anchor_test.cc", + "scrolling/main_thread_scrolling_reasons_test.cc", + "scrolling/root_scroller_test.cc", + "scrolling/scroll_into_view_test.cc", + "scrolling/scroll_metrics_test.cc", + "scrolling/scroll_state_test.cc", + "scrolling/scrolling_test.cc", + "scrolling/snap_coordinator_test.cc", + "slot_scoped_traversal_test.cc", + "spatial_navigation_test.cc", + "touch_adjustment_test.cc", + "validation_message_overlay_delegate_test.cc", + "viewport_test.cc", + "window_features_test.cc", +]
diff --git a/third_party/blink/renderer/core/page/page_animator.cc b/third_party/blink/renderer/core/page/page_animator.cc index 034216d..397b6e5 100644 --- a/third_party/blink/renderer/core/page/page_animator.cc +++ b/third_party/blink/renderer/core/page/page_animator.cc
@@ -103,12 +103,15 @@ animation_host->SetHasSmilAnimation(has_smil_animation_); animation_host->SetCurrentFrameHadRaf(current_frame_had_raf_); animation_host->SetNextFrameHasPendingRaf(next_frame_has_pending_raf_); + animation_host->SetHasSharedElementTransition( + has_shared_element_transition_); } has_canvas_invalidation_ = false; has_inline_style_mutation_ = false; has_smil_animation_ = false; current_frame_had_raf_ = false; // next_frame_has_pending_raf_ is reset at PostAnimate(). + // has_shared_element_transition_ is reset when the transition ends. } void PageAnimator::SetSuppressFrameRequestsWorkaroundFor704763Only( @@ -136,6 +139,11 @@ next_frame_has_pending_raf_ = true; } +void PageAnimator::SetHasSharedElementTransition( + bool has_shared_element_transition) { + has_shared_element_transition_ = has_shared_element_transition; +} + DISABLE_CFI_PERF void PageAnimator::ScheduleVisualUpdate(LocalFrame* frame) { if (servicing_animations_ || updating_layout_and_style_for_painting_ ||
diff --git a/third_party/blink/renderer/core/page/page_animator.h b/third_party/blink/renderer/core/page/page_animator.h index 7432037..d36d033d 100644 --- a/third_party/blink/renderer/core/page/page_animator.h +++ b/third_party/blink/renderer/core/page/page_animator.h
@@ -60,6 +60,7 @@ void SetHasSmilAnimation(); void SetCurrentFrameHadRaf(); void SetNextFrameHasPendingRaf(); + void SetHasSharedElementTransition(bool); void ReportFrameAnimations(cc::AnimationHost* animation_host); private: @@ -79,6 +80,8 @@ bool current_frame_had_raf_ = false; // True if there is a raf scheduled for the next frame. bool next_frame_has_pending_raf_ = false; + // True if there is an ongoing shared element transition. + bool has_shared_element_transition_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.h b/third_party/blink/renderer/modules/mediastream/user_media_processor.h index e8cbdb8..2390f9a 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_processor.h +++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.h
@@ -155,7 +155,7 @@ void OnStreamGenerated(int32_t request_id, blink::mojom::blink::MediaStreamRequestResult result, const String& label, - mojom::blink::StreamDevicesSetPtr streams_devices_set, + mojom::blink::StreamDevicesSetPtr stream_devices_set, bool pan_tilt_zoom_allowed); void GotAllVideoInputFormatsForDevice(
diff --git a/third_party/blink/renderer/platform/fonts/font_selector.cc b/third_party/blink/renderer/platform/fonts/font_selector.cc index 0df0d4f..4d996e6 100644 --- a/third_party/blink/renderer/platform/fonts/font_selector.cc +++ b/third_party/blink/renderer/platform/fonts/font_selector.cc
@@ -33,10 +33,13 @@ return g_empty_atom; if (IsWebkitBodyFamily(font_description)) { - // TODO(crbug.com/1065468): Remove this counter when it's no longer - // necessary. - UseCounter::Count(use_counter, - WebFeature::kFontSelectorCSSFontFamilyWebKitPrefixBody); + // TODO(yosin): We should make |use_counter| available for font threads. + if (use_counter) { + // TODO(crbug.com/1065468): Remove this counter when it's no longer + // necessary. + UseCounter::Count(use_counter, + WebFeature::kFontSelectorCSSFontFamilyWebKitPrefixBody); + } } else if (generic_family_name == font_family_names::kWebkitStandard && !generic_family.FamilyIsGeneric()) { // -webkit-standard is set internally only with a kGenericFamily type in
diff --git a/third_party/blink/renderer/platform/fonts/font_selector.h b/third_party/blink/renderer/platform/fonts/font_selector.h index fc2d7c85..da32354 100644 --- a/third_party/blink/renderer/platform/fonts/font_selector.h +++ b/third_party/blink/renderer/platform/fonts/font_selector.h
@@ -92,7 +92,7 @@ virtual void ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data) = 0; + scoped_refptr<SimpleFontData> resulting_font_data) = 0; // Called whenever a page attempts to find a local font based on a name. This // only includes lookups where the name is allowed to match PostScript names @@ -100,7 +100,7 @@ virtual void ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data, + scoped_refptr<SimpleFontData> resulting_font_data, bool is_loading_fallback = false) = 0; // Called whenever a page attempts to find a local font based on a fallback @@ -109,12 +109,12 @@ UChar32 fallback_character, FontFallbackPriority fallback_priority, const FontDescription& font_description, - SimpleFontData* resulting_font_data) = 0; + scoped_refptr<SimpleFontData> resulting_font_data) = 0; // Called whenever a page attempts to find a last-resort font. virtual void ReportLastResortFallbackFontLookup( const FontDescription& font_description, - SimpleFontData* resulting_font_data) = 0; + scoped_refptr<SimpleFontData> resulting_font_data) = 0; virtual void ReportNotDefGlyph() const = 0; @@ -137,6 +137,8 @@ const FontDescription&, const FontFamily& passed_family) = 0; + virtual bool IsContextThread() const = 0; + FontFallbackMap& GetFontFallbackMap(); void Trace(Visitor* visitor) const override;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index fd695ce2..a5c28b29 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -1944,8 +1944,7 @@ auto receiver = Context().TakePendingWorkerTimingReceiver( resource->GetResponse().RequestId()); info->SetWorkerTimingReceiver(std::move(receiver)); - if (resource->Options().request_initiator_context == kDocumentContext) - Context().AddResourceTiming(*info); + Context().AddResourceTiming(*info); } } @@ -2001,8 +2000,7 @@ if (scoped_refptr<ResourceTimingInfo> info = resource_timing_info_map_.Take(resource)) { PopulateAndAddResourceTimingInfo(resource, info, finish_time); - if (resource->Options().request_initiator_context == kDocumentContext) - Context().AddResourceTiming(*info); + Context().AddResourceTiming(*info); } resource->VirtualTimePauser().UnpauseVirtualTime();
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc index 89d650b2..4ea4ed39b 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc
@@ -40,7 +40,6 @@ scoped_refptr<const DOMWrapperWorld> world) : data_buffering_policy(kBufferData), content_security_policy_option(network::mojom::CSPDisposition::CHECK), - request_initiator_context(kDocumentContext), synchronous_policy(kRequestAsynchronously), parser_disposition(kParserInserted), cache_aware_loading_enabled(kNotCacheAwareLoadingEnabled),
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h index 4b6952ba..e505119 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
@@ -47,11 +47,6 @@ enum DataBufferingPolicy : uint8_t { kBufferData, kDoNotBufferData }; -enum RequestInitiatorContext : uint8_t { - kDocumentContext, - kWorkerContext, -}; - enum SynchronousPolicy : uint8_t { kRequestSynchronously, kRequestAsynchronously @@ -91,7 +86,6 @@ DataBufferingPolicy data_buffering_policy; network::mojom::CSPDisposition content_security_policy_option; - RequestInitiatorContext request_initiator_context; SynchronousPolicy synchronous_policy; // TODO(crbug.com/1064920): Remove this once PlzDedicatedWorker ships.
diff --git a/third_party/blink/renderer/platform/testing/font_test_helpers.cc b/third_party/blink/renderer/platform/testing/font_test_helpers.cc index 8f7e6046..46c4f45 100644 --- a/third_party/blink/renderer/platform/testing/font_test_helpers.cc +++ b/third_party/blink/renderer/platform/testing/font_test_helpers.cc
@@ -68,24 +68,25 @@ void ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data) override {} + scoped_refptr<SimpleFontData> resulting_font_data) override {} void ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - SimpleFontData* resulting_font_data, + scoped_refptr<SimpleFontData> resulting_font_data, bool is_loading_fallback = false) override {} void ReportFontLookupByFallbackCharacter( UChar32 hint, FontFallbackPriority fallback_priority, const FontDescription& font_description, - SimpleFontData* resulting_font_data) override {} + scoped_refptr<SimpleFontData> resulting_font_data) override {} void ReportLastResortFallbackFontLookup( const FontDescription& font_description, - SimpleFontData* resulting_font_data) override {} + scoped_refptr<SimpleFontData> resulting_font_data) override {} void ReportNotDefGlyph() const override {} void ReportEmojiSegmentGlyphCoverage(unsigned, unsigned) override {} ExecutionContext* GetExecutionContext() const override { return nullptr; } FontFaceCache* GetFontFaceCache() override { return nullptr; } + bool IsContextThread() const override { return true; } void RegisterForInvalidationCallbacks(FontSelectorClient*) override {} void UnregisterForInvalidationCallbacks(FontSelectorClient*) override {}
diff --git a/third_party/blink/tools/run_webgpu_cts.bat b/third_party/blink/tools/run_webgpu_cts.bat deleted file mode 100755 index fa276832..0000000 --- a/third_party/blink/tools/run_webgpu_cts.bat +++ /dev/null
@@ -1,6 +0,0 @@ -@echo off -:: Copyright 2021 The Chromium Authors. All rights reserved. -:: Use of this source code is governed by a BSD-style license that can be -:: found in the LICENSE file. - -vpython %~dp0\run_webgpu_cts.py %* \ No newline at end of file
diff --git a/third_party/blink/tools/run_webgpu_cts.py b/third_party/blink/tools/run_webgpu_cts.py deleted file mode 100755 index 2e3023b..0000000 --- a/third_party/blink/tools/run_webgpu_cts.py +++ /dev/null
@@ -1,9 +0,0 @@ -#!/usr/bin/env vpython -# Copyright 2021 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -from blinkpy.common import multiprocessing_bootstrap - -multiprocessing_bootstrap.run('..', '..', 'webgpu-cts', 'scripts', - 'run_webgpu_cts.py')
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=PendingBeaconAPI b/third_party/blink/web_tests/FlagExpectations/enable-features=PendingBeaconAPI similarity index 100% rename from third_party/blink/web_tests/FlagExpectations/enable-blink-features=PendingBeaconAPI rename to third_party/blink/web_tests/FlagExpectations/enable-features=PendingBeaconAPI
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index c118ddb8..2121b6e4 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -28,8 +28,6 @@ # Temporarily disabled for DevTools. crbug.com/1304217 http/tests/devtools/text-source-map.js [ Skip ] -crbug.com/1330482 http/tests/devtools/unit/viewport-datagrid-items-attached-to-dom.js [ Skip ] -crbug.com/1330482 http/tests/devtools/unit/viewport-datagrid-items-expandable-attached-to-dom.js [ Skip ] # Expected to time out. external/wpt/infrastructure/expected-fail/timeout.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index 0bff7d7..6868918 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: c801c26f4182f6e2fbf72ac3093a3746d8d50400 +Version: aa27d567c10dcdb2aea6884d5155dfaaa177a800
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 78bcbf9a..c184f90 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
@@ -15538,6 +15538,21 @@ ] ] }, + "css-tables": { + "tfoot-crash-print.html": [ + "00fa0070c507de945ae0653a3f5fcbb4e206185f", + [ + null, + [ + [ + "/common/blank.html", + "!=" + ] + ], + {} + ] + ] + }, "css-values": { "viewport-units-001-print.html": [ "3bff494e535b9101a11222a40a382384415eee3f", @@ -86567,6 +86582,19 @@ {} ] ], + "svg-with-transform.html": [ + "3aa7facf2d6a08e18a792b8739341b9bcc5014e5", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "table": { "break-after-table-cell-child.html": [ "60e09248923e633610555d533961b4f557f420b2", @@ -252622,6 +252650,12 @@ "1017427c5c28f582c92ba356af2153e4f9851a84", [] ], + "fedcm-manifest-not-in-list": { + "fedcm.json": [ + "9d919790050b4c0aaf8bd5a666ccf8a0ab40a40c", + [] + ] + }, "fedcm-mock.js": [ "955cb9727f4d6333336da89f7c274317c725a706", [] @@ -368349,7 +368383,7 @@ ] ], "fedcm-network-requests.sub.https.html": [ - "16da68b807932edd0128f15c25884f68d6da1f64", + "93899619e3f5dcbce6b7e5ef3d257e8e3a0827e1", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/tfoot-crash-print.html b/third_party/blink/web_tests/external/wpt/css/css-tables/tfoot-crash-print.html new file mode 100644 index 0000000..00fa007 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-tables/tfoot-crash-print.html
@@ -0,0 +1,33 @@ +<!-- quirks --> +<!-- + This is just a crashtest, but there's no way to express that in wpt right + now, so we just ensure we don't render blank +--> +<link rel="mismatch" href="/common/blank.html"> +<link rel="help" href="https://drafts.csswg.org/css-tables/"> +<style> + big { + font-size-adjust: 66; + border-right-style: dotted; + } +</style> +<script> + window.addEventListener('load', () => { + const table = document.createElement('table') + table.tFoot = document.getElementById('tfoot_0') + const element_0 = document.createElement('div') + table.appendChild(element_0) + document.documentElement.appendChild(table) + }) +</script> +</head> +<table> + <tfoot id='tfoot_0'> + <tr> + <tr readonly> + <caption> + <big></big> + </caption> + </tr> + </tfoot> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/crashtests/outline-scrollIntoView-crash.html b/third_party/blink/web_tests/external/wpt/css/css-ui/crashtests/outline-scrollIntoView-crash.html new file mode 100644 index 0000000..58bbd4c6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/crashtests/outline-scrollIntoView-crash.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<link rel="help" title="7.1. 'outline' property" href="http://www.w3.org/TR/css3-ui/#outline"> +<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org"> +<body onload="run_test()"> + <span id="root"></span> +<script> +function build_tree(n) { + let last_leaf = root; + for (let i = 0; i < n; ++i) { + const div = document.createElement('div'); + const inline_box = document.createElement('span'); + div.appendChild(inline_box); + last_leaf.appendChild(div); + last_leaf = inline_box; + } +} +build_tree(30); + +function run_test() { + root.scrollIntoView(); +} +</script> +</body>
diff --git a/third_party/blink/web_tests/flag-specific/enable-features=PendingBeaconAPI/pending_beacon/pending_beacon-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-features=PendingBeaconAPI/pending_beacon/pending_beacon-basic-expected.txt new file mode 100644 index 0000000..7404248 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-features=PendingBeaconAPI/pending_beacon/pending_beacon-basic-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE WARNING: The provided value 'FOO' is not a valid enum value of type BeaconMethod. +This is a testharness.js-based test. +PASS Basic configuration of a pending beacon. +PASS Verify that beacons default to POST if no options are provided. +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/enable-features=PendingBeaconAPI/pending_beacon/pending_beacon-deactivate-expected.txt b/third_party/blink/web_tests/flag-specific/enable-features=PendingBeaconAPI/pending_beacon/pending_beacon-deactivate-expected.txt new file mode 100644 index 0000000..96d96b9 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-features=PendingBeaconAPI/pending_beacon/pending_beacon-deactivate-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +PASS Tests deactivating a pending beacon +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/popups/popup-attribute-basic.tentative-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/popups/popup-attribute-basic.tentative-expected.txt index 481b2c2..6e885e2 100644 --- a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/popups/popup-attribute-basic.tentative-expected.txt +++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/popups/popup-attribute-basic.tentative-expected.txt
@@ -7,7 +7,7 @@ PASS The .showPopup() and .hidePopup() do NOT work on elements without a 'popup' attribute, <div>Non-popup</div>. PASS The .showPopup() and .hidePopup() do NOT work on elements without a 'popup' attribute, <div popup="popup">Non-popup</div>. PASS The .showPopup() and .hidePopup() do NOT work on elements without a 'popup' attribute, <div popup="invalid">Non-popup</div>. -FAIL IDL attribute reflection assert_equals: Invalid values should reflect as null expected (object) null but got (string) "" +FAIL IDL attribute reflection assert_equals: Attribute for "null" should still get set expected (string) "null" but got (object) null PASS Popup attribute value should be case insensitive PASS Changing attribute values for popup should work PASS Changing attribute values should close open popups
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-attached-to-dom-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-attached-to-dom-expected.txt index a3862dc0..a1b76ee 100644 --- a/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-attached-to-dom-expected.txt +++ b/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-attached-to-dom-expected.txt
@@ -6,7 +6,6 @@ a3 a4 a5 -a6 Scrolled down to 133px Nodes attached to dom: @@ -30,7 +29,6 @@ Scrolled down to 1000px - should be at bottom Nodes attached to dom: -a23 a24 a25 a26 @@ -46,7 +44,6 @@ a3 a4 a5 -a6 Testing removal of some nodes in viewport Should be missing node 0, 1, 3, 5 from dom: @@ -57,7 +54,6 @@ a7 a8 a9 -a10 Testing adding of some nodes back into viewport Nodes should be the same as previous dump because of throttling: @@ -68,7 +64,6 @@ a7 a8 a9 -a10 Should have nodes 0, 1, 3, 5 back in dom and previously added nodes removed: Nodes attached to dom: @@ -78,6 +73,5 @@ a3 a4 a5 -a6
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-expandable-attached-to-dom-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-expandable-attached-to-dom-expected.txt index f1fd2fe..0050c6c 100644 --- a/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-expandable-attached-to-dom-expected.txt +++ b/third_party/blink/web_tests/platform/generic/http/tests/devtools/unit/viewport-datagrid-items-expandable-attached-to-dom-expected.txt
@@ -7,7 +7,6 @@ a3 has children a4 a5 -a6 Expanding Node 3 and Node 24 Nodes attached to dom: @@ -17,7 +16,6 @@ a3 has children, expanded a3.0 depth: 1 a3.1 depth: 1 -a3.2 depth: 1 Collapsing Node 3 Nodes attached to dom: @@ -27,7 +25,6 @@ a3 has children a4 a5 -a6 Scrolled down to 220px Expanding Node 3 while not in dom @@ -39,7 +36,6 @@ a3 has children, expanded a3.0 depth: 1 a3.1 depth: 1 -a3.2 depth: 1 Moving node 0 to be a child of node 3 to make sure attributes adjust (name does not change) Nodes attached to dom: @@ -49,7 +45,6 @@ a0 depth: 1 a3.0 depth: 1 a3.1 depth: 1 -a3.2 depth: 1 Moving node that is attached to dom (node 0) to child of offscreen parent (node 24) Nodes attached to dom: @@ -59,11 +54,9 @@ a3.0 depth: 1 a3.1 depth: 1 a3.2 depth: 1 -a4 Scrolling down to 1000px - should be at bottom to make sure node 0 is attached properly to node 24 Nodes attached to dom: -a22 a23 a24 has children, expanded a0 depth: 1
diff --git a/third_party/blink/web_tests/webgpu/README.md b/third_party/blink/web_tests/webgpu/README.md index d8fd913..554acc70 100644 --- a/third_party/blink/web_tests/webgpu/README.md +++ b/third_party/blink/web_tests/webgpu/README.md
@@ -8,82 +8,21 @@ at different stages of implementation, and it is more useful to pin a particular revision of the CTS rather than use the latest version.) +Most of the WebGPU CTS runs on Chrome's infrastructure using the GPU Telemetry +harness (see content/test/gpu/gpu_tests/webgpu_cts_integration_test.py). Only +the reftests run using the web tests infrastructure. + An autoroller (https://autoroll.skia.org/r/webgpu-cts-chromium-autoroll) rolls the WebGPU CTS into Chromium regularly. Part of the roll requires regenerating a few files which the autoroller attempts to do. -1. `third_party/webgpu-cts/ts_sources.txt` is a generated file which tells GN the list of Typescript - sources that may impact compilation. -1. `third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html` is a generated file for WPT and - contains all of the "variants" the CTS is run with. It is generated with the script - `third_party/webgpu-cts/scripts/run_regenerate_internal_cts_html.py` based on a manual list of - tests to split into variants (`third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl`) - and `third_party/blink/web_tests/WebGPUExpectations`. +1. `third_party/webgpu-cts/ts_sources.txt` is a generated file which tells GN the list of Typescript sources to be transpiled to Javascript. +1. `third_party/webgpu-cts/resource_files.txt` is a generated file which tells GN the list of resources that should be included in the test isolate for CTS test pages to load. +1. `third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/**/*.html` are the +reftests and reference files which run on the web tests test infrastructure. -Should the autoroller fail, a manual roll is required. -See below for step-by-step instructions on performing a roll. +### Running reftests through WPT (Blink web_tests) -## How to manually roll the WebGPU CTS into Chromium - -1. Run `roll-dep --roll-to origin/main src/third_party/webgpu-cts/src`. This will produce a commit - that updates DEPS. -1. Run `third_party/webgpu-cts/scripts/gen_ts_dep_lists.py`, add any changes, and amend the previous - commit. GN requires us to include a list of all Typescript sources that will affect compilation. -1. Repeat until regeneration succeeds: - 1. Run `third_party/webgpu-cts/scripts/run_regenerate_internal_cts_html.py`. - 1. In `third_party/blink/web_tests/WebGPUExpectations`, - delete any expectations that caused regeneration errors - (or try to update them if there was a rename). -1. Commit changes, upload patch (ignore line-length warnings in generated files). -1. Run these tryjobs: `dawn-.*-deps-rel`. -1. Make sure there isn't anything terribly wrong - (e.g. a harness bug that causes all tests to fail, or not run at all). -1. Remove stale expectations: - 1. Look at the output of `webgpu_blink_web_tests` (and related) - on those tryjobs. - 1. Remove any expectations for "passed unexpectedly" test variants - in `WebGPUExpectations`. -1. Repeat until CQ passes: - 1. Look at output of `webgpu_blink_web_tests` on all bots. - 1. Look at the output of `webgpu_blink_web_tests` (and related) - on any failing bots. - 1. Add `WebGPUExpectations` lines for any test variants that - "failed unexpectedly" on any tryjob. - If they failed on all tryjobs, add them to the "Untriaged" section. - If they failed on a specific tryjob, add them to a platform-specific section. - 1. Fail and Skip expectations may be any valid WebGPU CTS test query. Other expectations - like Slow, Crash, and Timeout must list parameters in the same exact order that the - test runner loads them in. You can check the ordering by looking at the test code, or - by loading the standalone CTS runner in Chrome. - 1. If using a Slow, Crash, or Timeout expectation that is more precise than a whole variant, - it is necessary to **re-run `run_regenerate_internal_cts_html.py` - to automatically subdivide tests to fulfill the expectations**. - 1. If a test variant times out simply because it's very long, - add a test query to `third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl` - for one of its immediate children and re-run `run_regenerate_internal_cts_html.py`. - (TODO: Try to figure out if we can "ping" the harness to prevent - timeouts due to there being many CTS test cases in one WPT variant.) - 1. Run `dawn-.*-deps-rel`. -1. Get a review and land the CL! - -## Testing Locally - -This is not necessary for the roll process, but it can be useful to run tests locally. - -Chromium must be launched with `--enable-unsafe-webgpu` -(or `--enable-features=WebGPUService,WebGPU`). - -### Manually through standalone, without expectations - -- Open <https://gpuweb.github.io/cts/standalone/> - (or <http://localhost:8080/standalone/> if running the cts locally) - in the browser of your choice. - -(Note: reftests can be loaded this way, but they won't get compared against the -reference automatically. Use web_tests for that.) - -### Through WPT (Blink web_tests) - -(If you want to test unlanded changes to the WebGPU CTS, first check them out in +(If you want to test unlanded reftest changes to the WebGPU CTS, first check them out in `third_party/webgpu-cts/src`, then run `third_party/webgpu-cts/scripts/gen_ts_dep_lists.py` and `third_party/webgpu-cts/scripts/run_regenerate_internal_cts_html.py`.) @@ -99,7 +38,7 @@ #### Manually, without expectations - Run `third_party/blink/tools/run_blink_wptserve.py -t YOUR_TARGET` -- Open <http://localhost:8001/wpt_internal/webgpu/> in the browser of your choice. +- Open <http://localhost:8001/wpt_internal/webgpu/your_reftest.https.html> in the browser of your choice. #### Through the automated harness, with expectations @@ -115,10 +54,9 @@ - For backend validation, `--flag-specific` may be changed from `webgpu` to `webgpu-with-backend-validation` or `webgpu-with-partial-backend-validation`. -To run a particular test rather than the entire WebGPU CTS, add a test filter. -(Note, queries can't be more specific than "variants" already in `cts.https.html`). +To run a particular test rather than all the reftests, add a test filter. Examples: -- `--isolated-script-test-filter='wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,buffers,map:mapAsync,read:*'` -- `--isolated-script-test-filter='wpt_internal/webgpu/web_platform/reftests/canvas_clear.https.html'` +- `--isolated-script-test-filter='wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html` +- `--isolated-script-test-filter='wpt_internal/webgpu/web_platform/reftests/canvas_clear.https.html` Finally, to view the results, open `out/YOUR_TARGET/layout-test-results/results.html`.
diff --git a/third_party/blink/web_tests/webgpu/argsprefixes.txt b/third_party/blink/web_tests/webgpu/argsprefixes.txt deleted file mode 100644 index 294ecb3..0000000 --- a/third_party/blink/web_tests/webgpu/argsprefixes.txt +++ /dev/null
@@ -1 +0,0 @@ -?q=
diff --git a/third_party/blink/web_tests/webgpu/ctshtml-template.txt b/third_party/blink/web_tests/webgpu/ctshtml-template.txt deleted file mode 100644 index 7d3d169..0000000 --- a/third_party/blink/web_tests/webgpu/ctshtml-template.txt +++ /dev/null
@@ -1,53 +0,0 @@ -<!-- - This template lives in third_party/blink/web_tests/webgpu/. - - This template is a modified copy of templates/cts.https.html from the WebGPU CTS. - https://github.com/gpuweb/cts/blob/main/templates/cts.https.html - - Once autogenerated, this file functions identically to the default - cts.https.html generated by the WebGPU CTS, except it has a custom - variant list which breaks down the test cases further so that test - suppressions can be specific to individual tests or test cases. ---> - -<!doctype html> -<title>WebGPU CTS</title> -<meta charset=utf-8> -<link rel=help href='https://gpuweb.github.io/gpuweb/'> - -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<script> - const loadWebGPUExpectations = import('http://localhost:3000/webgpuCtsExpectations.js') - .then(m => m.expectations, () => { - console.error('Unable to connect to expectations server - running without expectations!'); - return []; - }); -</script> -<script type=module> - import { setBaseResourcePath } from '/gen/third_party/webgpu-cts/src/common/framework/resources.js'; - setBaseResourcePath('/gen/third_party/webgpu-cts/resources'); -</script> -<script type=module src=/gen/third_party/webgpu-cts/src/common/runtime/wpt.js></script> - -<!-- Manually-selected tests to run on worker: --> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mapAsync,write:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mapAsync,read:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mapAsync,read,typedArrayAccess:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mappedAtCreation:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:remapped_for_write:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map_detach:while_mapped:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,command_buffer,basic:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,command_buffer,copyBufferToBuffer:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,compute,basic:memcpy:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,compute,basic:large_dispatch:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,rendering,basic:clear:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,rendering,basic:fullscreen_quad:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,rendering,basic:large_draw:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,render_pass,storeOp:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,render_pass,storeop2:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,onSubmittedWorkDone:*'> -<meta name=variant content='?worker=1&q=webgpu:api,validation,buffer,destroy:*'> -<meta name=variant content='?worker=1&q=webgpu:api,validation,buffer,mapping:*'> - -<!-- Variant list is auto-generated below this line: -->
diff --git a/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl b/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl deleted file mode 100644 index ab55a05..0000000 --- a/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl +++ /dev/null
@@ -1,268 +0,0 @@ -# Copyright 2021 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This is a .pyl, or "Python Literal", file. You can treat it just like a -# .json file, with the following exceptions: -# * all keys must be quoted (use single quotes, please); -# * comments are allowed, using '#' syntax; and -# * trailing commas are allowed. - -# This is a list of manual test splits for the WebGPU CTS. They are added to workaround timeouts in the CTS due to -# large combinatoric tests with many parameterizations. -# Specifying a query will cause the parent of the the specified subtree to the expanded into separate WPT variants. -# For example, 'webgpu:some,path,to,file:foo:bar=2;*' will generate a variant for all values of bar. - -[ - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc1-rgba-unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc1-rgba-unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm";dstFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm-srgb";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm";dstFormat="bgra8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm-srgb";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32float";dstFormat="rgba32float";dimension="2d";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,validation,parse,var_and_let:initializer_type:variableOrConstant="var";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,validation,shader_io,shareable_types:io_shareable_type:storageClass="in";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="1d";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,createTexture:texture_usage:dimension="1d";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=0;first_instance=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=3;first_instance=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=6;first_instance=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=0;first_instance=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=3;first_instance=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=6;first_instance=0;*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="DepthTest";format="depth32float";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="zero";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="zero";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_aspect:compute=false;binding0InBundle=false;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_aspect:compute=true;binding0InBundle=false;*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint8x2";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint8x2";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=false;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=false;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=false;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=true;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=true;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=true;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=false;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=false;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=false;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=true;containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=true;containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=true;containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="read";containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="read";containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="read";containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="write";containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="write";containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="write";containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="read";containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="read";containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="read";containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="write";containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="write";containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="write";containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="read";containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="read";containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="read";containerType="vector";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="write";containerType="array";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="write";containerType="matrix";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="write";containerType="vector";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x3";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x3";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x4";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x2";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x3";shaderComponentCount=1;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x4";shaderComponentCount=1;*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint8x2";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint8x2";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rgba8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint8x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint8x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint8x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint8x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm8x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm8x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm8x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm8x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint16x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint16x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint16x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint16x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm16x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm16x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm16x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm16x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float16x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float16x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x3";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x3";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x4";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x2";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x3";arrayStride=256;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x4";arrayStride=256;*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint8x2";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r8unorm";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r8unorm";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint8x2";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint8x2";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint8x2";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,texture_related:format:method="WriteTexture";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:method="WriteTexture";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=0;*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=0;*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,blend_min_max:isAsync=false;component="color";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,blend_min_max:isAsync=true;component="color";*', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,memory_model,atomicity:atomicity:memType="atomic_storage";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,memory_model,atomicity:atomicity:memType="atomic_storage";testType="inter_workgroup"', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,memory_model,coherence:corr:memType="atomic_storage";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,memory_model,coherence:corr:memType="atomic_storage";testType="inter_workgroup"', - - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="uniform";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="uniform";vectorize="_undef_";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_r";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_r";vectorize="_undef_";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_rw";*', - 'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_rw";vectorize="_undef_";*', -]
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html deleted file mode 100644 index f55ad60..0000000 --- a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html +++ /dev/null
@@ -1,3917 +0,0 @@ -<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. --> -<!-- - This template lives in third_party/blink/web_tests/webgpu/. - - This template is a modified copy of templates/cts.https.html from the WebGPU CTS. - https://github.com/gpuweb/cts/blob/main/templates/cts.https.html - - Once autogenerated, this file functions identically to the default - cts.https.html generated by the WebGPU CTS, except it has a custom - variant list which breaks down the test cases further so that test - suppressions can be specific to individual tests or test cases. ---> - -<!doctype html> -<title>WebGPU CTS</title> -<meta charset=utf-8> -<link rel=help href='https://gpuweb.github.io/gpuweb/'> - -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<script> - const loadWebGPUExpectations = import('http://localhost:3000/webgpuCtsExpectations.js') - .then(m => m.expectations, () => { - console.error('Unable to connect to expectations server - running without expectations!'); - return []; - }); -</script> -<script type=module> - import { setBaseResourcePath } from '/gen/third_party/webgpu-cts/src/common/framework/resources.js'; - setBaseResourcePath('/gen/third_party/webgpu-cts/resources'); -</script> -<script type=module src=/gen/third_party/webgpu-cts/src/common/runtime/wpt.js></script> - -<!-- Manually-selected tests to run on worker: --> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mapAsync,write:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mapAsync,read:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mapAsync,read,typedArrayAccess:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:mappedAtCreation:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map:remapped_for_write:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,buffers,map_detach:while_mapped:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,command_buffer,basic:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,command_buffer,copyBufferToBuffer:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,compute,basic:memcpy:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,compute,basic:large_dispatch:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,rendering,basic:clear:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,rendering,basic:fullscreen_quad:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,rendering,basic:large_draw:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,render_pass,storeOp:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,render_pass,storeop2:*'> -<meta name=variant content='?worker=1&q=webgpu:api,operation,onSubmittedWorkDone:*'> -<meta name=variant content='?worker=1&q=webgpu:api,validation,buffer,destroy:*'> -<meta name=variant content='?worker=1&q=webgpu:api,validation,buffer,mapping:*'> - -<!-- Variant list is auto-generated below this line: --> - -<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:request_default_after_error:*'> -<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice_limits:unknown_limits:*'> -<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice_limits:supported_limits:*'> -<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice_limits:better_than_supported:*'> -<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice_limits:worse_than_default:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,write:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,write,unchanged_ranges_preserved:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,read:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,read,typedArrayAccess:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map:mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map:remapped_for_write:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map_ArrayBuffer:postMessage:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map_detach:while_mapped:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map_oom:mapAsync:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map_oom:mappedAtCreation,full_getMappedRange:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,map_oom:mappedAtCreation,smaller_getMappedRange:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,threading:serialize:*'> -<meta name=variant content='?q=webgpu:api,operation,buffers,threading:destroyed:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:empty:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:b2t2b:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:b2t2t2b:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,clearBuffer:clear:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:single:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:state_transitions:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:copy_order:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm";dstFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm";dstFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm";dstFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm";dstFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32float";dstFormat="rgba32float";dimension="2d";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32float";dstFormat="rgba32float";dimension="3d";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:zero_sized:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_depth_stencil:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_multisampled_color:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_multisampled_depth:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:undefined_params:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow_depth_stencil:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes_copy_depth_stencil:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_indices:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_order:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_before_pipeline:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:one_bind_group_multiple_slots:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_multiple_sets:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:compatible_pipelines:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_index_buffer_without_changing_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_vertex_buffer_without_changing_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:change_pipeline_before_and_after_vertex_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_vertex_buffer_but_not_used_in_draw:*'> -<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_index_buffer_before_non_indexed_draw:*'> -<meta name=variant content='?q=webgpu:api,operation,compute,basic:memcpy:*'> -<meta name=variant content='?q=webgpu:api,operation,compute,basic:large_dispatch:*'> -<meta name=variant content='?q=webgpu:api,operation,device,lost:not_lost_on_gc:*'> -<meta name=variant content='?q=webgpu:api,operation,device,lost:lost_on_destroy:*'> -<meta name=variant content='?q=webgpu:api,operation,device,lost:same_object:*'> -<meta name=variant content='?q=webgpu:api,operation,labels:object_has_descriptor_label:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:rw:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:wr:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:ww:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:rw:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:wr:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:ww:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_draws_in_the_same_render_pass:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_draws_in_the_same_render_bundle:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_dispatches_in_the_same_compute_pass:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw,single_pass,load_store:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw,single_pass,load_resolve:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:wr:*'> -<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:ww:*'> -<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:without_work:*'> -<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:with_work:*'> -<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:many,serial:*'> -<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:many,parallel:*'> -<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:many,parallel_order:*'> -<meta name=variant content='?q=webgpu:api,operation,pipeline,default_layout:getBindGroupLayout_js_object:*'> -<meta name=variant content='?q=webgpu:api,operation,pipeline,default_layout:incompatible_with_explicit:*'> -<meta name=variant content='?q=webgpu:api,operation,pipeline,default_layout:layout:*'> -<meta name=variant content='?q=webgpu:api,operation,queue,writeBuffer:array_types:*'> -<meta name=variant content='?q=webgpu:api,operation,queue,writeBuffer:multiple_writes_at_different_offsets_and_sizes:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:stored:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:loaded:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:srgb:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:layout:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,resolve:render_pass_resolve:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_with_depth_stencil_attachment:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,multiple_color_attachments:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,depth_stencil_attachment_only:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pass,storeop2:storeOp_controls_whether_1x1_drawn_quad_is_stored:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pipeline,culling_tests:culling:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,attachments:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count,blend:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pipeline,primitive_topology:basic:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pipeline,primitive_topology:unaligned_vertex_count:*'> -<meta name=variant content='?q=webgpu:api,operation,render_pipeline,vertex_only_render_pipeline:draw_depth_and_stencil_with_vertex_only_pipeline:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,basic:clear:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,basic:fullscreen_quad:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,basic:large_draw:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="zero";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="one";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="src";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="one-minus-src";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="src-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="one-minus-src-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="dst";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="one-minus-dst";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="dst-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="one-minus-dst-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="src-alpha-saturated";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="constant";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="color";srcFactor="one-minus-constant";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="zero";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="one";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="src";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="one-minus-src";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="src-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="one-minus-src-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="dst";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="one-minus-dst";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="dst-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="one-minus-dst-alpha";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="src-alpha-saturated";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="constant";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:GPUBlendComponent:component="alpha";srcFactor="one-minus-constant";*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:formats:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:clamp,blend_factor:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:clamp,blend_color:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,blending:clamp,blend_result:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_bias:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_disabled:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_write_disabled:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_compare_func:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,depth:reverse_depth:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,depth_clip_clamp:depth_clamp_and_clip:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,depth_clip_clamp:depth_test_input_clamped:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=0;first_instance=0;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=0;first_instance=2;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=3;first_instance=0;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=3;first_instance=2;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=6;first_instance=0;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=6;first_instance=2;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=0;first_instance=0;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=0;first_instance=2;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=3;first_instance=0;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=3;first_instance=2;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=6;first_instance=0;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=6;first_instance=2;*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:default_arguments:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:vertex_attributes,basic:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:vertex_attributes,formats:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,draw:largeish_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,rendering,indirect_draw:basics:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:partial_write_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:map_whole_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:map_partial_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:mapped_at_creation_whole_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:mapped_at_creation_partial_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:copy_buffer_to_buffer_copy_source:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:copy_buffer_to_texture:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:resolve_query_set_to_partial_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:copy_texture_to_partial_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:uniform_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:readonly_storage_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:storage_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:vertex_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:index_buffer:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:indirect_buffer_for_draw_indirect:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:indirect_buffer_for_dispatch_indirect:*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="1d";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="depth32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="depth16unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="stencil8";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="depth32float-stencil8";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="depth32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="depth16unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="stencil8";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="depth32float-stencil8";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="DepthTest";format="depth32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="DepthTest";format="depth16unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="DepthTest";format="depth24plus";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="DepthTest";format="depth24plus-stencil8";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="DepthTest";format="depth32float-stencil8";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="StencilTest";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,operation,sampling,anisotropy:anisotropic_filter_checkerboard:*'> -<meta name=variant content='?q=webgpu:api,operation,sampling,anisotropy:anisotropic_filter_mipmap_color:*'> -<meta name=variant content='?q=webgpu:api,operation,shader_module,compilation_info:compilationInfo_returns:*'> -<meta name=variant content='?q=webgpu:api,operation,shader_module,compilation_info:line_number_and_position:*'> -<meta name=variant content='?q=webgpu:api,operation,shader_module,compilation_info:offset_and_length:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,format_reinterpretation:texture_binding:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,format_reinterpretation:render_and_resolve_attachment:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,read:format:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,read:dimension:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,read:aspect:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,write:format:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,write:dimension:*'> -<meta name=variant content='?q=webgpu:api,operation,texture_view,write:aspect:*'> -<meta name=variant content='?q=webgpu:api,operation,uncapturederror:constructor:*'> -<meta name=variant content='?q=webgpu:api,operation,uncapturederror:iff_uncaptured:*'> -<meta name=variant content='?q=webgpu:api,operation,uncapturederror:only_original_device_is_event_target:*'> -<meta name=variant content='?q=webgpu:api,operation,uncapturederror:uncapturederror_from_non_originating_thread:*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint8x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint8x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm8x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm8x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint16x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint16x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="unorm16x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="snorm16x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float16x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x3";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x3";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x3";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x3";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="float32x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x3";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x3";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x3";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x3";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="uint32x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x2";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x2";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x2";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x2";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x3";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x3";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x3";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x3";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x4";shaderComponentCount=1;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x4";shaderComponentCount=2;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x4";shaderComponentCount=3;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:format="sint32x4";shaderComponentCount=4;*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="float32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="float32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:buffers_with_varying_step_mode:*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="float32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="float32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="float32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="float32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:discontiguous_location_and_attribs:*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="float32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:index_format,uint16:*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:index_format,uint32:*'> -<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:primitive_restart:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_and_bundle,color_format:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_and_bundle,color_count:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_and_bundle,color_sparse:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_and_bundle,depth_format:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_and_bundle,sample_count:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_format:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_count:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_sparse:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,depth_format:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,depth_stencil_read_only_write_state:*'> -<meta name=variant content='?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,sample_count:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,create:size:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,create:usage:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,create:createBuffer_invalid_and_oom:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:all_usages:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:error_buffer:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:twice:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:while_mapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,usage:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,invalidBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,destroyed:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mappingPending:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,sizeUnspecifiedOOB:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeAlignment:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeOOB:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,invalid_mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappedAgain:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,unmapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,destroyed:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappingPending:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,subrange,mapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,subrange,mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,offsetAndSizeAlignment,mapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,offsetAndSizeAlignment,mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,sizeAndOffsetOOB,mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,sizeAndOffsetOOB,mapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,disjointRanges:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,disjoinRanges_many:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,unmapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,destroyed:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,mapped:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,mappingPending:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:gc_behavior,mappedAtCreation:*'> -<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:gc_behavior,mapAsync:*'> -<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,depth_clip_control:createRenderPipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,query_types:createQuerySet:*'> -<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:texture_descriptor:*'> -<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:depth_stencil_state:*'> -<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:render_bundle_encoder_descriptor_depth_stencil_format:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_count_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_must_be_present_in_layout:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_must_contain_resource_defined_in_layout:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture_binding_must_have_correct_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture_must_have_correct_component_type:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture_must_have_correct_dimension:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer_offset_and_size_for_bind_groups_match:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:minBindingSize:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer,resource_state:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture,resource_state:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:bind_group_layout,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_resources,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:duplicate_bindings:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:visibility:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:multisampled_validation:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:max_dynamic_buffers:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_bind_group_layout:*'> -<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_pipeline_layout:*'> -<meta name=variant content='?q=webgpu:api,validation,createComputePipeline:basic_use_of_createComputePipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,createComputePipeline:shader_module_must_be_valid:*'> -<meta name=variant content='?q=webgpu:api,validation,createComputePipeline:shader_module_stage_must_be_compute:*'> -<meta name=variant content='?q=webgpu:api,validation,createComputePipeline:entry_point_name_must_match:*'> -<meta name=variant content='?q=webgpu:api,validation,createComputePipeline:pipeline_layout,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createComputePipeline:shader_module,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:number_of_dynamic_buffers_exceeds_the_maximum_value:*'> -<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:number_of_bind_group_layouts_exceeds_the_maximum_value:*'> -<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:bind_group_layouts,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:basic_use_of_createRenderPipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:create_vertex_only_pipeline_with_without_depth_stencil_state:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:at_least_one_color_state_is_required_for_complete_pipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:color_formats_must_be_renderable:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:depth_stencil_state,format:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:depth_stencil_state,depth_aspect,depth_test:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:depth_stencil_state,depth_aspect,depth_write:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:depth_stencil_state,stencil_aspect,stencil_test:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:depth_stencil_state,stencil_aspect,stencil_write:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:sample_count_must_be_valid:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,blend:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,format_blendable:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,blend_min_max:isAsync=false;component="color";*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,blend_min_max:isAsync=false;component="alpha";*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,blend_min_max:isAsync=true;component="color";*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_output_targets,blend_min_max:isAsync=true;component="alpha";*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:pipeline_layout,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:shader_module,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,createRenderPipeline:entry_point_name_must_match:*'> -<meta name=variant content='?q=webgpu:api,validation,createSampler:lodMinAndMaxClamp:*'> -<meta name=variant content='?q=webgpu:api,validation,createSampler:maxAnisotropy:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:zero_size:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:dimension_type_and_format_compatibility:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:mipLevelCount,format:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:mipLevelCount,bound_check:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:mipLevelCount,bound_check,bigger_than_integer_bit_width:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:sampleCount,various_sampleCount_with_all_formats:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="_undef_";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="1d";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="2d";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="3d";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,uncompressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,compressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,1d_texture:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,2d_texture,uncompressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,2d_texture,compressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,3d_texture,uncompressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,3d_texture,compressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_usage:dimension="_undef_";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_usage:dimension="1d";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_usage:dimension="2d";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_usage:dimension="3d";*'> -<meta name=variant content='?q=webgpu:api,validation,createTexture:viewFormats:*'> -<meta name=variant content='?q=webgpu:api,validation,createView:format:*'> -<meta name=variant content='?q=webgpu:api,validation,createView:dimension:*'> -<meta name=variant content='?q=webgpu:api,validation,createView:aspect:*'> -<meta name=variant content='?q=webgpu:api,validation,createView:array_layers:*'> -<meta name=variant content='?q=webgpu:api,validation,createView:mip_levels:*'> -<meta name=variant content='?q=webgpu:api,validation,createView:cube_faces_square:*'> -<meta name=variant content='?q=webgpu:api,validation,createView:texture_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,beginRenderPass:color_attachments,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,beginRenderPass:depth_stencil_attachment,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,beginRenderPass:occlusion_query_set,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,buffer_texture_copies:depth_stencil_format,copy_usage_and_aspect:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,buffer_texture_copies:depth_stencil_format,copy_buffer_size:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,buffer_texture_copies:depth_stencil_format,copy_buffer_offset:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:default_args:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:size_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:offset_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:overflow:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:out_of_bounds:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:set_pipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:pipeline,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:dispatch_sizes:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_size_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_offset_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_overflow:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_out_of_bounds:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_within_same_buffer:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_with_invalid_or_destroyed_texture:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:mipmap_level:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:sample_count:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:multisampled_copy_restrictions:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture_format_compatibility:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:depth_stencil_copy_restrictions:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_within_same_texture:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_aspects:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,debug:debug_group_balanced:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,debug:debug_group:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,debug:debug_marker:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,index_access:out_of_bounds:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,index_access:out_of_bounds_zero_sized_index_buffer:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:unused_buffer_bound:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:index_buffer_OOB:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:vertex_buffer_OOB:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:buffer_binding_overlap:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:last_buffer_setting_take_account:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,x_y_width_height_nonnegative:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,xy_rect_contained_in_attachment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,depth_rangeAndOrder:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setScissorRect,x_y_width_height_nonnegative:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setScissorRect,xy_rect_contained_in_attachment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setBlendConstant:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setStencilReference:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_offset_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_offset_oob:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:offset_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:offset_and_size_oob:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setPipeline:invalid_pipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setPipeline:pipeline,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:slot:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:offset_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:offset_and_size_oob:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:all_needed_vertex_buffer_should_be_bound:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:all_needed_index_buffer_should_be_bound:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:vertex_buffers_inherit_from_previous_pipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:vertex_buffers_do_not_inherit_between_render_passes:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:state_and_binding_index:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:bind_group,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_passed_but_not_expected:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_match_expectations_in_pass_encoder:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:u32array_start_and_length:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:valid_texture_formats:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:depth_stencil_readonly:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:depth_stencil_readonly_with_undefined_depth:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bind_groups_and_pipeline_layout_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:buffer_binding,render_pipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:sampler_binding,render_pipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_binding_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_visibility_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_resource_type_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,begin_end_balance:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,begin_end_invalid_nesting:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,disjoint_queries_with_same_query_index:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:nesting:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:occlusion_query,query_type:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:occlusion_query,invalid_query_set:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:occlusion_query,query_index:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:timestamp_query,query_type_and_index:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:timestamp_query,invalid_query_set:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:timestamp_query,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:queryset_and_destination_buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:first_query_and_query_count:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:destination_buffer_usage:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:destination_offset_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:resolve_buffer_oob:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:query_set_buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:empty_bundle_list:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:color_formats_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:depth_stencil_formats_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:depth_stencil_readonly_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:sample_count_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,error_scope:simple_case_where_the_error_scope_catches_an_error:*'> -<meta name=variant content='?q=webgpu:api,validation,error_scope:errors_bubble_to_the_parent_scope_if_not_handled_by_the_current_scope:*'> -<meta name=variant content='?q=webgpu:api,validation,error_scope:if_an_error_scope_matches_an_error_it_does_not_bubble_to_the_parent_scope:*'> -<meta name=variant content='?q=webgpu:api,validation,error_scope:if_no_error_scope_handles_an_error_it_fires_an_uncapturederror_event:*'> -<meta name=variant content='?q=webgpu:api,validation,error_scope:push,popping_sibling_error_scopes_must_be_balanced:*'> -<meta name=variant content='?q=webgpu:api,validation,error_scope:push,popping_nested_error_scopes_must_be_balanced:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:usage:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:bytes_per_row_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_rows_per_image:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:copy_end_overflows_u64:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="depth16unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="stencil8";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="WriteTexture";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="depth16unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="stencil8";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyB2T";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="r32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba8snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba8uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba8sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg11b10ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgb9e5ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rg32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba16uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba16sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba16float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba32uint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba32sint";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="rgba32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="depth32float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="depth16unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="stencil8";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc1-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc1-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc2-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc2-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc3-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc3-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc4-r-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc4-r-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc5-rg-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc5-rg-snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc6h-rgb-ufloat";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc6h-rgb-float";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc7-rgba-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="bc7-rgba-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="etc2-rgb8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="etc2-rgb8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="etc2-rgb8a1unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="etc2-rgba8unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="etc2-rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="eac-r11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="eac-r11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="eac-rg11unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="eac-rg11snorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-4x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-4x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-5x4-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-5x4-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-5x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-5x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-6x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-6x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-6x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-6x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-8x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-8x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-8x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-8x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-8x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-8x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x5-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x5-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x6-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x6-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x8-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x8-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-10x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-12x10-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-12x10-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-12x12-unorm";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:method="CopyT2B";format="astc-12x12-unorm-srgb";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:rows_per_image_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:offset_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_bytes_per_row:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_offset:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:valid:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:texture,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:usage:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:sample_count:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:mip_level:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:format:method="WriteTexture";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:format:method="CopyB2T";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:format:method="CopyT2B";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:method="WriteTexture";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:method="CopyB2T";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:method="CopyT2B";*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:size_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:copy_rectangle:*'> -<meta name=variant content='?q=webgpu:api,validation,initialization,requestDevice:features,nonexistent:*'> -<meta name=variant content='?q=webgpu:api,validation,initialization,requestDevice:features,known_but_unavailable:*'> -<meta name=variant content='?q=webgpu:api,validation,initialization,requestDevice:limits:*'> -<meta name=variant content='?q=webgpu:api,validation,query_set,create:count:*'> -<meta name=variant content='?q=webgpu:api,validation,query_set,destroy:twice:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:writeBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:copyBufferToBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:copyBufferToTexture:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:copyTextureToBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:map_command_recording_order:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_canvas,contexts:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_canvas,state:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_offscreenCanvas,contexts:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_offscreenCanvas,state:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_image,crossOrigin:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_imageBitmap,state:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,state:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,usage:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,sample_count:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,mipLevel:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,format:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:OOB,source:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:OOB,destination:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,destroyed,query_set:beginOcclusionQuery:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,destroyed,query_set:writeTimestamp:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,destroyed,query_set:resolveQuerySet:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,submit:command_buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:buffer_state:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:ranges:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:usages:*'> -<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:buffer,device_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass,resolve:resolve_attachment:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass,storeOp:store_op_and_read_only:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:a_render_pass_with_only_one_color_is_ok:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:a_render_pass_with_only_one_depth_attachment_is_ok:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:OOB_color_attachment_indices_are_handled:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:attachments_must_have_the_same_size:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:attachments_must_match_whether_they_are_used_for_color_or_depth_stencil:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:check_layer_count_for_color_or_depth_stencil:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:check_mip_level_count_for_color_or_depth_stencil:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:it_is_invalid_to_set_resolve_target_if_color_attachment_is_non_multisampled:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:check_the_use_of_multisampled_textures_as_color_attachments:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:it_is_invalid_to_use_a_multisampled_resolve_target:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:it_is_invalid_to_use_a_resolve_target_with_array_layer_count_greater_than_1:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:it_is_invalid_to_use_a_resolve_target_with_mipmap_level_count_greater_than_1:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:it_is_invalid_to_use_a_resolve_target_whose_usage_is_not_RENDER_ATTACHMENT:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:it_is_invalid_to_use_a_resolve_target_in_error_state:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:use_of_multisampled_attachment_and_non_multisampled_resolve_target_is_allowed:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:use_a_resolve_target_in_a_format_different_than_the_attachment_is_not_allowed:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:size_of_the_resolve_target_must_be_the_same_as_the_color_attachment:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:check_depth_stencil_attachment_sample_counts_mismatch:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:depth_stencil_attachment:*'> -<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:multisample_render_target_formats_support_resolve:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_compute_pass_with_no_dispatch:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_compute_pass_with_one_dispatch:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_compute_pass_with_two_dispatches:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_no_draw:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_one_draw:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_two_draws:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,reset_buffer_usage_before_dispatch:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,reset_buffer_usage_before_draw:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,buffer_usages_in_copy_and_pass:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_color:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_aspect:compute=false;binding0InBundle=false;*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_aspect:compute=false;binding0InBundle=true;*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_aspect:compute=true;binding0InBundle=false;*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:shader_stages_and_visibility:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:replaced_binding:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:bindings_in_bundle:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:unused_bindings_in_pipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:validation_scope,no_draw_or_dispatch:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:validation_scope,same_draw_or_dispatch:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:validation_scope,different_draws_or_dispatches:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:validation_scope,different_passes:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,color_attachments:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,color_attachment_and_bind_group:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,depth_stencil_attachment_and_bind_group:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,multiple_bind_groups:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,depth_stencil_texture_in_bind_groups:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_bind_group_on_same_index_color_texture:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_bind_group_on_same_index_depth_stencil_texture:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_unused_bind_group:*'> -<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,texture_usages_in_copy_and_render_pass:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,uncompressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,compressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,uncompressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,compressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createSampler:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBindGroupLayout:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBindGroup:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createPipelineLayout:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createShaderModule:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createComputePipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createRenderPipeline:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createCommandEncoder:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createRenderBundleEncoder:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createQuerySet:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToTexture:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToTexture:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,clearBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,writeTimestamp:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,resolveQuerySet:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,computePass,dispatch:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,draw:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,renderBundle:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeBuffer:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeTexture,2d,uncompressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeTexture,2d,compressed_format:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,copyExternalImageToTexture,canvas:*'> -<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,copyExternalImageToTexture,imageBitmap:*'> -<meta name=variant content='?q=webgpu:api,validation,texture,destroy:base:*'> -<meta name=variant content='?q=webgpu:api,validation,texture,destroy:twice:*'> -<meta name=variant content='?q=webgpu:api,validation,texture,destroy:submit_a_destroyed_texture_as_attachment:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:max_vertex_buffer_limit:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:max_vertex_attribute_limit:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:max_vertex_buffer_array_stride_limit:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_buffer_array_stride_limit_alignment:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_shaderLocation_limit:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_shaderLocation_unique:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_shader_input_location_limit:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_shader_input_location_in_vertex_state:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_shader_type_matches_attribute_format:*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint8x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint8x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint8x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint8x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint8x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint8x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint8x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint8x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm8x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm8x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm8x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm8x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm8x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm8x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm8x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm8x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint16x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint16x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint16x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint16x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint16x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint16x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint16x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint16x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm16x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm16x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm16x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="unorm16x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm16x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm16x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm16x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="snorm16x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float16x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float16x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float16x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float16x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x3";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x3";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="float32x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x3";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x3";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="uint32x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x2";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x2";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x3";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x3";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x4";arrayStride=256;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_offset_alignment:format="sint32x4";arrayStride=2048;*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint8x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint8x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint8x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint8x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="unorm8x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="unorm8x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="snorm8x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="snorm8x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint16x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint16x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint16x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint16x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="unorm16x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="unorm16x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="snorm16x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="snorm16x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="float16x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="float16x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="float32";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="float32x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="float32x3";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="float32x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint32";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint32x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint32x3";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="uint32x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint32";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint32x2";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint32x3";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:vertex_attribute_contained_in_stride:format="sint32x4";*'> -<meta name=variant content='?q=webgpu:api,validation,vertex_state:many_attributes_overlapping:*'> -<meta name=variant content='?q=webgpu:examples:test_name:*'> -<meta name=variant content='?q=webgpu:examples:not_implemented_yet,without_plan:*'> -<meta name=variant content='?q=webgpu:examples:not_implemented_yet,with_plan:*'> -<meta name=variant content='?q=webgpu:examples:basic:*'> -<meta name=variant content='?q=webgpu:examples:basic,async:*'> -<meta name=variant content='?q=webgpu:examples:basic,plain_cases:*'> -<meta name=variant content='?q=webgpu:examples:basic,plain_cases_private:*'> -<meta name=variant content='?q=webgpu:examples:basic,builder_cases:*'> -<meta name=variant content='?q=webgpu:examples:basic,builder_cases_subcases:*'> -<meta name=variant content='?q=webgpu:examples:basic,builder_subcases:*'> -<meta name=variant content='?q=webgpu:examples:basic,builder_subcases_short:*'> -<meta name=variant content='?q=webgpu:examples:gpu,async:*'> -<meta name=variant content='?q=webgpu:examples:gpu,buffers:*'> -<meta name=variant content='?q=webgpu:examples:gpu,with_texture_compression,bc:*'> -<meta name=variant content='?q=webgpu:examples:gpu,with_texture_compression,etc2:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:BufferUsage,count:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:BufferUsage,values:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:TextureUsage,count:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:TextureUsage,values:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:ColorWrite,count:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:ColorWrite,values:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:ShaderStage,count:*'> -<meta name=variant content='?q=webgpu:idl,constants,flags:ShaderStage,values:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_arith:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_logical:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_mixed:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:call:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:index_accessor:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:assignment:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:type_constructor:*'> -<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:member_accessor:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_or:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_and:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_exclusive_or:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:addition:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:subtraction:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:multiplication:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:division:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:modulus:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:equals:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:not_equals:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:less_than:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:less_equals:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:greater_than:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:greater_equals:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:abstract_int:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acos:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acos:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acos:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acosh:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acosh:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acosh:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,all:bool:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,any:bool:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,arrayLength:array:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asinh:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asinh:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asinh:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="uniform";vectorize="_undef_";*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="uniform";vectorize=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="uniform";vectorize=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="uniform";vectorize=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_r";vectorize="_undef_";*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_r";vectorize=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_r";vectorize=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_r";vectorize=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_rw";vectorize="_undef_";*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_rw";vectorize=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_rw";vectorize=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:storageClass="storage_rw";vectorize=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atanh:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atanh:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atanh:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAdd:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAdd:add:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAnd:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAnd:and:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicCompareExchangeWeak:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicCompareExchangeWeak:exchange:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicExchange:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicExchange:exchange:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicLoad:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicLoad:load:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMax:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMax:max:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMin:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMin:min:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicOr:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicOr:or:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicStore:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicStore:store:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicSub:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicSub:sub:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicXor:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicXor:xor:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ceil:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ceil:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ceil:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:abstract_int:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cos:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cos:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cos:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cosh:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cosh:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cosh:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countLeadingZeros:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countLeadingZeros:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countOneBits:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countOneBits:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countTrailingZeros:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countTrailingZeros:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cross:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cross:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cross:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,degrees:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,degrees:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,degrees:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,determinant:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,determinant:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,determinant:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:abstract_int:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdx:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdxCoarse:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdxFine:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdy:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdyCoarse:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdyFine:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp2:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp2:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp2:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,extractBits:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,extractBits:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstLeadingBit:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstLeadingBit:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstTrailingBit:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstTrailingBit:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,floor:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,floor:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,floor:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fma:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fma:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fma:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fract:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fract:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fract:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:scalar_f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:scalar_f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:vector_f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:vector_f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fwidth:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fwidthCoarse:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fwidthFine:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,insertBits:integer:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ldexp:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ldexp:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ldexp:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log2:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log2:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log2:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:abstract_int:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:abstract_int:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:matching_abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:matching_f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:scalar_f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:nonmatching_abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:nonmatching_f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:monmatching_f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:scalar_f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:scalar_f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:vector_f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:vector_f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack2x16float:pack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack2x16snorm:pack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack2x16unorm:pack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack4x8snorm:pack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack4x8unorm:pack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pow:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pow:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pow:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,quantizeToF16:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,radians:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,radians:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,radians:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reverseBits:u32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reverseBits:i32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,round:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,round:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,round:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,select:scalar:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,select:vector:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sign:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sign:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sign:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sin:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sin:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sin:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sinh:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sinh:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sinh:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,smoothstep:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,smoothstep:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,smoothstep:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sqrt:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sqrt:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sqrt:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,step:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,step:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,step:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,storageBarrier:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,storageBarrier:barrier:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tan:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tan:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tan:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tanh:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tanh:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tanh:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:sampled:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:depth:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:storage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:external:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:sampled_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:sampled_array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_1d:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_2d:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_3d:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:multisampled:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:depth:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:external:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:arrayed:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:sampled:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:arrayed:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:storage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLevels:sampled:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLevels:depth:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumSamples:sampled:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumSamples:depth:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:control_flow:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_1d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:control_flow:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:sampled_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:sampled_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:arrayed_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:arrayed_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:control_flow:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:arrayed_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:arrayed_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:control_flow:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:arrayed_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:arrayed_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_array_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:external:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_1d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_array_2d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_3d_coords:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,transpose:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,transpose:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,transpose:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,trunc:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,trunc:f32:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,trunc:f16:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack2x16float:unpack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack2x16snorm:unpack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack2x16unorm:unpack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack4x8snorm:unpack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack4x8unorm:unpack:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,workgroupBarrier:stage:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,workgroupBarrier:barrier:*'> -<meta name=variant content='?q=webgpu:shader,execution,expression,unary,f32_arithmetic:negation:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,atomicity:atomicity:memType="atomic_storage";testType="inter_workgroup"'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,atomicity:atomicity:memType="atomic_storage";testType="intra_workgroup";*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,atomicity:atomicity:memType="atomic_workgroup";*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_store_load:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_load_store:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_store_store:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corr:memType="atomic_storage";testType="inter_workgroup"'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corr:memType="atomic_storage";testType="inter_workgroup";extraFlags="rmw_variant";*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corr:memType="atomic_storage";testType="intra_workgroup";*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corr:memType="atomic_workgroup";*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:coww:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:cowr:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corw1:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corw2:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:message_passing:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:store:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:load_buffer:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:read:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:store_buffer:*'> -<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:2_plus_2_write:*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=false;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=false;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=false;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=true;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=true;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="write";access="write";dynamicOffset=true;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=false;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=false;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=false;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=true;containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=true;containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="uniform";access="read";dynamicOffset=true;containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="read";containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="read";containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="read";containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="write";containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="write";containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="private";access="write";containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="read";containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="read";containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="read";containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="write";containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="write";containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="function";access="write";containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="read";containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="read";containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="read";containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="write";containerType="array";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="write";containerType="matrix";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:storageClass="workgroup";access="write";containerType="vector";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";*'> -<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";*'> -<meta name=variant content='?q=webgpu:shader,execution,sampling,gradients_in_varying_loop:derivative_in_varying_loop:*'> -<meta name=variant content='?q=webgpu:shader,execution,shader_io,compute_builtins:inputs:*'> -<meta name=variant content='?q=webgpu:shader,execution,shader_io,shared_structs:shared_with_buffer:*'> -<meta name=variant content='?q=webgpu:shader,execution,shader_io,shared_structs:shared_between_stages:*'> -<meta name=variant content='?q=webgpu:shader,execution,shader_io,shared_structs:shared_with_non_entry_point_function:*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,1];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,32,1];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[64,1,1];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,48];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,47,1];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[33,1,1];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[1,1,63];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=30;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=31;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=0;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=1;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=2;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=3;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=4;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=5;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=6;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=7;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=8;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=9;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=10;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=11;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=12;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=13;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=14;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=15;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=16;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=17;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=18;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=19;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=20;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=21;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=22;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=23;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=24;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=25;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=26;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=27;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=28;*'> -<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=29;*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,blankspace:null_characters:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,blankspace:blankspace:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,comments:comments:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,comments:line_comment_terminators:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,comments:unterminated_block_comment:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,identifiers:identifiers:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,identifiers:non_normalized:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,literal:bools:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,literal:abstract_int:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,literal:i32:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,literal:u32:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,literal:abstract_float:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,literal:f32:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,literal:f16:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,source:valid_source:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,source:empty:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,source:invalid_source:*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,var_and_let:initializer_type:variableOrConstant="var";*'> -<meta name=variant content='?q=webgpu:shader,validation,parse,var_and_let:initializer_type:variableOrConstant="let";*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:stage_inout:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:type:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:nesting:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:duplicates:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:missing_vertex_position:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:type_and_sampling:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:require_location:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:integral_types:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:duplicate:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:valid_only_with_vertex_position_builtin:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:not_valid_on_user_defined_io:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:invalid_use_of_parameters:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:duplicate:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:stage_inout:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:type:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:nesting:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:duplicates:*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,shareable_types:io_shareable_type:storageClass="in";*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,shareable_types:io_shareable_type:storageClass="out";*'> -<meta name=variant content='?q=webgpu:shader,validation,shader_io,shareable_types:io_shareable_type:storageClass="private";*'> -<meta name=variant content='?q=webgpu:util,texture,texel_data:unorm_texel_data_in_shader:*'> -<meta name=variant content='?q=webgpu:util,texture,texel_data:snorm_texel_data_in_shader:*'> -<meta name=variant content='?q=webgpu:util,texture,texel_data:uint_texel_data_in_shader:*'> -<meta name=variant content='?q=webgpu:util,texture,texel_data:sint_texel_data_in_shader:*'> -<meta name=variant content='?q=webgpu:util,texture,texel_data:float_texel_data_in_shader:*'> -<meta name=variant content='?q=webgpu:util,texture,texel_data:ufloat_texel_data_in_shader:*'> -<meta name=variant content='?q=webgpu:util,texture,texture_ok:float32:*'> -<meta name=variant content='?q=webgpu:util,texture,texture_ok:norm:*'> -<meta name=variant content='?q=webgpu:util,texture,texture_ok:snorm_min:*'> -<meta name=variant content='?q=webgpu:web_platform,canvas,context_creation:return_type:*'> -<meta name=variant content='?q=webgpu:web_platform,canvas,getCurrentTexture:multiple_frames:*'> -<meta name=variant content='?q=webgpu:web_platform,canvas,getPreferredFormat:value:*'> -<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:onscreenCanvas,snapshot:*'> -<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:onscreenCanvas,uploadToWebGL:*'> -<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:offscreenCanvas,snapshot:*'> -<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:drawTo2DCanvas:*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";*'> -<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:color_space_conversion:*'> -<meta name=variant content='?q=webgpu:web_platform,external_texture,video:importExternalTexture,sample:*'> -<meta name=variant content='?q=webgpu:web_platform,external_texture,video:importExternalTexture,expired:*'> -<meta name=variant content='?q=webgpu:web_platform,external_texture,video:importExternalTexture,compute:*'> -<meta name=variant content='?q=webgpu:web_platform,worker,worker:worker:*'>
diff --git a/third_party/expat/fuzz/OWNERS b/third_party/expat/fuzz/OWNERS index 4116061..bc960c08 100644 --- a/third_party/expat/fuzz/OWNERS +++ b/third_party/expat/fuzz/OWNERS
@@ -1 +1 @@ -ochang@chromium.org +bookholt@chromium.org
diff --git a/third_party/libFuzzer/OWNERS b/third_party/libFuzzer/OWNERS index c1cc0d6..4422eda 100644 --- a/third_party/libFuzzer/OWNERS +++ b/third_party/libFuzzer/OWNERS
@@ -1,4 +1,2 @@ -inferno@chromium.org kcc@chromium.org metzman@chromium.org -ochang@chromium.org
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index 662325b25..294a37d3 100644 --- a/third_party/metrics_proto/README.chromium +++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Metrics Protos Short Name: metrics_proto URL: This is the canonical public repository -Version: 453427486 -Date: 2022/06/07 UTC +Version: 453819681 +Date: 2022/06/09 UTC License: BSD Security Critical: Yes
diff --git a/third_party/metrics_proto/system_profile.proto b/third_party/metrics_proto/system_profile.proto index ed3ee3e..f406bf4 100644 --- a/third_party/metrics_proto/system_profile.proto +++ b/third_party/metrics_proto/system_profile.proto
@@ -229,7 +229,7 @@ optional OS os = 5; // Information on the user's hardware. - // Next tag: 26 + // Next tag: 27 message Hardware { // OS CPU architecture. Taken from uname -m and modified in Chromium logic. // Common options are: x86, x86_64, armv7l, armv8l, aarch64. @@ -448,6 +448,10 @@ TPM_TYPE_RUNTIME_SELECTION = 4; } optional TpmType tpm_type = 23; + + // Firmware version of the TPM on the device. This field is only filled in + // on ChromeOS devices (both CrOS and LaCrOS platforms). + optional uint64 tpm_firmware_version = 26; } optional Hardware hardware = 6;
diff --git a/third_party/nearby/BUILD.gn b/third_party/nearby/BUILD.gn index 5950eed..d773a6f5 100644 --- a/third_party/nearby/BUILD.gn +++ b/third_party/nearby/BUILD.gn
@@ -29,25 +29,12 @@ # src/internal/analytics ############################################################################### # src/internal/analytics -source_set("analytics") { +source_set("analytics_event_logger") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] - sources = [ "src/internal/analytics/analytics_recorder.cc" ] - public = [ "src/internal/analytics/analytics_recorder.h" ] - public_deps = [ - ":connections_enums_proto", - ":connections_event_logger", - ":connections_log_proto", - ":connections_types", - ":error_code_enums_proto", - ":platform_base", - ":platform_base_error_code_recorder", - ":platform_public_logging", - ":platform_public_types", - "//third_party/abseil-cpp:absl", - ] + public = [ "src/internal/analytics/event_logger.h" ] configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } @@ -64,8 +51,8 @@ sources = [ "src/connections/core.cc" ] public = [ "src/connections/core.h" ] public_deps = [ + ":analytics_event_logger", ":connections_enums_proto", - ":connections_event_logger", ":connections_implementation", ":connections_types", ":platform_public_comm", @@ -86,6 +73,7 @@ "src/connections/connection_options.cc", "src/connections/discovery_options.cc", "src/connections/payload.cc", + "src/connections/status.cc", "src/connections/strategy.cc", ] public = [ @@ -112,16 +100,6 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } -source_set("connections_event_logger") { - public_configs = [ - ":nearby_include_config", - ":nearby_defines", - ] - public = [ "src/connections/event_logger.h" ] - public_deps = [ ":connections_log_proto" ] - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ "//build/config/compiler:no_chromium_code" ] -} # src/connections/implementation source_set("connections_implementation") { @@ -135,6 +113,7 @@ "src/connections/implementation/base_pcp_handler.cc", "src/connections/implementation/ble_advertisement.cc", "src/connections/implementation/ble_endpoint_channel.cc", + "src/connections/implementation/ble_v2_endpoint_channel.cc", "src/connections/implementation/bluetooth_bwu_handler.cc", "src/connections/implementation/bluetooth_device_name.cc", "src/connections/implementation/bluetooth_endpoint_channel.cc", @@ -169,6 +148,7 @@ "src/connections/implementation/base_pcp_handler.h", "src/connections/implementation/ble_advertisement.h", "src/connections/implementation/ble_endpoint_channel.h", + "src/connections/implementation/ble_v2_endpoint_channel.h", "src/connections/implementation/bluetooth_bwu_handler.h", "src/connections/implementation/bluetooth_device_name.h", "src/connections/implementation/bluetooth_endpoint_channel.h", @@ -204,8 +184,8 @@ "src/connections/implementation/wifi_lan_service_info.h", ] public_deps = [ - ":analytics", ":connections_enums_proto", + ":connections_implementation_analytics", ":connections_implementation_mediums", ":connections_implementation_mediums_webrtc", ":connections_types", @@ -238,6 +218,30 @@ ] } +# src/connections/implementation/analytics +source_set("connections_implementation_analytics") { + public_configs = [ + ":nearby_include_config", + ":nearby_defines", + ] + sources = [ "src/connections/implementation/analytics/analytics_recorder.cc" ] + public = [ "src/connections/implementation/analytics/analytics_recorder.h" ] + public_deps = [ + ":analytics_event_logger", + ":connections_enums_proto", + ":connections_log_proto", + ":connections_types", + ":error_code_enums_proto", + ":platform_base", + ":platform_base_error_code_recorder", + ":platform_public_logging", + ":platform_public_types", + "//third_party/abseil-cpp:absl", + ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +} + # src/connections/implementation/mediums source_set("connections_implementation_mediums") { public_configs = [ @@ -246,32 +250,36 @@ ] sources = [ "src/connections/implementation/mediums/ble.cc", + "src/connections/implementation/mediums/ble_v2.cc", "src/connections/implementation/mediums/ble_v2/advertisement_read_result.cc", "src/connections/implementation/mediums/ble_v2/ble_advertisement.cc", "src/connections/implementation/mediums/ble_v2/ble_advertisement_header.cc", "src/connections/implementation/mediums/ble_v2/ble_packet.cc", + "src/connections/implementation/mediums/ble_v2/ble_utils.cc", "src/connections/implementation/mediums/ble_v2/bloom_filter.cc", + "src/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.cc", "src/connections/implementation/mediums/bluetooth_classic.cc", "src/connections/implementation/mediums/bluetooth_radio.cc", "src/connections/implementation/mediums/mediums.cc", - "src/connections/implementation/mediums/uuid.cc", "src/connections/implementation/mediums/webrtc.cc", "src/connections/implementation/mediums/wifi_hotspot.cc", "src/connections/implementation/mediums/wifi_lan.cc", ] public = [ "src/connections/implementation/mediums/ble.h", + "src/connections/implementation/mediums/ble_v2.h", "src/connections/implementation/mediums/ble_v2/advertisement_read_result.h", "src/connections/implementation/mediums/ble_v2/ble_advertisement.h", "src/connections/implementation/mediums/ble_v2/ble_advertisement_header.h", "src/connections/implementation/mediums/ble_v2/ble_packet.h", - "src/connections/implementation/mediums/ble_v2/ble_peripheral.h", + "src/connections/implementation/mediums/ble_v2/ble_utils.h", "src/connections/implementation/mediums/ble_v2/bloom_filter.h", + "src/connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h", + "src/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.h", "src/connections/implementation/mediums/bluetooth_classic.h", "src/connections/implementation/mediums/bluetooth_radio.h", "src/connections/implementation/mediums/lost_entity_tracker.h", "src/connections/implementation/mediums/mediums.h", - "src/connections/implementation/mediums/uuid.h", "src/connections/implementation/mediums/webrtc.h", "src/connections/implementation/mediums/wifi_hotspot.h", "src/connections/implementation/mediums/wifi_lan.h", @@ -391,6 +399,7 @@ ":offline_wire_formats_proto", ":platform_base", ":platform_base_cancellation_flag", + ":platform_base_uuid", "//third_party/abseil-cpp:absl", "//third_party/webrtc_overrides:webrtc_component", ] @@ -407,7 +416,6 @@ "src/internal/platform/implementation/atomic_reference.h", "src/internal/platform/implementation/cancelable.h", "src/internal/platform/implementation/condition_variable.h", - "src/internal/platform/implementation/count_down_latch.h", "src/internal/platform/implementation/crypto.h", "src/internal/platform/implementation/executor.h", "src/internal/platform/implementation/future.h", @@ -497,6 +505,17 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } +source_set("platform_base_uuid") { + public_configs = [ + ":nearby_include_config", + ":nearby_defines", + ] + sources = [ "src/internal/platform/uuid.cc" ] + public = [ "src/internal/platform/uuid.h" ] + public_deps = [ ":platform_api_types" ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +} source_set("platform_base_util") { public_configs = [ ":nearby_include_config", @@ -620,23 +639,28 @@ ] sources = [ "src/internal/platform/ble.cc", + "src/internal/platform/ble_v2.cc", "src/internal/platform/bluetooth_classic.cc", "src/internal/platform/file.cc", "src/internal/platform/wifi_hotspot.cc", "src/internal/platform/wifi_lan.cc", + "src/internal/platform/wifi_utils.cc", ] public = [ "src/internal/platform/ble.h", + "src/internal/platform/ble_v2.h", "src/internal/platform/bluetooth_adapter.h", "src/internal/platform/bluetooth_classic.h", "src/internal/platform/webrtc.h", "src/internal/platform/wifi_hotspot.h", "src/internal/platform/wifi_lan.h", + "src/internal/platform/wifi_utils.h", ] public_deps = [ ":platform_api_comm", ":platform_api_platform", ":platform_base", + ":platform_base_uuid", ":platform_public_logging", ":platform_public_types", "//third_party/abseil-cpp:absl",
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index 3fb5af11..dd72fb0 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby -URL: https://github.com/google/nearby-connections -Version: 6347f80a1196ea15ee18ff6d0fd1917f1cb2b404 +URL: https://github.com/google/nearby +Version: d8453565db739ebbfbbeade9ec8f8239057b1e13 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/webgpu-cts/BUILD.gn b/third_party/webgpu-cts/BUILD.gn index e4a7a1e..128fecf6 100644 --- a/third_party/webgpu-cts/BUILD.gn +++ b/third_party/webgpu-cts/BUILD.gn
@@ -89,13 +89,9 @@ script = "scripts/run_regenerate_internal_cts_html.py" inputs = [ "scripts/compile_src.py", - "scripts/run_webgpu_cts.py", "scripts/tsc_ignore_errors.py", "scripts/regenerate_internal_cts_html.py", "//third_party/node/node.py", - "//third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html", - "//third_party/blink/web_tests/webgpu/ctshtml-template.txt", - "//third_party/blink/web_tests/webgpu/argsprefixes.txt", ] + ts_source_inputs outputs = [ "$target_out_dir/run_$target_name.stamp" ]
diff --git a/third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py b/third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py index 9de79b99..fb925e77 100755 --- a/third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py +++ b/third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py
@@ -30,82 +30,6 @@ with open(filepath, 'wb') as dst: dst.write(content) - -def generate_internal_cts_html(check): - split_list_fd, split_list_fname = tempfile.mkstemp() - cts_html_fd, cts_html_fname = tempfile.mkstemp() - js_out_dir = tempfile.mkdtemp() - contents = None - try: - logging.info('WebGPU CTS: Extracting expectation names...') - old_sys_path = sys.path - try: - sys.path = old_sys_path + [ - os.path.join(third_party_dir, 'blink', 'tools') - ] - - from run_webgpu_cts import split_cts_expectations_and_web_test_expectations - finally: - sys.path = old_sys_path - - with open( - os.path.join(third_party_dir, 'blink', 'web_tests', - 'WebGPUExpectations')) as f: - web_test_expectations = split_cts_expectations_and_web_test_expectations( - f.read())['web_test_expectations']['expectations'] - - logging.info('WebGPU CTS: Reading manual test splits...') - with open( - os.path.join(third_party_dir, 'blink', 'web_tests', 'webgpu', - 'internal_cts_test_splits.pyl')) as f: - manual_splits = ast.literal_eval(f.read()) - - with open(split_list_fname, 'w') as split_list_out: - for expectation in web_test_expectations: - if expectation.test: - split_list_out.write('%s\n' % expectation.test) - for test in manual_splits: - split_list_out.write('%s\n' % test) - - logging.info('WebGPU CTS: Transpiling tools...') - compile_src_for_node(js_out_dir) - - old_sys_path = sys.path - try: - sys.path = old_sys_path + [os.path.join(third_party_dir, 'node')] - from node import RunNode - finally: - sys.path = old_sys_path - - logging.info('WebGPU CTS: Generating cts.https.html...') - cmd = [ - os.path.join(js_out_dir, - 'common/tools/gen_wpt_cts_html.js'), cts_html_fname, - os.path.join(third_party_dir, 'blink', 'web_tests', 'webgpu', - 'ctshtml-template.txt'), - os.path.join(third_party_dir, 'blink', 'web_tests', 'webgpu', - 'argsprefixes.txt'), split_list_fname, - 'wpt_internal/webgpu/cts.https.html', 'webgpu' - ] - logging.info(RunNode(cmd)) - - with open(cts_html_fname, 'rb') as f: - contents = f.read() - - finally: - os.close(split_list_fd) - os.close(cts_html_fd) - shutil.rmtree(js_out_dir) - - out_cts_html = os.path.join(third_party_dir, 'blink', 'web_tests', - 'wpt_internal', 'webgpu', 'cts.https.html') - - if not contents: - raise RuntimeError('Failed to generate %s' % out_cts_html) - - check_or_write_file(out_cts_html, contents, check=check) - - def generate_reftest_html(check): # Update this to add/remove subdirectories to check. sub_dirs = ['web_platform'] @@ -170,7 +94,6 @@ parser.add_argument('--stamp', help='Stamp file to write after success.') args = parser.parse_args() - generate_internal_cts_html(check=args.check) generate_reftest_html(check=args.check) if args.stamp:
diff --git a/third_party/webgpu-cts/scripts/run_webgpu_cts.py b/third_party/webgpu-cts/scripts/run_webgpu_cts.py deleted file mode 100644 index 0892226b..0000000 --- a/third_party/webgpu-cts/scripts/run_webgpu_cts.py +++ /dev/null
@@ -1,257 +0,0 @@ -# Copyright 2021 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import json -from six.moves import BaseHTTPServer -from six.moves import urllib -import sys -from tempfile import mkstemp -import threading -import os -import logging - -# This script is run via //third_party/blink/tools/run_webgpu_cts.py which -# adds blinkpy to the Python path. -from blinkpy.common import path_finder -from blinkpy.common.host import Host -from blinkpy.web_tests import run_web_tests - -path_finder.add_typ_dir_to_sys_path() -from typ.expectations_parser import TaggedTestListParser, Expectation -from typ.json_results import ResultType - - -# Basic HTTP request handler to serve the WebGPU webgpuCtsExpectations.js file -class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def __init__(self, *args, **kwargs): - BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kwargs) - - def do_GET(self): - if self.path == "/webgpuCtsExpectations.js": - self.send_response(200) - self.send_header('Access-Control-Allow-Origin', '*') - self.send_header('Content-Type', 'application/javascript') - self.end_headers() - self.wfile.write(self.server.expectations_js.encode()) - elif self.path == '/_start' or self.path == '/_stop': - self.send_response(200) - self.end_headers() - else: - self.send_response(404) - self.end_headers() - self.wfile.write('Not found') - - -# Basic HTTP server which handles request using RequestHandler on a background thread. -class ExpectationsServer(BaseHTTPServer.HTTPServer): - def __init__(self, expectations_js, server_address): - BaseHTTPServer.HTTPServer.__init__(self, server_address, - RequestHandler) - self._should_run = False - self._thread = None - self.expectations_js = expectations_js - - def start(self): - assert not self._thread - - self._should_run = True - - def _loop(): - while self._should_run: - self.handle_request() - - self._thread = threading.Thread(name='webgpu_expectations_server', - target=_loop) - # Mark the thread as a daemon to be sure it exits. We still have an explicit - # |stop| method because daemon threads are stopped abruptly at shutdown without - # cleaning up resources. - self._thread.daemon = True - self._thread.start() - - # Ensure the server is running. - # We want to wait synchronously for this so that server startup time doesn't - # cut into test run time. - while True: - try: - urllib.request.urlopen( - 'http://%s:%d/_start' % - (self.server_address[0], self.server_address[1])).read() - except IOError as e: - logging.warning(e) - continue - return - - def stop(self): - self._should_run = False - try: - # Load a url so |handle_request| returns. - urllib.request.urlopen( - 'http://%s:%d/_stop' % - (self.server_address[0], self.server_address[1])).read() - except IOError as e: - logging.warning(e) - self._thread.join() - self._thread = None - - -def split_cts_expectations_and_web_test_expectations( - expectations_file_contents, platform_tags=None): - """Split web test expectations (bit.ly/chromium-test-list-format) into a Javascript - module containing expectations for the WebGPU CTS, and a filtered list of the same web - test expectations, excluding the bits handled by the WebGPU CTS. Returns an object: - { - cts_expectations_js: "export const expectations = [ ... ]", - web_test_expectations: { - expectations: <expectations contents> - tag_set: <frozenset of tags used by the expectations> - result_set: <frozenset of result tags used by the expectations> - } - }""" - - cts_expectations = [] - - out_tag_set = set() - out_result_set = set() - out_expectations = [] - - parser = TaggedTestListParser(expectations_file_contents) - - # For each expectation, append it to |cts_expectations| if the CTS can understand it. - # Expectations not supported by the CTS will be forwarded to the web tests harness. - # This allows us to preserve expectations like [ Slow Crash Timeout RetryOnFailure ]. - # It also preserves expectations like [ Pass ] which are used for test splitting. - # TODO(crbug.com/1186320): Handle test splits / variant generation separately? - # Web test expectations that are passed through are run as separate variants. - # Since [ Slow Crash Timeout RetryOnFailure Pass ] are Web test expectations, - # they have the downside that they must be a prefix of the test name. If they don't match - # anything the variant generator will warn. - # TODO(crbug.com/1186320): Also validate the CTS expectation query. - # TODO(crbug.com/1186320): We may be able to use skip expectations in the - # CTS for Crash/Timeout, and then have a separate test suite which runs only the problematic - # tests. We would generate variants specifically for each expectation to avoid the - # prefix problem. This would allow us to have exact test suppressions at the cost of - # potentially running some tests multiple times if there are overlapping expectations. - for exp in parser.expectations: - # Skip expectations that are not relevant to this platform - if platform_tags is not None and not exp.tags.issubset(platform_tags): - continue - - results = exp.results - raw_results = exp.raw_results - - # Do not do special handling of expectations that aren't for the CTS. - # ex.) ref tests run in WPT without the CTS. - # TODO(crbug.com/1186320): This could be a more robust check. - if 'q=webgpu:' in exp.test: - # Pass Skip expectations to the CTS. - if ResultType.Skip in results: - assert len( - results - ) == 1, 'Skip expectations must not be combined with other expectations' - cts_expectations.append({ - 'query': exp.test, - 'expectation': 'skip' - }) - continue - - # Consume the [ Failure ] expectation for the CTS, but forward along other expectations. - # [ Pass, Crash, Timeout ] will impact variant generation. - # TODO(crbug.com/1186320): Teach the CTS RetryOnFailure. - if ResultType.Failure in results and not exp.should_retry_on_failure: - cts_expectations.append({ - 'query': exp.test, - 'expectation': 'fail' - }) - - results = results.difference(set((ResultType.Failure, ))) - raw_results = [r for r in raw_results if r != 'Failure'] - - if len(raw_results) != 0: - # Forward everything, with the modified results. - out_exp = Expectation(reason=exp.reason, - test=exp.test, - results=results, - lineno=exp.lineno, - retry_on_failure=exp.should_retry_on_failure, - is_slow_test=exp.is_slow_test, - conflict_resolution=exp.conflict_resolution, - raw_tags=exp.raw_tags, - raw_results=raw_results, - is_glob=exp.is_glob, - trailing_comments=exp.trailing_comments) - - out_expectations.append(out_exp) - - # Add the results and tags the expectation uses to sets. - # We will prepend these to the top of the out file. - out_result_set = out_result_set.union(out_exp.raw_results) - out_tag_set = out_tag_set.union(out_exp.raw_tags) - - return { - 'cts_expectations_js': - 'export const expectations = ' + json.dumps(cts_expectations), - 'web_test_expectations': { - 'expectations': out_expectations, - 'tag_set': out_tag_set, - 'result_set': out_result_set - } - } - - -def main(args, stderr): - parser = argparse.ArgumentParser( - description= - 'Start the WebGPU expectations server, then forwards to run_web_tests.py' - ) - parser.add_argument('--webgpu-cts-expectations', required=True) - - options, rest_args = parser.parse_known_args(args) - - web_test_expectations_fd, web_test_expectations_file = mkstemp() - - forwarded_args = rest_args + [ - '--ignore-default-expectations', '--additional-expectations', - web_test_expectations_file - ] - - run_web_tests_options = run_web_tests.parse_args(forwarded_args)[0] - - # Construct a web tests port using the test arguments forwarded to run_web_tests.py - # (ex. --platform=android) in order to discover the tags that the web tests harness will - # use. This includes the OS, OS version, architecture, etc. - platform_tags = Host().port_factory.get( - run_web_tests_options.platform, - run_web_tests_options).get_platform_tags() - - with open(options.webgpu_cts_expectations) as f: - split_result = split_cts_expectations_and_web_test_expectations( - f.read(), platform_tags) - - # Write the out expectation file for web tests. - with open(web_test_expectations_file, 'w') as expectations_out: - web_test_exp = split_result['web_test_expectations'] - expectations_out.write('# tags: [ ' + - ' '.join(web_test_exp['tag_set']) + ' ]\n') - expectations_out.write('# results: [ Slow ' + - ' '.join(web_test_exp['result_set']) + ' ]\n\n') - for exp in web_test_exp['expectations']: - expectations_out.write(exp.to_string() + '\n') - - server = ExpectationsServer(split_result['cts_expectations_js'], - ('127.0.0.1', 3000)) - - logging.info('Starting expectations server...') - server.start() - - try: - return run_web_tests.main(forwarded_args, stderr) - finally: - logging.info('Stopping expectations server...') - server.stop() - os.close(web_test_expectations_fd) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:], sys.stderr))
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium index 45a46514..06ce5a8 100644 --- a/third_party/wpt_tools/README.chromium +++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@ Name: web-platform-tests - Test Suites for Web Platform specifications Short Name: wpt URL: https://github.com/web-platform-tests/wpt/ -Version: c4bb9ef47f7a8c5df8a597201a2f0c5f4d7f72a7 +Version: aa27d567c10dcdb2aea6884d5155dfaaa177a800 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) License File: NOT_SHIPPED Security Critical: no
diff --git a/tools/code_coverage/OWNERS b/tools/code_coverage/OWNERS index 6aff2a7..7b0fe27 100644 --- a/tools/code_coverage/OWNERS +++ b/tools/code_coverage/OWNERS
@@ -1,2 +1 @@ -inferno@chromium.org -pasthana@google.com \ No newline at end of file +pasthana@google.com
diff --git a/tools/ipc_fuzzer/OWNERS b/tools/ipc_fuzzer/OWNERS index a0e5c29e..703ed9d 100644 --- a/tools/ipc_fuzzer/OWNERS +++ b/tools/ipc_fuzzer/OWNERS
@@ -1,2 +1 @@ -inferno@chromium.org tsepez@chromium.org
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4a93fa5..100b919 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -24636,6 +24636,7 @@ <int value="58" label="evaluateExpressionsWithSourceMaps"/> <int value="59" label="cssLayers"/> <int value="60" label="eyedropperColorPicker"/> + <int value="61" label="instrumentationBreakpoints"/> <int value="62" label="cssAuthoringHints"/> </enum> @@ -74463,6 +74464,21 @@ <int value="12" label="Clicked the link passwords.google.com"/> </enum> +<enum name="PasswordNoteAction"> + <int value="0" + label="A new credential is added from settings, with the note field not + empty"/> + <int value="1" + label="Note changed from empty to non-empty from the password edit + dialog in settings"/> + <int value="2" + label="Note changed from non-empty to another non-empty value from the + password edit dialog in settings"/> + <int value="3" + label="Note changed from non-empty to empty from the password edit + dialog in settings"/> +</enum> + <enum name="PasswordProtectionInterstitialStringType"> <int value="0" label="Generic string without org name"/> <int value="1" label="Generic string with org name"/> @@ -74639,6 +74655,22 @@ <int value="4" label="DB Error"/> </enum> +<enum name="PasswordViewPageInteractions"> + <int value="0" label="Credential row is clicked to open password view page"/> + <int value="1" + label="The user opens the password view page to view an existing + credential."/> + <int value="2" + label="The user opens the password view page to view an non-existing + credential"/> + <int value="3" label="Copy username button clicked"/> + <int value="4" label="Copy password button clicked"/> + <int value="5" label="Show password button clicked"/> + <int value="6" label="Edit password button clicked"/> + <int value="7" label="Delete password button clicked"/> + <int value="8" label="Credential username, password or note edited"/> +</enum> + <enum name="PasswordWeaknessScore"> <int value="0" label="Too guessable password"/> <int value="1" label="Very guessable password"/>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml index 4c88c78..029ba51 100644 --- a/tools/metrics/histograms/metadata/compositing/histograms.xml +++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -765,6 +765,8 @@ <variant name=".PinchZoom"/> <variant name=".RAF"/> <variant name=".ScrollbarScroll"/> + <variant name=".SETCompositorAnimation"/> + <variant name=".SETMainThreadAnimation"/> <variant name=".TouchScroll"/> <variant name=".WheelScroll"/> </token> @@ -839,6 +841,8 @@ <variant name=".PinchZoom"/> <variant name=".RAF"/> <variant name=".ScrollbarScroll"/> + <variant name=".SETCompositorAnimation"/> + <variant name=".SETMainThreadAnimation"/> <variant name=".TouchScroll"/> <variant name=".WheelScroll"/> </token> @@ -1184,6 +1188,12 @@ <variant name="RAF" summary="reported for all raf driven animations."/> <variant name="ScrollbarScroll" summary="reported for all scrollbar scrolling."/> + <variant name="SETCompositorAnimation" + summary="reported for all compositor animations during a shared + element transition"/> + <variant name="SETMainThreadAnimation" + summary="reported for all main thread animations during a shared + element transition"/> <variant name="TouchScroll" summary="reported for all touch scrolling."/> <variant name="WheelScroll" summary="reported for all wheel scrolling."/> </token> @@ -1239,6 +1249,12 @@ <variant name="RAF" summary="reported for all raf driven animations."/> <variant name="ScrollbarScroll" summary="reported for all scrollbar scrolling."/> + <variant name="SETCompositorAnimation" + summary="reported for all compositor animations during a shared + element transition"/> + <variant name="SETMainThreadAnimation" + summary="reported for all main thread animations during a shared + element transition"/> <variant name="TouchScroll" summary="reported for all touch scrolling."/> <variant name="WheelScroll" summary="reported for all wheel scrolling."/> </token>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml index 4dc4368f..8055121a1 100644 --- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml +++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -173,6 +173,17 @@ </summary> </histogram> +<histogram name="CustomTabs.HadInteractionOnClose" enum="Boolean" + expires_after="2022-12-01"> + <owner>wenyufu@chromium.org</owner> + <owner>chrome-connective-tissue@google.com</owner> + <summary> + Whether current CCT has seen any interactions. "Interactions" + includes any form entries for text / drop down, and whether a tab can go + forward / back when it is closed. Recorded when CCT tab is closed. + </summary> +</histogram> + <histogram name="CustomTabs.IncognitoCCTCallerId" enum="IncognitoCCTCallerId" expires_after="2022-08-07"> <owner>roagarwal@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml index afb1674d..cd8fd56 100644 --- a/tools/metrics/histograms/metadata/gpu/histograms.xml +++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -888,6 +888,30 @@ </summary> </histogram> +<histogram name="GPU.GLES2DecoderImplLazyBindingCheck.WasBindNecessary" + units="Boolean" expires_after="2022-11-06"> + <owner>blundell@chromium.org</owner> + <owner>vasilyt@chromium.org</owner> + <summary> + For each lazy binding check of GLImage performed by GLES2DecoderImpl, + records whether binding was actually necessary or not. Used in the effort to + eliminate these lazy binding checks (crbug.com/1323341). + </summary> +</histogram> + +<histogram + name="GPU.GLES2DecoderPassthroughImplLazyBindingCheck.WasBindNecessary" + units="Boolean" expires_after="2022-11-06"> + <owner>blundell@chromium.org</owner> + <owner>vasilyt@chromium.org</owner> + <summary> + For each lazy binding check of GLImage performed by + GLES2DecoderPassthroughImpl, records whether binding was actually necessary + or not. Used in the effort to eliminate these lazy binding checks + (crbug.com/1323341). + </summary> +</histogram> + <histogram name="GPU.GLImplementation" enum="GLImplementation" expires_after="2022-10-30"> <owner>magchen@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index c4593ac1..309aef51 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -1081,6 +1081,9 @@ <histogram name="PasswordManager.ButtonTitlePerformance.HasFormTag" units="units" expires_after="2019-07-01"> + <obsolete> + Removed in M104. + </obsolete> <owner>kolos@chromium.org</owner> <summary> The time (ms) it takes to infer button titles within a form tag. @@ -1089,6 +1092,9 @@ <histogram name="PasswordManager.ButtonTitlePerformance.NoFormTag" units="units" expires_after="2019-07-01"> + <obsolete> + Removed in M104. + </obsolete> <owner>kolos@chromium.org</owner> <summary> The time (ms) it takes to infer button titles outside of form tags. @@ -2086,6 +2092,17 @@ </summary> </histogram> +<histogram name="PasswordManager.PasswordNoteActionInSettings" + enum="PasswordNoteAction" expires_after="2023-01-01"> + <owner>derinel@google.com</owner> + <owner>mamir@chromium.org</owner> + <summary> + This metric shows how user created / edited / cleared the note field in the + passwords settings page. Recorded after closing the add/edit password dialog + in settings. + </summary> +</histogram> + <histogram name="PasswordManager.PasswordReuse.NumberOfMatches" units="credentials" expires_after="2022-10-09"> <owner>vakh@chromium.org</owner> @@ -2543,6 +2560,16 @@ </summary> </histogram> +<histogram name="PasswordManager.PasswordViewPage.UserActions" + enum="PasswordViewPageInteractions" expires_after="2023-01-01"> + <owner>derinel@google.com</owner> + <owner>mamir@chromium.org</owner> + <summary> + Records the user actions performed on password viewing page in desktop + settings. Reported upon interactions with the password settings page. + </summary> +</histogram> + <histogram name="PasswordManager.PrefilledUsernameFillOutcome" enum="PrefilledUsernameFillOutcome" expires_after="M86"> <owner>khamutov@google.com</owner> @@ -2948,26 +2975,6 @@ <summary>The number of credentials shown in the Touch To Fill sheet.</summary> </histogram> -<histogram name="PasswordManager.TouchToFill.ObservedSuccessfulSubmission" - enum="Boolean" expires_after="2022-10-30"> - <owner>ioanap@chromium.org</owner> - <owner>fhorschig@chromium.org</owner> - <owner>kolos@chromium.org</owner> - <summary> - Measures whether a credential filling by Touch To Fill leads to a successful - submission or not (submission failed, or the submission could not be - associated with filling by Touch To Fill). A submission after filling is - considered successful iff the filled and submitted usernames coincide, the - timestamps are within one minute and a user hasn't modified any field after - filling. Otherwise, it is reported as 'no successful submission observed'. - The metric is used to compare a login success rate when automated submission - is enabled and disabled. Due to stale or wrong credentials, the success rate - will be degraded independently of automated submission. Recorded when the - password manager has classified a login submission (succeeded or failed) or - a user has modified a field after Touch-To-Fill. - </summary> -</histogram> - <histogram name="PasswordManager.TouchToFill.Outcome" enum="TouchToFill.Outcome" expires_after="2022-10-23"> <owner>ioanap@chromium.org</owner> @@ -2992,6 +2999,26 @@ </summary> </histogram> +<histogram name="PasswordManager.TouchToFill.SuccessfulSubmissionWasObserved" + enum="Boolean" expires_after="2022-10-30"> + <owner>ioanap@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> + <owner>kolos@chromium.org</owner> + <summary> + Measures whether a credential filling by Touch To Fill leads to a successful + submission or not (submission failed, or the submission could not be + associated with filling by Touch To Fill). A submission after filling is + considered successful iff the filled and submitted usernames coincide, the + timestamps are within one minute and a user hasn't modified any field after + filling. Otherwise, it is reported as 'no successful submission observed'. + The metric is used to compare a login success rate when automated submission + is enabled and disabled. Due to stale or wrong credentials, the success rate + will be degraded independently of automated submission. Recorded when the + password manager has classified a login submission (succeeded or failed) or + a user has modified a field after Touch-To-Fill. + </summary> +</histogram> + <histogram name="PasswordManager.TouchToFill.TimeToSuccessfulLogin" units="ms" expires_after="2022-10-30"> <owner>ioanap@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index c066a60..f2b3ec7 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,15 +6,15 @@ }, "win": { "hash": "929c4fd292208274ef28469051c43c60ab7006da", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/7479a87c2032ebc3504fb6bedbb688827a66bb4a/trace_processor_shell.exe" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/db7def5150207a574e8955afc591a5650b3ad290/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "a91d33c8f0282a876c3481bbb24bc2463f7d4a97", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/31772328c517b725c81994e4b9b99aac18319e40/trace_processor_shell" + "hash": "6af3a9278d34a68f13a0d8365535cf71e31f45a0", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/212917c7f1d6835440bfb550676eb6dd6d0470ad/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6", @@ -22,7 +22,7 @@ }, "linux": { "hash": "2ae07fc516b89c8ac44f70798f402c8f3e80bca4", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/7479a87c2032ebc3504fb6bedbb688827a66bb4a/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/db7def5150207a574e8955afc591a5650b3ad290/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/style_variable_generator/main.py b/tools/style_variable_generator/main.py index 40811999..63b8158b 100755 --- a/tools/style_variable_generator/main.py +++ b/tools/style_variable_generator/main.py
@@ -21,7 +21,7 @@ if options is None: return result for key_value_pair in options: - key, value = key_value_pair.split("=", 1) + key, value = key_value_pair.split('=', 1) key = key.strip() result[key] = value return result @@ -36,40 +36,52 @@ ProtoStyleGenerator, ProtoJSONStyleGenerator, TSStyleGenerator ] - parser.add_argument('--generator', - choices=[g.GetName() for g in generators], - required=True, - help='type of file to generate') + parser.add_argument( + '--generator', + choices=[g.GetName() for g in generators], + required=True, + help='type of file to generate, provide this option multiple ' + 'times to use multiple generators', + action='append') parser.add_argument('--generate-single-mode', choices=Modes.ALL, help='generates output for a single mode') - parser.add_argument('--out-file', help='file to write output to') - parser.add_argument("--generator-option", - metavar="KEY=VALUE", - action="append", - help="Set a option specific to the selected generator" - "via a key value pair. See the README.md for a" - "full list of generator specific options.") + parser.add_argument( + '--out-file', + help='file to write output to, the number of out-files ' + 'must match the number of generators if specified', + action='append') + parser.add_argument('--generator-option', + metavar='KEY=VALUE', + action='append', + help='Set a option specific to the selected generator ' + 'via a key value pair. See the README.md for a ' + 'full list of generator specific options.') parser.add_argument('targets', nargs='+', help='source json5 color files') args = parser.parse_args() - for g in generators: - if args.generator == g.GetName(): - style_generator = g() + if args.out_file and len(args.generator) != len(args.out_file): + raise ValueError( + 'number of --out-files must match number of --generators') - style_generator.AddJSONFilesToModel(args.targets) + for i, g in enumerate(args.generator): + gen_constructor = next(x for x in generators if g == x.GetName()) + style_generator = gen_constructor() - style_generator.generate_single_mode = args.generate_single_mode - style_generator.out_file_path = args.out_file - style_generator.generator_options = parseGeneratorOptionList( - args.generator_option) + style_generator.AddJSONFilesToModel(args.targets) - if args.out_file: - with open(args.out_file, 'w') as f: - f.write(style_generator.Render()) - else: - print(style_generator.Render()) + style_generator.generate_single_mode = args.generate_single_mode + style_generator.generator_options = parseGeneratorOptionList( + args.generator_option) + + if args.out_file: + style_generator.out_file_path = args.out_file[i] + with open(args.out_file[i], 'w') as f: + f.write(style_generator.Render()) + else: + print('=========', style_generator.GetName(), '=========') + print(style_generator.Render()) return 0
diff --git a/tools/style_variable_generator/style_variable_generator.gni b/tools/style_variable_generator/style_variable_generator.gni index 415e03d0..7ad4d07 100644 --- a/tools/style_variable_generator/style_variable_generator.gni +++ b/tools/style_variable_generator/style_variable_generator.gni
@@ -52,33 +52,11 @@ "--generator-option", "debug_placeholder=\$i18n{crosColorsDebugOverrides}", "--out-file", - rebase_path("$out_file", root_build_dir), + rebase_path(out_file, root_build_dir), ] + rebase_path(sources, root_build_dir) } - action("${target_name}_views_h_generator") { - script = script_file - forward_variables_from(invoker, - [ - "deps", - "sources", - ]) - - inputs = - common_inputs + [ - "//tools/style_variable_generator/views_generator.py", - "//tools/style_variable_generator/templates/views_generator_h.tmpl", - ] - out_file = "$target_gen_dir/${original_target_name}.h" - outputs = [ out_file ] - args = [ - "--generator=ViewsH", - "--out-file", - rebase_path("$out_file", root_build_dir), - ] + rebase_path(sources, root_build_dir) - } - - action("${target_name}_views_cc_generator") { + action("${target_name}_views_generator") { script = script_file forward_variables_from(invoker, [ @@ -90,13 +68,21 @@ common_inputs + [ "//tools/style_variable_generator/views_generator.py", "//tools/style_variable_generator/templates/views_generator_cc.tmpl", + "//tools/style_variable_generator/templates/views_generator_h.tmpl", ] - out_file = "$target_gen_dir/${original_target_name}.cc" - outputs = [ out_file ] + out_file_cc = "$target_gen_dir/${original_target_name}.cc" + out_file_h = "$target_gen_dir/${original_target_name}.h" + outputs = [ + out_file_cc, + out_file_h, + ] args = [ "--generator=ViewsCC", "--out-file", - rebase_path("$out_file", root_build_dir), + rebase_path(out_file_cc, root_build_dir), + "--generator=ViewsH", + "--out-file", + rebase_path(out_file_h, root_build_dir), ] + rebase_path(sources, root_build_dir) } @@ -106,56 +92,10 @@ "$target_gen_dir/${original_target_name}.h", ] deps = [ - ":${original_target_name}_views_cc_generator", - ":${original_target_name}_views_h_generator", + ":${original_target_name}_views_generator", "//base", "//skia", ] defines = [ "IS_${original_target_name}_IMPL" ] } - - action("${target_name}_proto") { - script = script_file - forward_variables_from(invoker, - [ - "deps", - "sources", - ]) - - inputs = - common_inputs + [ - "//tools/style_variable_generator/proto_generator.py", - "//tools/style_variable_generator/templates/proto_generator.tmpl", - ] - out_file = "$target_gen_dir/${original_target_name}.proto" - outputs = [ out_file ] - - args = [ - "--generator=proto", - "--out-file", - rebase_path("$out_file", root_build_dir), - ] + rebase_path(sources, root_build_dir) - } - - action("${target_name}_protojson") { - script = script_file - forward_variables_from(invoker, - [ - "deps", - "sources", - ]) - - inputs = common_inputs + [ - "//tools/style_variable_generator/proto_generator.py", - "//tools/style_variable_generator/templates/proto_json_generator.tmpl", - ] - out_file = "$target_gen_dir/${original_target_name}.protojson" - outputs = [ out_file ] - - args = [ - "--generator=proto", - "--out-file", - rebase_path("$out_file", root_build_dir), - ] + rebase_path(sources, root_build_dir) - } }
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc index acbd19e1..70552e9 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -942,16 +942,16 @@ } else if (delegate()->ConvertRectToPixels(pending_bounds_dip_) == GetBoundsInPixels() && pending_configures_.empty()) { - // If |pending_bounds_dip_| matches GetBounds(), and |pending_configures_| - // is empty, implying that the window is already rendering at - // |pending_bounds_dip_|, then a frame matching |pending_bounds_dip_| may - // not arrive soon, despite the window delegate receives the updated bounds. - // Without a new frame, UpdateVisualSize() is not invoked, leaving this - // |configure| unacknowledged. - // E.g. With static window content, |configure| that does not - // change window size will not cause the window to redraw. - // Hence, acknowledge this |configure| now to tell the Wayland compositor - // that this window has been configured. + // If |pending_bounds_dip_| matches the current window bounds, and + // |pending_configures_| is empty, which implies that the window is already + // rendering at |pending_bounds_dip_|, then a new frame matching it may take + // some time to arrive, despite the window delegate receives the updated + // bounds. Without a new frame, UpdateVisualSize() is not invoked, leaving + // this configure sequence unacknowledged. E.g: With static window content, + // a configure sequence that does not change the window size will not cause + // the window to redraw. Hence, acknowledge this configure sequence now to + // tell the Wayland compositor that the requested configuration for this + // window has been applied. SetWindowGeometry(pending_bounds_dip_); AckConfigure(serial); connection()->ScheduleFlush();
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc index 32c971cc..30a1743 100644 --- a/weblayer/browser/tab_impl.cc +++ b/weblayer/browser/tab_impl.cc
@@ -1130,7 +1130,7 @@ MediaStreamManager::FromWebContents(web_contents) ->RequestMediaAccessPermission(request, std::move(callback)); #else - std::move(callback).Run(blink::mojom::StreamDevices(), + std::move(callback).Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); #endif
diff --git a/weblayer/browser/webrtc/media_stream_manager.cc b/weblayer/browser/webrtc/media_stream_manager.cc index 415876d..c15b2227 100644 --- a/weblayer/browser/webrtc/media_stream_manager.cc +++ b/weblayer/browser/webrtc/media_stream_manager.cc
@@ -34,11 +34,14 @@ class MediaStreamManager::StreamUi : public content::MediaStreamUI { public: StreamUi(base::WeakPtr<MediaStreamManager> manager, - const blink::mojom::StreamDevices& devices) + const blink::mojom::StreamDevicesSet& stream_devices) : manager_(manager) { DCHECK(manager_); - streaming_audio_ = devices.audio_device.has_value(); - streaming_video_ = devices.video_device.has_value(); + DCHECK_EQ(1u, stream_devices.stream_devices.size()); + streaming_audio_ = + stream_devices.stream_devices[0]->audio_device.has_value(); + streaming_video_ = + stream_devices.stream_devices[0]->video_device.has_value(); } StreamUi(const StreamUi&) = delete; StreamUi& operator=(const StreamUi&) = delete; @@ -122,12 +125,12 @@ CHECK(request != requests_pending_client_approval_.end()); if (allowed) { std::move(request->second.callback) - .Run(request->second.devices, request->second.result, + .Run(*request->second.stream_devices_set_, request->second.result, std::make_unique<StreamUi>(weak_factory_.GetWeakPtr(), - request->second.devices)); + *request->second.stream_devices_set_)); } else { std::move(request->second.callback) - .Run(blink::mojom::StreamDevices(), + .Run(blink::mojom::StreamDevicesSet(), blink::mojom::MediaStreamRequestResult::NO_HARDWARE, {}); } requests_pending_client_approval_.erase(request); @@ -141,22 +144,28 @@ void MediaStreamManager::OnMediaAccessPermissionResult( content::MediaResponseCallback callback, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, bool blocked_by_permissions_policy, ContentSetting audio_setting, ContentSetting video_setting) { + // TODO(crbug.com/1300883): Generalize to multiple streams. + DCHECK((result != blink::mojom::MediaStreamRequestResult::OK && + stream_devices_set.stream_devices.empty()) || + (result == blink::mojom::MediaStreamRequestResult::OK && + stream_devices_set.stream_devices.size() == 1u)); if (result != blink::mojom::MediaStreamRequestResult::OK) { - std::move(callback).Run(devices, result, {}); + std::move(callback).Run(stream_devices_set, result, {}); return; } int request_id = next_request_id_++; - requests_pending_client_approval_[request_id] = - RequestPendingClientApproval(std::move(callback), devices, result); + requests_pending_client_approval_[request_id] = RequestPendingClientApproval( + std::move(callback), stream_devices_set, result); Java_MediaStreamManager_prepareToStream( base::android::AttachCurrentThread(), j_object_, - devices.audio_device.has_value(), devices.video_device.has_value(), + stream_devices_set.stream_devices[0]->audio_device.has_value(), + stream_devices_set.stream_devices[0]->video_device.has_value(), request_id); } @@ -199,9 +208,11 @@ MediaStreamManager::RequestPendingClientApproval::RequestPendingClientApproval( content::MediaResponseCallback callback, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result) - : callback(std::move(callback)), devices(devices), result(result) {} + : callback(std::move(callback)), + stream_devices_set_(stream_devices_set.Clone()), + result(result) {} MediaStreamManager::RequestPendingClientApproval:: ~RequestPendingClientApproval() = default;
diff --git a/weblayer/browser/webrtc/media_stream_manager.h b/weblayer/browser/webrtc/media_stream_manager.h index 6f92e92..7013b3f 100644 --- a/weblayer/browser/webrtc/media_stream_manager.h +++ b/weblayer/browser/webrtc/media_stream_manager.h
@@ -57,7 +57,7 @@ void OnMediaAccessPermissionResult( content::MediaResponseCallback callback, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, blink::mojom::MediaStreamRequestResult result, bool blocked_by_permissions_policy, ContentSetting audio_setting, @@ -73,16 +73,17 @@ // approval. struct RequestPendingClientApproval { RequestPendingClientApproval(); - RequestPendingClientApproval(content::MediaResponseCallback callback, - const blink::mojom::StreamDevices& devices, - blink::mojom::MediaStreamRequestResult result); + RequestPendingClientApproval( + content::MediaResponseCallback callback, + const blink::mojom::StreamDevicesSet& stream_devices_set, + blink::mojom::MediaStreamRequestResult result); ~RequestPendingClientApproval(); RequestPendingClientApproval& operator=( RequestPendingClientApproval&& other); content::MediaResponseCallback callback; - blink::mojom::StreamDevices devices; + blink::mojom::StreamDevicesSetPtr stream_devices_set_; blink::mojom::MediaStreamRequestResult result; }; std::map<int, RequestPendingClientApproval> requests_pending_client_approval_;