diff --git a/DEPS b/DEPS index 30d974b9..756923d 100644 --- a/DEPS +++ b/DEPS
@@ -312,7 +312,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': '625637fb612de63f127c57ca00783b2ecc66e3c8', + 'skia_revision': 'fbc5b8bb532a84c88a5d393d3849c171be6392eb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -387,7 +387,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': '5951e69a2333e36fbd7912bd160f4686347e6c5f', + 'chromium_variations_revision': '0a3f86862cfd84e4ec1a2fc43acfc5091d8923dc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -827,12 +827,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '64fe84c44408d892262ac3b64317ba9c697d267c', + '1e8d9e0abee2cc46c667b23e3ccccceb50f9ac37', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '0fa768e21e9cb653d0957201899713a86adafa8f', + 'url': Var('chromium_git') + '/website.git' + '@' + '192b4c1fca9c092343459067d75ba65fbc6ea856', }, 'src/ios/third_party/earl_grey2/src': { @@ -1192,13 +1192,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '609288a46b37758cbbfd82aefc01359631aec81f', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '495b23b39aaba2ca3b55dd27cadc523f1cb17ee6', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'e01752b3743faf0896f5c4b32deee5980c7f1cbd', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'af2d230f71174076f1668b20d3ec2b7a05dcb53f', 'condition': 'checkout_src_internal', }, @@ -1851,7 +1851,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'eaa860a0b3a9049d2caf88cb1ce9d7fb82fb05f2', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '352bfe3c44c3baf1f16a18f912b8b162ca581c54', + Var('webrtc_git') + '/src.git' + '@' + '1261863f87ff0f6c7910a039012d3469ee8ee2fb', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1974,7 +1974,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'lIGkmCXKVNJBMHHoZjJfAN1ttshc-N5xM7Ye7i8up18C', + 'version': 't34uT7nlIIJC1Yl_ohzouAQkKCkIW79UT68UkiY8htIC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1985,7 +1985,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'QcR3v4CyS1VNGwzhzOX0hu6lUNaLk9l3xE_R-pPfaUIC', + 'version': '-E_2mIUEbbKyJWZzHVRIuanUBTuj_qtcDBs4y87tagkC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3866,7 +3866,7 @@ 'src/ash/webui/conch': { 'url': Var('chrome_git') + '/ash/webui/conch.git' + '@' + - '075b11bb88297fb404eb1fd23e5d229cd568acb8', + '63688f1742cefae6fc6aaf7732838f4eb420b4d3', 'condition': 'checkout_src_internal and checkout_chromeos', }, @@ -4125,7 +4125,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '53de6672bc3762c361e52d3df3555ff6fd5e5aac', + '4f440ef57481bc0d056679d87cf6d4f6f1e8658f', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 930dfed..96a11918 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -276,6 +276,12 @@ network::mojom::HttpAuthStaticParams::New()); content::GetNetworkService()->ConfigureHttpAuthPrefs( AwBrowserProcess::GetInstance()->CreateHttpAuthDynamicParams()); + if (base::FeatureList::IsEnabled(features::kWebViewAsyncDns)) { + content::GetNetworkService()->ConfigureStubHostResolver( + /*insecure_dns_client_enabled=*/true, net::SecureDnsMode::kAutomatic, + net::DnsOverHttpsConfig(), + /*additional_dns_types_enabled=*/true); + } } void AwContentBrowserClient::ConfigureNetworkContextParams(
diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc index 33ef933..cd5010b 100644 --- a/android_webview/common/aw_features.cc +++ b/android_webview/common/aw_features.cc
@@ -248,5 +248,10 @@ "WebViewEnableCrash", base::FEATURE_ENABLED_BY_DEFAULT); +// Enables the built-in DNS resolver (Async DNS) on WebView. +BASE_FEATURE(kWebViewAsyncDns, + "WebViewAsyncDns", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace features } // namespace android_webview
diff --git a/android_webview/common/aw_features.h b/android_webview/common/aw_features.h index f90e913..ba9b2202 100644 --- a/android_webview/common/aw_features.h +++ b/android_webview/common/aw_features.h
@@ -57,6 +57,7 @@ BASE_DECLARE_FEATURE(kWebViewZoomKeyboardShortcuts); BASE_DECLARE_FEATURE(kWebViewReduceUAAndroidVersionDeviceModel); BASE_DECLARE_FEATURE(kWebViewEnableCrash); +BASE_DECLARE_FEATURE(kWebViewAsyncDns); } // namespace features } // namespace android_webview
diff --git a/android_webview/common/crash_reporter/crash_keys.cc b/android_webview/common/crash_reporter/crash_keys.cc index 99009de..1b7c385 100644 --- a/android_webview/common/crash_reporter/crash_keys.cc +++ b/android_webview/common/crash_reporter/crash_keys.cc
@@ -56,6 +56,7 @@ "crbug1523259-pw_form.password_id", "crbug1523259-fs.fields.size", "crbug1523259-fs.fields.global_ids", + "crbug1523259-fs.fields.global_ids", // components/viz "viz_deserialization",
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 d892f27..fa84d0e 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
@@ -965,6 +965,8 @@ "InputStreamOptimizations", "Enables optimizations to input stream handling."), Flag.baseFeature("WebViewOptimizeXrwNavigationFlow"), Flag.baseFeature( + AwFeatures.WEBVIEW_ASYNC_DNS, "Enables the built-in DNS resolver (Async DNS)."), + Flag.baseFeature( "UseMoveNotCopyInAXTreeCombiner", "Enables moves instead of copies of snapshot tree data when combining updates."), Flag.baseFeature(
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc index 2c0f65b..54daa5e4 100644 --- a/ash/accessibility/accessibility_controller.cc +++ b/ash/accessibility/accessibility_controller.cc
@@ -2622,14 +2622,10 @@ void AccessibilityController::UpdateLargeCursorFromPref() { DCHECK(active_user_prefs_); - const bool enabled = - active_user_prefs_->GetBoolean(prefs::kAccessibilityLargeCursorEnabled); - // Reset large cursor size to the default size when large cursor is disabled. - if (!enabled) { - active_user_prefs_->ClearPref(prefs::kAccessibilityLargeCursorDipSize); - } - const int size = - active_user_prefs_->GetInteger(prefs::kAccessibilityLargeCursorDipSize); + const bool enabled = large_cursor().enabled(); + const int size = enabled ? active_user_prefs_->GetInteger( + prefs::kAccessibilityLargeCursorDipSize) + : kDefaultLargeCursorSize; if (large_cursor_size_in_dip_ == size) { return; @@ -2640,9 +2636,8 @@ NotifyAccessibilityStatusChanged(); Shell* shell = Shell::Get(); - shell->cursor_manager()->SetCursorSize(large_cursor().enabled() - ? ui::CursorSize::kLarge - : ui::CursorSize::kNormal); + shell->cursor_manager()->SetCursorSize(enabled ? ui::CursorSize::kLarge + : ui::CursorSize::kNormal); shell->SetLargeCursorSizeInDip(large_cursor_size_in_dip_); shell->UpdateCursorCompositingEnabled(); } @@ -3107,10 +3102,6 @@ enabled); break; case FeatureType::kLargeCursor: - if (!enabled) { - active_user_prefs_->ClearPref(prefs::kAccessibilityLargeCursorDipSize); - } - Shell::Get()->cursor_manager()->SetCursorSize( large_cursor().enabled() ? ui::CursorSize::kLarge : ui::CursorSize::kNormal);
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc index 577183b..a785e45 100644 --- a/ash/accessibility/accessibility_controller_unittest.cc +++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -1226,9 +1226,16 @@ EXPECT_FALSE(controller->IsStickyKeysSettingVisibleInTray()); } -TEST_F(AccessibilityControllerTest, DisableLargeCursorResetsSize) { +TEST_F(AccessibilityControllerTest, DisableLargeCursorDoesNotResetSize) { + auto* shell = Shell::Get(); + shell->cursor_manager()->ShowCursor(); + auto* cursor_window_controller = + shell->window_tree_host_manager()->cursor_window_controller(); + ASSERT_NE(nullptr, cursor_window_controller); + EXPECT_FALSE(cursor_window_controller->is_cursor_compositing_enabled()); + PrefService* prefs = - Shell::Get()->session_controller()->GetLastActiveUserPrefService(); + shell->session_controller()->GetLastActiveUserPrefService(); EXPECT_EQ(kDefaultLargeCursorSize, prefs->GetInteger(prefs::kAccessibilityLargeCursorDipSize)); @@ -1236,11 +1243,25 @@ // custom size. prefs->SetBoolean(prefs::kAccessibilityLargeCursorEnabled, true); prefs->SetInteger(prefs::kAccessibilityLargeCursorDipSize, 48); + EXPECT_EQ(48, prefs->GetInteger(prefs::kAccessibilityLargeCursorDipSize)); - // Turning off large cursor resets the size to the default. + // Cursor compositing should be enabled and the size should be 48 dip. + EXPECT_TRUE(cursor_window_controller->is_cursor_compositing_enabled()); + EXPECT_EQ(cursor_window_controller->GetBoundsForTest().width(), 48); + EXPECT_EQ(cursor_window_controller->GetBoundsForTest().height(), 48); + + // Turning off large cursor does not reset the size to the default. prefs->SetBoolean(prefs::kAccessibilityLargeCursorEnabled, false); - EXPECT_EQ(kDefaultLargeCursorSize, - prefs->GetInteger(prefs::kAccessibilityLargeCursorDipSize)); + EXPECT_EQ(48, prefs->GetInteger(prefs::kAccessibilityLargeCursorDipSize)); + // It does stop cursor compositing, though, and the cursor is small again. + EXPECT_FALSE(cursor_window_controller->is_cursor_compositing_enabled()); + + // Turning it on again doesn't impact the preferred size pref either. + prefs->SetBoolean(prefs::kAccessibilityLargeCursorEnabled, true); + EXPECT_EQ(48, prefs->GetInteger(prefs::kAccessibilityLargeCursorDipSize)); + EXPECT_TRUE(cursor_window_controller->is_cursor_compositing_enabled()); + EXPECT_EQ(cursor_window_controller->GetBoundsForTest().width(), 48); + EXPECT_EQ(cursor_window_controller->GetBoundsForTest().height(), 48); } TEST_F(AccessibilityControllerTest, ChangingCursorColorPrefChangesCursorColor) {
diff --git a/ash/api/tasks/test_tasks_delegate.cc b/ash/api/tasks/test_tasks_delegate.cc index 61466f41..afb5ee7 100644 --- a/ash/api/tasks/test_tasks_delegate.cc +++ b/ash/api/tasks/test_tasks_delegate.cc
@@ -4,55 +4,37 @@ #include "ash/api/tasks/test_tasks_delegate.h" -#include <memory> - -#include "ash/api/tasks/fake_tasks_client.h" -#include "ash/api/tasks/tasks_types.h" -#include "base/logging.h" +#include "ash/api/tasks/tasks_client.h" +#include "base/notreached.h" #include "components/account_id/account_id.h" namespace ash::api { -TestTasksDelegate::TestTasksDelegate() { - AccountId account_id = EmptyAccountId(); - AddFakeTasksClient(account_id, std::make_unique<FakeTasksClient>()); - SetActiveAccount(account_id); -} +TestTasksDelegate::TestTasksDelegate() = default; TestTasksDelegate::~TestTasksDelegate() = default; void TestTasksDelegate::UpdateClientForProfileSwitch( const AccountId& account_id) { - if (clients_.find(account_id) == clients_.end()) { - LOG(WARNING) << "No FakeTasksClient exists for active account"; - } - - if (active_client_) { - active_client_->InvalidateCache(); - } - - SetActiveAccount(account_id); + NOTIMPLEMENTED(); } void TestTasksDelegate::GetTaskLists( bool force_fetch, TasksClient::GetTaskListsCallback callback) { - CHECK(active_client_); - active_client_->GetTaskLists(force_fetch, std::move(callback)); + NOTIMPLEMENTED(); } void TestTasksDelegate::GetTasks(const std::string& task_list_id, bool force_fetch, TasksClient::GetTasksCallback callback) { - CHECK(active_client_); - active_client_->GetTasks(task_list_id, force_fetch, std::move(callback)); + NOTIMPLEMENTED(); } void TestTasksDelegate::AddTask(const std::string& task_list_id, const std::string& title, TasksClient::OnTaskSavedCallback callback) { - CHECK(active_client_); - active_client_->AddTask(task_list_id, title, std::move(callback)); + NOTIMPLEMENTED(); } void TestTasksDelegate::UpdateTask(const std::string& task_list_id, @@ -60,21 +42,7 @@ const std::string& title, bool completed, TasksClient::OnTaskSavedCallback callback) { - CHECK(active_client_); - active_client_->UpdateTask(task_list_id, task_id, title, completed, - std::move(callback)); -} - -void TestTasksDelegate::AddFakeTasksClient( - const AccountId& account_id, - std::unique_ptr<FakeTasksClient> tasks_client) { - clients_.insert_or_assign(account_id, std::move(tasks_client)); -} - -void TestTasksDelegate::SetActiveAccount(const AccountId& account_id) { - const auto iter = clients_.find(account_id); - CHECK(iter != clients_.end()); - active_client_ = iter->second.get(); + NOTIMPLEMENTED(); } } // namespace ash::api
diff --git a/ash/api/tasks/test_tasks_delegate.h b/ash/api/tasks/test_tasks_delegate.h index e15ee607..4b1e05ea 100644 --- a/ash/api/tasks/test_tasks_delegate.h +++ b/ash/api/tasks/test_tasks_delegate.h
@@ -7,13 +7,9 @@ #include "ash/api/tasks/tasks_delegate.h" #include "ash/ash_export.h" -#include "base/containers/flat_map.h" -#include "components/account_id/account_id.h" namespace ash::api { -class FakeTasksClient; - class ASH_EXPORT TestTasksDelegate : public TasksDelegate { public: TestTasksDelegate(); @@ -36,20 +32,6 @@ const std::string& title, bool completed, TasksClient::OnTaskSavedCallback callback) override; - - // Helper function for adding pre-build `FakeTasksClient` objects. - void AddFakeTasksClient(const AccountId& account_id, - std::unique_ptr<FakeTasksClient> tasks_client); - - // Switches the active account for the delegate. - void SetActiveAccount(const AccountId& account_id); - - private: - // The client for the active account. - raw_ptr<FakeTasksClient> active_client_ = nullptr; - - // Maps account IDs to clients. - base::flat_map<AccountId, std::unique_ptr<FakeTasksClient>> clients_; }; } // namespace ash::api
diff --git a/ash/events/event_rewriter_controller_impl.cc b/ash/events/event_rewriter_controller_impl.cc index de774c3..be2bdebc 100644 --- a/ash/events/event_rewriter_controller_impl.cc +++ b/ash/events/event_rewriter_controller_impl.cc
@@ -122,12 +122,6 @@ event_rewriter_ash.get(), accessibility_event_rewriter_delegate); accessibility_event_rewriter_ = accessibility_event_rewriter.get(); - // EventRewriters are notified in the order they are added. - if (features::IsPeripheralCustomizationEnabled() || - ::features::IsShortcutCustomizationEnabled()) { - AddEventRewriter(std::move(peripheral_customization_event_rewriter)); - } - AddEventRewriter(std::move(prerewritten_event_forwarder)); AddEventRewriter(std::move(keyboard_device_id_event_rewriter)); if (features::IsKeyboardRewriterFixEnabled()) { auto keyboard_modifier_event_rewriter = @@ -139,6 +133,12 @@ ash::input_method::InputMethodManager::Get()->GetImeKeyboard()); AddEventRewriter(std::move(keyboard_modifier_event_rewriter)); } + // EventRewriters are notified in the order they are added. + if (features::IsPeripheralCustomizationEnabled() || + ::features::IsShortcutCustomizationEnabled()) { + AddEventRewriter(std::move(peripheral_customization_event_rewriter)); + } + AddEventRewriter(std::move(prerewritten_event_forwarder)); // Accessibility rewriter is applied between modifier event rewriters and // EventRewriterAsh. Specifically, Search modifier is captured by the // accessibility rewriter, that should be the ones after modifier remapping.
diff --git a/ash/picker/model/picker_model_unittest.cc b/ash/picker/model/picker_model_unittest.cc index 82f7c96..075f564a 100644 --- a/ash/picker/model/picker_model_unittest.cc +++ b/ash/picker/model/picker_model_unittest.cc
@@ -14,11 +14,11 @@ namespace ash { namespace { +using ::testing::Contains; using ::testing::ElementsAre; -TEST(PickerModel, AvailableCategoriesWithNoFocusAndCapsLockOff) { +TEST(PickerModel, AvailableCategoriesWithNoFocusHasCorrectOrdering) { input_method::FakeImeKeyboard fake_ime_keyboard; - fake_ime_keyboard.SetCapsLockEnabled(false); PickerModel model(/*focused_client=*/nullptr, &fake_ime_keyboard); EXPECT_THAT( model.GetAvailableCategories(), @@ -28,21 +28,8 @@ PickerCategory::kDatesTimes, PickerCategory::kUnitsMaths)); } -TEST(PickerModel, AvailableCategoriesWithNoFocusAndCapsLockOn) { +TEST(PickerModel, AvailableCategoriesWithNoSelectedTextHasCorrectOrdering) { input_method::FakeImeKeyboard fake_ime_keyboard; - fake_ime_keyboard.SetCapsLockEnabled(true); - PickerModel model(/*focused_client=*/nullptr, &fake_ime_keyboard); - EXPECT_THAT( - model.GetAvailableCategories(), - ElementsAre(PickerCategory::kCapsOff, PickerCategory::kLinks, - PickerCategory::kExpressions, PickerCategory::kClipboard, - PickerCategory::kDriveFiles, PickerCategory::kLocalFiles, - PickerCategory::kDatesTimes, PickerCategory::kUnitsMaths)); -} - -TEST(PickerModel, AvailableCategoriesWithNoSelectedTextAndCapsLockOff) { - input_method::FakeImeKeyboard fake_ime_keyboard; - fake_ime_keyboard.SetCapsLockEnabled(false); ui::FakeTextInputClient client({.type = ui::TEXT_INPUT_TYPE_TEXT}); client.SetTextAndSelection(u"a", gfx::Range(0)); @@ -55,22 +42,7 @@ PickerCategory::kDatesTimes, PickerCategory::kUnitsMaths)); } -TEST(PickerModel, AvailableCategoriesWithNoSelectedTextAndCapsLockOn) { - input_method::FakeImeKeyboard fake_ime_keyboard; - fake_ime_keyboard.SetCapsLockEnabled(true); - ui::FakeTextInputClient client({.type = ui::TEXT_INPUT_TYPE_TEXT}); - client.SetTextAndSelection(u"a", gfx::Range(0)); - - PickerModel model(&client, &fake_ime_keyboard); - EXPECT_THAT( - model.GetAvailableCategories(), - ElementsAre(PickerCategory::kCapsOff, PickerCategory::kLinks, - PickerCategory::kExpressions, PickerCategory::kClipboard, - PickerCategory::kDriveFiles, PickerCategory::kLocalFiles, - PickerCategory::kDatesTimes, PickerCategory::kUnitsMaths)); -} - -TEST(PickerModel, AvailableCategoriesWithSelectedText) { +TEST(PickerModel, AvailableCategoriesWithSelectedTextHasCorrectOrdering) { input_method::FakeImeKeyboard fake_ime_keyboard; ui::FakeTextInputClient client({.type = ui::TEXT_INPUT_TYPE_TEXT}); client.SetTextAndSelection(u"a", gfx::Range(0, 1)); @@ -82,6 +54,26 @@ PickerCategory::kSentenceCase, PickerCategory::kTitleCase)); } +TEST(PickerModel, AvailableCategoriesShowsCapsOffWhenCapsIsOn) { + input_method::FakeImeKeyboard fake_ime_keyboard; + fake_ime_keyboard.SetCapsLockEnabled(true); + ui::FakeTextInputClient client({.type = ui::TEXT_INPUT_TYPE_TEXT}); + + PickerModel model(&client, &fake_ime_keyboard); + EXPECT_THAT(model.GetAvailableCategories(), + Contains(PickerCategory::kCapsOff)); +} + +TEST(PickerModel, AvailableCategoriesShowsCapsOnWhenCapsIsOff) { + input_method::FakeImeKeyboard fake_ime_keyboard; + fake_ime_keyboard.SetCapsLockEnabled(false); + ui::FakeTextInputClient client({.type = ui::TEXT_INPUT_TYPE_TEXT}); + + PickerModel model(&client, &fake_ime_keyboard); + EXPECT_THAT(model.GetAvailableCategories(), + Contains(PickerCategory::kCapsOn)); +} + TEST(PickerModel, GetsEmptySelectedText) { input_method::FakeImeKeyboard fake_ime_keyboard; ui::FakeTextInputClient client({.type = ui::TEXT_INPUT_TYPE_TEXT});
diff --git a/ash/session/session_controller_impl.h b/ash/session/session_controller_impl.h index 1d79865..a57e5ad 100644 --- a/ash/session/session_controller_impl.h +++ b/ash/session/session_controller_impl.h
@@ -55,11 +55,6 @@ base::TimeDelta session_length_limit() const { return session_length_limit_; } base::Time session_start_time() const { return session_start_time_; } - // Returns the ash notion of login status. - // NOTE: Prefer GetSessionState() in new code because the concept of - // SessionState more closes matches the state in chrome. - LoginStatus login_status() const { return login_status_; } - // Returns the number of signed in users. If 0 is returned, there is either // no session in progress or no active user. int NumberOfLoggedInUsers() const; @@ -202,11 +197,16 @@ // the active user profile prefs. Returns null early during startup. PrefService* GetActivePrefService() const; + // Returns the ash notion of login status. + // NOTE: Prefer GetSessionState() in new code because the concept of + // SessionState more closes matches the state in chrome. + LoginStatus login_status() const { return login_status_; } + // Returns an object of `ScopedScreenLockBlocker`. // `CanLockScreen()` returns false while there is one or more living object. std::unique_ptr<ScopedScreenLockBlocker> GetScopedScreenLockBlocker(); - // SessionController: + // SessionController void SetClient(SessionControllerClient* client) override; void SetSessionInfo(const SessionInfo& info) override; void UpdateUserSession(const UserSession& user_session) override;
diff --git a/ash/system/mahi/mahi_constants.h b/ash/system/mahi/mahi_constants.h index 4dd828b..ba01a07 100644 --- a/ash/system/mahi/mahi_constants.h +++ b/ash/system/mahi/mahi_constants.h
@@ -94,6 +94,8 @@ "Ash.Mahi.UserJourneyTime"; inline constexpr char kMahiQuestionSourceHistogramName[] = "Ash.Mahi.QuestionSource"; +inline constexpr char kQuestionCountPerMahiSessionHistogramName[] = + "Ash.Mahi.QuestionCountPerMahiSession"; } // namespace ash::mahi_constants
diff --git a/ash/system/mahi/mahi_panel_view_unittest.cc b/ash/system/mahi/mahi_panel_view_unittest.cc index f2029ea..5386fa1 100644 --- a/ash/system/mahi/mahi_panel_view_unittest.cc +++ b/ash/system/mahi/mahi_panel_view_unittest.cc
@@ -1824,28 +1824,106 @@ base::HistogramTester histogram; histogram.ExpectTimeBucketCount( mahi_constants::kMahiUserJourneyTimeHistogramName, base::Seconds(3), - /*count=*/0); + /*expected_count=*/0); task_environment()->AdvanceClock(base::Seconds(3)); CreatePanelWidget(); histogram.ExpectTimeBucketCount( mahi_constants::kMahiUserJourneyTimeHistogramName, base::Seconds(3), - /*count=*/1); + /*expected_count=*/1); task_environment()->AdvanceClock(base::Minutes(3)); CreatePanelWidget(); histogram.ExpectTimeBucketCount( mahi_constants::kMahiUserJourneyTimeHistogramName, base::Minutes(3), - /*count=*/1); + /*expected_count=*/1); task_environment()->AdvanceClock(base::Minutes(10)); CreatePanelWidget(); histogram.ExpectTimeBucketCount( mahi_constants::kMahiUserJourneyTimeHistogramName, base::Minutes(10), - /*count=*/1); + /*expected_count=*/1); +} + +TEST_F(MahiPanelViewTest, ReportQuestionCountWhenRefresh) { + ON_CALL(mock_mahi_manager(), AnswerQuestion) + .WillByDefault( + [](const std::u16string& question, bool current_panel_content, + chromeos::MahiManager::MahiAnswerQuestionCallback callback) { + std::move(callback).Run(u"answer", + chromeos::MahiResponseStatus::kSuccess); + }); + + // Ask one question then refresh. Verify that the recorded question count + // in this Mahi session should be one. + base::HistogramTester histogram_tester; + SubmitTestQuestion(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, /*sample=*/1, + /*expected_count=*/0); + ui_controller()->RefreshContents(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, /*sample=*/1, + /*expected_count=*/1); + + // Ask two questions then refresh. Verify that the recorded question count + // in this Mahi session should be two. + SubmitTestQuestion(); + SubmitTestQuestion(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, /*sample=*/1, + /*expected_count=*/1); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, /*sample=*/2, + /*expected_count=*/0); + ui_controller()->RefreshContents(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, /*sample=*/2, + /*expected_count=*/1); +} + +TEST_F(MahiPanelViewTest, ReportQuestionCountWhenMahiPanelDestroyed) { + ON_CALL(mock_mahi_manager(), AnswerQuestion) + .WillByDefault( + [](const std::u16string& question, bool current_panel_content, + chromeos::MahiManager::MahiAnswerQuestionCallback callback) { + std::move(callback).Run(u"answer", + chromeos::MahiResponseStatus::kSuccess); + }); + + // Ask one question then destroy the Mahi panel. Verify that the recorded + // question count in this Mahi session should be one. + base::HistogramTester histogram_tester; + SubmitTestQuestion(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, /*sample=*/1, + /*expected_count=*/0); + ResetPanelWidget(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, /*sample=*/1, + /*expected_count=*/1); + + // Ask two questions then destroy the Mahi panel. Verify that the recorded + // question count in this Mahi session should be two. + CreatePanelWidget(); + SubmitTestQuestion(); + SubmitTestQuestion(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, + /*sample=*/1, + /*expected_count=*/1); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, + /*sample=*/2, + /*expected_count=*/0); + ResetPanelWidget(); + histogram_tester.ExpectBucketCount( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, + /*sample=*/2, + /*expected_count=*/1); } } // namespace ash
diff --git a/ash/system/mahi/mahi_question_answer_view.cc b/ash/system/mahi/mahi_question_answer_view.cc index 21a313f..eaecc533 100644 --- a/ash/system/mahi/mahi_question_answer_view.cc +++ b/ash/system/mahi/mahi_question_answer_view.cc
@@ -206,6 +206,27 @@ namespace ash { +// MahiQuestionAnswerView::QuestionCountReporter ------------------------------- + +MahiQuestionAnswerView::QuestionCountReporter::QuestionCountReporter() = + default; + +MahiQuestionAnswerView::QuestionCountReporter::~QuestionCountReporter() = + default; + +void MahiQuestionAnswerView::QuestionCountReporter::IncreaseQuestionCount() { + ++question_count_; +} + +void MahiQuestionAnswerView::QuestionCountReporter::ReportDataAndReset() { + base::UmaHistogramCounts100( + mahi_constants::kQuestionCountPerMahiSessionHistogramName, + question_count_); + question_count_ = 0; +} + +// MahiQuestionAnswerView ------------------------------------------------------ + MahiQuestionAnswerView::MahiQuestionAnswerView(MahiUiController* ui_controller) : MahiUiController::Delegate(ui_controller), ui_controller_(ui_controller) { CHECK(ui_controller); @@ -220,7 +241,9 @@ views::MaximumFlexSizeRule::kUnbounded)); } -MahiQuestionAnswerView::~MahiQuestionAnswerView() = default; +MahiQuestionAnswerView::~MahiQuestionAnswerView() { + question_count_reporter_.ReportDataAndReset(); +} views::View* MahiQuestionAnswerView::GetView() { return this; @@ -249,6 +272,7 @@ CreateQuestionAnswerRow(update.GetAnswer(), /*is_question=*/false)); return; case MahiUiUpdateType::kContentsRefreshInitiated: + question_count_reporter_.ReportDataAndReset(); RemoveAllChildViews(); return; case MahiUiUpdateType::kErrorReceived: { @@ -277,6 +301,7 @@ return; } case MahiUiUpdateType::kQuestionPosted: { + question_count_reporter_.IncreaseQuestionCount(); AddChildView(CreateQuestionAnswerRow(update.GetQuestion(), /*is_question=*/true)); // Destroys `error_bubble_` if any when the user posts a new question.
diff --git a/ash/system/mahi/mahi_question_answer_view.h b/ash/system/mahi/mahi_question_answer_view.h index 9da617f..062cda8 100644 --- a/ash/system/mahi/mahi_question_answer_view.h +++ b/ash/system/mahi/mahi_question_answer_view.h
@@ -35,6 +35,23 @@ ~MahiQuestionAnswerView() override; private: + // A helper class to count questions and report the metric data. + class QuestionCountReporter { + public: + QuestionCountReporter(); + QuestionCountReporter(const QuestionCountReporter&) = delete; + QuestionCountReporter& operator=(const QuestionCountReporter&) = delete; + ~QuestionCountReporter(); + + void IncreaseQuestionCount(); + + // Reports `question_count_` before reset. + void ReportDataAndReset(); + + private: + int question_count_ = 0; + }; + // MahiUiController::Delegate: views::View* GetView() override; bool GetViewVisibility(VisibilityState state) const override; @@ -57,6 +74,11 @@ // Records the time when `answer_loading_animated_image_` starts showing and // playing the animation. Used for metrics collection. base::TimeTicks answer_start_loading_time_; + + // Counts questions and reports the metric data when: + // 1. `MahiQuestionAnswerView` is destroyed. + // 2. `MahiQuestionAnswerView` is refreshed. + QuestionCountReporter question_count_reporter_; }; BEGIN_VIEW_BUILDER(ASH_EXPORT, MahiQuestionAnswerView, views::FlexLayoutView)
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc index c6850253..47c16d0e 100644 --- a/ash/system/power/power_button_controller.cc +++ b/ash/system/power/power_button_controller.cc
@@ -49,7 +49,7 @@ // Time that power button should be pressed after power menu is shown before // starting the cancellable pre-shutdown animation. -constexpr base::TimeDelta kRequestCancelableShutdownTimeout = +constexpr base::TimeDelta kStartShutdownAnimationTimeout = base::Milliseconds(650); enum PowerButtonUpState { @@ -141,8 +141,7 @@ } void PowerButtonController::OnPreShutdownTimeout() { - lock_state_controller_->RequestCancelableShutdown( - ShutdownReason::POWER_BUTTON); + lock_state_controller_->StartShutdownAnimation(ShutdownReason::POWER_BUTTON); // |menu_widget_| might be reset on login status change while shutting down. if (!menu_widget_) { return; @@ -213,8 +212,7 @@ display_controller_->SetBacklightsForcedOff(false); if (menu_shown_when_power_button_down_) { - pre_shutdown_timer_.Start(FROM_HERE, kRequestCancelableShutdownTimeout, - this, + pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this, &PowerButtonController::OnPreShutdownTimeout); return; } @@ -232,21 +230,16 @@ base::Unretained(this), ShutdownReason::POWER_BUTTON)); } } else { + uint32_t up_state = UP_NONE; + if (lock_state_controller_->CanCancelShutdownAnimation()) { + up_state |= UP_CAN_CANCEL_SHUTDOWN_ANIMATION; + lock_state_controller_->CancelShutdownAnimation(); + } const base::TimeTicks previous_up_time = last_button_up_time_; last_button_up_time_ = timestamp; const bool menu_timer_was_running = power_button_menu_timer_.IsRunning(); const bool pre_shutdown_timer_was_running = pre_shutdown_timer_.IsRunning(); - uint32_t up_state = UP_NONE; - // A cancelable shutdown will be requested after the menu is fully shown and - // `pre_shutdown_timer_` timeout. Check whether the shutdown is still - // cancelable only after the shutdown is requested. - if (show_menu_animation_done_ && !pre_shutdown_timer_was_running && - lock_state_controller_->CanCancelShutdownAnimation()) { - up_state |= UP_CAN_CANCEL_SHUTDOWN_ANIMATION; - lock_state_controller_->CancelShutdownAnimation(); - } - power_button_menu_timer_.Stop(); pre_shutdown_timer_.Stop(); @@ -566,8 +559,7 @@ show_menu_animation_done_ = true; if (button_type_ != ButtonType::LEGACY && shutdown_reason_ == ShutdownReason::POWER_BUTTON) { - pre_shutdown_timer_.Start(FROM_HERE, kRequestCancelableShutdownTimeout, - this, + pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this, &PowerButtonController::OnPreShutdownTimeout); } }
diff --git a/ash/system/power/power_button_menu_view.cc b/ash/system/power/power_button_menu_view.cc index 312fead..a151b51c 100644 --- a/ash/system/power/power_button_menu_view.cc +++ b/ash/system/power/power_button_menu_view.cc
@@ -201,7 +201,7 @@ add_remove_item( true, PowerButtonMenuActionType::kPowerOff, base::BindRepeating( - &LockStateController::RequestShutdown, + &LockStateController::StartShutdownAnimation, base::Unretained(Shell::Get()->lock_state_controller()), shutdown_reason_), kSystemPowerButtonMenuPowerOffIcon,
diff --git a/ash/system/unified/power_button.cc b/ash/system/unified/power_button.cc index 65f63f3..9325ccc93 100644 --- a/ash/system/unified/power_button.cc +++ b/ash/system/unified/power_button.cc
@@ -200,7 +200,7 @@ case VIEW_ID_QS_POWER_OFF_MENU_BUTTON: quick_settings_metrics_util::RecordQsButtonActivated( QsButtonCatalogName::kPowerOffMenuButton); - Shell::Get()->lock_state_controller()->RequestShutdown( + Shell::Get()->lock_state_controller()->StartShutdownAnimation( ShutdownReason::TRAY_SHUT_DOWN_BUTTON); break; case VIEW_ID_QS_POWER_SIGNOUT_MENU_BUTTON:
diff --git a/ash/webui/conch b/ash/webui/conch index 075b11b..63688f1 160000 --- a/ash/webui/conch +++ b/ash/webui/conch
@@ -1 +1 @@ -Subproject commit 075b11bb88297fb404eb1fd23e5d229cd568acb8 +Subproject commit 63688f1742cefae6fc6aaf7732838f4eb420b4d3
diff --git a/ash/webui/shimless_rma/3p_diagnostics/BUILD.gn b/ash/webui/shimless_rma/3p_diagnostics/BUILD.gn deleted file mode 100644 index ee915a2..0000000 --- a/ash/webui/shimless_rma/3p_diagnostics/BUILD.gn +++ /dev/null
@@ -1,27 +0,0 @@ -# Copyright 2023 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/chromeos/ui_mode.gni") - -assert(is_chromeos_ash, "Non-ChromeOS builds cannot depend on //ash") - -static_library("3p_diagnostics") { - sources = [ - "external_app_dialog.cc", - "external_app_dialog.h", - ] - - deps = [ - "//ash", - "//ash/public/cpp", - "//base", - "//content/public/browser", - "//ui/display", - "//ui/gfx", - "//ui/views", - "//ui/views/controls/webview", - "//ui/web_dialogs", - "//url", - ] -}
diff --git a/ash/webui/shimless_rma/backend/BUILD.gn b/ash/webui/shimless_rma/backend/BUILD.gn index 7fb9a99..549e972 100644 --- a/ash/webui/shimless_rma/backend/BUILD.gn +++ b/ash/webui/shimless_rma/backend/BUILD.gn
@@ -8,6 +8,8 @@ static_library("backend") { sources = [ + "external_app_dialog.cc", + "external_app_dialog.h", "shimless_rma_delegate.cc", "shimless_rma_delegate.h", "shimless_rma_service.cc", @@ -21,8 +23,8 @@ deps = [ "//ash", "//ash/public/cpp:cpp", - "//ash/webui/shimless_rma/3p_diagnostics", "//ash/webui/shimless_rma/mojom", + "//base", "//chromeos/ash/components/dbus", "//chromeos/ash/components/dbus/rmad", "//chromeos/ash/components/dbus/rmad:rmad_proto", @@ -36,6 +38,13 @@ "//chromeos/services/network_config/public/mojom", "//chromeos/version", "//components/qr_code_generator", + "//content/public/browser", + "//ui/display", + "//ui/gfx", + "//ui/views", + "//ui/views/controls/webview", + "//ui/web_dialogs", + "//url", ] } @@ -55,7 +64,6 @@ "//ash", "//ash:test_support", "//ash/public/cpp:cpp", - "//ash/webui/shimless_rma/3p_diagnostics", "//ash/webui/shimless_rma/mojom", "//base", "//base/test:test_support",
diff --git a/ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.cc b/ash/webui/shimless_rma/backend/external_app_dialog.cc similarity index 98% rename from ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.cc rename to ash/webui/shimless_rma/backend/external_app_dialog.cc index 4dc8ba3..7fa55f38 100644 --- a/ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.cc +++ b/ash/webui/shimless_rma/backend/external_app_dialog.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h" +#include "ash/webui/shimless_rma/backend/external_app_dialog.h" #include <memory> #include <string>
diff --git a/ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h b/ash/webui/shimless_rma/backend/external_app_dialog.h similarity index 93% rename from ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h rename to ash/webui/shimless_rma/backend/external_app_dialog.h index fce35de..957ef7a 100644 --- a/ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h +++ b/ash/webui/shimless_rma/backend/external_app_dialog.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_WEBUI_SHIMLESS_RMA_3P_DIAGNOSTICS_EXTERNAL_APP_DIALOG_H_ -#define ASH_WEBUI_SHIMLESS_RMA_3P_DIAGNOSTICS_EXTERNAL_APP_DIALOG_H_ +#ifndef ASH_WEBUI_SHIMLESS_RMA_BACKEND_EXTERNAL_APP_DIALOG_H_ +#define ASH_WEBUI_SHIMLESS_RMA_BACKEND_EXTERNAL_APP_DIALOG_H_ #include <string> @@ -99,4 +99,4 @@ } // namespace ash::shimless_rma -#endif // ASH_WEBUI_SHIMLESS_RMA_3P_DIAGNOSTICS_EXTERNAL_APP_DIALOG_H_ +#endif // ASH_WEBUI_SHIMLESS_RMA_BACKEND_EXTERNAL_APP_DIALOG_H_
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.cc b/ash/webui/shimless_rma/backend/shimless_rma_service.cc index ae17e272..e7086c7 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service.cc +++ b/ash/webui/shimless_rma/backend/shimless_rma_service.cc
@@ -13,7 +13,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/network_config_service.h" #include "ash/system/diagnostics/diagnostics_log_controller.h" -#include "ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h" +#include "ash/webui/shimless_rma/backend/external_app_dialog.h" #include "ash/webui/shimless_rma/backend/shimless_rma_delegate.h" #include "ash/webui/shimless_rma/backend/version_updater.h" #include "ash/webui/shimless_rma/mojom/shimless_rma.mojom.h"
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service_3p_diag_unittest.cc b/ash/webui/shimless_rma/backend/shimless_rma_service_3p_diag_unittest.cc index 0c19a12..73cd058 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service_3p_diag_unittest.cc +++ b/ash/webui/shimless_rma/backend/shimless_rma_service_3p_diag_unittest.cc
@@ -7,7 +7,7 @@ #include <string> #include <utility> -#include "ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h" +#include "ash/webui/shimless_rma/backend/external_app_dialog.h" #include "ash/webui/shimless_rma/backend/fake_shimless_rma_delegate.h" #include "ash/webui/shimless_rma/backend/shimless_rma_service.h" #include "ash/webui/shimless_rma/mojom/shimless_rma.mojom-shared.h"
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc index e2b6cbe7..ecee70f 100644 --- a/ash/wm/lock_state_controller.cc +++ b/ash/wm/lock_state_controller.cc
@@ -303,9 +303,8 @@ } void LockStateController::StartLockAnimation() { - if (animating_lock_) { + if (animating_lock_) return; - } animating_lock_ = true; StoreUnlockedProperties(); @@ -315,6 +314,26 @@ OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED); } +void LockStateController::StartShutdownAnimation(ShutdownReason reason) { + shutdown_reason_ = reason; + + HideAndMaybeLockCursor(/*lock=*/false); + ShutdownOnPine(/*with_pre_animation=*/true); +} + +void LockStateController::RequestRestart( + power_manager::RequestRestartReason reason, + const std::string& description) { + if (features::IsForestFeatureEnabled()) { + restart_reason_ = reason; + restart_description_ = description; + HideAndMaybeLockCursor(/*lock=*/false); + TakePineImageAndShutdown(/*with_pre_animation=*/true); + } else { + chromeos::PowerManagerClient::Get()->RequestRestart(reason, description); + } +} + void LockStateController::LockWithoutAnimation() { VLOG(1) << "LockWithoutAnimation : " << "animating_unlock_: " << static_cast<int>(animating_unlock_) @@ -351,6 +370,10 @@ return lock_fail_timer_.IsRunning(); } +bool LockStateController::ShutdownRequested() { + return shutting_down_; +} + void LockStateController::CancelLockAnimation() { VLOG(1) << "CancelLockAnimation"; animating_lock_ = false; @@ -381,6 +404,38 @@ pb_pressed_during_unlock_ = true; } +bool LockStateController::CanCancelShutdownAnimation() { + return pre_shutdown_timer_.IsRunning(); +} + +void LockStateController::CancelShutdownAnimation() { + if (!CanCancelShutdownAnimation()) + return; + + animator_->StartAnimation( + SessionStateAnimator::ROOT_CONTAINER, + SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS, + SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN); + pre_shutdown_timer_.Stop(); +} + +void LockStateController::RequestShutdown(ShutdownReason reason) { + if (shutting_down_) + return; + + shutting_down_ = true; + shutdown_reason_ = reason; + + if (reason == ShutdownReason::LOGIN_SHUT_DOWN_BUTTON) { + base::Time now_timestamp = base::DefaultClock::GetInstance()->Now(); + local_state_->SetTime(prefs::kLoginShutdownTimestampPrefName, + now_timestamp); + } + + HideAndMaybeLockCursor(/*lock=*/true); + ShutdownOnPine(/*with_pre_animation=*/false); +} + void LockStateController::OnUnlockAnimationBeforeLockUIDestroyedFinished() { if (pb_pressed_during_unlock_) { // Power button was pressed during the unlock animation and @@ -416,64 +471,6 @@ lock_screen_displayed_callback_ = std::move(callback); } -void LockStateController::RequestShutdown(ShutdownReason reason) { - if (shutting_down_) { - return; - } - - shutting_down_ = true; - shutdown_reason_ = reason; - - if (reason == ShutdownReason::LOGIN_SHUT_DOWN_BUTTON) { - base::Time now_timestamp = base::DefaultClock::GetInstance()->Now(); - local_state_->SetTime(prefs::kLoginShutdownTimestampPrefName, - now_timestamp); - } - - HideAndMaybeLockCursor(/*lock=*/true); - ShutdownOnPine(/*with_pre_animation=*/false); -} - -void LockStateController::RequestCancelableShutdown(ShutdownReason reason) { - shutdown_reason_ = reason; - - HideAndMaybeLockCursor(/*lock=*/false); - ShutdownOnPine(/*with_pre_animation=*/true); -} - -bool LockStateController::ShutdownRequested() { - return shutting_down_; -} - -bool LockStateController::CanCancelShutdownAnimation() { - return pre_shutdown_timer_.IsRunning(); -} - -void LockStateController::CancelShutdownAnimation() { - if (!CanCancelShutdownAnimation()) { - return; - } - - animator_->StartAnimation( - SessionStateAnimator::ROOT_CONTAINER, - SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS, - SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN); - pre_shutdown_timer_.Stop(); -} - -void LockStateController::RequestRestart( - power_manager::RequestRestartReason reason, - const std::string& description) { - if (features::IsForestFeatureEnabled()) { - restart_reason_ = reason; - restart_description_ = description; - HideAndMaybeLockCursor(/*lock=*/false); - TakePineImageAndShutdown(/*with_pre_animation=*/false); - } else { - chromeos::PowerManagerClient::Get()->RequestRestart(reason, description); - } -} - void LockStateController::OnHostCloseRequested(aura::WindowTreeHost* host) { Shell::Get()->session_controller()->RequestSignOut(); } @@ -541,6 +538,51 @@ Shell::Get()->session_controller()->RequestSignOut(); } +void LockStateController::StartPreShutdownAnimationTimer() { + pre_shutdown_timer_.Stop(); + pre_shutdown_timer_.Start( + FROM_HERE, + animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN), + this, &LockStateController::OnPreShutdownAnimationTimeout); +} + +void LockStateController::OnPreShutdownAnimationTimeout() { + VLOG(1) << "OnPreShutdownAnimationTimeout"; + shutting_down_ = true; + + HideAndMaybeLockCursor(/*lock=*/false); + StartRealShutdownTimer(false); +} + +void LockStateController::StartRealShutdownTimer(bool with_animation_time) { + base::TimeDelta duration = kShutdownRequestDelay; + if (with_animation_time) { + duration += + animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); + } + // Play and get shutdown sound duration from chrome in |sound_duration|. And + // start real shutdown after a delay of |duration|. + base::TimeDelta sound_duration = + std::min(Shell::Get()->accessibility_controller()->PlayShutdownSound(), + base::Milliseconds(kMaxShutdownSoundDurationMs)); + duration = std::max(duration, sound_duration); + real_shutdown_timer_.Start(FROM_HERE, duration, this, + &LockStateController::OnRealPowerTimeout); +} + +void LockStateController::OnRealPowerTimeout() { + VLOG(1) << "OnRealPowerTimeout"; + DCHECK(shutting_down_); + DCHECK(shutdown_reason_ || restart_reason_); + // Shut down or reboot based on device policy. + if (restart_reason_) { + chromeos::PowerManagerClient::Get()->RequestRestart(*restart_reason_, + restart_description_); + } else { + shutdown_controller_->ShutDownOrReboot(*shutdown_reason_); + } +} + void LockStateController::PreLockAnimation( SessionStateAnimator::AnimationSpeed speed, bool request_lock_on_completion) { @@ -767,51 +809,6 @@ observer.OnLockStateEvent(event); } -void LockStateController::StartPreShutdownAnimationTimer() { - pre_shutdown_timer_.Stop(); - pre_shutdown_timer_.Start( - FROM_HERE, - animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN), - this, &LockStateController::OnPreShutdownAnimationTimeout); -} - -void LockStateController::OnPreShutdownAnimationTimeout() { - VLOG(1) << "OnPreShutdownAnimationTimeout"; - shutting_down_ = true; - - HideAndMaybeLockCursor(/*lock=*/false); - StartRealShutdownTimer(false); -} - -void LockStateController::StartRealShutdownTimer(bool with_animation_time) { - base::TimeDelta duration = kShutdownRequestDelay; - if (with_animation_time) { - duration += - animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - } - // Play and get shutdown sound duration from chrome in |sound_duration|. And - // start real shutdown after a delay of |duration|. - base::TimeDelta sound_duration = - std::min(Shell::Get()->accessibility_controller()->PlayShutdownSound(), - base::Milliseconds(kMaxShutdownSoundDurationMs)); - duration = std::max(duration, sound_duration); - real_shutdown_timer_.Start(FROM_HERE, duration, this, - &LockStateController::OnRealPowerTimeout); -} - -void LockStateController::OnRealPowerTimeout() { - VLOG(1) << "OnRealPowerTimeout"; - DCHECK(shutting_down_); - DCHECK(shutdown_reason_ || restart_reason_); - // Shut down or reboot based on device policy. - if (restart_reason_) { - chromeos::PowerManagerClient::Get()->RequestRestart(*restart_reason_, - restart_description_); - } else { - shutdown_controller_->ShutDownOrReboot(*shutdown_reason_); - } -} - void LockStateController::ShutdownOnPine(bool with_pre_animation) { if (features::IsForestFeatureEnabled()) { TakePineImageAndShutdown(with_pre_animation);
diff --git a/ash/wm/lock_state_controller.h b/ash/wm/lock_state_controller.h index 221a221..f944ad0 100644 --- a/ash/wm/lock_state_controller.h +++ b/ash/wm/lock_state_controller.h
@@ -72,6 +72,15 @@ // Starts locking (with slow pre-lock animation) that can be cancelled. void StartLockAnimation(); + // Starts shutting down (with slow animation) that can be cancelled. + void StartShutdownAnimation(ShutdownReason reason); + + // Requests restart with the same animation as `StartShutdownAnimation`. + // `description` is a human-readable string describing the source of request + // the restart. + void RequestRestart(power_manager::RequestRestartReason reason, + const std::string& description); + // Starts locking without slow animation. void LockWithoutAnimation(); @@ -79,12 +88,25 @@ // confirmation yet. bool LockRequested(); + // Returns true if we are shutting down. + bool ShutdownRequested(); + // Cancels locking and reverts lock animation. void CancelLockAnimation(); // Cancels unlock animation. void CancelUnlockAnimation(); + // Returns true if we are within cancellable shutdown timeframe. + bool CanCancelShutdownAnimation(); + + // Cancels shutting down and reverts shutdown animation. + void CancelShutdownAnimation(); + + // Displays the shutdown animation and requests a system shutdown or system + // restart depending on the the state of the |RebootOnShutdown| device policy. + void RequestShutdown(ShutdownReason reason); + // Called when ScreenLocker is ready to close, but not yet destroyed. // Can be used to display "hiding" animations on unlock. // |callback| will be called when all animations are done. @@ -94,32 +116,6 @@ // Callback is guaranteed to be called once and then discarded. void SetLockScreenDisplayedCallback(base::OnceClosure callback); - // Displays the shutdown animation and requests a system shutdown or system - // restart depending on the the state of the |RebootOnShutdown| device policy. - void RequestShutdown(ShutdownReason reason); - - // The difference between this and `RequestShutdown` is that this one starts - // the shutdown that can be canceled. It is true if the `pre_shutdown_timer_` - // is still running (CanCancelShutdownAnimation). Please use only when - // necessary, e.g., requesting through the physical power button that it can - // be released with a very short press. - void RequestCancelableShutdown(ShutdownReason reason); - - // Returns true if we are shutting down. - bool ShutdownRequested(); - - // Returns true if we are within cancellable shutdown timeframe. - bool CanCancelShutdownAnimation(); - - // Cancels shutting down and reverts shutdown animation. - void CancelShutdownAnimation(); - - // Requests restart with the same animation as `RequestShutdown`. - // `description` is a human-readable string describing the source of request - // the restart. - void RequestRestart(power_manager::RequestRestartReason reason, - const std::string& description); - // aura::WindowTreeHostObserver override: void OnHostCloseRequested(aura::WindowTreeHost* host) override; @@ -142,6 +138,20 @@ // Reverts the pre-lock animation, reports the error. void OnLockFailTimeout(); + // Starts timer for undoable shutdown animation. + void StartPreShutdownAnimationTimer(); + + // Calls StartRealShutdownTimer(). + void OnPreShutdownAnimationTimeout(); + + // Starts timer for final shutdown animation. + // If |with_animation_time| is true, it will also include time of "fade to + // white" shutdown animation. + void StartRealShutdownTimer(bool with_animation_time); + + // Request that the machine be shut down. + void OnRealPowerTimeout(); + void PreLockAnimation(SessionStateAnimator::AnimationSpeed speed, bool request_lock_on_completion); void StartPostLockAnimation(); @@ -181,20 +191,6 @@ // Notifies observers. void OnLockStateEvent(LockStateObserver::EventType event); - // Starts timer for undoable shutdown animation. - void StartPreShutdownAnimationTimer(); - - // Calls StartRealShutdownTimer(). - void OnPreShutdownAnimationTimeout(); - - // Starts timer for final shutdown animation. - // If |with_animation_time| is true, it will also include time of "fade to - // white" shutdown animation. - void StartRealShutdownTimer(bool with_animation_time); - - // Request that the machine be shut down. - void OnRealPowerTimeout(); - // Triggers the shutdown way on `Pine`. void ShutdownOnPine(bool with_pre_animation);
diff --git a/build/config/siso/main.star b/build/config/siso/main.star index c41f3ff..3c80cb5 100644 --- a/build/config/siso/main.star +++ b/build/config/siso/main.star
@@ -38,6 +38,7 @@ "./lacros_clang_x64/obj/chrome/browser/browser/chrome_browser_interface_binders.o", "./lacros_clang_x64/obj/chrome/browser/browser/chrome_content_browser_client.o", "./lacros_clang_x64/obj/content/browser/browser/browser_interface_binders.o", + "./lacros_clang_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", "./lacros_clang_x64/obj/third_party/blink/public/mojom/mojom_platform/speech_recognition_grammar.mojom.o", "./obj/chrome/browser/ash/ash/autotest_private_api.o", "./obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o", @@ -67,6 +68,7 @@ "./obj/chrome/test/test_support_ui/web_app_integration_test_driver.o", "./obj/chrome/test/unit_tests/chrome_browsing_data_remover_delegate_unittest.o", "./obj/chrome/test/unit_tests/chrome_shelf_controller_unittest.o", + "./obj/chrome/test/unit_tests/render_view_context_menu_unittest.o", "./obj/content/browser/browser/browser_interface_binders.o", # Fallback happens with follwoing args.gn (try/linux-lacros-rel-compilator). @@ -204,17 +206,65 @@ # use_siso = true "./obj/content/test/content_browsertests__library/interest_group_browsertest.o", "./obj/content/test/content_browsertests__library/prerender_browsertest.o", + "./robolectric_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", # Fallback happens with the following args.gn # (linux-build-perf-developer, win-build-perf-developer) # is_component_build = true # is_debug = true # symbol_level = 2 # use_siso = true + "./clang_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", "./obj/content/browser/browser/render_process_host_impl.o", + "./obj/net/http/transport_security_state_generated_files/transport_security_state.o", + # Fallback happens with the following args.gn + # (try/mac-rel) + # coverage_instrumentation_input_file = "//.code-coverage/files_to_instrument.txt" + # dcheck_always_on = true + # enable_backup_ref_ptr_feature_flag = true + # enable_dangling_raw_ptr_checks = true + # enable_dangling_raw_ptr_feature_flag = true + # ffmpeg_branding = "Chrome" + # is_component_build = false + # is_debug = false + # proprietary_codecs = true + # symbol_level = 0 + # target_cpu = "x64" + # use_clang_coverage = true + # use_remoteexec = false + # use_siso = true + "./arm64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", + "./arm64_v8_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", + "./clang_arm64_v8_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", + # Fallback happens with the following args.gn + # (try/ios-simulator) + # coverage_instrumentation_input_file = "//.code-coverage/files_to_instrument.txt" + # enable_run_ios_unittests_with_xctest = true + # is_component_build = false + # is_debug = true + # symbol_level = 1 + # target_cpu = "x64" + # target_environment = "simulator" + # target_os = "ios" + # use_clang_coverage = true + # use_remoteexec = false + # use_siso = true + "./clang_arm64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", ] if runtime.os == "windows": exit137_list = [obj.removesuffix(".o") + ".obj" for obj in exit137_list if obj.startswith("./obj/")] + # Fallback happens with the following args.gn + # (win-build-perf-developer) + # is_component_build = true + # is_debug = true + # symbol_level = 2 + # use_siso = true + exit137_list.extend([ + "./obj/content/browser/browser/storage_partition_impl.obj", + "./obj/third_party/blink/renderer/core/core/local_frame_view.obj", + "./obj/third_party/blink/renderer/core/core_hot/document.obj", + ]) + new_rules = [] for rule in step_config["rules"]: if not rule["name"].endswith("/cxx"):
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 629520f4..682c108e 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -20.20240407.0.1 +20.20240414.1.1
diff --git a/chrome/VERSION b/chrome/VERSION index 8bc2af6b..33519bf 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=125 MINOR=0 -BUILD=6419 +BUILD=6421 PATCH=0
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java index e572ba3..de95f61 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
@@ -41,7 +41,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Features; import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.base.test.util.Features.EnableFeatures; @@ -214,7 +213,10 @@ @Test @MediumTest - @DisabledTest(message = "b/333905073") + @DisableFeatures({ + ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_NO_MIGRATION, + ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_WITH_MIGRATION + }) public void testManagePasswords() throws InterruptedException { setSuggestions(createPedalSuggestion(OmniboxPedalId.MANAGE_PASSWORDS)); clickOnPedalToSettings(() -> mOmniboxUtils.clickOnAction(0, 0), PasswordSettings.class);
diff --git a/chrome/app/resources/chromium_strings_da.xtb b/chrome/app/resources/chromium_strings_da.xtb index b6fce500..cc1016f 100644 --- a/chrome/app/resources/chromium_strings_da.xtb +++ b/chrome/app/resources/chromium_strings_da.xtb
@@ -75,7 +75,7 @@ <translation id="2398377054246527950">{NUM_DEVICES,plural, =0{En eller flere Chromium-udvidelser havde adgang til 1 HID-enhed}=1{En eller flere Chromium-udvidelser har adgang til 1 HID-enhed}one{En eller flere Chromium-udvidelser har adgang til # HID-enhed}other{En eller flere Chromium-udvidelser har adgang til # HID-enheder}}</translation> <translation id="2401032172288869980">Chromium skal have adgangstilladelse til kamera og mikrofon for at bruge dette website</translation> <translation id="2440750600860946460">Med <ph name="BEGIN_LINK" />værktøjer fra Chromium<ph name="END_LINK" /> kan du søge sikkert på nettet og bevare styringen</translation> -<translation id="2451727308784734061">Brug din genvej til hurtigt at gå til Adgangskodeadministrator. Du kan flytte din genvej til din computers startskærm eller appliste.</translation> +<translation id="2451727308784734061">Brug din genvej til hurtigt at gå til Adgangskodeadministrator. Du kan flytte din genvej til din computers startskærm eller appliste.</translation> <translation id="2478295928299953161">Chromium lukkes snart</translation> <translation id="2483889755041906834">I Chromium</translation> <translation id="2485422356828889247">Afinstaller</translation> @@ -132,7 +132,7 @@ <translation id="3350761136195634146">Der findes allerede en Chromium-profil med denne konto</translation> <translation id="3387527074123400161">Chromium OS</translation> <translation id="3406848076815591792">Vil du skifte til den eksisterende Chromium-profil?</translation> -<translation id="3412460710772753638">I Adgangskodeadministrator på denne enhed</translation> +<translation id="3412460710772753638">I Adgangskodeadministrator på denne enhed</translation> <translation id="3430503420100763906">Du kan organisere alle dine ting i Chromium ved hjælp af Chromium-profiler. Opret profiler til dine venner og din familie, eller brug dem til at holde arbejde og fornøjelse adskilt.</translation> <translation id="347328004046849135">Chromium giver dig besked, når du logger ind med en kompromitteret adgangskode</translation> <translation id="3474745554856756813">Denne handling sletter <ph name="ITEMS_COUNT" /> elementer på denne enhed. Hvis du senere vil hente dine data igen, skal du logge ind på Chromium som <ph name="USER_EMAIL" />.</translation> @@ -171,7 +171,7 @@ <translation id="4019629340646866719">Chromium OS leveres ved hjælp af <ph name="BEGIN_LINK_CROS_OSS" />open source-software<ph name="END_LINK_CROS_OSS" />. Det samme gælder for <ph name="BEGIN_LINK_LINUX_OSS" />Linux-udviklingsmiljøet<ph name="END_LINK_LINUX_OSS" />.</translation> <translation id="4036079820698952681">Hjælp med at gøre Chromium bedre ved at rapportere de <ph name="BEGIN_LINK" />aktuelle indstillinger<ph name="END_LINK" />.</translation> <translation id="4050175100176540509">Vigtige sikkerhedsforbedringer og nye funktioner er tilgængelige i den seneste version.</translation> -<translation id="4055805654398742145">Adgangskodeadministrator</translation> +<translation id="4055805654398742145">Adgangskodeadministrator</translation> <translation id="4095980151185649725">{COUNT,plural, =1{Din organisation lukker automatisk Chromium, når den ikke bruges i 1 minut. Browserdataene slettes. Disse kan omfatte historik, autofyld og downloads.}one{Din organisation lukker automatisk Chromium, når den ikke bruges i # minut. Browserdataene slettes. Disse kan omfatte historik, autofyld og downloads.}other{Din organisation lukker automatisk Chromium, når den ikke bruges i # minutter. Browserdataene slettes. Disse kan omfatte historik, autofyld og downloads.}}</translation> <translation id="4118474109249235144">Inkognitotilstand i Chromium</translation> <translation id="4148957013307229264">Installerer...</translation> @@ -184,7 +184,7 @@ <translation id="4271805377592243930">Få hjælp til Chromium</translation> <translation id="4281844954008187215">Servicevilkår</translation> <translation id="4285930937574705105">Installationen mislykkedes på grund af en ikke-specificeret fejl. Hvis Chromium kører, skal du lukke programmet og prøve igen.</translation> -<translation id="4304713468139749426">Adgangskodeadministrator</translation> +<translation id="4304713468139749426">Adgangskodeadministrator</translation> <translation id="4334294535648607276">Download fuldført.</translation> <translation id="439358628917130594"><ph name="MANAGER" /> kræver, at du læser og accepterer følgende servicevilkår, inden du bruger denne enhed. Disse vilkår udvider, ændrer eller begrænser på ingen måde vilkårene for Chromium OS.</translation> <translation id="4407044323746248786">Vil du afslutte Chromium alligevel?</translation> @@ -198,7 +198,7 @@ <translation id="454579500955453258">Vil du fortsætte på en ny Chromium-profil?</translation> <translation id="4567424176335768812">Du er logget ind som <ph name="USER_EMAIL_ADDRESS" />. Nu kan du få adgang til dine bogmærker, din historik og andre indstillinger på alle de enheder, hvor du er logget ind.</translation> <translation id="4570813286784708942">Chromium har blokeret denne download, fordi du har deaktiveret Beskyttet browsing, og filen ikke kan verificeres</translation> -<translation id="4594305310729380060">I Adgangskodeadministrator på denne enhed</translation> +<translation id="4594305310729380060">I Adgangskodeadministrator på denne enhed</translation> <translation id="459535195905078186">Chromium-apps</translation> <translation id="4613863813562375431">Chromium OS-version</translation> <translation id="4621240073146040695">Næsten opdateret. Genstart Chromium for at afslutte opdateringen.</translation> @@ -300,7 +300,7 @@ <translation id="6334986366598267305">Det er nu blevet nemmere at bruge Chromium med din Google-konto og på delte computere.</translation> <translation id="6366160072964553914">Chromium har blokeret denne download, fordi filen normalt ikke downloades og kan være skadelig</translation> <translation id="6373523479360886564">Er du sikker på, at du vil afinstallere Chromium?</translation> -<translation id="6375219077595103062">Tilføj en genvej til Adgangskodeadministrator</translation> +<translation id="6375219077595103062">Tilføj en genvej til Adgangskodeadministrator</translation> <translation id="6384011394608460044"><ph name="BEGIN_BOLD" />Sådan bruger vi disse data:<ph name="END_BOLD" /> Chromium kan estimere dine interesser. Senere kan et website, du besøger, anmode Chromium om at se dine interesser med henblik på at personligt tilpasse de annoncer, du ser.</translation> <translation id="6400112897226594999">Chromium-logo på en computerskærm.</translation> <translation id="6403826409255603130">Chromium er en webbrowser, der kører websider og apps med lynets hast. Den er hurtig, stabil og brugervenlig. Beskyttelse mod malware og phishing er indbygget i Chromium, så du kan søge mere sikkert på internettet.</translation> @@ -440,7 +440,7 @@ <translation id="8719993436687031146">Vil du logge ind i Chromium?</translation> <translation id="878572486461146056">Installationsfejl: Din netværksadministrator anvender en gruppepolitik, der forhindrer installationen: <ph name="INSTALL_ERROR" /></translation> <translation id="8796602469536043152">Chromium skal have tilladelse til at bruge dit kamera og din mikrofon på dette website</translation> -<translation id="8826492472752484139">Klik på "Adgangskodeadministrator"</translation> +<translation id="8826492472752484139">Klik på "Adgangskodeadministrator"</translation> <translation id="8833697763442816810">Chromium OS-system</translation> <translation id="8846118132221683440"><ph name="BEGIN_BOLD" />Disse data bruges:<ph name="END_BOLD" /> Din browserhistorik, dvs. en oversigt over, hvilke websites du har besøgt i Chromium på denne enhed.</translation> <translation id="8862326446509486874">Du har ikke de nødvendige rettigheder til en installation på systemniveau. Prøv at køre installationsprogrammet igen som administrator.</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb index 1d2b766..a7a243c 100644 --- a/chrome/app/resources/generated_resources_da.xtb +++ b/chrome/app/resources/generated_resources_da.xtb
@@ -135,7 +135,7 @@ <translation id="1093645050124056515">Ctrl + Alt + pil ned</translation> <translation id="1094219634413363886">Du får vist en notifikation, hvis en optagelse starter på denne administrerede enhed</translation> <translation id="1095761715416917775">Sørg for, at du altid kan få adgang til dine synkroniserede data</translation> -<translation id="1095879482467973146">Google Adgangskodeadministrator på nettet</translation> +<translation id="1095879482467973146">Google Adgangskodeadministrator på nettet</translation> <translation id="109647177154844434">Hvis du afinstallerer Parallels Desktop, slettes dit Windows-billede. Dette omfatter dens apps, indstillinger og data. Er du sikker på, at du vil fortsætte?</translation> <translation id="1097016918605049747">Denne side kunne ikke oversættes</translation> <translation id="1097658378307015415">Før du logger ind, skal du starte en gæstesession for at aktivere netværket <ph name="NETWORK_ID" /></translation> @@ -456,7 +456,7 @@ <translation id="13392265090583506">A11y</translation> <translation id="1340527397989195812">Sikkerhedskopiér medier fra enheden ved hjælp af appen Filer.</translation> <translation id="1341701348342335220">Sådan!</translation> -<translation id="1342886103232377846">Gå til Google Adgangskodeadministrator for at tjekke, om der er kompromitterede adgangskoder</translation> +<translation id="1342886103232377846">Gå til Google Adgangskodeadministrator for at tjekke, om der er kompromitterede adgangskoder</translation> <translation id="1343865611738742294">Giv Linux-apps adgang til USB-enheder. Linux husker ikke en USB-enhed, når den er fjernet.</translation> <translation id="1343920184519992513">Fortsæt, hvor du slap, og åbn en bestemt række sider</translation> <translation id="1344141078024003905">Du caster din skærm. Du kan til enhver tid sætte din casting af skærmen på pause eller stoppe den.</translation> @@ -897,7 +897,7 @@ <translation id="1651008383952180276">Du skal angive den samme adgangssætning to gange</translation> <translation id="1651609627703324721">Denne fane viser VR-indhold til et headset</translation> <translation id="1652326691684645429">Slå Deling tæt på til</translation> -<translation id="1652862280638399816">Hvis du vil bruge Adgangskodeadministrator sammen med macOS-nøgleringen, skal du genstarte Chromium og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="1652862280638399816">Hvis du vil bruge Adgangskodeadministrator sammen med macOS-nøgleringen, skal du genstarte Chromium og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="1653958716132599769">Gruppér relaterede faner</translation> <translation id="1654580009054503925">Har ikke tilladelse til at vise anmodninger</translation> <translation id="1656528038316521561">Baggrundens gennemsigtighed</translation> @@ -1437,7 +1437,7 @@ <translation id="2048653237708779538">Handlingen er ikke tilgængelig</translation> <translation id="204914487372604757">Opret genvej</translation> <translation id="2050339315714019657">Højformat</translation> -<translation id="2051266530792296582">Google Adgangskodeadministrator har oprettet en stærk adgangskode til dette website</translation> +<translation id="2051266530792296582">Google Adgangskodeadministrator har oprettet en stærk adgangskode til dette website</translation> <translation id="2051555741181591333">Deaktiver hotspot automatisk</translation> <translation id="2051669996101374349">Brug HTTPS, når det er muligt, og bliv advaret før indlæsning af websites, der ikke understøtter HTTPS. Du kan ikke ændre denne indstilling, fordi du har aktiveret Avanceret beskyttelse.</translation> <translation id="2052572566310583903">Installeret på dine andre enheder</translation> @@ -2303,7 +2303,7 @@ <translation id="2687407218262674387">Googles servicevilkår</translation> <translation id="2687621393791886981">Spørg mig senere</translation> <translation id="2688196195245426394">Fejl ved registrering af enheden med serveren: <ph name="CLIENT_ERROR" />.</translation> -<translation id="2688734475209947648">Du behøver ikke at huske denne adgangskode. Den gemmes i Googles Adgangskodeadministrator for <ph name="ACCOUNT" />.</translation> +<translation id="2688734475209947648">Du behøver ikke at huske denne adgangskode. Den gemmes i Googles Adgangskodeadministrator for <ph name="ACCOUNT" />.</translation> <translation id="2690024944919328218">Vis sprogindstillinger</translation> <translation id="2691385045260836588">Model</translation> <translation id="2691440343905273290">Skift indstillinger for indtastning</translation> @@ -3242,7 +3242,7 @@ <translation id="3432762828853624962">Shared Workers</translation> <translation id="3433507769937235446">Lås ved manglende tilstedeværelse</translation> <translation id="3433621910545056227">Ups! Systemet kunne ikke fastslå indstallationstidspunktet for enhedens attributlås.</translation> -<translation id="3434025015623587566">Google Adgangskodeadministrator skal bruge mere omfattende adgang</translation> +<translation id="3434025015623587566">Google Adgangskodeadministrator skal bruge mere omfattende adgang</translation> <translation id="3434107140712555581"><ph name="BATTERY_PERCENTAGE" /> %</translation> <translation id="3434272557872943250">Hvis indstillingen for yderligere web- og appaktivitet er aktiveret for dit barn, gemmes disse data muligvis på barnets Google-konto. Få flere oplysninger om disse indstillinger og om, hvordan du ændrer dem, ved at gå til families.google.com.</translation> <translation id="3434475275396485144">Denne indstilling administreres af administratoren af din telefon</translation> @@ -3486,7 +3486,7 @@ <translation id="3617062258679844578">Du kan klikke ved at trykke på din touchplade</translation> <translation id="3617891479562106823">Baggrunde er utilgængelige. Prøv igen senere.</translation> <translation id="3618286417582819036">Der opstod en fejl</translation> -<translation id="3618647122592024084"><ph name="RECIPIENT_NAME" /> kan nu bruge dit brugernavn og din adgangskode, når vedkommende bruger Google Adgangskodeadministrator. Bed vedkommende om at gå til <ph name="WEBSITE" /> for at logge ind.</translation> +<translation id="3618647122592024084"><ph name="RECIPIENT_NAME" /> kan nu bruge dit brugernavn og din adgangskode, når vedkommende bruger Google Adgangskodeadministrator. Bed vedkommende om at gå til <ph name="WEBSITE" /> for at logge ind.</translation> <translation id="3619115746895587757">Cappuccino</translation> <translation id="3619294456800709762">Websites kan automatisk åbne integreret billede</translation> <translation id="3620136223548713675">Geoplacering</translation> @@ -3644,7 +3644,7 @@ <translation id="372722114124766626">Kun én gang</translation> <translation id="3727332897090187514">Der er ikke tilføjet en note</translation> <translation id="3727473233247516571">Underramme i back/forward-cache: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation> -<translation id="3727850735097852673">Hvis du vil bruge Google Adgangskodeadministrator med macOS-nøgleringen, skal du genstarte Chrome og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="3727850735097852673">Hvis du vil bruge Google Adgangskodeadministrator med macOS-nøgleringen, skal du genstarte Chrome og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="3728188878314831180">Spejl notifikationer fra din telefon</translation> <translation id="3728681439294129328">Konfigurer netværksadresse</translation> <translation id="3728805180379554595">Denne indstilling administreres af <ph name="USER_EMAIL" /></translation> @@ -3770,7 +3770,7 @@ <translation id="3809272675881623365">Kanin</translation> <translation id="3809280248639369696">Rumvæsen</translation> <translation id="3810593934879994994"><ph name="ORIGIN" /> kan se filer i følgende mapper</translation> -<translation id="3810770279996899697">Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> +<translation id="3810770279996899697">Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> <translation id="3810914450553844415">Din administrator tillader ikke yderligere Google-konti.</translation> <translation id="3810973564298564668">Administrer</translation> <translation id="381202950560906753">Tilføj endnu et</translation> @@ -4147,7 +4147,7 @@ <translation id="4090103403438682346">Aktivér Verificeret adgang</translation> <translation id="4090947011087001172">Vil du nulstille tilladelserne for <ph name="SITE" />?</translation> <translation id="4092636882861724179">Du kan se og administrere dine gemte adgangskoder i <ph name="GOOGLE_PASSWORD_MANAGER" /></translation> -<translation id="4092709865241032354">Tilføj dit brugernavn for dette website for at hjælpe Google Adgangskodeadministrator med at gemme dine loginoplysninger</translation> +<translation id="4092709865241032354">Tilføj dit brugernavn for dette website for at hjælpe Google Adgangskodeadministrator med at gemme dine loginoplysninger</translation> <translation id="4093865285251893588">Profilbillede</translation> <translation id="4093955363990068916">Lokal fil:</translation> <translation id="4094647278880271855">Du bruger en variabel for miljøet, der ikke understøttes: <ph name="BAD_VAR" />. Dette går ud over stabiliteten og sikkerheden.</translation> @@ -4413,7 +4413,7 @@ <translation id="4301671483919369635">Denne side har tilladelse til at redigere filer</translation> <translation id="4301697210743228350">{COUNT,plural, =1{# kontakt er ikke tilgængelig. Hvis du vil bruge <ph name="FEATURE_NAME" /> med denne kontakt, skal du føje den mailadresse, der er tilknyttet vedkommendes Google-konto, til dine kontakter.}one{# kontakt er ikke tilgængelig. Hvis du vil bruge <ph name="FEATURE_NAME" /> med denne kontakt, skal du føje den mailadresse, der er tilknyttet vedkommendes Google-konto, til dine kontakter.}other{# kontakter er ikke tilgængelige. Hvis du vil bruge <ph name="FEATURE_NAME" /> med disse kontakter, skal du føje de mailadresser, der er tilknyttet deres Google-konti, til dine kontakter.}}</translation> <translation id="4303079906735388947">Opret en ny pinkode til din sikkerhedsnøgle</translation> -<translation id="4304713468139749426">Adgangskodeadministrator</translation> +<translation id="4304713468139749426">Adgangskodeadministrator</translation> <translation id="4305402730127028764">Kopiér til <ph name="DEVICE_NAME" /></translation> <translation id="4305817255990598646">Skift</translation> <translation id="4306119971288449206">Apps skal downloades med indholdstypen "<ph name="CONTENT_TYPE" />"</translation> @@ -4450,7 +4450,7 @@ <translation id="4333854382783149454">PKCS #1 SHA-1 med RSA-kryptering</translation> <translation id="4334768748331667190"><ph name="MODULE_NAME" /> vises ikke igen</translation> <translation id="4335835283689002019">Beskyttet browsing er slået fra</translation> -<translation id="4338034474804311322">Opdater Google Play-tjenester for at gemme adgangskoder i Google Adgangskodeadministrator igen</translation> +<translation id="4338034474804311322">Opdater Google Play-tjenester for at gemme adgangskoder i Google Adgangskodeadministrator igen</translation> <translation id="4338363401382232853">Vinduesforslag til opdelt skærm</translation> <translation id="4339203724549370495">Afinstaller app</translation> <translation id="4340125850502689798">Ugyldigt brugernavn</translation> @@ -4679,7 +4679,7 @@ <translation id="4508332912150723117">brugernavn <ph name="USER_EMAIL" />. Se oplysninger</translation> <translation id="450867954911715010">Indstillinger for hjælpefunktioner</translation> <translation id="4508765956121923607">Vis k&ilde</translation> -<translation id="4509277363725254222">Når du deler en kopi af dit <ph name="BEGIN_BOLD_USERNAME" />brugernavn<ph name="END_BOLD_USERNAME" /> og din <ph name="BEGIN_BOLD_PASSWORD" />adgangskode<ph name="END_BOLD_PASSWORD" />, kan dine familiemedlemmer udfylde dem ved hjælp af Google Adgangskodeadministrator</translation> +<translation id="4509277363725254222">Når du deler en kopi af dit <ph name="BEGIN_BOLD_USERNAME" />brugernavn<ph name="END_BOLD_USERNAME" /> og din <ph name="BEGIN_BOLD_PASSWORD" />adgangskode<ph name="END_BOLD_PASSWORD" />, kan dine familiemedlemmer udfylde dem ved hjælp af Google Adgangskodeadministrator</translation> <translation id="4509421746503122514">Genstart for at opdatere</translation> <translation id="4509741852167209430">Begrænsede typer af data deles mellem websites for at måle, hvor effektive deres annoncer er, f.eks. om du har foretaget et køb, når du har besøgt et website</translation> <translation id="4510195992002502722">Din feedback kunne ikke indsendes. Prøver igen...</translation> @@ -5207,7 +5207,7 @@ <translation id="4918134162946436591">Vis overlejring med hint</translation> <translation id="4918762404810341788">Kopiér og åbn</translation> <translation id="4921348630401250116">Oplæsning</translation> -<translation id="4922104989726031751">Hvis du vil bruge Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chromium og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="4922104989726031751">Hvis du vil bruge Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chromium og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="492299503953721473">Fjern Android-apps</translation> <translation id="492363500327720082">Afinstallerer <ph name="APP_NAME" />…</translation> <translation id="4923977675318667854">Vis fanegrupper</translation> @@ -5522,7 +5522,7 @@ <translation id="5177549709747445269">Du bruger mobildata</translation> <translation id="5178667623289523808">Find forrige</translation> <translation id="5181140330217080051">Downloader</translation> -<translation id="5181172023548002891">I Google Adgangskodeadministrator for <ph name="ACCOUNT" /></translation> +<translation id="5181172023548002891">I Google Adgangskodeadministrator for <ph name="ACCOUNT" /></translation> <translation id="5181551096188687373">Adgangskoden gemmes kun på denne enhed. Hvis du vil bruge den på dine andre enheder, skal du gemme den på din Google-konto, <ph name="USER_EMAIL" />.</translation> <translation id="5183344263225877832">Vil du nulstille alle HID-enhedstilladelser?</translation> <translation id="5184063094292164363">&JavaScript-konsol</translation> @@ -6877,7 +6877,7 @@ <translation id="6238982280403036866">Har tilladelse til at bruge JavaScript</translation> <translation id="6239558157302047471">Genindlæs &ramme</translation> <translation id="6240821072888636753">Spørg hver gang</translation> -<translation id="6240964651812394252">Hvis du vil bruge Google Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chrome og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="6240964651812394252">Hvis du vil bruge Google Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chrome og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="6241530762627360640">Få adgang til oplysninger om Bluetooth-enheder, der er parret med dit system, og registrér Bluetooth-enheder i nærheden.</translation> <translation id="6241844896329831164">Adgang er ikke påkrævet</translation> <translation id="6242574558232861452">Tjekker downloaden i henhold til din organisations sikkerhedspolitikker.</translation> @@ -6886,9 +6886,9 @@ <translation id="6242852299490624841">Sæt denne fane i fokus</translation> <translation id="6243774244933267674">Serveren er utilgængelig</translation> <translation id="6244245036423700521">Importér ONC-fil</translation> -<translation id="6245523954602476652">Du kan få adgang til den i Google Adgangskodeadministrator.</translation> +<translation id="6245523954602476652">Du kan få adgang til den i Google Adgangskodeadministrator.</translation> <translation id="6246790815526961700">Upload fra enhed</translation> -<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> +<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> <translation id="6247620186971210352">Der blev ikke fundet nogen apps</translation> <translation id="6247708409970142803"><ph name="PERCENTAGE" /> %</translation> <translation id="6247802389331535091">System: <ph name="ARC_PROCESS_NAME" /></translation> @@ -6913,7 +6913,7 @@ <translation id="6264365405983206840">Vælg &alle</translation> <translation id="6264376385120300461">Download alligevel</translation> <translation id="6264520534872750757">Fortsæt med at bruge enheden</translation> -<translation id="6264636978858465832">Adgangskodeadministrator skal bruge mere omfattende adgang</translation> +<translation id="6264636978858465832">Adgangskodeadministrator skal bruge mere omfattende adgang</translation> <translation id="6265159465845424232">Spørg, før der kopieres eller flyttes Microsoft-filer til Microsoft OneDrive</translation> <translation id="6265687851677020761">Fjern port</translation> <translation id="6266532094411434237">Der oprettes forbindelse til <ph name="DEVICE" /></translation> @@ -7218,10 +7218,10 @@ <ph name="FILE_INFO" /> <ph name="EVENT_NAME" /></translation> <translation id="6519689855001245063">Tjekker berettigelse</translation> -<translation id="6520087076882753524">Du kan se og administrere gemte adgangskoder i Google Adgangskodeadministrator</translation> +<translation id="6520087076882753524">Du kan se og administrere gemte adgangskoder i Google Adgangskodeadministrator</translation> <translation id="6520876759015997832">Søgeresultat <ph name="LIST_POSITION" /> af <ph name="LIST_SIZE" />: <ph name="SEARCH_RESULT_TEXT" />. Tryk på Enter for at gå til sektionen.</translation> <translation id="6521214596282732365">Websites bruger som regel dine skrifttyper, så du kan oprette indhold i høj kvalitet med design- og grafikværktøjer online</translation> -<translation id="6523574494641144162">Google Adgangskodeadministrator kunne ikke gemme disse adgangskoder på din Google-konto. Du kan gemme dem på denne enhed.</translation> +<translation id="6523574494641144162">Google Adgangskodeadministrator kunne ikke gemme disse adgangskoder på din Google-konto. Du kan gemme dem på denne enhed.</translation> <translation id="652492607360843641">Du har oprettet forbindelse til et <ph name="NETWORK_TYPE" />-netværk.</translation> <translation id="6525767484449074555">Klik på "Installer"</translation> <translation id="6527303717912515753">Del</translation> @@ -7314,11 +7314,11 @@ <translation id="6595322909015878027">Har ikke tilladelse til automatisk at åbne integreret billede</translation> <translation id="6595408197871512625">{COUNT,plural, =1{Den kompromitterede adgangskode blev ændret. -Du har # anden kompromitteret adgangskode. Google Adgangskodeadministrator anbefaler, at du tjekker denne adgangskode nu.}one{Den kompromitterede adgangskode blev ændret. +Du har # anden kompromitteret adgangskode. Google Adgangskodeadministrator anbefaler, at du tjekker denne adgangskode nu.}one{Den kompromitterede adgangskode blev ændret. -Du har # anden kompromitteret adgangskode. Google Adgangskodeadministrator anbefaler, at du tjekker denne adgangskode nu.}other{Den kompromitterede adgangskode blev ændret. +Du har # anden kompromitteret adgangskode. Google Adgangskodeadministrator anbefaler, at du tjekker denne adgangskode nu.}other{Den kompromitterede adgangskode blev ændret. -Du har # andre kompromitterede adgangskoder. Google Adgangskodeadministrator anbefaler, at du tjekker disse adgangskoder nu.}}</translation> +Du har # andre kompromitterede adgangskoder. Google Adgangskodeadministrator anbefaler, at du tjekker disse adgangskoder nu.}}</translation> <translation id="6596325263575161958">Krypteringsmuligheder</translation> <translation id="6596816719288285829">IP-adresse</translation> <translation id="6596916244504302242">Genindlæs denne side for at anvende dine opdaterede indstillinger for udvidelser på dette website</translation> @@ -7523,7 +7523,7 @@ <translation id="6762861159308991328">Du kan ændre, hvordan links åbnes, i appindstillingerne</translation> <translation id="6764633064754857889">Se forhåndsvisning af link</translation> <translation id="676560328519657314">Dine betalingsmetoder i Google Pay</translation> -<translation id="6766488013065406604">Gå til Google Adgangskodeadministrator</translation> +<translation id="6766488013065406604">Gå til Google Adgangskodeadministrator</translation> <translation id="6767566652486411142">Vælg et andet sprog...</translation> <translation id="6768034047581882264">Har ikke tilladelse til at vise usikkert indhold</translation> <translation id="6769902329858794251"><ph name="BEGIN_PARAGRAPH1" /><ph name="DEVICE_OS" /> indsamler hardwaredata om enheder og deler dem med Google for at fastslå, hvilke opdateringer der skal leveres. Du kan vælge at give Google tilladelse til at bruge disse data til yderligere formål som f.eks. support til og forbedringer af <ph name="DEVICE_OS" />-oplevelsen og -tjenesten.<ph name="END_PARAGRAPH1" /> @@ -7542,7 +7542,7 @@ <translation id="6777845730143344223">Få flere oplysninger om Passpoint-abonnementer</translation> <translation id="6778660707554364320"><ph name="APP" /> åbnes nu som en app</translation> <translation id="6779092717724412415">Vælg en tekst, og højreklik på den for at oprette en markering som denne.</translation> -<translation id="6779348349813025131">Google Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> +<translation id="6779348349813025131">Google Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> <translation id="6779447100905857289">dine indkøbskurve</translation> <translation id="677965093459947883">Meget lille</translation> <translation id="6781005693196527806">&Administrer søgemaskiner...</translation> @@ -8070,7 +8070,7 @@ <translation id="7189965711416741966">Fingeraftrykket er tilføjet.</translation> <translation id="7191063546666816478">Nogle understøttede links åbnes fortsat i <ph name="APP_NAME" />, <ph name="APP_NAME_2" />, <ph name="APP_NAME_3" /> og <ph name="NUMBER_OF_OTHER_APPS" /> andre apps.</translation> <translation id="7191159667348037">Ukendt printer (USB)</translation> -<translation id="7191632649590906354">Dine familiemedlemmer kan nu bruge dit brugernavn og din adgangskode, når de bruger Google Adgangskodeadministrator. Bed dem om at gå til <ph name="WEBSITE" /> for at logge ind.</translation> +<translation id="7191632649590906354">Dine familiemedlemmer kan nu bruge dit brugernavn og din adgangskode, når de bruger Google Adgangskodeadministrator. Bed dem om at gå til <ph name="WEBSITE" /> for at logge ind.</translation> <translation id="7193051357671784796">Din app blev tilføjet af din organisation. Genstart appen for at afslutte installationen.</translation> <translation id="7193374945610105795">Der er ikke gemt nogen adgangskoder til <ph name="ORIGIN" /></translation> <translation id="7193663868864659844">Send feedback om foreslåede grupper</translation> @@ -8703,7 +8703,7 @@ <translation id="7666531788977935712">Knappen Fortsæt er aktiveret</translation> <translation id="7668002322287525834">{NUM_WEEKS,plural, =1{Returner <ph name="DEVICE_TYPE" /> inden for {NUM_WEEKS} uge}one{Returner <ph name="DEVICE_TYPE" /> inden for {NUM_WEEKS} uge}other{Returner <ph name="DEVICE_TYPE" /> inden for {NUM_WEEKS} uger}}</translation> <translation id="7668205084604701639">Office-filindstillinger</translation> -<translation id="7668423670802040666">I Google Adgangskodeadministrator for <ph name="ACCOUNT" /></translation> +<translation id="7668423670802040666">I Google Adgangskodeadministrator for <ph name="ACCOUNT" /></translation> <translation id="7668648754769651616">Hjælpefunktioner gør din enhed nemmere at bruge. Du kan få adgang til kvikmenuen ved at vælge klokkeslættet nederst på skærmen.</translation> <translation id="7669620291129890197">Synlig for dine enheder</translation> <translation id="7669825497510425694">{NUM_ATTEMPTS,plural, =1{Pinkoden er forkert. Du har ét forsøg tilbage.}one{Pinkoden er forkert. Du har # forsøg tilbage.}other{Pinkoden er forkert. Du har # forsøg tilbage.}}</translation> @@ -9220,7 +9220,7 @@ <translation id="8041089156583427627">Send feedback</translation> <translation id="8041267120753677077">Stream din telefons apps</translation> <translation id="8042142357103597104">Tekstens gennemsigtighed</translation> -<translation id="8042331986490021244">Dine adgangskoder krypteres på din enhed, før de gemmes i Google Adgangskodeadministrator</translation> +<translation id="8042331986490021244">Dine adgangskoder krypteres på din enhed, før de gemmes i Google Adgangskodeadministrator</translation> <translation id="8044262338717486897"><ph name="LINUX_APP_NAME" /> svarer ikke.</translation> <translation id="8044899503464538266">Langsom</translation> <translation id="8045253504249021590">Synkronisering er blevet stoppet via Google Kontrolpanel.</translation> @@ -9566,7 +9566,7 @@ <translation id="8295450130892483256">Installer Microsoft 365</translation> <translation id="8297292446125062288">HID-indstillinger</translation> <translation id="8298429963694909221">Nu kan du få notifikationer fra din telefon på din <ph name="DEVICE_TYPE" />. Hvis du afviser notifikationer på din <ph name="DEVICE_TYPE" />, afvises de også på din telefon. Sørg for, at din telefon er i nærheden, og at Bluetooth og Wi-Fi er aktiveret.</translation> -<translation id="829923460755755423">Tilføj en genvej til Google Adgangskodeadministrator</translation> +<translation id="829923460755755423">Tilføj en genvej til Google Adgangskodeadministrator</translation> <translation id="8299319456683969623">Du er i øjeblikket offline.</translation> <translation id="829937697336000302">Øg din produktivitet</translation> <translation id="8299951061833867575">Wi-Fi, mobildata</translation>
diff --git a/chrome/app/resources/google_chrome_strings_da.xtb b/chrome/app/resources/google_chrome_strings_da.xtb index 8059353..ec292d1 100644 --- a/chrome/app/resources/google_chrome_strings_da.xtb +++ b/chrome/app/resources/google_chrome_strings_da.xtb
@@ -140,7 +140,7 @@ <translation id="3037838751736561277">Google Chrome kører i baggrunden.</translation> <translation id="3038232873781883849">Venter på at installere…</translation> <translation id="3059710691562604940">Beskyttet browsing er deaktiveret. Chrome anbefaler, at du aktiverer funktionen.</translation> -<translation id="306179102415443347">Brug din genvej til hurtigt at gå til Google Adgangskodeadministrator. Du kan flytte din genvej til din computers startskærm eller appliste.</translation> +<translation id="306179102415443347">Brug din genvej til hurtigt at gå til Google Adgangskodeadministrator. Du kan flytte din genvej til din computers startskærm eller appliste.</translation> <translation id="3065168410429928842">Fanen Chrome</translation> <translation id="3080151273017101988">Fortsæt med at køre baggrundsapps, når Google Chrome er lukket</translation> <translation id="3089968997497233615">Der findes en ny, sikker version af Google Chrome.</translation> @@ -256,7 +256,7 @@ <translation id="4970761609246024540">Velkommen til Chrome-profiler</translation> <translation id="4970880042055371251">ChromeOS-version</translation> <translation id="4990567037958725628">Google Chrome Canary</translation> -<translation id="5003967926796347400">Klik på "Google Adgangskodeadministrator"</translation> +<translation id="5003967926796347400">Klik på "Google Adgangskodeadministrator"</translation> <translation id="5126049312684316860">Chrome forudindlæser endnu flere sider, som du sandsynligvis vil besøge, så de indlæses hurtigere, når du besøger dem</translation> <translation id="5132929315877954718">Find fantastiske apps, spil, udvidelser og temaer til Google Chrome.</translation> <translation id="5139423532931106058">Tilpas din Chrome-profil</translation> @@ -317,7 +317,7 @@ <translation id="6182736845697986886">Installationen mislykkedes på grund af en intern fejl i opdateringsserveren.</translation> <translation id="6235018212288296708">Indgående regel for Google Chrome om at tillade mDNS-trafik.</translation> <translation id="624230925347970731">Chrome lukkes snart</translation> -<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> +<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> <translation id="6251759518630934363">Advarer dig om skadelige websites – også websites, som Google ikke tidligere har kendt til – ved at analysere flere data fra websites end Standardbeskyttelse. Du kan vælge at springe Chrome-advarsler over.</translation> <translation id="6273793429163604305">Klar…</translation> <translation id="6277547788421725101">Din forælder har deaktiveret "Tilladelser for websites, apps og udvidelser" for Chrome</translation> @@ -334,7 +334,7 @@ <translation id="6497147134301593682">Chrome blev automatisk lukket</translation> <translation id="6506909944137591434">Chrome skal have adgangstilladelse til kamera for at oprette et 3D-kort over dine omgivelser</translation> <translation id="6515495397637126556"><ph name="PAGE_TITLE" /> – Google Chrome for udviklere</translation> -<translation id="659498884637196217">I Google Adgangskodeadministrator på denne enhed</translation> +<translation id="659498884637196217">I Google Adgangskodeadministrator på denne enhed</translation> <translation id="6632473616050862500">ChromeOS Flex leveres ved hjælp af <ph name="BEGIN_LINK_CROS_OSS" />open source-software<ph name="END_LINK_CROS_OSS" />.</translation> <translation id="6676384891291319759">Få adgang til internettet</translation> <translation id="6679975945624592337">Lad Google Chrome køre i baggrunden</translation> @@ -419,7 +419,7 @@ <translation id="7959172989483770734">Administrer Chrome-profiler</translation> <translation id="7962368738413920945">Websites fungerer sandsynligvis som forventet, men de husker dig ikke, når du har lukket alle Chrome-vinduer</translation> <translation id="7962410387636238736">Denne computer modtager ikke længere Google Chrome-opdateringer, da Windows XP og Windows Vista ikke længere understøttes.</translation> -<translation id="8005666035647241369">I Google Adgangskodeadministrator på denne enhed</translation> +<translation id="8005666035647241369">I Google Adgangskodeadministrator på denne enhed</translation> <translation id="8008534537613507642">Geninstaller Chrome</translation> <translation id="8009904340233602924">Brug Chrome uden en konto</translation> <translation id="8013993649590906847">Hvis et billede ikke har en brugbar beskrivelse, forsøger Chrome at angive en for dig. Billederne sendes til Google, så der kan oprettes beskrivelser.</translation> @@ -436,7 +436,7 @@ <translation id="8270775718612349140">Certifikater, der administreres af Chrome</translation> <translation id="8286862437124483331">Google Chrome forsøger at vise adgangskoder. Angiv din Windows-adgangskode for at tillade dette.</translation> <translation id="8290100596633877290">Hovsa! Google Chrome er gået ned. Vil du genstarte nu?</translation> -<translation id="829923460755755423">Tilføj en genvej til Google Adgangskodeadministrator</translation> +<translation id="829923460755755423">Tilføj en genvej til Google Adgangskodeadministrator</translation> <translation id="8336463659890584292">Når et website anmoder om at forudindlæse links privat på websitets side, anvender Chrome Googles servere. På denne måde skjules din identitet fra det forudindlæste website, men Google registrerer, hvilke websites der forudindlæses.</translation> <translation id="8342675569599923794">Denne fil er farlig, så Chrome har blokeret den.</translation> <translation id="8349795646647783032"><ph name="BEGIN_BOLD" />Sådan bruger vi disse data:<ph name="END_BOLD" /> Websites kan gemme oplysninger med Chrome om dine interesser. Hvis du f.eks. besøger et website for at købe sko til et maraton, kan websitet muligvis definere, at din interesse er at løbe maraton. Hvis du derefter besøger et andet website for at tilmelde dig et løb, kan det website vise dig en annonce for løbesko baseret på dine interesser.</translation> @@ -450,7 +450,7 @@ <translation id="842386925677997438">Chromes sikkerhedsværktøjer</translation> <translation id="8433638294851456451">Hvis du vil sende et nummer fra denne enhed til din Android-telefon, skal du logge ind på Chrome på begge enheder.</translation> <translation id="8451192282033883849">Din konto administreres af <ph name="MANAGER_NAME" />. Din administrator kan se og redigere denne Chrome-browserprofil og dens data som f.eks. bogmærker, historik og adgangskoder.</translation> -<translation id="8496177819998570653">Google Adgangskodeadministrator</translation> +<translation id="8496177819998570653">Google Adgangskodeadministrator</translation> <translation id="8498858610309223613">En særlig sikkerhedsopdatering til Google Chrome blev netop anvendt. Genstart nu, hvorefter vi gendanner dine faner.</translation> <translation id="8516431725144212809">Dine interesser, som de er estimeret af Chrome</translation> <translation id="8521348052903287641">Indgående regel for udviklerversionen af Chrome om at tillade mDNS-trafik.</translation>
diff --git a/chrome/browser/apps/app_service/app_install/app_install_service_ash.cc b/chrome/browser/apps/app_service/app_install/app_install_service_ash.cc index 82b7da5..fa3f1eb 100644 --- a/chrome/browser/apps/app_service/app_install/app_install_service_ash.cc +++ b/chrome/browser/apps/app_service/app_install/app_install_service_ash.cc
@@ -118,6 +118,7 @@ switch (package_id.package_type()) { case PackageType::kArc: { + // TODO(b/334733649): Avoid hard coding install URLs. constexpr char kPlayStoreAppDetailsPage[] = "https://play.google.com/store/apps/details"; GURL url = net::AppendOrReplaceQueryParameter( @@ -127,22 +128,6 @@ std::move(result_callback).Run(AppInstallResult::kUnknown); return; } - case PackageType::kWeb: { - // Observe for `anchor_window` being destroyed during async work. - std::unique_ptr<views::NativeWindowTracker> anchor_window_tracker; - if (anchor_window) { - anchor_window_tracker = - views::NativeWindowTracker::Create(*anchor_window); - } - - FetchAppInstallData( - package_id, - base::BindOnce(&AppInstallServiceAsh::ShowDialogAndInstall, - weak_ptr_factory_.GetWeakPtr(), surface, package_id, - anchor_window, std::move(anchor_window_tracker), - std::move(result_callback))); - return; - } case PackageType::kBorealis: { if (!base::FeatureList::IsEnabled( ash::features::kAppInstallServiceUriBorealis)) { @@ -166,6 +151,33 @@ std::move(result_callback).Run(AppInstallResult::kUnknown); return; } + case PackageType::kGeForceNow: { + // TODO(b/334733649): Avoid hard coding install URLs. + constexpr char kGeForceNowAppDetailsPage[] = + "https://play.geforcenow.com/games"; + GURL url = net::AppendOrReplaceQueryParameter( + GURL(kGeForceNowAppDetailsPage), "game-id", package_id.identifier()); + MaybeLaunchPreferredAppForUrl(&*profile_, url, + LaunchSource::kFromInstaller); + std::move(result_callback).Run(AppInstallResult::kUnknown); + return; + } + case PackageType::kWeb: { + // Observe for `anchor_window` being destroyed during async work. + std::unique_ptr<views::NativeWindowTracker> anchor_window_tracker; + if (anchor_window) { + anchor_window_tracker = + views::NativeWindowTracker::Create(*anchor_window); + } + + FetchAppInstallData( + package_id, + base::BindOnce(&AppInstallServiceAsh::ShowDialogAndInstall, + weak_ptr_factory_.GetWeakPtr(), surface, package_id, + anchor_window, std::move(anchor_window_tracker), + std::move(result_callback))); + return; + } case PackageType::kChromeApp: case PackageType::kUnknown: // TODO(b/303350800): Generalize to work with all app types.
diff --git a/chrome/browser/apps/app_service/app_install/app_install_service_ash_browsertest.cc b/chrome/browser/apps/app_service/app_install/app_install_service_ash_browsertest.cc index a505fb7..e2b94ba4 100644 --- a/chrome/browser/apps/app_service/app_install/app_install_service_ash_browsertest.cc +++ b/chrome/browser/apps/app_service/app_install/app_install_service_ash_browsertest.cc
@@ -47,6 +47,29 @@ expected_result, 1); } +IN_PROC_BROWSER_TEST_F(AppInstallServiceAshBrowserTest, InstallGfnAppOpensGfn) { + base::HistogramTester histogram_tester; + + content::TestNavigationObserver navigation_observer( + GURL("https://play.geforcenow.com/games?game-id=test")); + navigation_observer.StartWatchingNewWebContents(); + + AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->AppInstallService() + .InstallApp(AppInstallSurface::kAppInstallUriUnknown, + PackageId(PackageType::kGeForceNow, "test"), + /*anchor_window=*/std::nullopt, base::DoNothing()); + + navigation_observer.Wait(); + + AppInstallResult expected_result = AppInstallResult::kUnknown; + histogram_tester.ExpectUniqueSample("Apps.AppInstallService.AppInstallResult", + expected_result, 1); + histogram_tester.ExpectUniqueSample( + "Apps.AppInstallService.AppInstallResult.AppInstallUriUnknown", + expected_result, 1); +} + class AppInstallServiceAshGuestBrowserTest : public InProcessBrowserTest, public testing::WithParamInterface<bool> {
diff --git a/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc index 733b79b..19abfdf 100644 --- a/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc +++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
@@ -16,16 +16,11 @@ #include "base/test/bind.h" #include "chrome/browser/ash/app_list/search/test/test_search_controller.h" #include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h" -#include "chrome/browser/ash/crosapi/crosapi_ash.h" -#include "chrome/browser/ash/crosapi/crosapi_manager.h" -#include "chrome/browser/ash/crosapi/idle_service_ash.h" -#include "chrome/browser/ash/crosapi/search_provider_ash.h" -#include "chrome/browser/ash/crosapi/test_crosapi_dependency_registry.h" +#include "chrome/browser/ash/crosapi/search_controller_ash.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/common/chrome_constants.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" -#include "chromeos/ash/components/login/login_state/login_state.h" #include "chromeos/crosapi/mojom/launcher_search.mojom.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/test/browser_task_environment.h" @@ -151,11 +146,6 @@ ~OmniboxLacrosProviderTest() override = default; void SetUp() override { - // The `CrosapiManager` requires: - // - An active profile manager and profile. - // - Various services disabled that can't run in unit tests. - // - A valid login state. - // Create the profile manager and an active profile. profile_manager_ = std::make_unique<TestingProfileManager>( TestingBrowserProcess::GetGlobal()); @@ -166,23 +156,13 @@ {{TemplateURLServiceFactory::GetInstance(), base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor)}}); - // The idle service has dependencies we can't instantiate in unit tests. - crosapi::IdleServiceAsh::DisableForTesting(); - - // The crosapi manager reads the global login state. - ash::LoginState::Initialize(); - - crosapi_manager_ = crosapi::CreateCrosapiManagerWithTestRegistry(); - // Create client of our provider. search_controller_ = std::make_unique<TestSearchController>(); // Create the object to actually test. auto omnibox_provider = std::make_unique<OmniboxLacrosProvider>( profile_, &list_controller_, base::BindLambdaForTesting([this] { - return crosapi_manager_->crosapi_ash() - ->search_provider_ash() - ->GetController(); + return crosapi_search_controller_ash_.get(); })); omnibox_provider_ = omnibox_provider.get(); search_controller_->AddProvider(std::move(omnibox_provider)); @@ -191,17 +171,15 @@ void TearDown() override { omnibox_provider_ = nullptr; search_controller_.reset(); - crosapi_manager_.reset(); - ash::LoginState::Shutdown(); profile_ = nullptr; profile_manager_->DeleteTestingProfile(chrome::kInitialProfile); } void RegisterSearchController( mojo::PendingRemote<cam::SearchController> search_controller) { - crosapi_manager_->crosapi_ash() - ->search_provider_ash() - ->RegisterSearchController(std::move(search_controller)); + crosapi_search_controller_ash_ = + std::make_unique<crosapi::SearchControllerAsh>( + std::move(search_controller)); } // Starts a search and waits for the query to be sent to "lacros" over a Mojo @@ -229,7 +207,7 @@ std::unique_ptr<TestingProfileManager> profile_manager_; raw_ptr<TestingProfile> profile_; - std::unique_ptr<crosapi::CrosapiManager> crosapi_manager_; + std::unique_ptr<crosapi::SearchControllerAsh> crosapi_search_controller_ash_; raw_ptr<OmniboxLacrosProvider> omnibox_provider_; };
diff --git a/chrome/browser/ash/apps/DEPS b/chrome/browser/ash/apps/DEPS index ef7dce7..99498d8 100644 --- a/chrome/browser/ash/apps/DEPS +++ b/chrome/browser/ash/apps/DEPS
@@ -34,6 +34,7 @@ "+chrome/browser/web_applications/web_app_install_info.h", "+chrome/browser/web_applications/web_app_install_params.h", "+chrome/browser/web_applications/web_app_install_utils.h", + "+chrome/browser/web_applications/web_app_proto_utils.h", "+chrome/browser/web_applications/web_app_provider_factory.h", "+chrome/browser/web_applications/web_app_provider.h", "+chrome/browser/web_applications/web_app_registrar.h",
diff --git a/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc b/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc index 7051cdd..5a7cda5 100644 --- a/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc +++ b/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/ash/apps/apk_web_app_installer.h" + #include <memory> #include <utility> #include <vector> @@ -20,7 +22,6 @@ #include "base/test/test_future.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" -#include "chrome/browser/ash/apps/apk_web_app_installer.h" #include "chrome/browser/ash/apps/apk_web_app_service.h" #include "chrome/browser/ash/arc/arc_util.h" #include "chrome/browser/ash/arc/session/arc_session_manager.h" @@ -38,6 +39,7 @@ #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_icon_generator.h" #include "chrome/browser/web_applications/web_app_install_finalizer.h" +#include "chrome/browser/web_applications/web_app_proto_utils.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/test/base/in_process_browser_test.h" @@ -110,19 +112,23 @@ ASSERT_TRUE(web_app->theme_color().has_value()); EXPECT_EQ(SK_ColorBLUE, web_app->theme_color().value()); - ASSERT_TRUE(web_app->sync_fallback_data().theme_color.has_value()); - EXPECT_EQ(SK_ColorBLUE, web_app->sync_fallback_data().theme_color.value()); + ASSERT_TRUE(web_app->sync_proto().has_theme_color()); + EXPECT_EQ(SK_ColorBLUE, web_app->sync_proto().theme_color()); - EXPECT_EQ("App Title", web_app->sync_fallback_data().name); - EXPECT_EQ(url.Resolve("scope"), web_app->sync_fallback_data().scope); + EXPECT_EQ("App Title", web_app->sync_proto().name()); + EXPECT_EQ(url.Resolve("scope").spec(), web_app->sync_proto().scope()); { SCOPED_TRACE("web_app->manifest_icons()"); ExpectInitialIconInfosFromWebAppInstallInfo(web_app->manifest_icons(), url); } { - SCOPED_TRACE("web_app->sync_fallback_data().icon_infos"); - ExpectInitialIconInfosFromWebAppInstallInfo( - web_app->sync_fallback_data().icon_infos, url); + SCOPED_TRACE("web_app->sync_proto().icon_infos"); + std::optional<std::vector<apps::IconInfo>> parsed_icon_infos = + web_app::ParseAppIconInfos( + "ExpectInitialManifestFieldsFromWebAppInstallInfo", + web_app->sync_proto().icon_infos()); + ASSERT_TRUE(parsed_icon_infos.has_value()); + ExpectInitialIconInfosFromWebAppInstallInfo(parsed_icon_infos.value(), url); } // Manifest Resources:
diff --git a/chrome/browser/ash/assistant/assistant_integration_test.yaml b/chrome/browser/ash/assistant/assistant_integration_test.yaml new file mode 100644 index 0000000..95b14c2 --- /dev/null +++ b/chrome/browser/ash/assistant/assistant_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "AssistantIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "assistive-eng@google.com" +hw_agnostic: False +criteria: | + Test Assistant hotkey to toggle launcher. +cases: + - id: "DISABLED_Hotkey" + tags: [] +...
diff --git a/chrome/browser/ash/bluetooth/bluetooth_integration_test.yaml b/chrome/browser/ash/bluetooth/bluetooth_integration_test.yaml new file mode 100644 index 0000000..30d268aa --- /dev/null +++ b/chrome/browser/ash/bluetooth/bluetooth_integration_test.yaml
@@ -0,0 +1,21 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "BluetoothIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: False +criteria: | + Crosier Bluetooth test. +cases: + - id: "ToggleBluetoothFromQuickSettings" + tags: ["crosier:crosierdemosuite", "crosier:cq"] + - id: "ToggleBluetoothFromOsSettings" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/child_accounts/web_approvals_integration_test.yaml b/chrome/browser/ash/child_accounts/web_approvals_integration_test.yaml new file mode 100644 index 0000000..ec0c759 --- /dev/null +++ b/chrome/browser/ash/child_accounts/web_approvals_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "WebApprovalsIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "courtneywong@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Checks that matures sites are blocked for Unicorn users +cases: + - id: "DISABLED_TestMatureSiteBlocked" + tags: [] +...
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index 534f684..55595a2c 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -190,50 +190,6 @@ } } -// Returns whether the lacros is enabled currently. -bool IsLacrosEnabledInternal(const User* user, - LacrosAvailability lacros_availability, - bool check_migration_status) { - if (!ash::standalone_browser::BrowserSupport::IsAllowedInternal( - user, lacros_availability)) { - return false; - } - - DCHECK(user); - - // If profile migration is enabled, the completion of it is necessary for - // Lacros to be enabled. - if (check_migration_status && - !base::FeatureList::IsEnabled( - ash::standalone_browser::features::kLacrosProfileMigrationForceOff)) { - PrefService* local_state = g_browser_process->local_state(); - // Note that local_state can be nullptr in tests. - if (local_state && !ash::standalone_browser::migrator_util:: - IsProfileMigrationCompletedForUser( - local_state, user->username_hash())) { - // If migration has not been completed, do not enable lacros. - return false; - } - } - - switch (lacros_availability) { - case LacrosAvailability::kUserChoice: - break; - case LacrosAvailability::kLacrosDisallowed: - NOTREACHED(); // Guarded by IsLacrosAllowedInternal. - return false; - case LacrosAvailability::kLacrosOnly: - return true; - } - - if (base::FeatureList::IsEnabled( - ash::standalone_browser::features::kLacrosOnly)) { - return true; - } - - return false; -} - } // namespace constexpr char kLacrosStabilitySwitch[] = "lacros-stability"; @@ -332,9 +288,9 @@ } bool IsLacrosEnabled() { - return IsLacrosEnabledInternal(GetPrimaryUser(), - GetCachedLacrosAvailability(), - /*check_migration_status=*/true); + return ash::standalone_browser::BrowserSupport::IsEnabledInternal( + GetPrimaryUser(), GetCachedLacrosAvailability(), + /*check_migration_status=*/true); } bool IsLacrosEnabledForMigration(const User* user, @@ -344,8 +300,8 @@ if (!lacros_availability.has_value()) { return false; } - return IsLacrosEnabledInternal(user, *lacros_availability, - /*check_migration_status=*/false); + return ash::standalone_browser::BrowserSupport::IsEnabledInternal( + user, *lacros_availability, /*check_migration_status=*/false); } bool IsProfileMigrationEnabled(const user_manager::User* user,
diff --git a/chrome/browser/ash/crosapi/search_controller_factory_ash.cc b/chrome/browser/ash/crosapi/search_controller_factory_ash.cc index 90e9cef..930a807c 100644 --- a/chrome/browser/ash/crosapi/search_controller_factory_ash.cc +++ b/chrome/browser/ash/crosapi/search_controller_factory_ash.cc
@@ -27,6 +27,21 @@ search_controller_factory_.reset(); search_controller_factory_.Bind(std::move(remote)); + + for (Observer& observer : observers_) { + observer.OnSearchControllerFactoryBound(this); + } +} + +void SearchControllerFactoryAsh::AddObserver(Observer* obs) { + observers_.AddObserver(obs); + if (IsBound()) { + obs->OnSearchControllerFactoryBound(this); + } +} + +void SearchControllerFactoryAsh::RemoveObserver(Observer* obs) { + observers_.RemoveObserver(obs); } std::unique_ptr<SearchControllerAsh>
diff --git a/chrome/browser/ash/crosapi/search_controller_factory_ash.h b/chrome/browser/ash/crosapi/search_controller_factory_ash.h index 0340ded..d326e4f 100644 --- a/chrome/browser/ash/crosapi/search_controller_factory_ash.h +++ b/chrome/browser/ash/crosapi/search_controller_factory_ash.h
@@ -7,6 +7,8 @@ #include <memory> +#include "base/observer_list.h" +#include "base/observer_list_types.h" #include "chromeos/crosapi/mojom/launcher_search.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -17,11 +19,22 @@ class SearchControllerFactoryAsh { public: + class Observer : public base::CheckedObserver { + public: + virtual void OnSearchControllerFactoryBound( + SearchControllerFactoryAsh* factory) = 0; + }; + SearchControllerFactoryAsh(); ~SearchControllerFactoryAsh(); void BindRemote(mojo::PendingRemote<mojom::SearchControllerFactory> remote); + // Calls `OnSearchControllerFactoryBound` immediately if this instance is + // already bound. + void AddObserver(Observer* obs); + void RemoveObserver(Observer* obs); + // Creates a `SearchControllerAsh` for Picker with the given parameters. // This function returns nullptr iff `!IsBound()`. std::unique_ptr<SearchControllerAsh> @@ -31,6 +44,7 @@ private: mojo::Remote<mojom::SearchControllerFactory> search_controller_factory_; + base::ObserverList<Observer> observers_; }; } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/search_controller_factory_ash_unittest.cc b/chrome/browser/ash/crosapi/search_controller_factory_ash_unittest.cc index 79ffb88..fad5222 100644 --- a/chrome/browser/ash/crosapi/search_controller_factory_ash_unittest.cc +++ b/chrome/browser/ash/crosapi/search_controller_factory_ash_unittest.cc
@@ -15,9 +15,11 @@ #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" #include "base/run_loop.h" +#include "base/scoped_observation.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "chrome/browser/ash/crosapi/search_controller_ash.h" +#include "chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.h" #include "chromeos/crosapi/mojom/launcher_search.mojom-forward.h" #include "chromeos/crosapi/mojom/launcher_search.mojom-shared.h" #include "chromeos/crosapi/mojom/launcher_search.mojom.h" @@ -130,6 +132,30 @@ mojo::Receiver<mojom::SearchControllerFactory> receiver_{this}; }; +class TestFactoryObserver : public SearchControllerFactoryAsh::Observer { + public: + explicit TestFactoryObserver(SearchControllerFactoryAsh* factory) { + obs_.Observe(factory); + } + ~TestFactoryObserver() override = default; + + void OnSearchControllerFactoryBound( + SearchControllerFactoryAsh* factory) override { + on_bound_.SetValue(factory); + } + + base::test::TestFuture<SearchControllerFactoryAsh*>& on_bound() { + return on_bound_; + } + + private: + base::test::TestFuture<SearchControllerFactoryAsh*> on_bound_; + + base::ScopedObservation<SearchControllerFactoryAsh, + SearchControllerFactoryAsh::Observer> + obs_{this}; +}; + using SearchControllerFactoryAshTest = ::testing::Test; TEST_F(SearchControllerFactoryAshTest, @@ -273,5 +299,72 @@ EXPECT_TRUE(mojom_controller->open_tabs()); } +TEST_F(SearchControllerFactoryAshTest, OnBoundNotCalledIfNotBound) { + base::test::SingleThreadTaskEnvironment environment; + SearchControllerFactoryAsh factory; + + TestFactoryObserver observer(&factory); + + EXPECT_FALSE(observer.on_bound().IsReady()); +} + +TEST_F(SearchControllerFactoryAshTest, OnBoundCalledIfAlreadyBound) { + base::test::SingleThreadTaskEnvironment environment; + SearchControllerFactoryAsh factory; + TestMojomSearchControllerFactory mojom_factory; + factory.BindRemote(mojom_factory.BindToRemote()); + + TestFactoryObserver observer(&factory); + + EXPECT_TRUE(observer.on_bound().IsReady()); +} + +TEST_F(SearchControllerFactoryAshTest, OnBoundCalledWhenBoundLater) { + base::test::SingleThreadTaskEnvironment environment; + SearchControllerFactoryAsh factory; + TestFactoryObserver observer(&factory); + ASSERT_FALSE(observer.on_bound().IsReady()); + + TestMojomSearchControllerFactory mojom_factory; + factory.BindRemote(mojom_factory.BindToRemote()); + + EXPECT_TRUE(observer.on_bound().IsReady()); +} + +TEST_F(SearchControllerFactoryAshTest, OnBoundCalledWhenRebound) { + base::test::SingleThreadTaskEnvironment environment; + SearchControllerFactoryAsh factory; + TestFactoryObserver observer(&factory); + { + // Connect a remote factory... + TestMojomSearchControllerFactory mojom_factory; + factory.BindRemote(mojom_factory.BindToRemote()); + ASSERT_TRUE(observer.on_bound().IsReady()); + observer.on_bound().Clear(); + // ...then disconnect it. + } + // Ensure that the factory receives the disconnection so it can be rebound. + // TODO: b/326147929 - Use a `QuitClosure` for this. + base::RunLoop().RunUntilIdle(); + + // Rebind another remote factory. + TestMojomSearchControllerFactory mojom_factory; + factory.BindRemote(mojom_factory.BindToRemote()); + + EXPECT_TRUE(observer.on_bound().IsReady()); +} + +TEST_F(SearchControllerFactoryAshTest, OnBoundCalledWithFactoryPtr) { + base::test::SingleThreadTaskEnvironment environment; + SearchControllerFactoryAsh factory; + TestMojomSearchControllerFactory mojom_factory; + factory.BindRemote(mojom_factory.BindToRemote()); + + TestFactoryObserver observer(&factory); + + SearchControllerFactoryAsh* ptr = observer.on_bound().Take(); + EXPECT_EQ(ptr, &factory); +} + } // namespace } // namespace crosapi
diff --git a/chrome/browser/ash/external_metrics_integration_test.yaml b/chrome/browser/ash/external_metrics_integration_test.yaml new file mode 100644 index 0000000..5edc773 --- /dev/null +++ b/chrome/browser/ash/external_metrics_integration_test.yaml
@@ -0,0 +1,20 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "ExternalMetricsIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "brettw@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Integration test between histograms reported by libmetrics in ChromeOS and + Ash's importer of these metrics. +cases: + - id: "SyncHistograms" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/featured_integration_test.yaml b/chrome/browser/ash/featured_integration_test.yaml new file mode 100644 index 0000000..c36ca2e --- /dev/null +++ b/chrome/browser/ash/featured_integration_test.yaml
@@ -0,0 +1,27 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "All/FeaturedIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "mutexlox@google.com" + - email: "chromeos-data-eng@google.com" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Verifies features are enabled/disabled as expected and parameters are unchanged +cases: + - id: "FeatureLibraryLateBoot/experiment_default" + tags: ["crosier:crosierdemosuite", "crosier:cq"] + - id: "FeatureLibraryLateBoot/experiment_disabled_without_params" + tags: ["crosier:crosierdemosuite", "crosier:cq"] + - id: "FeatureLibraryLateBoot/experiment_enabled_with_params" + tags: ["crosier:crosierdemosuite", "crosier:cq"] + - id: "FeatureLibraryLateBoot/experiment_enabled_without_params" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/input_method/editor_switch.cc b/chrome/browser/ash/input_method/editor_switch.cc index 871552e0..9f3d139 100644 --- a/chrome/browser/ash/input_method/editor_switch.cc +++ b/chrome/browser/ash/input_method/editor_switch.cc
@@ -61,6 +61,9 @@ extension_misc::kGoogleSheetsAppId, extension_misc::kGoogleDriveAppId, extension_misc::kGoogleKeepAppId, + extension_misc::kGoogleMeetPwaAppId, + extension_misc::kGoogleDocsPwaAppId, + extension_misc::kGoogleSheetsPwaAppId, // App ids in demo mode extension_misc::kCalendarDemoAppId, extension_misc::kGoogleDocsDemoAppId,
diff --git a/chrome/browser/ash/login/lock/lock_screen_integration_test.yaml b/chrome/browser/ash/login/lock/lock_screen_integration_test.yaml new file mode 100644 index 0000000..5e5fff89 --- /dev/null +++ b/chrome/browser/ash/login/lock/lock_screen_integration_test.yaml
@@ -0,0 +1,25 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "LockScreen" +harness: "crosier" +category: "integration" +owners: + - email: "brettw@chromium.org" + - email: "jamescook@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: False +criteria: | + Tests that dbus messages for lid close trigger screen lock. This only tests + the "lock on lid close" pref state because it's difficult to test the inverse + (that the screen didn't lock) without a long timeout. The pref behavior is + tested separately in the CloseLidPref test below. +cases: + - id: "CloseLidDbusIntegration" + tags: ["crosier:crosierdemosuite", "crosier:cq"] + - id: "CloseLidPref" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/login/login_integration_test.yaml b/chrome/browser/ash/login/login_integration_test.yaml new file mode 100644 index 0000000..da52b0bf --- /dev/null +++ b/chrome/browser/ash/login/login_integration_test.yaml
@@ -0,0 +1,20 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "LoginIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "xiyuan@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: False +criteria: | + Integration test for ChromeOS login using oobe test api, + same as Tast's default login. +cases: + - id: "TestLogin" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/login/supervised_user_login_integration_test.yaml b/chrome/browser/ash/login/supervised_user_login_integration_test.yaml new file mode 100644 index 0000000..2e65e7c --- /dev/null +++ b/chrome/browser/ash/login/supervised_user_login_integration_test.yaml
@@ -0,0 +1,24 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "SupervisedUserLoginIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "courtneywong@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: False +criteria: | + Tests CrOS login using prod GAIA with the different types of + supervised accounts. +cases: + - id: "DISABLED_TestUnicornLogin" + tags: [] + - id: "DISABLED_TestGellerLogin" + tags: [] + - id: "DISABLED_TestGriffinLogin" + tags: [] +...
diff --git a/chrome/browser/ash/ml_integration_test.yaml b/chrome/browser/ash/ml_integration_test.yaml new file mode 100644 index 0000000..70199c8 --- /dev/null +++ b/chrome/browser/ash/ml_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "MLIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "brettw@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Test that the ml-service daemon can be started and an ML model can be loaded +cases: + - id: "Bootstrap" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/power/ml/smart_dim/smart_dim_integration_test.yaml b/chrome/browser/ash/power/ml/smart_dim/smart_dim_integration_test.yaml new file mode 100644 index 0000000..3d68d15 --- /dev/null +++ b/chrome/browser/ash/power/ml/smart_dim/smart_dim_integration_test.yaml
@@ -0,0 +1,20 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "SmartDimIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + The test triggers the user activity manager, which asks the platform + ML Service for a decision about whether to dim the screen +cases: + - id: "SmartDim" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/scanning/multi_page_scan_integration_test.yaml b/chrome/browser/ash/scanning/multi_page_scan_integration_test.yaml new file mode 100644 index 0000000..8683245 --- /dev/null +++ b/chrome/browser/ash/scanning/multi_page_scan_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "MultiPageScanIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "michaelcheco@google.com" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Perform a multi page scan and verify that the scan was performed successfully. +cases: + - id: "MultiPageScan" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/scanning/scan_integration_test.yaml b/chrome/browser/ash/scanning/scan_integration_test.yaml new file mode 100644 index 0000000..6b5c13a6 --- /dev/null +++ b/chrome/browser/ash/scanning/scan_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "ScanIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "michaelcheco@google.com" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Perform a scan and verify the expected output using a golden file +cases: + - id: "ScanWithDefaultSettings" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/screenshot_integration_test.yaml b/chrome/browser/ash/screenshot_integration_test.yaml new file mode 100644 index 0000000..5245e03 --- /dev/null +++ b/chrome/browser/ash/screenshot_integration_test.yaml
@@ -0,0 +1,22 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "Vulkan/ScreenshotIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "chromeos-gfx@google.com" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: False +criteria: | + Takes a screenshot and validates its average color +cases: + - id: "AverageColor/0" + tags: ["crosier:crosierdemosuite", "crosier:cq"] + - id: "AverageColor/1" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/security_files_integration_test.yaml b/chrome/browser/ash/security_files_integration_test.yaml new file mode 100644 index 0000000..fc7083be --- /dev/null +++ b/chrome/browser/ash/security_files_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "SecurityFilesIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Checks ownership and permissions of user files for logged-in users +cases: + - id: "UserFilesLoggedIn" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/system_web_apps/apps/terminal_integration_test.yaml b/chrome/browser/ash/system_web_apps/apps/terminal_integration_test.yaml new file mode 100644 index 0000000..4224083 --- /dev/null +++ b/chrome/browser/ash/system_web_apps/apps/terminal_integration_test.yaml
@@ -0,0 +1,20 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "TerminalIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "brettw@chromium.org" + - email: "jamescook@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Sends the given text to the element as individual key press commands +cases: + - id: "Crosh" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ash/web_handwriting_integration_test.yaml b/chrome/browser/ash/web_handwriting_integration_test.yaml new file mode 100644 index 0000000..80139f2 --- /dev/null +++ b/chrome/browser/ash/web_handwriting_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "WebHandwritingIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Navigate to the appropriate test page, based on whether handwriting recognition is supported or not +cases: + - id: "Recognition" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc index ba59718d03..d1e6cfc 100644 --- a/chrome/browser/autofill/android/personal_data_manager_android.cc +++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -230,8 +230,9 @@ bool PersonalDataManagerAndroid::IsCountryEligibleForAccountStorage( JNIEnv* env, const JavaParamRef<jstring>& country_code) const { - return personal_data_manager_->IsCountryEligibleForAccountStorage( - ConvertJavaStringToUTF8(env, country_code)); + return personal_data_manager_->address_data_manager() + .IsCountryEligibleForAccountStorage( + ConvertJavaStringToUTF8(env, country_code)); } ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::SetProfile(
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/DEPS b/chrome/browser/chromeos/extensions/telemetry/api/DEPS index fb365cc..6ed1d96 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/DEPS +++ b/chrome/browser/chromeos/extensions/telemetry/api/DEPS
@@ -1,6 +1,6 @@ include_rules = [ # Guarded by IS_CHROMEOS_ASH or in is_chromeos_ash sources. - "+ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h", + "+ash/webui/shimless_rma/backend/external_app_dialog.h", "+chrome/browser/ash/telemetry_extension", ]
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/common/BUILD.gn b/chrome/browser/chromeos/extensions/telemetry/api/common/BUILD.gn index 71fa4d4..7a1bc1d 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/common/BUILD.gn +++ b/chrome/browser/chromeos/extensions/telemetry/api/common/BUILD.gn
@@ -68,7 +68,7 @@ if (is_chromeos_ash) { deps += [ "//ash/constants", - "//ash/webui/shimless_rma/3p_diagnostics", + "//ash/webui/shimless_rma/backend", ] } } @@ -208,7 +208,7 @@ if (is_chromeos_ash) { deps += [ - "//ash/webui/shimless_rma/3p_diagnostics", + "//ash/webui/shimless_rma/backend", "//chrome/browser/ash:test_support", "//chrome/common/chromeos/extensions", "//components/user_manager",
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc b/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc index fda457dbb..e8853eec 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc
@@ -39,7 +39,7 @@ #include "ash/public/cpp/session/session_controller.h" #include "ash/public/cpp/session/session_types.h" #include "ash/shell.h" -#include "ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h" +#include "ash/webui/shimless_rma/backend/external_app_dialog.h" #include "base/command_line.h" #include "base/strings/string_util.h" #include "base/task/sequenced_task_runner.h"
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/common/util.cc b/chrome/browser/chromeos/extensions/telemetry/api/common/util.cc index fd66996c..deda2a37 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/common/util.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/common/util.cc
@@ -17,7 +17,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_features.h" -#include "ash/webui/shimless_rma/3p_diagnostics/external_app_dialog.h" +#include "ash/webui/shimless_rma/backend/external_app_dialog.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) namespace content {
diff --git a/chrome/browser/direct_sockets/direct_sockets_apitest.cc b/chrome/browser/direct_sockets/direct_sockets_apitest.cc index 6de78163..b2abbd4e3 100644 --- a/chrome/browser/direct_sockets/direct_sockets_apitest.cc +++ b/chrome/browser/direct_sockets/direct_sockets_apitest.cc
@@ -11,7 +11,6 @@ #include "base/strings/stringprintf.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" -#include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h" @@ -178,15 +177,8 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) -class ExtensionApiTestWithDirectSocketsEnabled - : public extensions::ExtensionApiTest { - private: - base::test::ScopedFeatureList features_{ - extensions::kDirectSocketsInChromeApps}; -}; - using ChromeDirectSocketsTcpApiTest = - ChromeDirectSocketsTcpTest<ExtensionApiTestWithDirectSocketsEnabled>; + ChromeDirectSocketsTcpTest<extensions::ExtensionApiTest>; IN_PROC_BROWSER_TEST_F(ChromeDirectSocketsTcpApiTest, TcpReadWrite) { extensions::TestExtensionDir dir; @@ -323,7 +315,7 @@ } using ChromeDirectSocketsUdpApiTest = - ChromeDirectSocketsUdpTest<ExtensionApiTestWithDirectSocketsEnabled>; + ChromeDirectSocketsUdpTest<extensions::ExtensionApiTest>; IN_PROC_BROWSER_TEST_F(ChromeDirectSocketsUdpApiTest, UdpReadWrite) { extensions::TestExtensionDir dir; @@ -529,8 +521,7 @@ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); } -using ChromeDirectSocketsTcpServerApiTest = - ExtensionApiTestWithDirectSocketsEnabled; +using ChromeDirectSocketsTcpServerApiTest = extensions::ExtensionApiTest; IN_PROC_BROWSER_TEST_F(ChromeDirectSocketsTcpServerApiTest, TcpServerSocketUndefinedWithoutSocketsPermission) {
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc index 21f0d492..53cef83 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -115,8 +115,9 @@ personal_data->address_data_manager().IsEligibleForAddressAccountStorage() ? autofill::AutofillProfile::Source::kAccount : autofill::AutofillProfile::Source::kLocalOrSyncable; - if (country_code && !personal_data->IsCountryEligibleForAccountStorage( - country_code.value())) { + if (country_code && + !personal_data->address_data_manager().IsCountryEligibleForAccountStorage( + country_code.value())) { // Note: addresses from unsupported countries can't be saved in account. // TODO(crbug.com/1432505): remove temporary unsupported countries // filtering.
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc index 9bf26a4a..88456e5 100644 --- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc +++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
@@ -105,11 +105,11 @@ "StopUsingRenderProcessHostPrivilege", base::FEATURE_ENABLED_BY_DEFAULT); -// This feature tracks the work to enable Direct Sockets in Chrome Apps by -// default. See crbug.com/329445684 for details. +// This feature is a kill switch for the Direct Sockets API in Chrome Apps. +// See crbug.com/329445684 for details. BASE_FEATURE(kDirectSocketsInChromeApps, "DirectSocketsInChromeApps", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); namespace {
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 980c8d6..fd2b928 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -325,6 +325,8 @@ &password_manager::features:: kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration, &password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsAndroidWithMigration, + &password_manager::features:: kUnifiedPasswordManagerLocalPasswordsMigrationWarning, &permissions::features::kPermissionsPromptSurvey, &privacy_sandbox::kIpProtectionUx,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index e7313ec..e6b6ba2 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -495,6 +495,8 @@ public static final String SHARED_PASSWORD_NOTIFICATION_UI = "SharedPasswordNotificationUI"; public static final String UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_NO_MIGRATION = "UnifiedPasswordManagerLocalPasswordsAndroidNoMigration"; + public static final String UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_WITH_MIGRATION = + "UnifiedPasswordManagerLocalPasswordsAndroidWithMigration"; public static final String UNIFIED_PASSWORD_MANAGER_LOCAL_PWD_MIGRATION_WARNING = "UnifiedPasswordManagerLocalPasswordsMigrationWarning"; public static final String USE_CHIME_ANDROID_SDK = "UseChimeAndroidSdk";
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc index 5d247508..468bcdd 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc
@@ -565,12 +565,15 @@ std::vector<GURL> fetched_fonts = PredictFetchedFontUrls(lcpp_data); std::vector<GURL> preconnect_origins = PredictPreconnectableOrigins(lcpp_data); + std::vector<GURL> unused_preloads = PredictUnusedPreloads(lcpp_data); if (!lcp_element_locators.empty() || !lcp_influencer_scripts.empty() || - !fetched_fonts.empty() || !preconnect_origins.empty()) { + !fetched_fonts.empty() || !preconnect_origins.empty() || + !unused_preloads.empty()) { return blink::mojom::LCPCriticalPathPredictorNavigationTimeHint( std::move(lcp_element_locators), std::move(lcp_influencer_scripts), - std::move(fetched_fonts), std::move(preconnect_origins)); + std::move(fetched_fonts), std::move(preconnect_origins), + std::move(unused_preloads)); } return std::nullopt; } @@ -683,6 +686,29 @@ return subresource_urls; } +std::vector<GURL> PredictUnusedPreloads(const LcppData& data) { + const double frequency_threshold = + blink::features::kLCPPDeferUnusedPreloadFrequencyThreshold.Get(); + std::vector<GURL> unused_preloads; + if (!base::FeatureList::IsEnabled(blink::features::kLCPPDeferUnusedPreload)) { + return unused_preloads; + } + + for (const auto& [frequency, url] : + ConvertToFrequencyStringPair(data.lcpp_stat().unused_preload_stat())) { + // The frequencies are reverse sorted by `ConvertToFrequencyStringPair`. + if (frequency < frequency_threshold) { + break; + } + GURL parsed_url(url); + if (!parsed_url.is_valid() || !parsed_url.SchemeIsHTTPOrHTTPS()) { + continue; + } + unused_preloads.push_back(std::move(parsed_url)); + } + return unused_preloads; +} + LcppDataInputs::LcppDataInputs() = default; LcppDataInputs::~LcppDataInputs() = default;
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h index d57af3b..04d399d 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h
@@ -37,6 +37,12 @@ // vector. std::vector<GURL> PredictFetchedSubresourceUrls(const LcppData& data); +// Returns possible unused preload URLs from past loads for a given `data`. +// The returned URLs are ordered by descending frequency (the most +// frequent one comes first). If there is no data, it returns an empty +// vector. +std::vector<GURL> PredictUnusedPreloads(const LcppData& data); + // An input to update LcppData. struct LcppDataInputs { LcppDataInputs();
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc index 2f1ab36..e786abb5 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc
@@ -631,6 +631,97 @@ PredictPreconnectableOrigins(lcpp_data)); } +TEST(PredictUnusedPreloads, Empty) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeaturesAndParameters( + {{blink::features::kLCPPDeferUnusedPreload, + {{blink::features::kLCPPDeferUnusedPreloadFrequencyThreshold.name, + "0.5"}}}}, + {}); + + EXPECT_EQ(std::vector<GURL>(), PredictUnusedPreloads({})); +} + +TEST(PredictUnusedPreloads, SingleEntry) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeaturesAndParameters( + {{blink::features::kLCPPDeferUnusedPreload, + {{blink::features::kLCPPDeferUnusedPreloadFrequencyThreshold.name, + "0.5"}}}}, + {}); + + LcppData lcpp_data; + lcpp_data.mutable_lcpp_stat() + ->mutable_unused_preload_stat() + ->mutable_main_buckets() + ->insert({"https://example.com/a.jpeg", 0.9}); + EXPECT_EQ(std::vector<GURL>({GURL("https://example.com/a.jpeg")}), + PredictUnusedPreloads(lcpp_data)); +} + +TEST(PredictUnusedPreloads, SortedByFrequencyInDescendingOrder) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeaturesAndParameters( + {{blink::features::kLCPPDeferUnusedPreload, + {{blink::features::kLCPPDeferUnusedPreloadFrequencyThreshold.name, + "0"}}}}, + {}); + + LcppData lcpp_data; + auto* buckets = lcpp_data.mutable_lcpp_stat() + ->mutable_unused_preload_stat() + ->mutable_main_buckets(); + buckets->insert({"https://example.com/c.jpeg", 0.1}); + buckets->insert({"https://example.com/a.jpeg", 0.3}); + buckets->insert({"https://example.com/b.jpeg", 0.2}); + EXPECT_EQ(std::vector<GURL>({GURL("https://example.com/a.jpeg"), + GURL("https://example.com/b.jpeg"), + GURL("https://example.com/c.jpeg")}), + PredictUnusedPreloads(lcpp_data)); +} + +TEST(PredictUnusedPreloads, FilterUrls) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeaturesAndParameters( + {{blink::features::kLCPPDeferUnusedPreload, + {{blink::features::kLCPPDeferUnusedPreloadFrequencyThreshold.name, + "0"}}}}, + {}); + + LcppData lcpp_data; + auto* buckets = lcpp_data.mutable_lcpp_stat() + ->mutable_unused_preload_stat() + ->mutable_main_buckets(); + buckets->insert({"https://example.com/a.jpeg", 0.1}); + buckets->insert({"https://example.com/b.jpeg", 0.2}); + // Not an HTTP/HTTPS. + buckets->insert({"file://example.com/c.jpeg", 0.7}); + // Not an URL. + buckets->insert({"d.jpeg", 0.8}); + EXPECT_EQ(4U, buckets->size()); + EXPECT_EQ(std::vector<GURL>({GURL("https://example.com/b.jpeg"), + GURL("https://example.com/a.jpeg")}), + PredictUnusedPreloads(lcpp_data)); +} + +TEST(PredictUnusedPreloads, Threshold) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeaturesAndParameters( + {{blink::features::kLCPPDeferUnusedPreload, + {{blink::features::kLCPPDeferUnusedPreloadFrequencyThreshold.name, + "0.5"}}}}, + {}); + + LcppData lcpp_data; + auto* buckets = lcpp_data.mutable_lcpp_stat() + ->mutable_unused_preload_stat() + ->mutable_main_buckets(); + buckets->insert({"https://example.com/a.jpeg", 0.9}); + buckets->insert({"https://example.com/b.jpeg", 0.1}); + EXPECT_EQ(std::vector<GURL>({GURL("https://example.com/a.jpeg")}), + PredictUnusedPreloads(lcpp_data)); +} + TEST(LcppKeyTest, InvalidURLs) { const std::string invalid_urls[] = { // Invalid urls
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc b/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc index 3930eea..0b17c819 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc
@@ -86,7 +86,8 @@ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); // Avoid making network service to be more busy during the browser startup. - if (!AfterStartupTaskUtils::IsBrowserStartupComplete()) { + if (blink::features::kHttpDiskCachePrewarmingSkipDuringBrowserStartup.Get() && + !AfterStartupTaskUtils::IsBrowserStartupComplete()) { return; }
diff --git a/chrome/browser/predictors/predictor_database.cc b/chrome/browser/predictors/predictor_database.cc index a9adc778..d86eb42 100644 --- a/chrome/browser/predictors/predictor_database.cc +++ b/chrome/browser/predictors/predictor_database.cc
@@ -11,7 +11,10 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" +#include "base/metrics/histogram_functions.h" +#include "base/numerics/safe_conversions.h" #include "base/task/sequenced_task_runner.h" +#include "base/timer/timer.h" #include "chrome/browser/predictors/autocomplete_action_predictor_table.h" #include "chrome/browser/predictors/loading_predictor_config.h" #include "chrome/browser/predictors/resource_prefetch_predictor.h" @@ -60,6 +63,8 @@ // Cancels pending DB transactions. Should only be called on the UI thread. void SetCancelled(); + void ReportUMA(); + bool is_loading_predictor_enabled_; base::FilePath db_path_; std::unique_ptr<sql::Database> db_; @@ -69,6 +74,7 @@ // to using a WeakPtr instead. scoped_refptr<AutocompleteActionPredictorTable> autocomplete_table_; scoped_refptr<ResourcePrefetchPredictorTables> resource_prefetch_tables_; + std::unique_ptr<base::RepeatingTimer> uma_report_timer_; }; PredictorDatabaseInternal::PredictorDatabaseInternal( @@ -93,6 +99,13 @@ } PredictorDatabaseInternal::~PredictorDatabaseInternal() { + if (uma_report_timer_) { + // Since `uma_report_timer_` run on `db_task_runner_`, we need to shut down + // it on DB sequence. + db_task_runner_->PostTask(FROM_HERE, + base::BindOnce(&base::RepeatingTimer::Stop, + std::move(uma_report_timer_))); + } // The connection pointer needs to be deleted on the DB sequence since there // might be a task in progress on the DB sequence which uses this connection. db_task_runner_->DeleteSoon(FROM_HERE, db_.release()); @@ -115,6 +128,11 @@ resource_prefetch_tables_->Initialize(db_.get()); LogDatabaseStats(); + ReportUMA(); + uma_report_timer_ = std::make_unique<base::RepeatingTimer>(); + // Report DB usage periodically to see its growth. + uma_report_timer_->Start(FROM_HERE, base::Days(1), this, + &PredictorDatabaseInternal::ReportUMA); } void PredictorDatabaseInternal::SetCancelled() { @@ -133,6 +151,17 @@ resource_prefetch_tables_->LogDatabaseStats(); } +void PredictorDatabaseInternal::ReportUMA() { + int64_t db_file_size; + if (!base::GetFileSize(db_path_, &db_file_size)) { + return; + } + // "x>>10 == x/1024" + const int kb_size = base::saturated_cast<int>(db_file_size >> 10); + base::UmaHistogramCounts1M("LoadingPredictor.PredictorDatabaseFileSize", + kb_size); +} + PredictorDatabase::PredictorDatabase( Profile* profile, scoped_refptr<base::SequencedTaskRunner> db_task_runner)
diff --git a/chrome/browser/predictors/predictors_features.cc b/chrome/browser/predictors/predictors_features.cc index a845dd8a..dde7ecf 100644 --- a/chrome/browser/predictors/predictors_features.cc +++ b/chrome/browser/predictors/predictors_features.cc
@@ -113,6 +113,6 @@ // browser startup. BASE_FEATURE(kAvoidLoadingPredictorPrefetchDuringBrowserStartup, "AvoidLoadingPredictorPrefetchDuringBrowserStartup", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); } // namespace features
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc index 1495a16..2556627 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" + #include <memory> #include <set> #include <utility> @@ -11,11 +13,11 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task/sequenced_task_runner.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/predictors/loading_test_util.h" #include "chrome/browser/predictors/predictor_database.h" #include "chrome/browser/predictors/predictors_features.h" -#include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" #include "chrome/test/base/testing_profile.h" #include "components/sqlite_proto/key_value_table.h" #include "content/public/test/browser_task_environment.h" @@ -50,12 +52,15 @@ void TestDeleteData(); void TestDeleteAllData(); - content::BrowserTaskEnvironment task_environment_; + content::BrowserTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; scoped_refptr<base::SequencedTaskRunner> task_runner_; TestingProfile profile_; std::unique_ptr<PredictorDatabase> db_; scoped_refptr<ResourcePrefetchPredictorTables> tables_; + base::HistogramTester tester_; + private: // Initializes the tables, |test_url_data_|, |test_host_data_|, // |test_url_redirect_data_|, |test_host_redirect_data_| and @@ -534,6 +539,36 @@ EXPECT_TRUE(origin_data.empty()); } +TEST_F(ResourcePrefetchPredictorTablesTest, ReportUMA) { + const std::string name = "LoadingPredictor.PredictorDatabaseFileSize"; + const std::vector<base::Bucket> samples = tester_.GetAllSamples(name); + EXPECT_EQ(1u, samples.size()); + const base::Bucket& sample = samples[0]; + EXPECT_EQ(1, sample.count); + const base::HistogramBase::Sample file_size = sample.min; + EXPECT_GT(file_size, 0); + + // Write some data. + { + OriginData data; + data.set_host("a.test"); + for (int i = 0; i < 300; i++) { + InitializeOriginStat(data.add_origins(), "https://cdn.a.test", 10, 1, 0, + 12., false, true); + } + tables_->ExecuteDBTaskOnDBSequence(base::BindOnce( + &KeyValueTable<OriginData>::UpdateData, + base::Unretained(tables_->origin_table()), data.host(), data)); + } + task_environment_.FastForwardBy(base::Days(1)); + const std::vector<base::Bucket> samples2 = tester_.GetAllSamples(name); + EXPECT_EQ(2u, samples2.size()); + const base::Bucket& sample2 = samples2[1]; + EXPECT_EQ(1, sample2.count); + const base::HistogramBase::Sample file_size2 = sample2.min; + EXPECT_GT(file_size2, file_size); +} + TEST_F(ResourcePrefetchPredictorTablesReopenTest, GetAllData) { TestGetAllData(); }
diff --git a/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc b/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc index 106290c..725201b6 100644 --- a/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc
@@ -7,29 +7,38 @@ #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/sync/test/integration/apps_helper.h" #include "chrome/browser/sync/test/integration/fake_server_match_status_checker.h" #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/web_apps_sync_test_base.h" +#include "chrome/browser/web_applications/commands/set_user_display_mode_command.h" +#include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h" #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/test/web_app_test_observers.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_proto_utils.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_sync_bridge.h" +#include "components/services/app_service/public/cpp/icon_info.h" #include "components/sync/base/features.h" #include "components/sync/base/model_type.h" #include "components/sync/base/user_selectable_type.h" #include "components/sync/protocol/app_specifics.pb.h" #include "components/sync/protocol/entity_specifics.pb.h" +#include "components/sync/protocol/proto_value_conversions.h" #include "components/sync/service/sync_service_impl.h" #include "components/sync/service/sync_user_settings.h" #include "components/sync/test/fake_server_verifier.h" +#include "components/webapps/common/web_app_id.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkColor.h" #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_features.h" @@ -166,6 +175,203 @@ } IN_PROC_BROWSER_TEST_F(SingleClientWebAppsSyncTest, + SyncInstalledAppDoesNotChangeResponseToSync) { + GURL url("https://example.com/"); + const std::string app_id = + GenerateAppId(/*manifest_id_path=*/"manifest-id", url); + + // Create a sync proto with all relevant fields set (so the client won't try + // to fill in any missing fields). + sync_pb::WebAppSpecifics synced_web_app; + synced_web_app.set_start_url(url.spec()); + synced_web_app.set_name(app_id); + synced_web_app.set_user_display_mode_default( + sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE); + synced_web_app.set_theme_color(SK_ColorRED); + synced_web_app.set_scope("https://example.com/scope/"); + synced_web_app.set_relative_manifest_id("manifest-id"); + synced_web_app.set_user_display_mode_cros( + sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE); + + sync_pb::WebAppIconInfo icon_info; + icon_info.set_size_in_px(32); + icon_info.set_url("https://example.com/icon.png"); + icon_info.set_purpose(sync_pb::WebAppIconInfo_Purpose_ANY); + *(synced_web_app.add_icon_infos()) = std::move(icon_info); + + sync_pb::EntitySpecifics entity_specifics; + *(entity_specifics.mutable_web_app()) = synced_web_app; + + GetFakeServer()->InjectEntity( + syncer::PersistentUniqueClientEntity::CreateFromSpecificsForTesting( + /*non_unique_name=*/"", app_id, entity_specifics, kDefaultTime, + kDefaultTime)); + + ASSERT_TRUE(SetupSync()); + AwaitWebAppQuiescence(); + + // Installed app should store sync data. + auto& web_app_registrar = + WebAppProvider::GetForTest(GetProfile(0))->registrar_unsafe(); + const WebApp* web_app = web_app_registrar.GetAppById(app_id); + ASSERT_TRUE(web_app); + EXPECT_EQ(syncer::WebAppSpecificsToValue(synced_web_app), + syncer::WebAppSpecificsToValue(web_app->sync_proto())); + + std::string entity_id; + { + std::vector<sync_pb::SyncEntity> sync_entities = + GetFakeServer()->GetSyncEntitiesByModelType(syncer::WEB_APPS); + ASSERT_EQ(sync_entities.size(), 1u); + entity_id = sync_entities[0].id_string(); + sync_pb::WebAppSpecifics result_web_app = + sync_entities[0].specifics().web_app(); + + // The client will get the update but should not send out any updates in + // response. Verify the server data matches what was given to it. + EXPECT_EQ(syncer::WebAppSpecificsToValue(synced_web_app), + syncer::WebAppSpecificsToValue(result_web_app)); + } + + // Start listening for incoming changes from sync. + WebAppTestRegistryObserverAdapter registry_observer{&web_app_registrar}; + base::test::TestFuture<const std::vector<const WebApp*>&> + updated_from_sync_future; + registry_observer.SetWebAppWillBeUpdatedFromSyncDelegate( + updated_from_sync_future.GetRepeatingCallback()); + + // Modify the entity on the server, simulating another client making a change. + sync_pb::WebAppSpecifics modified_web_app = synced_web_app; + modified_web_app.set_user_display_mode_default( + sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER); + modified_web_app.clear_scope(); + modified_web_app.set_theme_color(SK_ColorBLUE); + *(entity_specifics.mutable_web_app()) = modified_web_app; + sync_pb::EntitySpecifics modified_entity_specifics; + *(modified_entity_specifics.mutable_web_app()) = modified_web_app; + GetFakeServer()->ModifyEntitySpecifics(entity_id, modified_entity_specifics); + + // Wait for the client to get the update. + ASSERT_TRUE(updated_from_sync_future.Wait()); + // Allow the client to finish processing and potentially update sync. + AwaitWebAppQuiescence(); + + // Installed app should have the modified sync data. + EXPECT_EQ(syncer::WebAppSpecificsToValue(modified_web_app), + syncer::WebAppSpecificsToValue(web_app->sync_proto())); + + std::vector<sync_pb::SyncEntity> sync_entities = + GetFakeServer()->GetSyncEntitiesByModelType(syncer::WEB_APPS); + ASSERT_EQ(sync_entities.size(), 1u); + sync_pb::WebAppSpecifics result_web_app = + sync_entities[0].specifics().web_app(); + + // The client should not send out any updates in response. + // Verify the server data matches what was given to it. + EXPECT_EQ(syncer::WebAppSpecificsToValue(modified_web_app), + syncer::WebAppSpecificsToValue(result_web_app)); +} + +IN_PROC_BROWSER_TEST_F(SingleClientWebAppsSyncTest, InstalledAppUpdatesSync) { + ASSERT_TRUE(SetupSync()); + AwaitWebAppQuiescence(); + + apps::IconInfo icon(GURL("https://example.com/icon.png"), /*size=*/32); + GURL app_url("https://example.com/"); + GURL scope("https://example.com/scope/"); + webapps::ManifestId manifest_id("https://example.com/manifest-id"); + std::string app_name = "app name"; + auto install_info = absl::make_unique<WebAppInstallInfo>(); + install_info->start_url = app_url; + install_info->manifest_id = manifest_id; + install_info->scope = scope; + install_info->title = base::UTF8ToUTF16(app_name); + install_info->description = base::UTF8ToUTF16(app_name); + install_info->user_display_mode = mojom::UserDisplayMode::kStandalone; + install_info->install_url = app_url; + install_info->manifest_icons.push_back(icon); + install_info->user_display_mode = mojom::UserDisplayMode::kStandalone; + install_info->theme_color = SK_ColorRED; + + const std::string app_id = + test::InstallWebApp(GetProfile(0), std::move(install_info), + /*overwrite_existing_manifest_fields=*/true, + webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON); + + sync_pb::WebAppSpecifics expected_sync_data; + expected_sync_data.set_start_url(app_url.spec()); + expected_sync_data.set_name(app_name); +#if BUILDFLAG(IS_CHROMEOS) + expected_sync_data.set_user_display_mode_cros( + sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE); +#else + expected_sync_data.set_user_display_mode_default( + sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE); +#endif + expected_sync_data.set_theme_color(SK_ColorRED); + expected_sync_data.set_scope("https://example.com/scope/"); + expected_sync_data.set_relative_manifest_id("manifest-id"); + sync_pb::WebAppIconInfo icon_info; + icon_info.set_size_in_px(icon.square_size_px.value()); + icon_info.set_url(icon.url.spec()); + icon_info.set_purpose(sync_pb::WebAppIconInfo_Purpose_ANY); + *(expected_sync_data.add_icon_infos()) = std::move(icon_info); + + // Check the locally-installed app stored the expected sync data. + auto& web_app_registrar = + WebAppProvider::GetForTest(GetProfile(0))->registrar_unsafe(); + const WebApp* web_app = web_app_registrar.GetAppById(app_id); + ASSERT_TRUE(web_app); + EXPECT_EQ(syncer::WebAppSpecificsToValue(expected_sync_data), + syncer::WebAppSpecificsToValue(web_app->sync_proto())); + + AwaitWebAppQuiescence(); + + { + std::vector<sync_pb::SyncEntity> sync_entities = + GetFakeServer()->GetSyncEntitiesByModelType(syncer::WEB_APPS); + ASSERT_EQ(sync_entities.size(), 1u); + sync_pb::WebAppSpecifics synced_web_app = + sync_entities[0].specifics().web_app(); + + // The client should have sent the data to the server. + EXPECT_EQ(syncer::WebAppSpecificsToValue(expected_sync_data), + syncer::WebAppSpecificsToValue(synced_web_app)); + } + + // Make a change to the installed app that affects sync. + base::test::TestFuture<void> done_future; + WebAppProvider::GetForTest(GetProfile(0)) + ->command_manager() + .ScheduleCommand(absl::make_unique<SetUserDisplayModeCommand>( + app_id, mojom::UserDisplayMode::kBrowser, done_future.GetCallback())); + ASSERT_TRUE(done_future.Wait()); + + AwaitWebAppQuiescence(); + + sync_pb::WebAppSpecifics updated_sync_data = expected_sync_data; +#if BUILDFLAG(IS_CHROMEOS) + updated_sync_data.set_user_display_mode_cros( + sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER); +#else + updated_sync_data.set_user_display_mode_default( + sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER); +#endif + + { + std::vector<sync_pb::SyncEntity> sync_entities = + GetFakeServer()->GetSyncEntitiesByModelType(syncer::WEB_APPS); + ASSERT_EQ(sync_entities.size(), 1u); + sync_pb::WebAppSpecifics synced_web_app = + sync_entities[0].specifics().web_app(); + + // The client should have sent the data to the server. + EXPECT_EQ(syncer::WebAppSpecificsToValue(updated_sync_data), + syncer::WebAppSpecificsToValue(synced_web_app)); + } +} + +IN_PROC_BROWSER_TEST_F(SingleClientWebAppsSyncTest, AppWithMalformedIdNotSyncInstalled) { const std::string app_id = "invalid_id"; GURL url("https://example.com/");
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb index c47f1bf..a201f2f 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb
@@ -54,7 +54,7 @@ <translation id="1240288207750131269"><ph name="LANG" /> indlæses</translation> <translation id="1240903469550363138">For at fortsætte deler <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> dit navn, din mailadresse og dit profilbillede med dette website. Se dette websites <ph name="BEGIN_LINK1" />privatlivspolitik<ph name="END_LINK1" /> og <ph name="BEGIN_LINK2" />servicevilkår<ph name="END_LINK2" />.</translation> <translation id="124116460088058876">Flere sprog</translation> -<translation id="1241792820757384812">Dine adgangskoder slettes fra Google Adgangskodeadministrator for <ph name="CHROME_CHANNEL" />. Du kan beholde den adgangskodefil, du lige har downloadet.</translation> +<translation id="1241792820757384812">Dine adgangskoder slettes fra Google Adgangskodeadministrator for <ph name="CHROME_CHANNEL" />. Du kan beholde den adgangskodefil, du lige har downloadet.</translation> <translation id="1242883863226959074">enhed</translation> <translation id="124678866338384709">Luk aktuel fane</translation> <translation id="1246905108078336582">Vil du fjerne forslaget fra udklipsholderen?</translation> @@ -144,7 +144,7 @@ <translation id="1750259112639922169">Fanegruppe – <ph name="TAB_COUNT" /> faner</translation> <translation id="17513872634828108">Åbne faner</translation> <translation id="1755203724116202818">Med henblik på at måle en annonces effektivitet deles der begrænsede typer data mellem websites, f.eks. om du har foretaget et køb, når du har besøgt et website.</translation> -<translation id="1757620656501361327">Opdatering af Google Adgangskodeadministrator</translation> +<translation id="1757620656501361327">Opdatering af Google Adgangskodeadministrator</translation> <translation id="1760873718737761808">{FILE_COUNT,plural, =1{Sider, 1 side på listen}one{Sider, # side på listen}other{Sider, # sider på listen}}</translation> <translation id="1778457539567749232">Markér som ulæst</translation> <translation id="1779766957982586368">Luk vindue</translation> @@ -228,7 +228,7 @@ <translation id="2234827758954819389">Privatlivsguide</translation> <translation id="2239812875700136898">Administrer dine historier ved hjælp af knappen Indstillinger for Discover</translation> <translation id="2247789808226901522">Kortet er udløbet</translation> -<translation id="2248941474044011069">Dine adgangskoder krypteres på din enhed, inden de gemmes i Googles Adgangskodeadministrator</translation> +<translation id="2248941474044011069">Dine adgangskoder krypteres på din enhed, inden de gemmes i Googles Adgangskodeadministrator</translation> <translation id="2249635629516220541">Tilpas de oplysninger, som websites kan bruge til at vise dig annoncer</translation> <translation id="2259659629660284697">Eksportér adgangskoder…</translation> <translation id="2276696007612801991">Log ind på din Google-konto for at tjekke dine adgangskoder</translation> @@ -569,7 +569,7 @@ <translation id="4084682180776658562">Bogmærke</translation> <translation id="4084712963632273211">Fra <ph name="PUBLISHER_ORIGIN" /> – <ph name="BEGIN_DEEMPHASIZED" />leveret af Google<ph name="END_DEEMPHASIZED" /></translation> <translation id="409109920254068737">Du kan bruge denne tablet til at logge ind på den enhed, der viser QR-koden.</translation> -<translation id="4092709865241032354">Tilføj dit brugernavn for dette website for at hjælpe Google Adgangskodeadministrator med at gemme dine loginoplysninger</translation> +<translation id="4092709865241032354">Tilføj dit brugernavn for dette website for at hjælpe Google Adgangskodeadministrator med at gemme dine loginoplysninger</translation> <translation id="4095146165863963773">Vil du slette appdata?</translation> <translation id="4095425503313512126">Browsing og søgning er hurtigere</translation> <translation id="4096227151372679484">Flow til lagring af bogmærker er åbnet i halv højde</translation> @@ -577,7 +577,7 @@ <translation id="4108314971463891922">Følg</translation> <translation id="4108998448622696017">Registrerer og advarer dig om skadelige hændelser, når de opstår.</translation> <translation id="4116038641877404294">Download sider for at bruge dem, når du er offline</translation> -<translation id="4121654769234887259">Du behøver ikke at huske denne adgangskode. Den gemmes i Google Adgangskodeadministrator for <ph name="USERNAME" />.</translation> +<translation id="4121654769234887259">Du behøver ikke at huske denne adgangskode. Den gemmes i Google Adgangskodeadministrator for <ph name="USERNAME" />.</translation> <translation id="4124152339699379357">Flow for notifikationstilladelse er åbnet i fuld højde</translation> <translation id="4126285640274188657">Sideindsigt</translation> <translation id="4135200667068010335">Lukket liste over enheder, der skal deles en fane med.</translation> @@ -603,7 +603,7 @@ <translation id="424864128008805179">Vil du logge ud af Chrome?</translation> <translation id="4249955472157341256">Sortér efter seneste</translation> <translation id="4256782883801055595">Open source-licenser</translation> -<translation id="4257230861809842349">Vil du slette adgangskoderne fra Google Adgangskodeadministrator?</translation> +<translation id="4257230861809842349">Vil du slette adgangskoderne fra Google Adgangskodeadministrator?</translation> <translation id="426652736638196239">Dette IBAN gemmes kun på denne enhed</translation> <translation id="4269820728363426813">Kopiér linkadresse</translation> <translation id="4277529130885813215">Brug en anden enhed</translation> @@ -613,7 +613,7 @@ <translation id="4296252229500326964">Ny inkognitofane</translation> <translation id="4298388696830689168">Tilknyttede websites</translation> <translation id="4303044213806199882">chrome_screenshot_<ph name="CURRENT_TIMESTAMP_MS" /></translation> -<translation id="4304713468139749426">Adgangskodeadministrator</translation> +<translation id="4304713468139749426">Adgangskodeadministrator</translation> <translation id="4307992518367153382">Grundlæggende valgmuligheder</translation> <translation id="4311652497846705514">Vil du åbne PDF-filen?</translation> <translation id="4320177379694898372">Ingen internetforbindelse</translation> @@ -708,7 +708,7 @@ <translation id="4758061975920522644">Del kun billede</translation> <translation id="4759238208242260848">Downloads</translation> <translation id="4763480195061959176">video</translation> -<translation id="4766313118839197559">Adgangskoder gemmes i Adgangskodeadministrator på denne enhed</translation> +<translation id="4766313118839197559">Adgangskoder gemmes i Adgangskodeadministrator på denne enhed</translation> <translation id="4766678251456904326">Føj konto til enhed</translation> <translation id="4767947714785277816">Vi lancerer en ny privatlivsfunktion til annoncer ved navn annoncemåling. Chrome deler kun meget begrænsede oplysninger mellem websites og apps, f.eks. hvornår du fik vist en annonce, for at hjælpe med at måle annonceeffektiviteten.</translation> <translation id="4769095993849849966">Nyt filnavn</translation> @@ -725,7 +725,7 @@ <translation id="4835385943915508971">Chrome har ikke adgang til den ressource, du anmoder om.</translation> <translation id="4837753911714442426">Åbn valgmuligheder for udskrivning af siden</translation> <translation id="4842092870884894799">Viser pop op for generering af adgangskoder</translation> -<translation id="4844633725025837809">For at beskytte adgangskoderne yderligere krypteres de på din enhed, inden de gemmes i Googles Adgangskodeadministrator</translation> +<translation id="4844633725025837809">For at beskytte adgangskoderne yderligere krypteres de på din enhed, inden de gemmes i Googles Adgangskodeadministrator</translation> <translation id="4850886885716139402">Vis</translation> <translation id="4852014461738377247">Logger ind\u2026</translation> <translation id="4860895144060829044">Ring op</translation> @@ -989,7 +989,7 @@ <translation id="6186394685773237175">Der blev ikke fundet nogen kompromitterede adgangskoder</translation> <translation id="6192907950379606605">Få billedbeskrivelser</translation> <translation id="6193448654517602979">Vælg faner</translation> -<translation id="6196315980958524839">Adgangskoder gemmes i Google Adgangskodeadministrator på denne enhed</translation> +<translation id="6196315980958524839">Adgangskoder gemmes i Google Adgangskodeadministrator på denne enhed</translation> <translation id="6202812185118613467">Log ind igen for at synkronisere</translation> <translation id="6205314730813004066">Privatliv ved annoncering</translation> <translation id="6210748933810148297">Ikke <ph name="EMAIL" />?</translation> @@ -1170,7 +1170,7 @@ <translation id="6987047470128880212">Inkognitofaner er ikke tilgængelige på denne enhed</translation> <translation id="6995899638241819463">Få en underretning, hvis adgangskoder afsløres i forbindelse med et brud på datasikkerheden</translation> <translation id="6996145122199359148">Download denne side</translation> -<translation id="7013762323294215682">Denne adgangsnøgle gemmes i Adgangskodeadministrator. Alle med adgang til Adgangskodeadministrator kan bruge denne adgangsnøgle.</translation> +<translation id="7013762323294215682">Denne adgangsnøgle gemmes i Adgangskodeadministrator. Alle med adgang til Adgangskodeadministrator kan bruge denne adgangsnøgle.</translation> <translation id="7020741890149022655">Føj til læseliste <ph name="BEGIN_NEW" />Nyhed<ph name="END_NEW" /></translation> <translation id="7022756207310403729">Åbn i browser</translation> <translation id="7027549951530753705">Gendannet den <ph name="ITEM_TITLE" /></translation> @@ -1370,7 +1370,7 @@ <translation id="7960972236129063347">Knappen Tilbage på arket med sideindsigt</translation> <translation id="7961926449547174351">Du har deaktiveret adgangen til lagerplads. Gå til Indstillinger for at aktivere den.</translation> <translation id="7963646190083259054">Leverandør:</translation> -<translation id="7965838025086216108">Du kan bruge gemte adgangskoder på alle enheder. De er gemt i Google Adgangskodeadministrator for <ph name="ACCOUNT" />.</translation> +<translation id="7965838025086216108">Du kan bruge gemte adgangskoder på alle enheder. De er gemt i Google Adgangskodeadministrator for <ph name="ACCOUNT" />.</translation> <translation id="7968014550143838305">Føjet til læseliste</translation> <translation id="7971136598759319605">Aktiv for 1 dag siden</translation> <translation id="7975379999046275268">Se forhåndsvisning af siden <ph name="BEGIN_NEW" />Ny<ph name="END_NEW" /></translation> @@ -1418,7 +1418,7 @@ <translation id="8130309322784422030">Dine gemte loginoplysninger kan være forældede</translation> <translation id="813082847718468539">Se websiteoplysninger</translation> <translation id="8135406045838672858">Downloadede PDF-filer åbnes automatisk med <ph name="APP_NAME" /></translation> -<translation id="8137562778192957619">Du behøver ikke at huske denne adgangskode. Den gemmes i Google Adgangskodeadministrator.</translation> +<translation id="8137562778192957619">Du behøver ikke at huske denne adgangskode. Den gemmes i Google Adgangskodeadministrator.</translation> <translation id="8163820386638255770">Verificer din identitet for at bruge og gemme adgangskoder på din Google-konto</translation> <translation id="8171286197772512427">Feedback om Oversigtsark til deling er åbnet</translation> <translation id="8179976553408161302">Enter</translation>
diff --git a/chrome/browser/ui/ash/container_app/DEPS b/chrome/browser/ui/ash/container_app/DEPS new file mode 100644 index 0000000..b2e521c --- /dev/null +++ b/chrome/browser/ui/ash/container_app/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + "container_app_interactive_uitest\.cc": [ + # TODO(http://b/333907855): Remove after migrating app. + "+chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h", + ] +}
diff --git a/chrome/browser/ui/ash/container_app/container_app_interactive_uitest.cc b/chrome/browser/ui/ash/container_app/container_app_interactive_uitest.cc index c8bcd88..e5fa69e 100644 --- a/chrome/browser/ui/ash/container_app/container_app_interactive_uitest.cc +++ b/chrome/browser/ui/ash/container_app/container_app_interactive_uitest.cc
@@ -25,19 +25,24 @@ #include "chrome/browser/ash/app_list/app_list_client_impl.h" #include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h" #include "chrome/browser/ash/file_manager/app_id.h" +#include "chrome/browser/ash/login/test/guest_session_mixin.h" +#include "chrome/browser/ash/login/test/logged_in_user_mixin.h" #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/resources/preinstalled_web_apps/internal/container.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/browser/web_applications/web_app_id_constants.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/chrome_switches.h" +#include "chrome/test/base/mixin_based_in_process_browser_test.h" #include "chrome/test/interaction/interactive_browser_test.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/constants/chromeos_switches.h" #include "components/app_constants/constants.h" +#include "components/sync/base/command_line_switches.h" #include "components/webapps/common/web_app_id.h" #include "content/public/test/browser_test.h" #include "ui/events/test/event_generator.h" @@ -56,7 +61,10 @@ using ::testing::IsEmpty; using ::testing::Not; using ::testing::Pointer; +using ::testing::PrintToStringParamName; using ::testing::Property; +using ::testing::ValuesIn; +using ::testing::WithParamInterface; // Elements -------------------------------------------------------------------- @@ -73,8 +81,23 @@ inline char kGmailAppElementName[] = "GmailApp"; inline char kShowAppInfoMenuItemElementName[] = "ShowAppInfoMenuItem"; +// Users ----------------------------------------------------------------------- + +inline char kManagedUserEmail[] = "managed@example.com"; +inline char kManagedUserGaiaId[] = "<MANAGED_USER_GAIA_ID>"; +inline char kUnmanagedUserEmail[] = "unmanaged@gmail.com"; +inline char kUnmanagedUserGaiaId[] = "<UNMANAGED_USER_GAIA_ID>"; + // Helpers --------------------------------------------------------------------- +// Returns an `AccountId` for either a `managed` or an unmanaged user. +AccountId GetAccountId(bool managed) { + return managed ? AccountId::FromUserEmailGaiaId(kManagedUserEmail, + kManagedUserGaiaId) + : AccountId::FromUserEmailGaiaId(kUnmanagedUserEmail, + kUnmanagedUserGaiaId); +} + // Returns all `descendants` of the specified `parent` matching the given class. template <typename ViewClass> void FindDescendantsOfClass(views::View* parent, @@ -146,8 +169,9 @@ std::reference_wrapper<const raw_ptr<ash::ShelfView>> shelf, std::string_view id, const views::View* view) { - return views::IsViewClass<ash::ShelfAppButton>(view) && - shelf.get()->GetShelfAppButton(FindShelfItemForWebApp(id)->id) == view; + const ash::ShelfItem* const item = FindShelfItemForWebApp(id); + return views::IsViewClass<ash::ShelfAppButton>(view) && item && + shelf.get()->GetShelfAppButton(item->id) == view; } } // namespace @@ -155,24 +179,27 @@ // ContainerAppInteractiveUiTest ----------------------------------------------- // Base class for interactive UI tests of the container app. -class ContainerAppInteractiveUiTest : public InteractiveBrowserTest { +class ContainerAppInteractiveUiTest + : public InteractiveBrowserTestT<MixinBasedInProcessBrowserTest> { public: - ContainerAppInteractiveUiTest() { + ContainerAppInteractiveUiTest( + const AccountId& account_id = GetAccountId(/*managed=*/false), + user_manager::UserType user_type = user_manager::UserType::kRegular, + bool should_ignore_feature_key = true) + : user_session_mixin_(CreateUserSessionMixin(account_id, user_type)) { + // Conditionally ignore the container app preinstallation key. + if (should_ignore_feature_key) { + ignore_container_app_preinstall_key_ = std::make_unique< + base::AutoReset<bool>>( + chromeos::features::SetIgnoreContainerAppPreinstallKeyForTesting()); + } + // Enable container app preinstallation. scoped_feature_list_.InitWithFeatures( {chromeos::features::kContainerAppPreinstall, chromeos::features::kFeatureManagementContainerAppPreinstall}, {}); - // Do not launch the browser. The only browser expected to launch will be - // that associated with the container app. - set_launch_browser_for_testing(nullptr); - - // Since we suppressed the browser from launching, we also need to prevent - // premature shutdown that would otherwise occur due to the lack of a - // browser. If we did not do so, system web apps would fail to launch. - set_exit_when_last_browser_closes(false); - // Use a consistent context for element tracking. Otherwise each widget has // its own context, greatly increasing the complexity of tracking // cross-widget CUJs as is the case in this test suite. @@ -218,51 +245,83 @@ return Do([ptr]() { ptr.get() = nullptr; }); } - private: - // InteractiveBrowserTest: + protected: + // InteractiveBrowserTestT<MixinBasedInProcessBrowserTest>: void SetUpDefaultCommandLine(base::CommandLine* command_line) override { - InteractiveBrowserTest::SetUpDefaultCommandLine(command_line); + InteractiveBrowserTestT< + MixinBasedInProcessBrowserTest>::SetUpDefaultCommandLine(command_line); // Remove the `switches::kDisableDefaultApps` switch to ensure that default // apps are installed. The container app is a default app. command_line->RemoveSwitch(switches::kDisableDefaultApps); + + // Disable sync as it would otherwise block updating of shelf pins. + command_line->AppendSwitch(syncer::kDisableSync); } void SetUpOnMainThread() override { - InteractiveBrowserTest::SetUpOnMainThread(); + // For logged-in user sessions, perform login prior to + // `InteractiveBrowserTestT<>::SetUpOnMainThread()` so that the interactive + // browser test base class will successfully set the context widget for the + // test sequence. The context widget will be associated with the browser. + if (absl::holds_alternative<ash::LoggedInUserMixin>(user_session_mixin_)) { + absl::get<ash::LoggedInUserMixin>(user_session_mixin_).LogInUser(); + } + + InteractiveBrowserTestT< + MixinBasedInProcessBrowserTest>::SetUpOnMainThread(); // Wait for installation of both system and external web apps. The container // app is an external app and this test suite will verify its adjacency to // system web apps. - Profile* const profile = ProfileManager::GetActiveUserProfile(); + Profile* const profile = browser()->profile(); ash::SystemWebAppManager::GetForTest(profile) ->InstallSystemAppsForTesting(); web_app::test::WaitUntilWebAppProviderAndSubsystemsReady( web_app::WebAppProvider::GetForTest(profile)); AppListClientImpl::GetInstance()->UpdateProfile(); - // `InteractiveBrowserTest`s must set a context widget prior to invoking - // `RunTestSequence()`. This needs to be done explicitly since we suppressed - // launching the browser. Note that it doesn't matter what this widget is, - // but convention is to use the `ash::StatusAreaWidget`. - SetContextWidget(ash::Shell::GetPrimaryRootWindowController() - ->shelf() - ->GetStatusAreaWidget()); - // Cache install info for the container app. container_app_install_info_ = web_app::GetConfigForContainer().app_info_factory.Run(); } - // Used to ignore the container app preinstallation key. - const base::AutoReset<bool> ignore_container_app_preinstall_key_{ - chromeos::features::SetIgnoreContainerAppPreinstallKeyForTesting()}; + private: + // Creates the appropriate guest or logged-in user session mixin based on + // the specified `account_id` and `user_type`. + absl::variant<ash::GuestSessionMixin, ash::LoggedInUserMixin> + CreateUserSessionMixin(const AccountId& account_id, + user_manager::UserType user_type) { + if (user_type == user_manager::UserType::kGuest) { + return absl::variant<ash::GuestSessionMixin, ash::LoggedInUserMixin>( + absl::in_place_type_t<ash::GuestSessionMixin>(), &mixin_host_); + } + + CHECK(user_type == user_manager::UserType::kChild || + user_type == user_manager::UserType::kRegular); + + return absl::variant<ash::GuestSessionMixin, ash::LoggedInUserMixin>( + absl::in_place_type_t<ash::LoggedInUserMixin>(), &mixin_host_, + user_type == user_manager::UserType::kChild + ? ash::LoggedInUserMixin::LogInType::kChild + : ash::LoggedInUserMixin::LogInType::kRegular, + embedded_test_server(), this, /*should_launch_browser=*/true, + account_id); + } + + // Used to manage either a guest or logged-in user session based on test + // parameterization. + absl::variant<ash::GuestSessionMixin, ash::LoggedInUserMixin> + user_session_mixin_; // Used to enable the container app preinstallation. base::test::ScopedFeatureList scoped_feature_list_; // Used to retrieve expected title/URL for the container app. std::unique_ptr<web_app::WebAppInstallInfo> container_app_install_info_; + + // Used to conditionally ignore the container app preinstallation key. + std::unique_ptr<base::AutoReset<bool>> ignore_container_app_preinstall_key_; }; // Tests ----------------------------------------------------------------------- @@ -571,5 +630,221 @@ Eq(ash::UNINSTALL)))))))); } +// ContainerAppInteractiveUiIneligibilityTest ---------------------------------- + +// Reasons why the user may be ineligible for container app preinstallation. +enum class IneligibilityReason { + kMinValue = 0, + kFeatureFlagDisabled = kMinValue, + kFeatureKeyEmpty, + kFeatureKeyParamIncorrect, + kFeatureKeySwitchIncorrect, + kFeatureManagementFlagDisabled, + kUserManaged, + kUserTypeChild, + kUserTypeGuest, + kMaxValue = kUserTypeGuest, +}; + +#define INELIGIBILITY_REASON_CASE(reason) \ + case IneligibilityReason::reason: \ + return os << std::string(#reason) + +inline std::ostream& operator<<(std::ostream& os, IneligibilityReason reason) { + switch (reason) { + INELIGIBILITY_REASON_CASE(kFeatureFlagDisabled); + INELIGIBILITY_REASON_CASE(kFeatureKeyEmpty); + INELIGIBILITY_REASON_CASE(kFeatureKeyParamIncorrect); + INELIGIBILITY_REASON_CASE(kFeatureKeySwitchIncorrect); + INELIGIBILITY_REASON_CASE(kFeatureManagementFlagDisabled); + INELIGIBILITY_REASON_CASE(kUserManaged); + INELIGIBILITY_REASON_CASE(kUserTypeChild); + INELIGIBILITY_REASON_CASE(kUserTypeGuest); + } +} + +// Base class for interactive UI tests of container app ineligibility. +class ContainerAppInteractiveUiIneligibilityTest + : public ContainerAppInteractiveUiTest, + public WithParamInterface<IneligibilityReason> { + public: + // Incorrect key param/switch for the container app preinstallation feature. + static constexpr char kIncorrectKey[] = "<INCORRECT_KEY>"; + + ContainerAppInteractiveUiIneligibilityTest() + : ContainerAppInteractiveUiTest(GetAccountId(), + GetUserType(), + ShouldIgnoreFeatureKey()) { + std::vector<base::test::FeatureRefAndParams> enabled; + std::vector<base::test::FeatureRef> disabled; + + // Feature flag and key param. + if (IsFeatureFlagDisabled()) { + disabled.emplace_back(chromeos::features::kContainerAppPreinstall); + } else { + enabled.emplace_back( + chromeos::features::kContainerAppPreinstall, + IsFeatureKeyParamIncorrect() + ? base::FieldTrialParams({{"key", kIncorrectKey}}) + : base::FieldTrialParams()); + } + + // Feature management flag. + if (IsFeatureManagementFlagDisabled()) { + disabled.emplace_back( + chromeos::features::kFeatureManagementContainerAppPreinstall); + } else { + enabled.emplace_back( + chromeos::features::kFeatureManagementContainerAppPreinstall, + base::FieldTrialParams()); + } + + scoped_feature_list_.InitWithFeaturesAndParameters(enabled, disabled); + } + + private: + // ContainerAppInteractiveUiTest: + void SetUpDefaultCommandLine(base::CommandLine* command_line) override { + ContainerAppInteractiveUiTest::SetUpDefaultCommandLine(command_line); + + // Feature key switch. + if (IsFeatureKeySwitchIncorrect()) { + command_line->AppendSwitchASCII( + chromeos::switches::kContainerAppPreinstallKey, kIncorrectKey); + } + } + + void SetUpOnMainThread() override { + // Web app preinstallation times out for child user types due to failure to + // install some default web apps. Since this test suite only cares about the + // preinstallation of the container app, circumvent timeouts by disabling + // other default web apps. + std::unique_ptr<web_app::ScopedTestingPreinstalledAppData> app_data; + if (GetUserType() == user_manager::UserType::kChild) { + app_data = std::make_unique<web_app::ScopedTestingPreinstalledAppData>(); + app_data->apps.emplace_back(web_app::GetConfigForContainer()); + } + + ContainerAppInteractiveUiTest::SetUpOnMainThread(); + } + + // Returns the `AccountId` for the user given test parameterization. + AccountId GetAccountId() const { + return ::GetAccountId(/*managed=*/GetParam() == + IneligibilityReason::kUserManaged); + } + + // Returns the type for the user given test parameterization. + user_manager::UserType GetUserType() const { + switch (GetParam()) { + case IneligibilityReason::kUserTypeChild: + return user_manager::UserType::kChild; + case IneligibilityReason::kUserTypeGuest: + return user_manager::UserType::kGuest; + default: + return user_manager::UserType::kRegular; + } + } + + // Returns whether the feature flag is disabled given test parameterization. + bool IsFeatureFlagDisabled() const { + return GetParam() == IneligibilityReason::kFeatureFlagDisabled; + } + + // Returns whether the feature key param is incorrect given test + // parameterization. + bool IsFeatureKeyParamIncorrect() const { + return GetParam() == IneligibilityReason::kFeatureKeyParamIncorrect; + } + + // Returns whether the feature key switch is incorrect given test + // parameterization. + bool IsFeatureKeySwitchIncorrect() const { + return GetParam() == IneligibilityReason::kFeatureKeySwitchIncorrect; + } + + // Returns whether the feature management flag is disabled given test + // parameterization. + bool IsFeatureManagementFlagDisabled() const { + return GetParam() == IneligibilityReason::kFeatureManagementFlagDisabled; + } + + // Returns whether the feature key should be ignored given test + // parameterization. + bool ShouldIgnoreFeatureKey() const { + return !std::set<IneligibilityReason>( + {IneligibilityReason::kFeatureKeyEmpty, + IneligibilityReason::kFeatureKeyParamIncorrect, + IneligibilityReason::kFeatureKeySwitchIncorrect}) + .contains(GetParam()); + } + + // Used to enable/disable the container app preinstallation based on test + // parameterization. + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + All, + ContainerAppInteractiveUiIneligibilityTest, + ValuesIn(([]() { + std::vector<IneligibilityReason> reasons( + static_cast<int>(IneligibilityReason::kMaxValue) - + static_cast<int>(IneligibilityReason::kMinValue) + 1); + base::ranges::generate( + reasons.begin(), reasons.end(), + [i = static_cast<int>(IneligibilityReason::kMinValue)]() mutable { + return static_cast<IneligibilityReason>(i++); + }); + return reasons; + })()), + PrintToStringParamName()); + +// Tests ----------------------------------------------------------------------- + +// Verifies the container app is absent from the app list for ineligible users. +IN_PROC_BROWSER_TEST_P(ContainerAppInteractiveUiIneligibilityTest, + AbsentFromAppList) { + RunTestSequence( + // Launch app list. + DoDefaultAction(ash::kHomeButtonElementId), + + // Find apps page. + NameDescendantViewByType<ash::AppListBubbleAppsPage>( + ash::kAppListBubbleViewElementId, kAppListBubbleAppsPageElementName), + + // Find apps grid. + NameDescendantViewByType<ash::AppsGridView>( + kAppListBubbleAppsPageElementName, kAppsGridViewElementName), + + // Check container app absent. + CheckView( + kAppsGridViewElementName, [](ash::AppsGridView* apps_grid_view) { + std::vector<raw_ptr<ash::AppListItemView>> apps; + FindDescendantsOfClass(apps_grid_view, apps); + return apps.size() && + base::ranges::none_of(apps, [&](ash::AppListItemView* app) { + return IsAppListItemViewForWebApp(web_app::kContainerAppId, + app); + }); + })); +} + +// Verifies the container app is absent from the shelf for ineligible users. +IN_PROC_BROWSER_TEST_P(ContainerAppInteractiveUiIneligibilityTest, + AbsentFromShelf) { + RunTestSequence( + // Check container app absent. + CheckView(ash::kShelfViewElementId, [](ash::ShelfView* shelf) { + std::vector<raw_ptr<ash::ShelfAppButton>> apps; + FindDescendantsOfClass(shelf, apps); + return apps.size() && + base::ranges::none_of( + apps, [&, shelf = raw_ptr(shelf)](ash::ShelfAppButton* app) { + return IsShelfAppButtonForWebApp( + std::cref(shelf), web_app::kContainerAppId, app); + }); + })); +} + // TODO(http://b/331668699): Test container app position for existing users. -// TODO(http://b/331668699): Test container app preinstall ineligibility.
diff --git a/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.cc b/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.cc index 77c5990..ad2c375 100644 --- a/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.cc +++ b/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.cc
@@ -7,7 +7,6 @@ #include <memory> #include <utility> -#include "base/check_deref.h" #include "base/functional/bind.h" #include "chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h" #include "chrome/browser/ash/crosapi/crosapi_ash.h" @@ -20,14 +19,8 @@ bool bookmarks, bool history, bool open_tabs) - : bookmarks_(bookmarks), - history_(history), - open_tabs_(open_tabs), - factory_(CHECK_DEREF(factory)) { - if (factory_->IsBound()) { - controller_ = factory_->CreateSearchControllerPicker(bookmarks_, history_, - open_tabs_); - } + : bookmarks_(bookmarks), history_(history), open_tabs_(open_tabs) { + obs_.Observe(factory); } PickerLacrosOmniboxSearchProvider::~PickerLacrosOmniboxSearchProvider() = @@ -35,13 +28,15 @@ crosapi::SearchControllerAsh* PickerLacrosOmniboxSearchProvider::GetController() { - if (!controller_ && factory_->IsBound()) { - controller_ = factory_->CreateSearchControllerPicker(bookmarks_, history_, - open_tabs_); - } return controller_.get(); } +void PickerLacrosOmniboxSearchProvider::OnSearchControllerFactoryBound( + crosapi::SearchControllerFactoryAsh* factory) { + controller_ = + factory->CreateSearchControllerPicker(bookmarks_, history_, open_tabs_); +} + app_list::OmniboxLacrosProvider::SearchControllerCallback PickerLacrosOmniboxSearchProvider::CreateControllerCallback(bool bookmarks, bool history,
diff --git a/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.h b/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.h index 74d6ddc9..4736ef7 100644 --- a/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.h +++ b/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider.h
@@ -7,19 +7,20 @@ #include <memory> -#include "base/memory/raw_ref.h" +#include "base/scoped_observation.h" #include "chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h" +#include "chrome/browser/ash/crosapi/search_controller_factory_ash.h" namespace crosapi { class SearchControllerAsh; -class SearchControllerFactoryAsh; } // Manages a dedicated Picker `crosapi::SearchControllerAsh` obtained from a // given `crosapi::SearchControllerFactoryAsh`. // Intended to be used to construct a `app_list::OmniboxLacrosProvider` - see // the `CreateControllerCallback` static method below. -class PickerLacrosOmniboxSearchProvider { +class PickerLacrosOmniboxSearchProvider + : public crosapi::SearchControllerFactoryAsh::Observer { public: explicit PickerLacrosOmniboxSearchProvider( crosapi::SearchControllerFactoryAsh* factory, @@ -30,7 +31,7 @@ delete; PickerLacrosOmniboxSearchProvider& operator=( const PickerLacrosOmniboxSearchProvider&) = delete; - ~PickerLacrosOmniboxSearchProvider(); + ~PickerLacrosOmniboxSearchProvider() override; crosapi::SearchControllerAsh* GetController(); @@ -42,13 +43,19 @@ CreateControllerCallback(bool bookmarks, bool history, bool open_tabs); private: + // crosapi::SearchControllerFactoryAsh::Observer overrides: + void OnSearchControllerFactoryBound( + crosapi::SearchControllerFactoryAsh* factory) override; + bool bookmarks_; bool history_; bool open_tabs_; std::unique_ptr<crosapi::SearchControllerAsh> controller_; - base::raw_ref<crosapi::SearchControllerFactoryAsh> factory_; + base::ScopedObservation<crosapi::SearchControllerFactoryAsh, + crosapi::SearchControllerFactoryAsh::Observer> + obs_{this}; }; #endif // CHROME_BROWSER_UI_ASH_PICKER_PICKER_LACROS_OMNIBOX_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider_unittest.cc b/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider_unittest.cc index 41459b4b..8886e7d 100644 --- a/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider_unittest.cc +++ b/chrome/browser/ui/ash/picker/picker_lacros_omnibox_search_provider_unittest.cc
@@ -171,11 +171,8 @@ EXPECT_TRUE(mojom_factory.TakeLastTestController()); } -// The three tests below show the UNWANTED behaviour of the provider. -// The provider SHOULD re-call the factory when it is bound, not when -// `GetController` is called. TEST_F(PickerLacrosOmniboxSearchProviderTest, - CallsFactoryAfterConstructionOnGetController) { + CallsFactoryAfterConstructionWhenBound) { base::test::SingleThreadTaskEnvironment environment; crosapi::SearchControllerFactoryAsh factory; ASSERT_FALSE(factory.IsBound()); @@ -184,31 +181,12 @@ TestMojomSearchControllerFactory mojom_factory; factory.BindRemote(mojom_factory.BindToRemote()); ASSERT_TRUE(factory.IsBound()); - (void)provider.GetController(); mojom_factory.RunUntilCreateSearchController(); EXPECT_TRUE(mojom_factory.TakeLastTestController()); } -TEST_F(PickerLacrosOmniboxSearchProviderTest, - DoesNotCallFactoryAfterConstructionWhenBound) { - base::test::SingleThreadTaskEnvironment environment; - crosapi::SearchControllerFactoryAsh factory; - ASSERT_FALSE(factory.IsBound()); - - PickerLacrosOmniboxSearchProvider provider(&factory, false, false, false); - TestMojomSearchControllerFactory mojom_factory; - factory.BindRemote(mojom_factory.BindToRemote()); - ASSERT_TRUE(factory.IsBound()); - // Ensure that the factory is NOT called. - // There is no way to have a callback for "function is not called", so we need - // to use `RunUntilIdle` here. - base::RunLoop().RunUntilIdle(); - - EXPECT_FALSE(mojom_factory.TakeLastTestController()); -} - -TEST_F(PickerLacrosOmniboxSearchProviderTest, DoesNotCallFactoryWhenRebound) { +TEST_F(PickerLacrosOmniboxSearchProviderTest, CallsFactoryWhenRebound) { base::test::SingleThreadTaskEnvironment environment; crosapi::SearchControllerFactoryAsh factory; PickerLacrosOmniboxSearchProvider provider(&factory, false, false, false); @@ -216,7 +194,6 @@ // Connect a remote factory... TestMojomSearchControllerFactory mojom_factory; factory.BindRemote(mojom_factory.BindToRemote()); - (void)provider.GetController(); mojom_factory.RunUntilCreateSearchController(); ASSERT_TRUE(mojom_factory.TakeLastTestController()); // ...then disconnect it. @@ -228,13 +205,9 @@ // Rebind another remote factory. TestMojomSearchControllerFactory mojom_factory; factory.BindRemote(mojom_factory.BindToRemote()); - (void)provider.GetController(); - // Ensure that the factory is NOT called. - // There is no way to have a callback for "function is not called", so we need - // to use `RunUntilIdle` here. - base::RunLoop().RunUntilIdle(); + mojom_factory.RunUntilCreateSearchController(); - EXPECT_FALSE(mojom_factory.TakeLastTestController()); + EXPECT_TRUE(mojom_factory.TakeLastTestController()); } TEST_F(PickerLacrosOmniboxSearchProviderTest, DoesNotCallFactoryMultipleTimes) {
diff --git a/chrome/browser/ui/ash/quick_settings_integration_test.yaml b/chrome/browser/ui/ash/quick_settings_integration_test.yaml new file mode 100644 index 0000000..fc7514f --- /dev/null +++ b/chrome/browser/ui/ash/quick_settings_integration_test.yaml
@@ -0,0 +1,22 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "QuickSettingsIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "brettw@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Testing the OS Settings system web app. +cases: + - id: "OpenOsSettings" + tags: ["crosier:crosierdemosuite", "crosier:cq"] + - id: "ManagedDeviceInfo" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ui/ash/shelf/shelf_integration_test.yaml b/chrome/browser/ui/ash/shelf/shelf_integration_test.yaml new file mode 100644 index 0000000..32ed3e71 --- /dev/null +++ b/chrome/browser/ui/ash/shelf/shelf_integration_test.yaml
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Schema can be found at: platform/dev/test/gtest/gtest_schema.yaml +--- +name: "ShelfIntegrationTest" +harness: "crosier" +category: "integration" +owners: + - email: "jamescook@chromium.org" + - email: "chromeos-sw-engprod@google.com" +hw_agnostic: True +criteria: | + Integration test that opens and closes ChromeOS app shelf. +cases: + - id: "OpenCloseSwitchApps" + tags: ["crosier:crosierdemosuite", "crosier:cq"] +...
diff --git a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h index 2f62245..2c9fd68 100644 --- a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h +++ b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h
@@ -38,6 +38,13 @@ const PasswordCrossDomainConfirmationPopupControllerImpl&) = delete; ~PasswordCrossDomainConfirmationPopupControllerImpl() override; + // PasswordCrossDomainConfirmationPopupController: + void Show(const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) override; + // autofill::AutofillPopupViewDelegate: void Hide(autofill::PopupHidingReason reason) override; void ViewDestroyed() override; @@ -46,13 +53,6 @@ const gfx::RectF& element_bounds() const override; base::i18n::TextDirection GetElementTextDirection() const override; - // PasswordCrossDomainConfirmationPopupController: - void Show(const gfx::RectF& element_bounds, - base::i18n::TextDirection text_direction, - const GURL& domain, - const std::u16string& password_origin, - base::OnceClosure confirmation_callback) override; - // content::WebContentsObserver: void DidGetUserInteraction(const blink::WebInputEvent& event) override;
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc index 7c146a67..4752b53 100644 --- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc +++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -69,6 +69,7 @@ #include "chrome/browser/web_applications/web_app_install_finalizer.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/browser/web_applications/web_app_install_params.h" +#include "chrome/browser/web_applications/web_app_proto_utils.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_registry_update.h" @@ -636,16 +637,17 @@ mojom::UserDisplayMode::kBrowser); synced_specifics_data->SetName("Name From Sync"); - WebApp::SyncFallbackData sync_fallback_data; - sync_fallback_data.name = "Name From Sync"; - sync_fallback_data.theme_color = SK_ColorMAGENTA; - sync_fallback_data.scope = GURL("https://example.com/sync_scope"); + sync_pb::WebAppSpecifics sync_proto; + sync_proto.set_name("Name From Sync"); + sync_proto.set_theme_color(SK_ColorMAGENTA); + sync_proto.set_scope(GURL("https://example.com/sync_scope").spec()); apps::IconInfo apps_icon_info = CreateIconInfo( /*icon_base_url=*/start_url, IconPurpose::MONOCHROME, 64); - sync_fallback_data.icon_infos.push_back(std::move(apps_icon_info)); + sync_proto.mutable_icon_infos()->Add( + AppIconInfoToSyncProto(std::move(apps_icon_info))); - synced_specifics_data->SetSyncFallbackData(std::move(sync_fallback_data)); + synced_specifics_data->SetSyncProto(std::move(sync_proto)); add_synced_apps_data.push_back(std::move(synced_specifics_data)); }
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc index 58e59e0f..c3bdd1b 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
@@ -118,23 +118,23 @@ EXPECT_EQ(web_app->display_mode(), DisplayMode::kStandalone); EXPECT_FALSE(web_app->theme_color().has_value()); - EXPECT_FALSE(web_app->sync_fallback_data().theme_color.has_value()); - EXPECT_EQ("Basic web app", web_app->sync_fallback_data().name); - EXPECT_EQ(expect_scope.spec(), web_app->sync_fallback_data().scope); + EXPECT_FALSE(web_app->sync_proto().has_theme_color()); + EXPECT_EQ("Basic web app", web_app->sync_proto().name()); + EXPECT_EQ(expect_scope.spec(), web_app->sync_proto().scope()); - EXPECT_EQ(2u, web_app->sync_fallback_data().icon_infos.size()); + ASSERT_EQ(2, web_app->sync_proto().icon_infos_size()); - EXPECT_EQ(expect_start_url.Resolve("basic-48.png"), - web_app->sync_fallback_data().icon_infos[0].url); - EXPECT_EQ(48, web_app->sync_fallback_data().icon_infos[0].square_size_px); - EXPECT_EQ(apps::IconInfo::Purpose::kAny, - web_app->sync_fallback_data().icon_infos[0].purpose); + EXPECT_EQ(expect_start_url.Resolve("basic-48.png").spec(), + web_app->sync_proto().icon_infos(0).url()); + EXPECT_EQ(48, web_app->sync_proto().icon_infos(0).size_in_px()); + EXPECT_EQ(sync_pb::WebAppIconInfo_Purpose_ANY, + web_app->sync_proto().icon_infos(0).purpose()); - EXPECT_EQ(expect_start_url.Resolve("basic-192.png"), - web_app->sync_fallback_data().icon_infos[1].url); - EXPECT_EQ(192, web_app->sync_fallback_data().icon_infos[1].square_size_px); - EXPECT_EQ(apps::IconInfo::Purpose::kAny, - web_app->sync_fallback_data().icon_infos[1].purpose); + EXPECT_EQ(expect_start_url.Resolve("basic-192.png").spec(), + web_app->sync_proto().icon_infos(1).url()); + EXPECT_EQ(192, web_app->sync_proto().icon_infos(1).size_in_px()); + EXPECT_EQ(sync_pb::WebAppIconInfo_Purpose_ANY, + web_app->sync_proto().icon_infos(1).purpose()); // Manifest Resources: This is chrome/test/data/web_apps/basic-192.png EXPECT_EQ(IconManagerReadAppIconPixel(icon_manager, web_app->app_id(),
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.cc b/chrome/browser/web_applications/test/web_app_test_utils.cc index b8071eb5..03a3b40 100644 --- a/chrome/browser/web_applications/test/web_app_test_utils.cc +++ b/chrome/browser/web_applications/test/web_app_test_utils.cc
@@ -53,6 +53,7 @@ #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_install_info.h" +#include "chrome/browser/web_applications/web_app_proto_utils.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registry_update.h" #include "chrome/browser/web_applications/web_app_sync_bridge.h" @@ -663,22 +664,42 @@ app->SetIsLocallyInstalled(random.next_bool()); app->SetIsFromSyncAndPendingInstallation(random.next_bool()); - const mojom::UserDisplayMode user_display_modes[3] = { - mojom::UserDisplayMode::kBrowser, mojom::UserDisplayMode::kStandalone, - mojom::UserDisplayMode::kTabbed}; + const sync_pb::WebAppSpecifics::UserDisplayMode user_display_modes[3] = { + sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER, + sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE, + sync_pb::WebAppSpecifics_UserDisplayMode_TABBED}; // Explicitly set a UserDisplayMode for each platform (instead of calling // `SetUserDisplayMode` which sets the current platform's value only) so the // test expectations are consistent across platforms. - if (base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { + { + // Copy proto, retaining existing fields (including unknown fields). + sync_pb::WebAppSpecifics sync_proto = app->sync_proto(); + if (base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { + if (random.next_bool()) { + sync_proto.set_user_display_mode_default( + user_display_modes[random.next_uint(3)]); + } + // Must have at least one platform's UserDisplayMode set. + if (!sync_proto.has_user_display_mode_default() || random.next_bool()) { + sync_proto.set_user_display_mode_cros( + user_display_modes[random.next_uint(3)]); + } + } else { + sync_proto.set_user_display_mode_default( + user_display_modes[random.next_uint(3)]); + } + if (random.next_bool()) { - app->SetUserDisplayModeDefault(user_display_modes[random.next_uint(3)]); + sync_proto.set_user_launch_ordinal( + syncer::StringOrdinal::CreateInitialOrdinal().ToInternalValue()); } - // Must have at least one platform's UserDisplayMode set. - if (!app->user_display_mode_default().has_value() || random.next_bool()) { - app->SetUserDisplayModeCrOS(user_display_modes[random.next_uint(3)]); + + if (random.next_bool()) { + sync_proto.set_user_page_ordinal( + syncer::StringOrdinal::CreateInitialOrdinal().ToInternalValue()); } - } else { - app->SetUserDisplayModeDefault(user_display_modes[random.next_uint(3)]); + + app->SetSyncProto(std::move(sync_proto)); } app->SetLastBadgingTime(random.next_time()); @@ -806,12 +827,19 @@ app->SetWindowControlsOverlayEnabled(false); - WebApp::SyncFallbackData sync_fallback_data; - sync_fallback_data.name = "Sync" + name; - sync_fallback_data.theme_color = synced_theme_color; - sync_fallback_data.scope = app->scope(); - sync_fallback_data.icon_infos = app->manifest_icons(); - app->SetSyncFallbackData(std::move(sync_fallback_data)); + { + // Copy proto, retaining existing fields (including unknown fields). + sync_pb::WebAppSpecifics sync_proto = app->sync_proto(); + sync_proto.set_name("Sync" + name); + if (synced_theme_color.has_value()) { + sync_proto.set_theme_color(synced_theme_color.value()); + } + sync_proto.set_scope(app->scope().spec()); + for (const apps::IconInfo& icon_info : app->manifest_icons()) { + *(sync_proto.add_icon_infos()) = AppIconInfoToSyncProto(icon_info); + } + app->SetSyncProto(std::move(sync_proto)); + } if (random.next_bool()) { app->SetLaunchHandler(
diff --git a/chrome/browser/web_applications/user_display_mode.cc b/chrome/browser/web_applications/user_display_mode.cc index 92b39f1..7aa9ede 100644 --- a/chrome/browser/web_applications/user_display_mode.cc +++ b/chrome/browser/web_applications/user_display_mode.cc
@@ -37,22 +37,48 @@ } } -mojom::UserDisplayMode ResolvePlatformSpecificUserDisplayMode( +sync_pb::WebAppSpecifics::UserDisplayMode +ResolvePlatformSpecificUserDisplayMode( const sync_pb::WebAppSpecifics& sync_proto) { if (!base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { - return ToMojomUserDisplayMode(sync_proto.user_display_mode_default()); + return sync_proto.user_display_mode_default(); } - sync_pb::WebAppSpecifics_UserDisplayMode user_display_mode; + sync_pb::WebAppSpecifics_UserDisplayMode resolved_default_udm = + sync_proto.has_user_display_mode_default() + ? sync_proto.user_display_mode_default() + : sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE; #if BUILDFLAG(IS_CHROMEOS) - user_display_mode = sync_proto.has_user_display_mode_cros() - ? sync_proto.user_display_mode_cros() - : sync_proto.user_display_mode_default(); + return sync_proto.has_user_display_mode_cros() + ? sync_proto.user_display_mode_cros() + : resolved_default_udm; #else - // Defaults to UNSPECIFIED, which will be converted to kStandalone. - user_display_mode = sync_proto.user_display_mode_default(); + return resolved_default_udm; #endif // BUILDFLAG(IS_CHROMEOS) - return ToMojomUserDisplayMode(user_display_mode); +} + +void SetPlatformSpecificUserDisplayMode( + sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode, + sync_pb::WebAppSpecifics* sync_proto) { + if (!base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { + sync_proto->set_user_display_mode_default(user_display_mode); + return; + } + +#if BUILDFLAG(IS_CHROMEOS) + sync_proto->set_user_display_mode_cros(user_display_mode); +#else + sync_proto->set_user_display_mode_default(user_display_mode); +#endif // BUILDFLAG(IS_CHROMEOS) +} + +bool HasCurrentPlatformUserDisplayMode( + const sync_pb::WebAppSpecifics& sync_proto) { +#if BUILDFLAG(IS_CHROMEOS) + return sync_proto.has_user_display_mode_cros(); +#else + return sync_proto.has_user_display_mode_default(); +#endif // BUILDFLAG(IS_CHROMEOS) } } // namespace web_app
diff --git a/chrome/browser/web_applications/user_display_mode.h b/chrome/browser/web_applications/user_display_mode.h index fdea46b..c0ea5c4 100644 --- a/chrome/browser/web_applications/user_display_mode.h +++ b/chrome/browser/web_applications/user_display_mode.h
@@ -16,11 +16,23 @@ mojom::UserDisplayMode ToMojomUserDisplayMode( sync_pb::WebAppSpecifics::UserDisplayMode display_mode); -// Get the platform-specific UserDisplayMode field in the `sync_proto` based on -// the current platform (CrOS or non-CrOS), falling back to the other platform's -// field if unavailable. At least one platform's UserDisplayMode field must be -// populated. -mojom::UserDisplayMode ResolvePlatformSpecificUserDisplayMode( +// Returns the platform-specific UserDisplayMode field in `sync_proto`. +// If the current-platform's field is unset, falls back to the default field. If +// the default field is unset, falls back to Standalone. +sync_pb::WebAppSpecifics::UserDisplayMode +ResolvePlatformSpecificUserDisplayMode( + const sync_pb::WebAppSpecifics& sync_proto); + +// Set `user_display_mode` onto the platform-specific UserDisplayMode field in +// the `sync_proto` based on the current platform (CrOS or default). +void SetPlatformSpecificUserDisplayMode( + sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode, + sync_pb::WebAppSpecifics* sync_proto); + +// Return whether `sync_proto` has a UserDisplayMode set for the current +// platform. May be false for not-yet-migrated apps loaded from the database, or +// incoming sync data from another platform. +bool HasCurrentPlatformUserDisplayMode( const sync_pb::WebAppSpecifics& sync_proto); } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index 04f6ca8..13e4fdb 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc
@@ -27,11 +27,15 @@ #include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h" #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h" #include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h" +#include "chrome/browser/web_applications/user_display_mode.h" #include "chrome/browser/web_applications/web_app_chromeos_data.h" #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/browser/web_applications/web_app_helpers.h" +#include "chrome/browser/web_applications/web_app_proto_utils.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "components/sync/base/time.h" +#include "components/sync/protocol/proto_value_conversions.h" +#include "components/sync/protocol/web_app_specifics.pb.h" #include "components/webapps/browser/installable/installable_metrics.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/public/common/manifest/manifest_util.h" @@ -443,6 +447,11 @@ .IsSameOriginWith(url::Origin::Create(start_url))) << manifest_id().spec() << " " << start_url.spec(); start_url_ = start_url; + + // Ensure sync proto is initialized and remains consistent. Logic in + // `SetSyncProto` will populate an unset `start_url` on the proto. + sync_proto_.clear_start_url(); + SetSyncProto(sync_proto_); } void WebApp::SetScope(const GURL& scope) { @@ -474,26 +483,9 @@ } void WebApp::SetUserDisplayMode(mojom::UserDisplayMode user_display_mode) { - if (!base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { - user_display_mode_default_ = user_display_mode; - return; - } - -#if BUILDFLAG(IS_CHROMEOS) - user_display_mode_cros_ = user_display_mode; -#else - user_display_mode_default_ = user_display_mode; -#endif // BUILDFLAG(IS_CHROMEOS) -} - -void WebApp::SetUserDisplayModeCrOS( - mojom::UserDisplayMode user_display_mode_cros) { - user_display_mode_cros_ = user_display_mode_cros; -} - -void WebApp::SetUserDisplayModeDefault( - mojom::UserDisplayMode user_display_mode_default) { - user_display_mode_default_ = user_display_mode_default; + sync_pb::WebAppSpecifics_UserDisplayMode sync_udm = + ToWebAppSpecificsUserDisplayMode(user_display_mode); + SetPlatformSpecificUserDisplayMode(sync_udm, &sync_proto_); } void WebApp::SetDisplayModeOverride( @@ -501,14 +493,6 @@ display_mode_override_ = std::move(display_mode_override); } -void WebApp::SetUserPageOrdinal(syncer::StringOrdinal page_ordinal) { - user_page_ordinal_ = std::move(page_ordinal); -} - -void WebApp::SetUserLaunchOrdinal(syncer::StringOrdinal launch_ordinal) { - user_launch_ordinal_ = std::move(launch_ordinal); -} - void WebApp::SetWebAppChromeOsData( std::optional<WebAppChromeOsData> chromeos_data) { chromeos_data_ = std::move(chromeos_data); @@ -640,8 +624,51 @@ run_on_os_login_os_integration_state_ = state; } -void WebApp::SetSyncFallbackData(SyncFallbackData sync_fallback_data) { - sync_fallback_data_ = std::move(sync_fallback_data); +void WebApp::SetSyncProto(sync_pb::WebAppSpecifics sync_proto) { + // Sync data must never be set on an app with mismatching start_url. + if (!start_url().is_empty()) { + CHECK(start_url().is_valid(), base::NotFatalUntil::M126); + if (sync_proto.has_start_url()) { + CHECK_EQ(sync_proto.start_url(), start_url().spec(), + base::NotFatalUntil::M126); + } else { + sync_proto.set_start_url(start_url().spec()); + } + } + + // Sync data must never be set on an app with mismatching manifest_id. + CHECK(manifest_id().is_valid(), base::NotFatalUntil::M126); + // The relative id does not include the initial '/' character. + std::string relative_manifest_id_path = manifest_id().PathForRequest(); + if (relative_manifest_id_path.starts_with("/")) { + relative_manifest_id_path = relative_manifest_id_path.substr(1); + } + if (sync_proto.has_relative_manifest_id()) { + CHECK_EQ(sync_proto.relative_manifest_id(), relative_manifest_id_path, + base::NotFatalUntil::M126); + } else { + sync_proto.set_relative_manifest_id(relative_manifest_id_path); + } + + // Clear any invalid less-important fields. + if (sync_proto.has_scope() && !GURL(sync_proto.scope()).is_valid()) { + DLOG(ERROR) << "SetSyncProto: scope has invalid url: " + << sync_proto.scope(); + sync_proto.clear_scope(); + } + if (!ParseAppIconInfos("SetSyncProto", sync_proto.icon_infos()).has_value()) { + sync_proto.clear_icon_infos(); + } + if (sync_proto.has_user_launch_ordinal() && + !syncer::StringOrdinal(sync_proto.user_launch_ordinal()).IsValid()) { + sync_proto.clear_user_launch_ordinal(); + } + if (sync_proto.has_user_page_ordinal() && + !syncer::StringOrdinal(sync_proto.user_page_ordinal()).IsValid()) { + sync_proto.clear_user_page_ordinal(); + } + + sync_proto_ = std::move(sync_proto); } void WebApp::SetCaptureLinks(blink::mojom::CaptureLinks capture_links) { @@ -664,6 +691,11 @@ .IsSameOriginWith(url::Origin::Create(manifest_id))) << start_url_.spec() << " vs " << manifest_id.spec(); manifest_id_ = manifest_id; + + // Ensure sync proto is initialized and remains consistent. Logic in + // `SetSyncProto` will populate an unset `relative_manifest_id` on the proto. + sync_proto_.clear_relative_manifest_id(); + SetSyncProto(sync_proto_); } void WebApp::SetWindowControlsOverlayEnabled(bool enabled) { @@ -810,31 +842,6 @@ return base::Value(std::move(root)); } -WebApp::SyncFallbackData::SyncFallbackData() = default; - -WebApp::SyncFallbackData::~SyncFallbackData() = default; - -WebApp::SyncFallbackData::SyncFallbackData( - const SyncFallbackData& sync_fallback_data) = default; - -WebApp::SyncFallbackData::SyncFallbackData( - SyncFallbackData&& sync_fallback_data) noexcept = default; - -WebApp::SyncFallbackData& WebApp::SyncFallbackData::operator=( - SyncFallbackData&& sync_fallback_data) = default; - -base::Value WebApp::SyncFallbackData::AsDebugValue() const { - base::Value::Dict root; - root.Set("name", name); - root.Set("theme_color", ColorToString(theme_color)); - root.Set("scope", scope.spec()); - base::Value::List manifest_icons_json; - for (const apps::IconInfo& icon_info : icon_infos) - manifest_icons_json.Append(icon_info.AsDebugValue()); - root.Set("manifest_icons", std::move(manifest_icons_json)); - return base::Value(std::move(root)); -} - WebApp::ExternalManagementConfig::ExternalManagementConfig() = default; WebApp::ExternalManagementConfig::ExternalManagementConfig( bool is_placeholder, @@ -971,11 +978,7 @@ app.background_color_, app.dark_mode_background_color_, app.display_mode_, - app.user_display_mode_cros_, - app.user_display_mode_default_, app.display_mode_override_, - app.user_page_ordinal_, - app.user_launch_ordinal_, app.chromeos_data_, app.is_locally_installed_, app.is_from_sync_and_pending_installation_, @@ -1003,7 +1006,7 @@ app.manifest_update_time_, app.run_on_os_login_mode_, app.run_on_os_login_os_integration_state_, - app.sync_fallback_data_, + app.sync_proto_, app.capture_links_, app.manifest_url_, app.manifest_id_, @@ -1209,7 +1212,7 @@ root.Set("start_url", base::ToString(start_url_)); - root.Set("sync_fallback_data", sync_fallback_data_.AsDebugValue()); + root.Set("sync_proto", syncer::WebAppSpecificsToValue(sync_proto_)); root.Set("theme_color", ColorToString(theme_color_)); @@ -1222,16 +1225,6 @@ root.Set("scope_extensions_validated", ConvertDebugValueList(validated_scope_extensions_)); - root.Set("user_display_mode_cros", - OptionalToStringValue(user_display_mode_cros_)); - - root.Set("user_display_mode_default", - OptionalToStringValue(user_display_mode_default_)); - - root.Set("user_launch_ordinal", user_launch_ordinal_.ToDebugString()); - - root.Set("user_page_ordinal", user_page_ordinal_.ToDebugString()); - root.Set("window_controls_overlay_enabled", window_controls_overlay_enabled_); root.Set("tab_strip", OptTabStripToDebugValue(tab_strip_)); @@ -1277,19 +1270,6 @@ return out << app.AsDebugValue(); } -bool operator==(const WebApp::SyncFallbackData& sync_fallback_data1, - const WebApp::SyncFallbackData& sync_fallback_data2) { - return std::tie(sync_fallback_data1.name, sync_fallback_data1.theme_color, - sync_fallback_data1.scope, sync_fallback_data1.icon_infos) == - std::tie(sync_fallback_data2.name, sync_fallback_data2.theme_color, - sync_fallback_data2.scope, sync_fallback_data2.icon_infos); -} - -bool operator!=(const WebApp::SyncFallbackData& sync_fallback_data1, - const WebApp::SyncFallbackData& sync_fallback_data2) { - return !(sync_fallback_data1 == sync_fallback_data2); -} - std::ostream& operator<<( std::ostream& out, const WebApp::ExternalManagementConfig& management_config) { @@ -1343,3 +1323,17 @@ } } // namespace web_app + +namespace sync_pb { + +bool operator==(const WebAppSpecifics& sync_proto1, + const WebAppSpecifics& sync_proto2) { + return sync_proto1.SerializeAsString() == sync_proto2.SerializeAsString(); +} + +bool operator!=(const WebAppSpecifics& sync_proto1, + const WebAppSpecifics& sync_proto2) { + return !(sync_proto1 == sync_proto2); +} + +} // namespace sync_pb
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index 57431ae..ac7599c 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -27,6 +27,7 @@ #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h" #include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h" #include "chrome/browser/web_applications/scope_extension_info.h" +#include "chrome/browser/web_applications/user_display_mode.h" #include "chrome/browser/web_applications/web_app_chromeos_data.h" #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/browser/web_applications/web_app_install_info.h" @@ -36,6 +37,7 @@ #include "components/services/app_service/public/cpp/share_target.h" #include "components/services/app_service/public/cpp/url_handler_info.h" #include "components/sync/model/string_ordinal.h" +#include "components/sync/protocol/web_app_specifics.pb.h" #include "components/webapps/common/web_app_id.h" #include "third_party/blink/public/common/manifest/manifest.h" #include "third_party/blink/public/common/permissions_policy/permissions_policy_declaration.h" @@ -100,37 +102,20 @@ DisplayMode display_mode() const { return display_mode_; } - std::optional<mojom::UserDisplayMode> user_display_mode() const { - if (!base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { - return user_display_mode_default_; - } - -#if BUILDFLAG(IS_CHROMEOS) - CHECK(user_display_mode_cros_.has_value(), base::NotFatalUntil::M125); - return user_display_mode_cros_; -#else - CHECK(user_display_mode_default_.has_value(), base::NotFatalUntil::M125); - return user_display_mode_default_; -#endif // BUILDFLAG(IS_CHROMEOS) - } - - // Exposed for database/sync layer only. Elsewhere use `user_display_mode()`. - std::optional<mojom::UserDisplayMode> user_display_mode_cros() const { - return user_display_mode_cros_; - } - - // Exposed for database/sync layer only. Elsewhere use `user_display_mode()`. - std::optional<mojom::UserDisplayMode> user_display_mode_default() const { - return user_display_mode_default_; + mojom::UserDisplayMode user_display_mode() const { + return ToMojomUserDisplayMode( + ResolvePlatformSpecificUserDisplayMode(sync_proto())); } const std::vector<DisplayMode>& display_mode_override() const { return display_mode_override_; } - syncer::StringOrdinal user_page_ordinal() const { return user_page_ordinal_; } + syncer::StringOrdinal user_page_ordinal() const { + return syncer::StringOrdinal(sync_proto().user_page_ordinal()); + } syncer::StringOrdinal user_launch_ordinal() const { - return user_launch_ordinal_; + return syncer::StringOrdinal(sync_proto().user_launch_ordinal()); } const std::optional<WebAppChromeOsData>& chromeos_data() const { @@ -258,25 +243,14 @@ // While local |name| and |theme_color| may vary from device to device, the // synced copies of these fields are replicated to all devices. The synced // copies are read by a device to generate a placeholder icon (if needed). Any - // device may write new values to |sync_fallback_data|, random last update + // device may write new values to |sync_proto|, random last update // wins. - struct SyncFallbackData { - SyncFallbackData(); - ~SyncFallbackData(); - // Copyable and move-assignable to support Copy-on-Write with Commit. - SyncFallbackData(const SyncFallbackData& sync_fallback_data); - SyncFallbackData(SyncFallbackData&& sync_fallback_data) noexcept; - SyncFallbackData& operator=(SyncFallbackData&& sync_fallback_data); - - base::Value AsDebugValue() const; - - std::string name; - std::optional<SkColor> theme_color; - GURL scope; - std::vector<apps::IconInfo> icon_infos; - }; - const SyncFallbackData& sync_fallback_data() const { - return sync_fallback_data_; + const sync_pb::WebAppSpecifics& sync_proto() const { + // Ensure the sync proto has been initialized. + CHECK(sync_proto_.has_start_url(), base::NotFatalUntil::M126); + CHECK(GURL(sync_proto_.start_url()).is_valid(), base::NotFatalUntil::M126); + CHECK(sync_proto_.has_relative_manifest_id(), base::NotFatalUntil::M126); + return sync_proto_; } // Represents the "shortcuts" field in the manifest. @@ -488,16 +462,7 @@ void SetDisplayMode(DisplayMode display_mode); // Sets the UserDisplayMode for the current platform (CrOS or default). void SetUserDisplayMode(mojom::UserDisplayMode user_display_mode); - // Sets the UserDisplayMode for CrOS (exists on all platforms to maintain - // sync information). - void SetUserDisplayModeCrOS(mojom::UserDisplayMode user_display_mode_cros); - // Sets the non-platform-specific UserDisplayMode value (exists on all - // platforms to maintain sync information). - void SetUserDisplayModeDefault( - mojom::UserDisplayMode user_display_mode_default); void SetDisplayModeOverride(std::vector<DisplayMode> display_mode_override); - void SetUserPageOrdinal(syncer::StringOrdinal page_ordinal); - void SetUserLaunchOrdinal(syncer::StringOrdinal launch_ordinal); void SetWebAppChromeOsData(std::optional<WebAppChromeOsData> chromeos_data); void SetIsLocallyInstalled(bool is_locally_installed); void SetIsFromSyncAndPendingInstallation( @@ -535,7 +500,7 @@ void SetManifestUpdateTime(const base::Time& time); void SetRunOnOsLoginMode(RunOnOsLoginMode mode); void SetRunOnOsLoginOsIntegrationState(RunOnOsLoginMode os_integration_state); - void SetSyncFallbackData(SyncFallbackData sync_fallback_data); + void SetSyncProto(sync_pb::WebAppSpecifics sync_proto); void SetCaptureLinks(blink::mojom::CaptureLinks capture_links); void SetManifestUrl(const GURL& manifest_url); void SetManifestId(const webapps::ManifestId& manifest_id); @@ -618,11 +583,7 @@ std::optional<SkColor> background_color_; std::optional<SkColor> dark_mode_background_color_; DisplayMode display_mode_ = DisplayMode::kUndefined; - std::optional<mojom::UserDisplayMode> user_display_mode_cros_; - std::optional<mojom::UserDisplayMode> user_display_mode_default_; std::vector<DisplayMode> display_mode_override_; - syncer::StringOrdinal user_page_ordinal_; - syncer::StringOrdinal user_launch_ordinal_; std::optional<WebAppChromeOsData> chromeos_data_; bool is_locally_installed_ = false; bool is_from_sync_and_pending_installation_ = false; @@ -660,7 +621,7 @@ // TODO(crbug.com/1401125): Remove after all OS Integration sub managers have // been implemented and Synchronize() is running fine. std::optional<RunOnOsLoginMode> run_on_os_login_os_integration_state_; - SyncFallbackData sync_fallback_data_; + sync_pb::WebAppSpecifics sync_proto_; blink::mojom::CaptureLinks capture_links_ = blink::mojom::CaptureLinks::kUndefined; ClientData client_data_; @@ -719,8 +680,6 @@ // - WebAppDatabase::CreateWebApp() // - WebAppDatabase::CreateWebAppProto() // - CreateRandomWebApp() - // - WebAppTest.EmptyAppAsDebugValue - // - WebAppTest.SampleAppAsDebugValue // - web_app.proto // If parsed from manifest, also add to: // - GetManifestDataChanges() inside manifest_update_utils.h @@ -732,11 +691,6 @@ // For logging and debug purposes. std::ostream& operator<<(std::ostream& out, const WebApp& app); -bool operator==(const WebApp::SyncFallbackData& sync_fallback_data1, - const WebApp::SyncFallbackData& sync_fallback_data2); -bool operator!=(const WebApp::SyncFallbackData& sync_fallback_data1, - const WebApp::SyncFallbackData& sync_fallback_data2); - std::ostream& operator<<( std::ostream& out, const WebApp::ExternalManagementConfig& management_config); @@ -761,4 +715,11 @@ } // namespace web_app +namespace sync_pb { +bool operator==(const WebAppSpecifics& sync_proto1, + const WebAppSpecifics& sync_proto2); +bool operator!=(const WebAppSpecifics& sync_proto1, + const WebAppSpecifics& sync_proto2); +} // namespace sync_pb + #endif // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_H_
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc index fc25a0f06..41bfb68 100644 --- a/chrome/browser/web_applications/web_app_command_scheduler.cc +++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -65,6 +65,7 @@ #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h" #include "chrome/browser/web_applications/web_app_command_manager.h" #include "chrome/browser/web_applications/web_app_constants.h" +#include "chrome/browser/web_applications/web_app_proto_utils.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_sync_bridge.h" #include "chrome/browser/web_applications/web_app_ui_manager.h" @@ -364,11 +365,17 @@ OnceInstallCallback callback, const base::Location& location) { DCHECK(web_app.is_from_sync_and_pending_installation()); + std::vector<apps::IconInfo> icon_infos = + ParseAppIconInfos("InstallFromSync", web_app.sync_proto().icon_infos()) + .value_or(std::vector<apps::IconInfo>()); + std::optional<SkColor> theme_color; + if (web_app.sync_proto().has_theme_color()) { + theme_color = web_app.sync_proto().theme_color(); + } InstallFromSyncCommand::Params params = InstallFromSyncCommand::Params( web_app.app_id(), web_app.manifest_id(), web_app.start_url(), - web_app.sync_fallback_data().name, web_app.sync_fallback_data().scope, - web_app.sync_fallback_data().theme_color, web_app.user_display_mode(), - web_app.sync_fallback_data().icon_infos); + web_app.sync_proto().name(), GURL(web_app.sync_proto().scope()), + theme_color, web_app.user_display_mode(), icon_infos); provider_->command_manager().ScheduleCommand( std::make_unique<InstallFromSyncCommand>(&profile_.get(), params, std::move(callback)),
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc index f664aa79..576bafd 100644 --- a/chrome/browser/web_applications/web_app_database.cc +++ b/chrome/browser/web_applications/web_app_database.cc
@@ -481,7 +481,7 @@ DCHECK(web_app.manifest_id().is_valid()); // Set sync data to sync proto. - *(local_data->mutable_sync_data()) = WebAppToSyncProto(web_app); + *(local_data->mutable_sync_data()) = web_app.sync_proto(); local_data->set_name(web_app.untranslated_name()); @@ -1015,35 +1015,7 @@ return nullptr; } - // Store both platform-specific UserDisplayModes from sync_data if available. - if (base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { - if (sync_data.has_user_display_mode_cros()) { - web_app->SetUserDisplayModeCrOS( - ToMojomUserDisplayMode(sync_data.user_display_mode_cros())); - } - if (sync_data.has_user_display_mode_default()) { - web_app->SetUserDisplayModeDefault( - ToMojomUserDisplayMode(sync_data.user_display_mode_default())); - } - // Note: migration runs after database opened to ensure the current platform - // always has a UserDisplayMode set (see - // `EnsureAppsHaveUserDisplayModeForCurrentPlatform`). - } else { - web_app->SetUserDisplayModeDefault( - ToMojomUserDisplayMode(sync_data.user_display_mode_default())); - } - - // Ordinals used for chrome://apps page. - syncer::StringOrdinal page_ordinal = - syncer::StringOrdinal(sync_data.user_page_ordinal()); - if (!page_ordinal.IsValid()) - page_ordinal = syncer::StringOrdinal(); - syncer::StringOrdinal launch_ordinal = - syncer::StringOrdinal(sync_data.user_launch_ordinal()); - if (!launch_ordinal.IsValid()) - launch_ordinal = syncer::StringOrdinal(); - web_app->SetUserPageOrdinal(page_ordinal); - web_app->SetUserLaunchOrdinal(launch_ordinal); + web_app->SetSyncProto(sync_data); if (!local_data.has_is_locally_installed()) { DLOG(ERROR) << "WebApp proto parse error: no is_locally_installed field"; @@ -1168,14 +1140,6 @@ syncer::ProtoTimeToTime(local_data.first_install_time())); } - std::optional<WebApp::SyncFallbackData> parsed_sync_fallback_data = - ParseSyncFallbackDataStruct(sync_data); - if (!parsed_sync_fallback_data.has_value()) { - // ParseSyncFallbackDataStruct() reports any errors. - return nullptr; - } - web_app->SetSyncFallbackData(std::move(parsed_sync_fallback_data.value())); - std::optional<std::vector<apps::IconInfo>> parsed_manifest_icons = ParseAppIconInfos("WebApp", local_data.manifest_icons()); if (!parsed_manifest_icons) { @@ -1883,22 +1847,6 @@ } } -DisplayMode ToMojomDisplayMode( - ::sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode) { - switch (user_display_mode) { - case ::sync_pb::WebAppSpecifics::BROWSER: - return DisplayMode::kBrowser; - case ::sync_pb::WebAppSpecifics::TABBED: - return DisplayMode::kTabbed; - // New display modes will most likely be of the window variety than the - // browser tab variety so default to windowed if it's an enum value we don't - // know about. - case ::sync_pb::WebAppSpecifics::UNSPECIFIED: - case ::sync_pb::WebAppSpecifics::STANDALONE: - return DisplayMode::kStandalone; - } -} - WebAppProto::DisplayMode ToWebAppProtoDisplayMode(DisplayMode display_mode) { switch (display_mode) { case DisplayMode::kBrowser:
diff --git a/chrome/browser/web_applications/web_app_database.h b/chrome/browser/web_applications/web_app_database.h index 29ebbb4b..e097e8b 100644 --- a/chrome/browser/web_applications/web_app_database.h +++ b/chrome/browser/web_applications/web_app_database.h
@@ -99,9 +99,6 @@ DisplayMode ToMojomDisplayMode(WebAppProto::DisplayMode display_mode); -DisplayMode ToMojomDisplayMode( - ::sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode); - WebAppProto::DisplayMode ToWebAppProtoDisplayMode(DisplayMode display_mode); } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_database_unittest.cc b/chrome/browser/web_applications/web_app_database_unittest.cc index ec2a96d..43b7a8c 100644 --- a/chrome/browser/web_applications/web_app_database_unittest.cc +++ b/chrome/browser/web_applications/web_app_database_unittest.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/web_applications/test/fake_web_app_provider.h" #include "chrome/browser/web_applications/test/web_app_test.h" #include "chrome/browser/web_applications/test/web_app_test_utils.h" +#include "chrome/browser/web_applications/user_display_mode.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_command_manager.h" #include "chrome/browser/web_applications/web_app_constants.h" @@ -141,22 +142,24 @@ void EnsureHasUserDisplayModeForCurrentPlatform(WebApp& app) { if (!base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { - DCHECK(app.user_display_mode_default()); + ASSERT_TRUE(app.sync_proto().has_user_display_mode_default()); return; } // Avoid using `WebApp::user_display_mode` because it DCHECKs for a valid // UDM. #if BUILDFLAG(IS_CHROMEOS) - if (app.user_display_mode_cros()) { + if (app.sync_proto().has_user_display_mode_cros()) { return; } #else - if (app.user_display_mode_default()) { + if (app.sync_proto().has_user_display_mode_default()) { return; } #endif // BUILDFLAG(IS_CHROMEOS) - app.SetUserDisplayMode(app.user_display_mode_default().value_or( - mojom::UserDisplayMode::kStandalone)); + app.SetUserDisplayMode(ToMojomUserDisplayMode( + app.sync_proto().has_user_display_mode_default() + ? app.sync_proto().user_display_mode_default() + : sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE)); } protected: @@ -403,23 +406,20 @@ if (!base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { // Default to standalone if we don't have a platform-specific value and the // flag is turned off. Safer than trying to migrate back. - EXPECT_EQ(app->user_display_mode().value(), - mojom::UserDisplayMode::kStandalone); - EXPECT_EQ(new_proto->sync_data().user_display_mode_default(), - sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE); - EXPECT_FALSE(new_proto->sync_data().has_user_display_mode_cros()); + EXPECT_EQ(app->user_display_mode(), mojom::UserDisplayMode::kStandalone); + // Proto values are preserved. + EXPECT_EQ(new_proto->sync_data().user_display_mode_cros(), + sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER); + EXPECT_FALSE(new_proto->sync_data().has_user_display_mode_default()); return; } - // Regardless of platform, the current platform's UDM should be set. - EXPECT_TRUE(app->user_display_mode().has_value()); - #if BUILDFLAG(IS_CHROMEOS) - // On CrOS, the non-CrOS field should remain absent. + // On CrOS, the default field should remain absent. EXPECT_EQ(new_proto->sync_data().user_display_mode_cros(), sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER); EXPECT_FALSE(new_proto->sync_data().has_user_display_mode_default()); - EXPECT_EQ(app->user_display_mode().value(), mojom::UserDisplayMode::kBrowser); + EXPECT_EQ(app->user_display_mode(), mojom::UserDisplayMode::kBrowser); #else // On non-CrOS, both platform's fields should now be populated. EXPECT_EQ(new_proto->sync_data().user_display_mode_cros(), @@ -428,8 +428,7 @@ // standalone. EXPECT_EQ(new_proto->sync_data().user_display_mode_default(), sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE); - EXPECT_EQ(app->user_display_mode().value(), - mojom::UserDisplayMode::kStandalone); + EXPECT_EQ(app->user_display_mode(), mojom::UserDisplayMode::kStandalone); #endif // BUILDFLAG(IS_CHROMEOS) } @@ -453,7 +452,7 @@ // Regardless of platform, the current platform's UDM should be set: the // default value should have been migrated in CrOS. - EXPECT_EQ(app->user_display_mode().value(), mojom::UserDisplayMode::kBrowser); + EXPECT_EQ(app->user_display_mode(), mojom::UserDisplayMode::kBrowser); std::unique_ptr<WebAppProto> new_proto = WebAppDatabase::CreateWebAppProto(*app); @@ -520,10 +519,10 @@ EXPECT_TRUE(app->downloaded_icon_sizes(IconPurpose::MONOCHROME).empty()); EXPECT_FALSE(app->is_generated_icon()); EXPECT_FALSE(app->is_from_sync_and_pending_installation()); - EXPECT_TRUE(app->sync_fallback_data().name.empty()); - EXPECT_FALSE(app->sync_fallback_data().theme_color.has_value()); - EXPECT_FALSE(app->sync_fallback_data().scope.is_valid()); - EXPECT_TRUE(app->sync_fallback_data().icon_infos.empty()); + EXPECT_FALSE(app->sync_proto().has_name()); + EXPECT_FALSE(app->sync_proto().has_theme_color()); + EXPECT_FALSE(app->sync_proto().has_scope()); + EXPECT_EQ(app->sync_proto().icon_infos_size(), 0); EXPECT_TRUE(app->file_handlers().empty()); EXPECT_FALSE(app->share_target().has_value()); EXPECT_TRUE(app->additional_search_terms().empty()); @@ -595,10 +594,10 @@ EXPECT_TRUE(app_copy->downloaded_icon_sizes(IconPurpose::MONOCHROME).empty()); EXPECT_FALSE(app_copy->is_generated_icon()); EXPECT_FALSE(app_copy->is_from_sync_and_pending_installation()); - EXPECT_TRUE(app_copy->sync_fallback_data().name.empty()); - EXPECT_FALSE(app_copy->sync_fallback_data().theme_color.has_value()); - EXPECT_FALSE(app_copy->sync_fallback_data().scope.is_valid()); - EXPECT_TRUE(app_copy->sync_fallback_data().icon_infos.empty()); + EXPECT_FALSE(app_copy->sync_proto().has_name()); + EXPECT_FALSE(app_copy->sync_proto().has_theme_color()); + EXPECT_FALSE(app_copy->sync_proto().has_scope()); + EXPECT_EQ(app_copy->sync_proto().icon_infos_size(), 0); EXPECT_TRUE(app_copy->file_handlers().empty()); EXPECT_FALSE(app_copy->share_target().has_value()); EXPECT_TRUE(app_copy->additional_search_terms().empty());
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc index e649dbe..bec03fa2 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.cc +++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -17,6 +17,8 @@ #include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" +#include "base/notreached.h" #include "base/strings/utf_string_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" @@ -54,6 +56,7 @@ #include "chrome/browser/web_applications/web_app_utils.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/sync/protocol/web_app_specifics.pb.h" #include "components/webapps/browser/uninstall_result_code.h" #include "components/webapps/common/web_app_id.h" #include "content/public/browser/browser_thread.h" @@ -133,7 +136,7 @@ } // Guaranteed by EnsureAppsHaveUserDisplayModeForCurrentPlatform(). - CHECK(web_app.user_display_mode_cros().has_value(), + CHECK(web_app.sync_proto().has_user_display_mode_cros(), base::NotFatalUntil::M125); // Don't mitigate installations from sync, this is only for installs that will @@ -148,22 +151,24 @@ } // Don't override existing default-platform value. - if (web_app.user_display_mode_default().has_value()) { + if (web_app.sync_proto().has_user_display_mode_default()) { return; } - switch (web_app.user_display_mode_cros().value()) { - case mojom::UserDisplayMode::kBrowser: + sync_pb::WebAppSpecifics sync_proto = web_app.sync_proto(); + + switch (web_app.sync_proto().user_display_mode_cros()) { + case sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER: if (!base::FeatureList::IsEnabled( kUserDisplayModeSyncBrowserMitigation)) { - break; + return; } // CrOS devices with kSeparateUserDisplayModeForCrOS disabled (including // pre-M122 devices) use the user_display_mode_default sync field instead // of user_display_mode_cros. If user_display_mode_default is ever unset // they will fallback to using kStandalone even if user_display_mode_cros - // is set to kBrowser. This mitigation esures user_display_mode_default + // is set to kBrowser. This mitigation ensures user_display_mode_default // is set to kBrowser for these devices. // Example user journey: // - Install web app as browser shortcut on post-M122 CrOS device. @@ -171,13 +176,14 @@ // - Check that it is synced as a browser shortcut. // TODO(b/321617981): Remove when there are sufficiently few pre-M122 CrOS // devices in circulation. - web_app.SetUserDisplayModeDefault(mojom::UserDisplayMode::kBrowser); + sync_proto.set_user_display_mode_default( + sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER); break; - case mojom::UserDisplayMode::kStandalone: { + case sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE: { if (!base::FeatureList::IsEnabled( kUserDisplayModeSyncStandaloneMitigation)) { - break; + return; } // Ensure standalone averse apps don't get defaulted to kStandalone on @@ -194,15 +200,21 @@ if (!is_standalone_averse_app) { break; } - web_app.SetUserDisplayModeDefault(mojom::UserDisplayMode::kBrowser); + sync_proto.set_user_display_mode_default( + sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER); break; } - case mojom::UserDisplayMode::kTabbed: + case sync_pb::WebAppSpecifics_UserDisplayMode_TABBED: // This can only be reached when kDesktopPWAsTabStripSettings is enabled, // this is only for testing and is planned to be removed. - break; + return; + case sync_pb::WebAppSpecifics_UserDisplayMode_UNSPECIFIED: + // Ignore unknown UserDisplayMode values. + return; } + + web_app.SetSyncProto(std::move(sync_proto)); } #endif // BUILDFLAG(IS_CHROMEOS) @@ -285,6 +297,15 @@ web_app = std::make_unique<WebApp>(*existing_web_app); } else { web_app = std::make_unique<WebApp>(app_id); + // Ensure `web_app` has a start_url and manifest_id set before other calls + // that depend on state being complete, eg. `WebApp::sync_proto()`. + web_app->SetStartUrl(web_app_info.start_url); + // TODO(b/280862254): CHECK that the manifest_id isn't empty after the + // no-arg `WebAppInstallInfo` constructor is removed. Currently, + // `SetStartUrl` sets a default manifest_id based on the start_url. + if (web_app_info.manifest_id.is_valid()) { + web_app->SetManifestId(web_app_info.manifest_id); + } } web_app->SetValidatedScopeExtensions(validated_scope_extensions);
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc index 78a6cc0..719ec12 100644 --- a/chrome/browser/web_applications/web_app_install_utils.cc +++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -29,6 +29,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_functions.h" +#include "base/not_fatal_until.h" #include "base/notreached.h" #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" @@ -48,6 +49,7 @@ #include "chrome/browser/web_applications/web_app_icon_generator.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/browser/web_applications/web_app_install_params.h" +#include "chrome/browser/web_applications/web_app_proto_utils.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "chrome/common/chrome_features.h" #include "components/services/app_service/public/cpp/file_handler.h" @@ -55,6 +57,7 @@ #include "components/services/app_service/public/cpp/protocol_handler_info.h" #include "components/services/app_service/public/cpp/share_target.h" #include "components/services/app_service/public/cpp/url_handler_info.h" +#include "components/sync/protocol/web_app_specifics.pb.h" #include "components/webapps/browser/banners/app_banner_settings_helper.h" #include "components/webapps/browser/installable/installable_evaluator.h" #include "components/webapps/browser/installable/installable_manager.h" @@ -1157,12 +1160,25 @@ SK_AlphaOPAQUE); web_app.SetDarkModeBackgroundColor(web_app_info.dark_mode_background_color); - WebApp::SyncFallbackData sync_fallback_data; - sync_fallback_data.name = base::UTF16ToUTF8(web_app_info.title); - sync_fallback_data.theme_color = web_app_info.theme_color; - sync_fallback_data.scope = web_app_info.scope; - sync_fallback_data.icon_infos = web_app_info.manifest_icons; - web_app.SetSyncFallbackData(std::move(sync_fallback_data)); + sync_pb::WebAppSpecifics sync_proto = web_app.sync_proto(); + // Sync proto has already been initialized by setting the start_url and/or + // manifest_id above. + CHECK(sync_proto.has_start_url(), base::NotFatalUntil::M126); + CHECK(sync_proto.has_relative_manifest_id(), base::NotFatalUntil::M126); + sync_proto.set_name(base::UTF16ToUTF8(web_app_info.title)); + sync_proto.clear_theme_color(); + if (web_app_info.theme_color.has_value()) { + sync_proto.set_theme_color(web_app_info.theme_color.value()); + } + sync_proto.clear_scope(); + if (web_app_info.scope.is_valid()) { + sync_proto.set_scope(web_app_info.scope.spec()); + } + sync_proto.clear_icon_infos(); + for (const apps::IconInfo& icon_info : web_app_info.manifest_icons) { + *(sync_proto.add_icon_infos()) = AppIconInfoToSyncProto(icon_info); + } + web_app.SetSyncProto(std::move(sync_proto)); if (!skip_icons_on_download_failure) { SetWebAppProductIconFields(web_app_info, web_app);
diff --git a/chrome/browser/web_applications/web_app_proto_utils.cc b/chrome/browser/web_applications/web_app_proto_utils.cc index d8384ae..2c0347b 100644 --- a/chrome/browser/web_applications/web_app_proto_utils.cc +++ b/chrome/browser/web_applications/web_app_proto_utils.cc
@@ -229,55 +229,6 @@ return manifest_icons; } -sync_pb::WebAppSpecifics WebAppToSyncProto(const WebApp& app) { - CHECK(app.start_url().is_valid(), base::NotFatalUntil::M124); - CHECK(app.manifest_id().is_valid(), base::NotFatalUntil::M124); - - sync_pb::WebAppSpecifics sync_proto; - // The relative id does not include the initial '/' character. - std::string relative_manifest_id_path = app.manifest_id().PathForRequest(); - if (relative_manifest_id_path.starts_with("/")) { - relative_manifest_id_path = relative_manifest_id_path.substr(1); - } - sync_proto.set_relative_manifest_id(relative_manifest_id_path); - sync_proto.set_start_url(app.start_url().spec()); - - CHECK(app.user_display_mode_cros() || app.user_display_mode_default(), - base::NotFatalUntil::M125); - - if (base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS) || - base::FeatureList::IsEnabled(kSyncOnlySeparateUserDisplayModeForCrOS)) { - if (app.user_display_mode_cros()) { - sync_proto.set_user_display_mode_cros(ToWebAppSpecificsUserDisplayMode( - app.user_display_mode_cros().value())); - } - if (app.user_display_mode_default()) { - sync_proto.set_user_display_mode_default(ToWebAppSpecificsUserDisplayMode( - app.user_display_mode_default().value())); - } - } else { - sync_proto.set_user_display_mode_default(ToWebAppSpecificsUserDisplayMode( - app.user_display_mode_default().value())); - } - - sync_proto.set_name(app.sync_fallback_data().name); - if (app.sync_fallback_data().theme_color.has_value()) - sync_proto.set_theme_color(app.sync_fallback_data().theme_color.value()); - if (app.user_page_ordinal().IsValid()) { - sync_proto.set_user_page_ordinal(app.user_page_ordinal().ToInternalValue()); - } - if (app.user_launch_ordinal().IsValid()) { - sync_proto.set_user_launch_ordinal( - app.user_launch_ordinal().ToInternalValue()); - } - if (app.sync_fallback_data().scope.is_valid()) - sync_proto.set_scope(app.sync_fallback_data().scope.spec()); - for (const apps::IconInfo& icon_info : app.sync_fallback_data().icon_infos) { - *(sync_proto.add_icon_infos()) = AppIconInfoToSyncProto(icon_info); - } - return sync_proto; -} - sync_pb::WebAppIconInfo AppIconInfoToSyncProto( const apps::IconInfo& icon_info) { sync_pb::WebAppIconInfo icon_info_proto; @@ -314,34 +265,6 @@ return image_resource_proto; } -std::optional<WebApp::SyncFallbackData> ParseSyncFallbackDataStruct( - const sync_pb::WebAppSpecifics& sync_proto) { - WebApp::SyncFallbackData parsed_sync_fallback_data; - - parsed_sync_fallback_data.name = sync_proto.name(); - - if (sync_proto.has_theme_color()) - parsed_sync_fallback_data.theme_color = sync_proto.theme_color(); - - if (sync_proto.has_scope()) { - parsed_sync_fallback_data.scope = GURL(sync_proto.scope()); - if (!parsed_sync_fallback_data.scope.is_valid()) { - DLOG(ERROR) << "WebAppSpecifics scope has invalid url: " - << parsed_sync_fallback_data.scope.possibly_invalid_spec(); - return std::nullopt; - } - } - - std::optional<std::vector<apps::IconInfo>> parsed_icon_infos = - ParseAppIconInfos("WebAppSpecifics", sync_proto.icon_infos()); - if (!parsed_icon_infos) - return std::nullopt; - - parsed_sync_fallback_data.icon_infos = std::move(parsed_icon_infos.value()); - - return parsed_sync_fallback_data; -} - RunOnOsLoginMode ToRunOnOsLoginMode(WebAppProto::RunOnOsLoginMode mode) { switch (mode) { case WebAppProto::MINIMIZED:
diff --git a/chrome/browser/web_applications/web_app_proto_utils.h b/chrome/browser/web_applications/web_app_proto_utils.h index be314946..9e3d66c 100644 --- a/chrome/browser/web_applications/web_app_proto_utils.h +++ b/chrome/browser/web_applications/web_app_proto_utils.h
@@ -38,9 +38,6 @@ ParseAppImageResource(const char* container_name_for_logging, const RepeatedImageResourceProto& manifest_icons_proto); -// Use the given |app| to populate a |WebAppSpecifics| sync proto. -sync_pb::WebAppSpecifics WebAppToSyncProto(const WebApp& app); - // Use the given |icon_info| to populate a |WebAppIconInfo| sync proto. sync_pb::WebAppIconInfo AppIconInfoToSyncProto(const apps::IconInfo& icon_info); @@ -48,9 +45,6 @@ content::proto::ImageResource AppImageResourceToProto( const blink::Manifest::ImageResource& image_resource); -std::optional<WebApp::SyncFallbackData> ParseSyncFallbackDataStruct( - const sync_pb::WebAppSpecifics& sync_proto); - RunOnOsLoginMode ToRunOnOsLoginMode(WebAppProto::RunOnOsLoginMode mode); WebAppProto::RunOnOsLoginMode ToWebAppProtoRunOnOsLoginMode(
diff --git a/chrome/browser/web_applications/web_app_proto_utils_unittest.cc b/chrome/browser/web_applications/web_app_proto_utils_unittest.cc index ed77d0908..7ebcf09f 100644 --- a/chrome/browser/web_applications/web_app_proto_utils_unittest.cc +++ b/chrome/browser/web_applications/web_app_proto_utils_unittest.cc
@@ -11,6 +11,8 @@ #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_registrar.h" +#include "components/sync/protocol/web_app_specifics.pb.h" +#include "components/webapps/common/web_app_id.h" #include "testing/gtest/include/gtest/gtest.h" namespace web_app { @@ -56,20 +58,29 @@ EXPECT_EQ(kAppName, sync_proto.name()); EXPECT_EQ(sync_pb::WebAppSpecifics::BROWSER, sync_proto.user_display_mode_default()); + ASSERT_EQ(1, sync_proto.icon_infos_size()); + EXPECT_EQ(kIconUrl, sync_proto.icon_infos(0).url()); + EXPECT_FALSE(sync_proto.icon_infos(0).has_purpose()); - // Check the fields were parsed into the web app struct. - std::optional<WebApp::SyncFallbackData> fallback_data = - ParseSyncFallbackDataStruct(sync_proto); - ASSERT_TRUE(fallback_data.has_value()); - EXPECT_EQ(kAppName, fallback_data->name); - ASSERT_EQ(1u, fallback_data->icon_infos.size()); - EXPECT_EQ(kIconUrl, fallback_data->icon_infos[0].url.spec()); + // Check the fields can be parsed into the IconInfo struct. + std::optional<std::vector<apps::IconInfo>> parsed_icon_infos = + ParseAppIconInfos("WebAppProtoUtilsTest", sync_proto.icon_infos()); + ASSERT_TRUE(parsed_icon_infos.has_value()); + ASSERT_EQ(1u, parsed_icon_infos.value().size()); + EXPECT_EQ(kIconUrl, parsed_icon_infos.value()[0].url); + // Missing `purpose` parsed as `kAny`. EXPECT_EQ(apps::IconInfo::Purpose::kAny, - fallback_data->icon_infos[0].purpose); + parsed_icon_infos.value()[0].purpose); + + // Check the proto can be stored on a web app struct. + WebApp web_app("app_id"); + web_app.SetStartUrl(GURL(kStartUrl)); + web_app.SetManifestId(webapps::ManifestId(kStartUrl)); + web_app.SetSyncProto(sync_proto); } // Test that a minimal M85 proto (ie. only fields that would always be set in -// M85) is correctly parsed to a WebApp::SyncFallbackData in the current +// M85) is correctly parsed to a apps::IconInfo in the current // Chromium version. TEST(WebAppProtoUtilsTest, M85SpecificsProtoToWebApp_Minimal) { // Set the minimal proto fields. @@ -78,18 +89,25 @@ sync_proto.set_name(kAppName); sync_proto.set_user_display_mode_default(sync_pb::WebAppSpecifics::BROWSER); - // Parse the proto. - std::optional<WebApp::SyncFallbackData> fallback_data = - ParseSyncFallbackDataStruct(sync_proto); + EXPECT_EQ(kAppName, sync_proto.name()); + + // Check the fields were parsed into the IconInfo struct. + std::optional<std::vector<apps::IconInfo>> parsed_icon_infos = + ParseAppIconInfos("WebAppProtoUtilsTest", sync_proto.icon_infos()); // Check the fields were parsed. - ASSERT_TRUE(fallback_data.has_value()); - EXPECT_EQ(kAppName, fallback_data->name); - ASSERT_EQ(0u, fallback_data->icon_infos.size()); + ASSERT_TRUE(parsed_icon_infos.has_value()); + ASSERT_EQ(0u, parsed_icon_infos->size()); + + // Check the proto can be stored on a web app struct. + WebApp web_app("app_id"); + web_app.SetStartUrl(GURL(kStartUrl)); + web_app.SetManifestId(webapps::ManifestId(kStartUrl)); + web_app.SetSyncProto(sync_proto); } // Test that a M85 proto with all fields populated is correctly parsed to a -// WebApp::SyncFallbackData in the current Chromium version. +// apps::IconInfo in the current Chromium version. TEST(WebAppProtoUtilsTest, M85SpecificsProtoToWebApp_FullyPopulated) { // Set all proto fields. sync_pb::WebAppSpecifics sync_proto; @@ -110,24 +128,104 @@ icon_info_2->set_size_in_px(kIconSizePx); icon_info_2->set_purpose(sync_pb::WebAppIconInfo_Purpose_MASKABLE); - // Parse the proto. - std::optional<WebApp::SyncFallbackData> fallback_data = - ParseSyncFallbackDataStruct(sync_proto); + // Check the fields can be parsed into the IconInfo struct. + std::optional<std::vector<apps::IconInfo>> icon_infos = + ParseAppIconInfos("WebAppProtoUtilsTest", sync_proto.icon_infos()); + ASSERT_TRUE(icon_infos.has_value()); + ASSERT_EQ(2u, icon_infos->size()); + EXPECT_EQ(kIconUrl, icon_infos.value()[0].url); + EXPECT_EQ(kIconSizePx, icon_infos.value()[0].square_size_px); + EXPECT_EQ(apps::IconInfo::Purpose::kAny, icon_infos.value()[0].purpose); + EXPECT_EQ(kIconUrl, icon_infos.value()[1].url); + EXPECT_EQ(kIconSizePx, icon_infos.value()[1].square_size_px); + EXPECT_EQ(apps::IconInfo::Purpose::kMaskable, icon_infos.value()[1].purpose); +} - // Check the fields were parsed. - ASSERT_TRUE(fallback_data.has_value()); - EXPECT_EQ(kAppName, fallback_data->name); - EXPECT_EQ(SK_ColorRED, fallback_data->theme_color); - EXPECT_EQ(kScope, fallback_data->scope.spec()); - ASSERT_EQ(2u, fallback_data->icon_infos.size()); - EXPECT_EQ(kIconUrl, fallback_data->icon_infos[0].url.spec()); - EXPECT_EQ(kIconSizePx, fallback_data->icon_infos[0].square_size_px); - EXPECT_EQ(apps::IconInfo::Purpose::kAny, - fallback_data->icon_infos[0].purpose); - EXPECT_EQ(kIconUrl, fallback_data->icon_infos[1].url.spec()); - EXPECT_EQ(kIconSizePx, fallback_data->icon_infos[1].square_size_px); - EXPECT_EQ(apps::IconInfo::Purpose::kMaskable, - fallback_data->icon_infos[1].purpose); +// Test that a serialized proto with an unrecognized new field parses correctly +// in the current version and preserves the field value. +TEST(WebAppProtoUtilsTest, SpecificsProtoWithNewFieldParses) { + // Serialized in M125 by modifying web_app_specifics.proto: + // +optional string test_new_field = 5372767; + // Then: + // sync_pb::WebAppSpecifics sync_proto; + // sync_proto.set_start_url(kStartUrl); + // sync_proto.set_name(kAppName); + // sync_proto.set_user_display_mode_default( + // sync_pb::WebAppSpecifics::BROWSER); + // sync_proto.set_test_new_field("hello"); + // sync_proto.SerializeAsString(); + const std::string serialized_proto = { + 10, 29, 104, 116, 116, 112, 115, 58, 47, 47, 101, 120, 97, 109, + 112, 108, 101, 46, 99, 111, 109, 47, 108, 97, 117, 110, 99, 104, + 117, 114, 108, 18, 9, 84, 101, 115, 116, 32, 110, 97, 109, 101, + 24, 1, -6, -75, -65, 20, 5, 104, 101, 108, 108, 111}; + + // Parse the proto. + sync_pb::WebAppSpecifics sync_proto; + bool parsed = sync_proto.ParseFromString(serialized_proto); + + // Check the proto was parsed. + ASSERT_TRUE(parsed); + EXPECT_EQ(kStartUrl, sync_proto.start_url()); + + // Check the proto can be stored on a web app struct. + WebApp web_app("app_id"); + web_app.SetStartUrl(GURL(kStartUrl)); + web_app.SetManifestId(webapps::ManifestId(kStartUrl)); + web_app.SetSyncProto(sync_proto); + + // Clear the extra field added due to normalizing the proto in `SetSyncProto`. + sync_pb::WebAppSpecifics result_proto = web_app.sync_proto(); + result_proto.clear_relative_manifest_id(); + + // Check that the sync proto retained its value, including the unknown field. + EXPECT_EQ(result_proto.SerializeAsString(), serialized_proto); +} + +// Test that a serialized proto with an unrecognized new enum value parses +// correctly in the current version and preserves the enum value. +TEST(WebAppProtoUtilsTest, SpecificsProtoWithNewEnumValueParses) { + // Serialized in M125 by modifying web_app_specifics.proto: + // in "enum UserDisplayMode": + // +TEST_NEW_ENUM = 5372767; + // Then: + // sync_pb::WebAppSpecifics sync_proto; + // sync_proto.set_start_url(kStartUrl); + // sync_proto.set_name(kAppName); + // sync_proto.set_user_display_mode_default( + // sync_pb::WebAppSpecifics::TEST_NEW_ENUM); + // sync_proto.SerializeAsString(); + const std::string serialized_proto = { + 10, 29, 104, 116, 116, 112, 115, 58, 47, 47, 101, 120, + 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 108, 97, + 117, 110, 99, 104, 117, 114, 108, 18, 9, 84, 101, 115, + 116, 32, 110, 97, 109, 101, 24, -33, -10, -57, 2}; + + // Parse the proto. + sync_pb::WebAppSpecifics sync_proto; + bool parsed = sync_proto.ParseFromString(serialized_proto); + + // Check the proto was parsed. + ASSERT_TRUE(parsed); + EXPECT_EQ(kStartUrl, sync_proto.start_url()); + // Unfortunately, proto2 reports unknown field values as unset. + EXPECT_FALSE(sync_proto.has_user_display_mode_default()); + // Unknown field value parses as 0, ie. "Unspecified". + EXPECT_EQ(sync_proto.user_display_mode_default(), + sync_pb::WebAppSpecifics_UserDisplayMode_UNSPECIFIED); + + // Check the proto can be stored on a web app struct. + WebApp web_app("app_id"); + web_app.SetStartUrl(GURL(kStartUrl)); + web_app.SetManifestId(webapps::ManifestId(kStartUrl)); + web_app.SetSyncProto(sync_proto); + + // Clear the extra field added due to normalizing the proto in `SetSyncProto`. + sync_pb::WebAppSpecifics result_proto = web_app.sync_proto(); + result_proto.clear_relative_manifest_id(); + + // Check that the sync proto retained its value, including the unknown field. + EXPECT_EQ(result_proto.SerializeAsString(), serialized_proto); } TEST(WebAppProtoUtilsTest, RunOnOsLoginModes) {
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc index d7c94ff9..c0ea2882 100644 --- a/chrome/browser/web_applications/web_app_sync_bridge.cc +++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -117,24 +117,13 @@ return base::ok(manifest_id.value()); } + } // namespace BASE_FEATURE(kDeleteBadWebAppSyncEntitites, "DeleteBadWebAppSyncEntitites", base::FEATURE_DISABLED_BY_DEFAULT); -namespace { -// Return whether `app` has a UserDisplayMode set for the current platform. -// May be false for not-yet-migrated apps loaded from the database. -bool HasCurrentPlatformUserDisplayMode(const WebApp& app) { -#if BUILDFLAG(IS_CHROMEOS) - return app.user_display_mode_cros().has_value(); -#else - return app.user_display_mode_default().has_value(); -#endif // BUILDFLAG(IS_CHROMEOS) -} -} // namespace - std::unique_ptr<syncer::EntityData> CreateSyncEntityData(const WebApp& app) { // The Sync System doesn't allow empty entity_data name. DCHECK(!app.untranslated_name().empty()); @@ -145,54 +134,50 @@ if (entity_data->name.empty()) entity_data->name = app.start_url().spec(); - *(entity_data->specifics.mutable_web_app()) = WebAppToSyncProto(app); + *(entity_data->specifics.mutable_web_app()) = app.sync_proto(); return entity_data; } -void ApplySyncDataToApp(const sync_pb::WebAppSpecifics& sync_data, +void ApplySyncDataToApp(const sync_pb::WebAppSpecifics& sync_proto, WebApp* app) { app->AddSource(WebAppManagement::kSync); - // Store both platform-specific UserDisplayModes from sync_data if - // available. This ensures the sync data is preserved. - if (base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS) || - base::FeatureList::IsEnabled(kSyncOnlySeparateUserDisplayModeForCrOS)) { - if (sync_data.has_user_display_mode_cros()) { - app->SetUserDisplayModeCrOS( - ToMojomUserDisplayMode(sync_data.user_display_mode_cros())); + sync_pb::WebAppSpecifics modified_sync_proto = sync_proto; + + // Prevent incoming sync data from clearing recently-added fields in our local + // copy. This ensures new sync fields are preserved despite old (pre-M125) + // clients incorrectly clearing unknown fields. Any new fields added to the + // sync proto should also be added here (if we don't want them to be cleared + // by old clients) until this block can be removed. This can be removed when + // there are few <M125 clients remaining. + if (base::FeatureList::IsEnabled(kSyncOnlySeparateUserDisplayModeForCrOS)) { + if (app->sync_proto().has_user_display_mode_cros() && + !modified_sync_proto.has_user_display_mode_cros()) { + modified_sync_proto.set_user_display_mode_cros( + app->sync_proto().user_display_mode_cros()); } - if (sync_data.has_user_display_mode_default()) { - app->SetUserDisplayModeDefault( - ToMojomUserDisplayMode(sync_data.user_display_mode_default())); + if (base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { + if (app->sync_proto().has_user_display_mode_default() && + !modified_sync_proto.has_user_display_mode_default()) { + modified_sync_proto.set_user_display_mode_default( + app->sync_proto().user_display_mode_default()); + } + + // Ensure the current platform's UserDisplayMode is set. + // Conditional to avoid clobbering a valid UDM with an absent one, for the + // case of old clients clearing the CrOS UDM value or non-sync-installed + // apps. + if (!HasCurrentPlatformUserDisplayMode(modified_sync_proto)) { + auto udm = ResolvePlatformSpecificUserDisplayMode(modified_sync_proto); + SetPlatformSpecificUserDisplayMode(udm, &modified_sync_proto); + } } + // If `kSeparateUserDisplayModeForCrOS` is disabled, maintain original + // behaviour of clobbering UDM-default with the synced value, even if + // absent. } - if (base::FeatureList::IsEnabled(kSeparateUserDisplayModeForCrOS)) { - // Ensure the current platform's UserDisplayMode is set. - // Conditional to avoid clobbering a valid UDM with an absent one, for the - // case of old clients clearing the CrOS UDM value or non-sync-installed - // apps. - if (!HasCurrentPlatformUserDisplayMode(*app)) { - app->SetUserDisplayMode( - ResolvePlatformSpecificUserDisplayMode(sync_data)); - } - } else { - // Always overwrite the original UserDisplayMode with sync data. - app->SetUserDisplayMode( - ToMojomUserDisplayMode(sync_data.user_display_mode_default())); - } - - app->SetUserPageOrdinal(syncer::StringOrdinal(sync_data.user_page_ordinal())); - app->SetUserLaunchOrdinal( - syncer::StringOrdinal(sync_data.user_launch_ordinal())); - - std::optional<WebApp::SyncFallbackData> parsed_sync_fallback_data = - ParseSyncFallbackDataStruct(sync_data); - if (!parsed_sync_fallback_data.has_value()) { - // ParseSyncFallbackDataStruct() reports any errors. - return; - } - app->SetSyncFallbackData(std::move(parsed_sync_fallback_data.value())); + app->SetSyncProto(std::move(modified_sync_proto)); } WebAppSyncBridge::WebAppSyncBridge(WebAppRegistrarMutable* registrar) @@ -360,6 +345,7 @@ void WebAppSyncBridge::SetUserPageOrdinal(const webapps::AppId& app_id, syncer::StringOrdinal page_ordinal) { + CHECK(page_ordinal.IsValid(), base::NotFatalUntil::M126); ScopedRegistryUpdate update = BeginUpdate(); WebApp* web_app = update->UpdateApp(app_id); // Due to the extensions sync system setting ordinals on sync, this can get @@ -370,13 +356,16 @@ return; } if (web_app) { - web_app->SetUserPageOrdinal(std::move(page_ordinal)); + sync_pb::WebAppSpecifics mutable_sync_proto = web_app->sync_proto(); + mutable_sync_proto.set_user_page_ordinal(page_ordinal.ToInternalValue()); + web_app->SetSyncProto(std::move(mutable_sync_proto)); } } void WebAppSyncBridge::SetUserLaunchOrdinal( const webapps::AppId& app_id, syncer::StringOrdinal launch_ordinal) { + CHECK(launch_ordinal.IsValid(), base::NotFatalUntil::M126); ScopedRegistryUpdate update = BeginUpdate(); // Due to the extensions sync system setting ordinals on sync, this can get // called before the app is installed in the web apps system. Until apps are @@ -387,7 +376,10 @@ } WebApp* web_app = update->UpdateApp(app_id); if (web_app) { - web_app->SetUserLaunchOrdinal(std::move(launch_ordinal)); + sync_pb::WebAppSpecifics mutable_sync_proto = web_app->sync_proto(); + mutable_sync_proto.set_user_launch_ordinal( + launch_ordinal.ToInternalValue()); + web_app->SetSyncProto(std::move(mutable_sync_proto)); } } @@ -593,13 +585,14 @@ void WebAppSyncBridge::EnsureAppsHaveUserDisplayModeForCurrentPlatform() { web_app::ScopedRegistryUpdate update = BeginUpdate(); for (const WebApp& app : registrar().GetAppsIncludingStubs()) { - if (!HasCurrentPlatformUserDisplayMode(app)) { + if (!HasCurrentPlatformUserDisplayMode(app.sync_proto())) { // On CrOS, populate the UDM-CrOS value by copying from the default value // (falling back to Standalone). On non-CrOS, populate the UDM-Default // value with Standalone. - mojom::UserDisplayMode udm = app.user_display_mode_default().value_or( - mojom::UserDisplayMode::kStandalone); - update->UpdateApp(app.app_id())->SetUserDisplayMode(udm); + sync_pb::WebAppSpecifics_UserDisplayMode udm = + ResolvePlatformSpecificUserDisplayMode(app.sync_proto()); + update->UpdateApp(app.app_id()) + ->SetUserDisplayMode(ToMojomUserDisplayMode(udm)); } } } @@ -713,9 +706,6 @@ ApplySyncDataToApp(specifics, web_app.get()); if (existing_web_app) { - CHECK(existing_web_app->user_display_mode().has_value(), - base::NotFatalUntil::M125); - CHECK(web_app->user_display_mode().has_value(), base::NotFatalUntil::M125); if (existing_web_app->user_display_mode() != web_app->user_display_mode()) { apps_display_mode_changed.push_back(app_id); } @@ -753,9 +743,8 @@ for (const webapps::AppId& app_id : apps_display_mode_changed) { const WebApp* app = registrar_->GetAppById(app_id); - DCHECK(app->user_display_mode().has_value()); - registrar_->NotifyWebAppUserDisplayModeChanged( - app_id, app->user_display_mode().value()); + registrar_->NotifyWebAppUserDisplayModeChanged(app_id, + app->user_display_mode()); } std::vector<webapps::AppId> apps_to_delete;
diff --git a/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc index c4e090a5..a122829 100644 --- a/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc +++ b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
@@ -229,6 +229,21 @@ callback.Run(app->app_id(), code); } +syncer::EntityChangeList ToEntityChageList( + const webapps::AppId& app_id, + const sync_pb::WebAppSpecifics& sync_proto, + WebAppSyncBridge& sync_bridge) { + syncer::EntityChangeList entity_change_list; + syncer::EntityData entity_data; + *entity_data.specifics.mutable_web_app() = sync_proto; + CHECK(sync_bridge.IsEntityDataValid(entity_data)); + std::string storage_key = sync_bridge.GetClientTag(entity_data); + DCHECK_EQ(storage_key, app_id); + entity_change_list.push_back( + syncer::EntityChange::CreateUpdate(storage_key, std::move(entity_data))); + return entity_change_list; +} + } // namespace // TODO(dmurph): Replace these tests with tests in SingleClientWebAppsSyncTest, @@ -319,10 +334,10 @@ std::unique_ptr<WebApp> synced_app1 = CreateWebAppWithSyncOnlyFields("https://example.com/app1/"); { - WebApp::SyncFallbackData sync_fallback_data; - sync_fallback_data.name = "Sync Name"; - sync_fallback_data.theme_color = SK_ColorCYAN; - synced_app1->SetSyncFallbackData(std::move(sync_fallback_data)); + sync_pb::WebAppSpecifics sync_data; + sync_data.set_name("Sync Name"); + sync_data.set_theme_color(SK_ColorCYAN); + synced_app1->SetSyncProto(std::move(sync_data)); } InsertAppIntoRegistry(®istry, std::move(synced_app1)); @@ -724,10 +739,10 @@ auto app_to_update = std::make_unique<WebApp>(*merged_apps[i]); app_to_update->SetUserDisplayMode(UserDisplayMode::kStandalone); - WebApp::SyncFallbackData sync_fallback_data; - sync_fallback_data.name = "Sync Name"; - sync_fallback_data.theme_color = SK_ColorYELLOW; - app_to_update->SetSyncFallbackData(std::move(sync_fallback_data)); + sync_pb::WebAppSpecifics sync_data = app_to_update->sync_proto(); + sync_data.set_name("Sync Name"); + sync_data.set_theme_color(SK_ColorYELLOW); + app_to_update->SetSyncProto(std::move(sync_data)); ConvertAppToEntityChange( *app_to_update, syncer::EntityChange::ACTION_UPDATE, &entity_changes); @@ -820,10 +835,10 @@ auto app_to_update = std::make_unique<WebApp>(*policy_and_sync_apps[i]); app_to_update->SetUserDisplayMode(UserDisplayMode::kBrowser); - WebApp::SyncFallbackData sync_fallback_data; - sync_fallback_data.name = "Updated Sync Name"; - sync_fallback_data.theme_color = SK_ColorWHITE; - app_to_update->SetSyncFallbackData(std::move(sync_fallback_data)); + sync_pb::WebAppSpecifics sync_data = app_to_update->sync_proto(); + sync_data.set_name("Updated Sync Name"); + sync_data.set_theme_color(SK_ColorWHITE); + app_to_update->SetSyncProto(std::move(sync_data)); ConvertAppToEntityChange( *app_to_update, syncer::EntityChange::ACTION_UPDATE, &entity_changes); @@ -1017,10 +1032,10 @@ // Obtain a writeable handle. WebApp* sync_app = update->UpdateApp(app->app_id()); - WebApp::SyncFallbackData sync_fallback_data; - sync_fallback_data.name = "Updated Sync Name"; - sync_fallback_data.theme_color = SK_ColorBLACK; - sync_app->SetSyncFallbackData(std::move(sync_fallback_data)); + sync_pb::WebAppSpecifics sync_data; + sync_data.set_name("Updated Sync Name"); + sync_data.set_theme_color(SK_ColorBLACK); + sync_app->SetSyncProto(std::move(sync_data)); sync_app->SetUserDisplayMode(UserDisplayMode::kBrowser); // Override the app in the expected registry. @@ -1361,13 +1376,74 @@ base::Bucket(StorageKeyParseResult::kInvalidManifestId, 1))); } +// Test that a serialized proto with an unrecognized new field can successfully +// sync install in the current version and preserves the field value. +TEST_F(WebAppSyncBridgeTest, SpecificsProtoWithNewFieldPreserved) { + // Serialized in M125 by modifying web_app_specifics.proto: + // +optional string test_new_field = 5372767; + // Then: + // const char kAppName[] = "Test name"; + // sync_pb::WebAppSpecifics sync_proto; + // sync_proto.set_start_url(kStartUrl); + // sync_proto.set_name(kAppName); + // sync_proto.set_user_display_mode_default( + // sync_pb::WebAppSpecifics::BROWSER); + // sync_proto.set_test_new_field("hello"); + // sync_proto.SerializeAsString(); + const char kStartUrl[] = "https://example.com/launchurl"; + const std::string serialized_proto = { + 10, 29, 104, 116, 116, 112, 115, 58, 47, 47, 101, 120, 97, 109, + 112, 108, 101, 46, 99, 111, 109, 47, 108, 97, 117, 110, 99, 104, + 117, 114, 108, 18, 9, 84, 101, 115, 116, 32, 110, 97, 109, 101, + 24, 1, -6, -75, -65, 20, 5, 104, 101, 108, 108, 111}; + const GURL start_url = GURL(kStartUrl); + const webapps::AppId app_id = + GenerateAppId(/*manifest_id_path=*/std::nullopt, start_url); + + // Parse the proto. + sync_pb::WebAppSpecifics sync_proto; + bool parsed = sync_proto.ParseFromString(serialized_proto); + + // Sanity check the proto was parsed. + ASSERT_TRUE(parsed); + EXPECT_EQ(kStartUrl, sync_proto.start_url()); + + StartWebAppProvider(); + + // Listen for sync installs. + WebAppTestInstallObserver install_observer(profile()); + install_observer.BeginListening(); + + EXPECT_FALSE(sync_bridge().ApplyIncrementalSyncChanges( + sync_bridge().CreateMetadataChangeList(), + ToEntityChageList(app_id, sync_proto, sync_bridge()))); + + // Await sync install. + EXPECT_EQ(install_observer.Wait(), app_id); + + const WebApp* app = fake_provider().registrar_unsafe().GetAppById(app_id); + ASSERT_TRUE(app); + + // Clear the fields added due to normalizing the proto in `SetSyncProto` and + // `ApplySyncDataToApp`. + sync_pb::WebAppSpecifics result_proto = app->sync_proto(); + result_proto.clear_relative_manifest_id(); +#if BUILDFLAG(IS_CHROMEOS) + result_proto.clear_user_display_mode_cros(); +#endif + + // Check that the sync proto retained its value, including the unknown field. + EXPECT_EQ(result_proto.SerializeAsString(), serialized_proto); +} + namespace { using UserDisplayModeSplitParam = std::tuple< bool /*flag_enabled*/, std::optional<WebAppSpecifics_UserDisplayMode> /*sync_cros_udm*/, std::optional<WebAppSpecifics_UserDisplayMode> /*sync_non_cros_udm*/, std::optional<UserDisplayMode> /*installed_udm*/, - std::optional<UserDisplayMode> /*local_other_platform_udm*/>; + std::optional< + WebAppSpecifics_UserDisplayMode> /*local_other_platform_udm*/>; constexpr std::optional<WebAppSpecifics_UserDisplayMode> kSyncUserDisplayModes[]{std::nullopt, @@ -1455,7 +1531,8 @@ return std::get<3>(GetParam()); } // UDM stored locally for the other platform. - std::optional<UserDisplayMode> local_other_platform_udm() const { + std::optional<WebAppSpecifics_UserDisplayMode> local_other_platform_udm() + const { return std::get<4>(GetParam()); } @@ -1481,40 +1558,12 @@ WebAppProvider& provider() { return *WebAppProvider::GetForTest(profile()); } WebAppSyncBridge& sync_bridge() { return provider().sync_bridge_unsafe(); } - syncer::EntityData ToEntityData(const sync_pb::WebAppSpecifics& sync_proto) { - syncer::EntityData data; - *data.specifics.mutable_web_app() = sync_proto; - DCHECK(sync_bridge().IsEntityDataValid(data)); - return data; - } - - syncer::EntityChangeList ToEntityChageList( - const webapps::AppId& app_id, - const sync_pb::WebAppSpecifics& sync_proto) { - syncer::EntityChangeList entity_change_list; - syncer::EntityData entity_data = ToEntityData(sync_proto); - std::string storage_key = sync_bridge().GetClientTag(entity_data); - DCHECK_EQ(storage_key, app_id); - entity_change_list.push_back(syncer::EntityChange::CreateUpdate( - storage_key, std::move(entity_data))); - return entity_change_list; - } - UserDisplayMode ToMojomUdmFallbackToStandalone( std::optional<WebAppSpecifics_UserDisplayMode> sync_udm) { if (!sync_udm.has_value()) { return mojom::UserDisplayMode::kStandalone; } - switch (sync_udm.value()) { - case sync_pb::WebAppSpecifics_UserDisplayMode_UNSPECIFIED: - case sync_pb::WebAppSpecifics_UserDisplayMode_STANDALONE: - return mojom::UserDisplayMode::kStandalone; - case sync_pb::WebAppSpecifics_UserDisplayMode_BROWSER: - return mojom::UserDisplayMode::kBrowser; - case sync_pb::WebAppSpecifics_UserDisplayMode_TABBED: - // Not used in this test. - NOTREACHED_NORETURN(); - } + return ToMojomUserDisplayMode(sync_udm.value()); } protected: @@ -1555,11 +1604,16 @@ ScopedRegistryUpdate update = sync_bridge().BeginUpdate(); WebApp* web_app = update->UpdateApp(app_id); DCHECK(web_app); + sync_pb::WebAppSpecifics sync_proto = web_app->sync_proto(); + if (IsChromeOs()) { - web_app->SetUserDisplayModeDefault(local_other_platform_udm().value()); + sync_proto.set_user_display_mode_default( + local_other_platform_udm().value()); } else { - web_app->SetUserDisplayModeCrOS(local_other_platform_udm().value()); + sync_proto.set_user_display_mode_cros( + local_other_platform_udm().value()); } + web_app->SetSyncProto(std::move(sync_proto)); } } @@ -1582,7 +1636,7 @@ EXPECT_FALSE(sync_bridge().ApplyIncrementalSyncChanges( sync_bridge().CreateMetadataChangeList(), - ToEntityChageList(app_id, sync_proto))); + ToEntityChageList(app_id, sync_proto, sync_bridge()))); // Await sync install. if (!installed_before_sync()) { @@ -1595,7 +1649,9 @@ //// kSeparateUserDisplayModeForCrOS Disabled //// if (!flag_enabled()) { - EXPECT_EQ(app->user_display_mode(), app->user_display_mode_default()); + EXPECT_EQ(app->user_display_mode(), + ToMojomUdmFallbackToStandalone( + app->sync_proto().user_display_mode_default())); // Expect to always overwrite local UDM state with non-CrOS sync data, // including treating absent/unspecified as standalone. @@ -1605,21 +1661,23 @@ // CrOS UDM should still be stored from sync/DB, just not used. if (sync_cros_udm()) { // Sync overwrites DB values. - EXPECT_EQ(app->user_display_mode_cros(), - ToMojomUdmFallbackToStandalone(sync_cros_udm())); + EXPECT_EQ(app->sync_proto().user_display_mode_cros(), + sync_cros_udm().value()); } else { if (IsChromeOs()) { // Due to tests setting a local value (which sets UDM-non-CrOS because // the flag is off) and an other platform value (which also sets // UDM-non-CrOS), there is never a CrOS value set locally in this test // case. - EXPECT_EQ(app->user_display_mode_cros(), std::nullopt); + EXPECT_FALSE(app->sync_proto().has_user_display_mode_cros()); } else { // We should still have preserved a CrOS value in the DB. if (installed_before_sync()) { - EXPECT_EQ(app->user_display_mode_cros(), local_other_platform_udm()); + EXPECT_EQ(app->sync_proto().user_display_mode_cros(), + local_other_platform_udm().value_or( + WebAppSpecifics_UserDisplayMode_UNSPECIFIED)); } else { - EXPECT_EQ(app->user_display_mode_cros(), std::nullopt); + EXPECT_FALSE(app->sync_proto().has_user_display_mode_cros()); } } } @@ -1648,22 +1706,32 @@ } } - std::optional<UserDisplayMode> app_this_platform_udm; - std::optional<UserDisplayMode> app_other_platform_udm; + std::optional<sync_pb::WebAppSpecifics::UserDisplayMode> + app_this_platform_udm; + std::optional<sync_pb::WebAppSpecifics::UserDisplayMode> + app_other_platform_udm; if (IsChromeOs()) { - app_this_platform_udm = app->user_display_mode_cros(); - app_other_platform_udm = app->user_display_mode_default(); + if (app->sync_proto().has_user_display_mode_cros()) { + app_this_platform_udm = app->sync_proto().user_display_mode_cros(); + } + if (app->sync_proto().has_user_display_mode_default()) { + app_other_platform_udm = app->sync_proto().user_display_mode_default(); + } } else { - app_this_platform_udm = app->user_display_mode_default(); - app_other_platform_udm = app->user_display_mode_cros(); + if (app->sync_proto().has_user_display_mode_default()) { + app_this_platform_udm = app->sync_proto().user_display_mode_default(); + } + if (app->sync_proto().has_user_display_mode_cros()) { + app_other_platform_udm = app->sync_proto().user_display_mode_cros(); + } } - EXPECT_EQ(app->user_display_mode(), app_this_platform_udm); + EXPECT_EQ(app->user_display_mode(), + ToMojomUdmFallbackToStandalone(app_this_platform_udm)); if (sync_other_platform_udm()) { // If UDM is set for the other platform in sync, it should be preserved // (though Unspecified values currently become standalone). - EXPECT_EQ(app_other_platform_udm, - ToMojomUdmFallbackToStandalone(sync_other_platform_udm())); + EXPECT_EQ(app_other_platform_udm, sync_other_platform_udm()); } else if (installed_before_sync()) { // Otherwise, if installed, we should preserve a local UDM value (or unset). EXPECT_EQ(app_other_platform_udm, local_other_platform_udm()); @@ -1682,7 +1750,7 @@ /*sync_non_cros_udm=*/testing::ValuesIn(kSyncUserDisplayModes), /*installed_udm=*/testing::ValuesIn(kInstalledUserDisplayModes), /*local_other_platform_udm=*/ - testing::ValuesIn(kInstalledUserDisplayModes)), + testing::ValuesIn(kSyncUserDisplayModes)), WebAppSyncBridgeTest_UserDisplayModeSplit::ParamToString); } // namespace web_app
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index cd451e7..8a81e4d 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1713095737-7f1b5d4ad7bc14a8d7a40d07ff1c1dbec54d9a73-40bccbbd8c994232a5656ff12156d9e8957cbfa7.profdata +chrome-android32-main-1713160129-19bd45ad627314f403cd5919e25dc24b587fee6b-7b6936db325be513ca27d0b28f000d5555adbd2f.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index b38ac0f..60f4df03 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1713087987-d07b6dce5e7c11227ec5e6de6cd0a6f59b64a4c6-937f9f85465d8bb34405c05426ac365fce91e4dc.profdata +chrome-android64-main-1713153282-8e49b5260bb93c6e1a244227e25d64fb7e91dc5a-0517029fb0aabc450fbc5fa8f1ade1cd80e98b76.profdata
diff --git a/chrome/build/lacros-arm64.pgo.txt b/chrome/build/lacros-arm64.pgo.txt index 7a8f9943..fc248da 100644 --- a/chrome/build/lacros-arm64.pgo.txt +++ b/chrome/build/lacros-arm64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-arm64-generic-main-1713050068-dbedbb6e8f332055a4031be2cbee01d35ee552d3-0ff190bd93917bb83bb2b4eb6d164cfe71105f23.profdata +chrome-chromeos-arm64-generic-main-1713138865-e4366b1e74fcd8d5a3864edb61cf715e4a651ce4-0e275deada7de65b89c1a83b77086f7a996ae85b.profdata
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index 3184ac1..38515192 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1713050068-09a3165a4ae6d3029c92eea204ab2ff3eaac5f10-0ff190bd93917bb83bb2b4eb6d164cfe71105f23.profdata +chrome-chromeos-amd64-generic-main-1713138865-75fa35509e2f194f141a8858fd859c463a04bc79-0e275deada7de65b89c1a83b77086f7a996ae85b.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index c9a33f6..ce180e5 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1713095737-84f143778c9debf4706dc1efe3fffbc1cd37a4ce-40bccbbd8c994232a5656ff12156d9e8957cbfa7.profdata +chrome-linux-main-1713138865-055a9dca1096aa0029b457c85468d6c6d9088017-0e275deada7de65b89c1a83b77086f7a996ae85b.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index f3117d78..bdb8273 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1713095737-cf555c13ce7e1423de3976eb6966e99288339e3c-40bccbbd8c994232a5656ff12156d9e8957cbfa7.profdata +chrome-mac-arm-main-1713160129-2c845fd1cec63ad94d25798e0902535ec8af6717-7b6936db325be513ca27d0b28f000d5555adbd2f.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index ccf60d9..0595004 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1713095737-430a9b6af3e86ca8d27be223a69b184f0f1c01cb-40bccbbd8c994232a5656ff12156d9e8957cbfa7.profdata +chrome-win-arm64-main-1713160129-6e38cb08879581a2f777099e3fbbcc5144633ebd-7b6936db325be513ca27d0b28f000d5555adbd2f.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index a393e816..523c691 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1713084877-6711e593ce84091d1e7e5e6edecc42baef64190e-4c36832aa422c0aa2dfe839a2f6fea7f0a9dc92e.profdata +chrome-win32-main-1713149073-c6891a576eb65f1d1033671cb6be6a30c5c01ed3-180400296cfea323ddeadf1537675f95953d7e34.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index f105d3f7..7aa5964 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1713084877-48a2a402648131f36ad20368ede96056dba77823-4c36832aa422c0aa2dfe839a2f6fea7f0a9dc92e.profdata +chrome-win64-main-1713149073-98695be254e5c383804ff3252186c3dbdda358f5-180400296cfea323ddeadf1537675f95953d7e34.profdata
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index bad4ec47..cadf7afe 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -2574,7 +2574,7 @@ EXPECT_CALL(fake_driver_, ShowPasswordSuggestions); autofill_agent_->TriggerSuggestions( form_util::GetFieldRendererId(username_element_), - AutofillSuggestionTriggerSource::kTextFieldDidChange); + AutofillSuggestionTriggerSource::kManualFallbackPasswords); } TEST_F(PasswordAutofillAgentTest,
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 6478728..7177b526 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1097,6 +1097,32 @@ } if (is_chromeos && is_chromeos_device) { + if (is_chromeos_ash) { + copy("crosier_metadata") { + sources = [ + "../browser/ash/assistant/assistant_integration_test.yaml", + "../browser/ash/bluetooth/bluetooth_integration_test.yaml", + "../browser/ash/child_accounts/web_approvals_integration_test.yaml", + "../browser/ash/external_metrics_integration_test.yaml", + "../browser/ash/featured_integration_test.yaml", + "../browser/ash/login/lock/lock_screen_integration_test.yaml", + "../browser/ash/login/login_integration_test.yaml", + "../browser/ash/login/supervised_user_login_integration_test.yaml", + "../browser/ash/ml_integration_test.yaml", + "../browser/ash/power/ml/smart_dim/smart_dim_integration_test.yaml", + "../browser/ash/scanning/multi_page_scan_integration_test.yaml", + "../browser/ash/scanning/scan_integration_test.yaml", + "../browser/ash/screenshot_integration_test.yaml", + "../browser/ash/security_files_integration_test.yaml", + "../browser/ash/system_web_apps/apps/terminal_integration_test.yaml", + "../browser/ash/web_handwriting_integration_test.yaml", + "../browser/ui/ash/quick_settings_integration_test.yaml", + "../browser/ui/ash/shelf/shelf_integration_test.yaml", + ] + outputs = [ "$root_out_dir/crosier_metadata/{{source_file_part}}" ] + } + } + test("chromeos_integration_tests") { configs += [ "//build/config:precompiled_headers" ] defines = [ @@ -1116,6 +1142,8 @@ data_deps += [ "//chrome:chrome(//build/toolchain/cros:lacros_clang)" ] } if (is_chromeos_ash) { + # Note: for each test case in the below list, add a metadata file + # in the `crosier_metadata` build rule above. sources += [ "../browser/ash/assistant/assistant_integration_test.cc", "../browser/ash/bluetooth/bluetooth_integration_test.cc", @@ -1175,6 +1203,7 @@ ] data_deps += [ + ":crosier_metadata", "//chrome/test/base/chromeos/crosier/helper", "//chrome/test/base/chromeos/crosier/helper/fake_chrome", ] @@ -11971,6 +12000,7 @@ "//components/trusted_vault:test_support", "//components/undo", "//components/webapps/browser", + "//components/webapps/common", "//components/webauthn/core/browser", "//testing/gmock", "//testing/gtest",
diff --git a/chrome/test/data/focus_rings/focus_ring_browsertest_anchor_win.png b/chrome/test/data/focus_rings/focus_ring_browsertest_anchor_win.png index b50c35e..6b146c1 100644 --- a/chrome/test/data/focus_rings/focus_ring_browsertest_anchor_win.png +++ b/chrome/test/data/focus_rings/focus_ring_browsertest_anchor_win.png Binary files differ
diff --git a/chrome/test/data/focus_rings/focus_ring_browsertest_button_win.png b/chrome/test/data/focus_rings/focus_ring_browsertest_button_win.png index 0680afc6..3fced26 100644 --- a/chrome/test/data/focus_rings/focus_ring_browsertest_button_win.png +++ b/chrome/test/data/focus_rings/focus_ring_browsertest_button_win.png Binary files differ
diff --git a/chrome/test/data/focus_rings/focus_ring_browsertest_checkbox_win.png b/chrome/test/data/focus_rings/focus_ring_browsertest_checkbox_win.png index 5eb51cb..e13284c 100644 --- a/chrome/test/data/focus_rings/focus_ring_browsertest_checkbox_win.png +++ b/chrome/test/data/focus_rings/focus_ring_browsertest_checkbox_win.png Binary files differ
diff --git a/chrome/test/data/focus_rings/focus_ring_browsertest_dark_mode_button_win.png b/chrome/test/data/focus_rings/focus_ring_browsertest_dark_mode_button_win.png index a621f12e..89d7308 100644 --- a/chrome/test/data/focus_rings/focus_ring_browsertest_dark_mode_button_win.png +++ b/chrome/test/data/focus_rings/focus_ring_browsertest_dark_mode_button_win.png Binary files differ
diff --git a/chrome/test/data/focus_rings/focus_ring_browsertest_radio_win.png b/chrome/test/data/focus_rings/focus_ring_browsertest_radio_win.png index 0bce232..62241ce 100644 --- a/chrome/test/data/focus_rings/focus_ring_browsertest_radio_win.png +++ b/chrome/test/data/focus_rings/focus_ring_browsertest_radio_win.png Binary files differ
diff --git a/chrome/test/data/web_apps/empty_web_app.json b/chrome/test/data/web_apps/empty_web_app.json index 0e4f6f2c..34759c4 100644 --- a/chrome/test/data/web_apps/empty_web_app.json +++ b/chrome/test/data/web_apps/empty_web_app.json
@@ -60,19 +60,11 @@ "start_url": "", "supported_links_offer_dismiss_count": 0, "supported_links_offer_ignore_count": 0, - "sync_fallback_data": { - "manifest_icons": [ ], - "name": "", - "scope": "", - "theme_color": "none" + "sync_proto": { }, "tab_strip": null, "theme_color": "none", "url_handlers": [ ], - "user_display_mode_cros": null, - "user_display_mode_default": null, - "user_launch_ordinal": "INVALID[]", "user_link_capturing_preference": "0", - "user_page_ordinal": "INVALID[]", "window_controls_overlay_enabled": false }
diff --git a/chrome/test/data/web_apps/sample_web_app.json b/chrome/test/data/web_apps/sample_web_app.json index 1094987b..3dba7707 100644 --- a/chrome/test/data/web_apps/sample_web_app.json +++ b/chrome/test/data/web_apps/sample_web_app.json
@@ -418,15 +418,21 @@ "start_url": "https://example.com/scope1234/start1234", "supported_links_offer_dismiss_count": -1706110566, "supported_links_offer_ignore_count": -1701779570, - "sync_fallback_data": { - "manifest_icons": [ { - "purpose": "kAny", - "square_size_px": 256, + "sync_proto": { + "icon_infos": [ { + "purpose": "ANY", + "size_in_px": "256", "url": "https://example.com/icon322714900" } ], "name": "SyncName1234", + "relative_manifest_id": "manifest_id_1234?query=test", "scope": "https://example.com/scope1234/", - "theme_color": "rgba(77,188,194,0.9686274509803922)" + "start_url": "https://example.com/scope1234/start1234", + "theme_color": "4149066946", + "user_display_mode_cros": "STANDALONE", + "user_display_mode_default": "TABBED", + "user_launch_ordinal": "n", + "user_page_ordinal": "n" }, "tab_strip": { "home_tab": { @@ -482,10 +488,6 @@ "origin": "https://app-17838994132.com", "paths": [ ] } ], - "user_display_mode_cros": "kStandalone", - "user_display_mode_default": "kTabbed", - "user_launch_ordinal": "INVALID[]", "user_link_capturing_preference": "1", - "user_page_ordinal": "INVALID[]", "window_controls_overlay_enabled": false }
diff --git a/chrome/updater/app/app_install.h b/chrome/updater/app/app_install.h index dc673fd8..5abee31 100644 --- a/chrome/updater/app/app_install.h +++ b/chrome/updater/app/app_install.h
@@ -78,7 +78,8 @@ void RegisterUpdater(); - // Installs an application if the `app_id_` is valid. + // Handles the --tag and --app-id command line arguments, and triggers + // installing of the corresponding application if either argument is present. void MaybeInstallApp(); // Bound to the main sequence.
diff --git a/chrome/updater/constants.cc b/chrome/updater/constants.cc index dfc09eb..9e7f8e7 100644 --- a/chrome/updater/constants.cc +++ b/chrome/updater/constants.cc
@@ -38,6 +38,7 @@ const char kInstallSwitch[] = "install"; const char kEulaRequiredSwitch[] = "eularequired"; const char kOemSwitch[] = "oem"; +const char kRuntimeSwitch[] = "runtime"; const char kUninstallSwitch[] = "uninstall"; const char kUninstallSelfSwitch[] = "uninstall-self"; const char kUninstallIfUnusedSwitch[] = "uninstall-if-unused"; @@ -56,6 +57,7 @@ const char kAppVersionSwitch[] = "app-version"; const char kWakeSwitch[] = "wake"; const char kWakeAllSwitch[] = "wake-all"; +const char kTagSwitch[] = "tag"; const char kInstallerDataSwitch[] = "installerdata"; const char kServerServiceSwitch[] = "service";
diff --git a/chrome/updater/constants.h b/chrome/updater/constants.h index e1459cd..afb127c 100644 --- a/chrome/updater/constants.h +++ b/chrome/updater/constants.h
@@ -80,18 +80,21 @@ // Updates the updater. extern const char kUpdateSwitch[]; -// Installs the updater. Takes an optional argument for the meta installer tag. -// The tag is a string of arguments, separated by a delimiter (in this case, the -// delimiter is `&`). The tag is typically embedded in the program image of the -// metainstaller, but for testing purposes, the tag could be passed directly as -// a command line argument. The tag is currently encoded as an ASCII string. +// Installs the updater. extern const char kInstallSwitch[]; - +extern const char kRuntimeSwitch[]; extern const char kEulaRequiredSwitch[]; // Specifies that this is an OEM install in audit mode. extern const char kOemSwitch[]; +// Contains the meta installer tag. The tag is a string of arguments, separated +// by a delimiter (in this case, the delimiter is =). The tag is typically +// embedded in the program image of the metainstaller, but for testing purposes, +// the tag could be passed directly as a command line argument. The tag is +// currently encoded as a ASCII string. +extern const char kTagSwitch[]; + // The --installerdata=file.dat switch is passed to an installer if an // installdataindex is specified in the tag or if installerdata is passed in via // --appargs. The corresponding installerdata is written to file.dat with an
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index a659463a..522c908 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -168,6 +168,8 @@ // TODO(crbug.com/1476296) - eliminate the need to have a UI message type // on the main sequence by refactoring the splash screen and the rest of UI. const bool is_app_install_mode = command_line->HasSwitch(kInstallSwitch) || + command_line->HasSwitch(kTagSwitch) || + command_line->HasSwitch(kRuntimeSwitch) || command_line->HasSwitch(kHandoffSwitch); const bool is_silent = command_line->HasSwitch(kSilentSwitch); base::SingleThreadTaskExecutor main_task_executor( @@ -227,20 +229,14 @@ const char* GetUpdaterCommand(const base::CommandLine* command_line) { // Contains the literals which are associated with specific updater commands. const char* commands[] = { - kWindowsServiceSwitch, - kCrashHandlerSwitch, - kInstallSwitch, - kRecoverSwitch, - kServerSwitch, - kTestSwitch, - kUninstallIfUnusedSwitch, - kUninstallSelfSwitch, - kUninstallSwitch, - kUpdateSwitch, - kWakeSwitch, - kWakeAllSwitch, - kHealthCheckSwitch, - kHandoffSwitch, + kWindowsServiceSwitch, kCrashHandlerSwitch, + kInstallSwitch, kRecoverSwitch, + kServerSwitch, kTagSwitch, + kTestSwitch, kUninstallIfUnusedSwitch, + kUninstallSelfSwitch, kUninstallSwitch, + kUpdateSwitch, kWakeSwitch, + kWakeAllSwitch, kHealthCheckSwitch, + kHandoffSwitch, kRuntimeSwitch, }; const char** it = base::ranges::find_if(commands, [command_line](auto cmd) { return command_line->HasSwitch(cmd);
diff --git a/chrome/updater/updater_scope.h b/chrome/updater/updater_scope.h index fe4b85eb..4aa38394 100644 --- a/chrome/updater/updater_scope.h +++ b/chrome/updater/updater_scope.h
@@ -44,8 +44,8 @@ // Returns the scope of the updater, which is either per-system or per-user. // The updater scope is determined from command line arguments of the process, -// the presence and content of the tag, and the integrity level of the process, -// where applicable. +// the presence and content of the --tag argument, and the integrity level +// of the process, where applicable. UpdaterScope GetUpdaterScope(); bool IsSystemInstall();
diff --git a/chrome/updater/updater_scope_unittest.cc b/chrome/updater/updater_scope_unittest.cc index 0b36e148..62aaab9 100644 --- a/chrome/updater/updater_scope_unittest.cc +++ b/chrome/updater/updater_scope_unittest.cc
@@ -59,6 +59,7 @@ INSTANTIATE_TEST_SUITE_P(TagSwitchTestCases, TagSwitchTest, ::testing::ValuesIn(std::vector<TagSwitchTestCase>{ + {kTagSwitch}, {kInstallSwitch}, {kHandoffSwitch}, }));
diff --git a/chrome/updater/util/util.cc b/chrome/updater/util/util.cc index 2ad5d09..1f99b07 100644 --- a/chrome/updater/util/util.cc +++ b/chrome/updater/util/util.cc
@@ -180,7 +180,9 @@ TagParsingResult GetTagArgsForCommandLine( const base::CommandLine& command_line) { - std::string tag = command_line.HasSwitch(kInstallSwitch) + std::string tag = command_line.HasSwitch(kTagSwitch) + ? command_line.GetSwitchValueASCII(kTagSwitch) + : command_line.HasSwitch(kInstallSwitch) ? command_line.GetSwitchValueASCII(kInstallSwitch) : command_line.GetSwitchValueASCII(kHandoffSwitch); if (tag.empty()) {
diff --git a/chrome/updater/util/util.h b/chrome/updater/util/util.h index 48afe8b..993add3 100644 --- a/chrome/updater/util/util.h +++ b/chrome/updater/util/util.h
@@ -110,8 +110,9 @@ // Returns the path to the crashpad database, creating it if it does not exist. std::optional<base::FilePath> EnsureCrashDatabasePath(UpdaterScope scope); -// Contains the parsed values from the tag. The tag is provided as a command -// line argument to the `--install` or the `--handoff` switch. +// Return the parsed values from --tag command line argument. The functions +// return {} if there was no tag at all. An error is set if the tag fails to +// parse. struct TagParsingResult { TagParsingResult(); TagParsingResult(std::optional<tagging::TagArgs> tag_args, @@ -123,8 +124,6 @@ tagging::ErrorCode error = tagging::ErrorCode::kSuccess; }; -// These functions return {} if there was no tag at all. An error is set if the -// tag fails to parse. TagParsingResult GetTagArgsForCommandLine( const base::CommandLine& command_line); TagParsingResult GetTagArgs();
diff --git a/chrome/updater/util/util_unittest.cc b/chrome/updater/util/util_unittest.cc index 1b66e50..2caaf8c 100644 --- a/chrome/updater/util/util_unittest.cc +++ b/chrome/updater/util/util_unittest.cc
@@ -40,6 +40,7 @@ INSTANTIATE_TEST_SUITE_P(UtilTagArgsTestCases, UtilTagArgsTest, ::testing::ValuesIn(std::vector<UtilTagArgsTestCase>{ + {kTagSwitch}, {kInstallSwitch}, {kHandoffSwitch}, }));
diff --git a/chrome/updater/win/installer/installer.cc b/chrome/updater/win/installer/installer.cc index a568dbd..1daf2634 100644 --- a/chrome/updater/win/installer/installer.cc +++ b/chrome/updater/win/installer/installer.cc
@@ -211,13 +211,14 @@ *cmd_line_args = '\0'; - // Use the tag from the `--install` command line argument if such argument + // Use the tag from the --tag/--install command line argument if such argument // exists. Otherwise, try extracting a tag embedded in the program image of // the meta installer. - if (args.GetSwitchValueASCII(kInstallSwitch).empty()) { + if (args.GetSwitchValueASCII(kTagSwitch).empty() && + args.GetSwitchValueASCII(kInstallSwitch).empty()) { const std::string tag = ExtractTag(); if (!tag.empty()) { - args.AppendSwitchASCII(kInstallSwitch, tag.c_str()); + args.AppendSwitchASCII(kTagSwitch, tag.c_str()); } }
diff --git a/chrome/updater/win/installer/installer_win_unittest.cc b/chrome/updater/win/installer/installer_win_unittest.cc index e5708f2..27824c1b 100644 --- a/chrome/updater/win/installer/installer_win_unittest.cc +++ b/chrome/updater/win/installer/installer_win_unittest.cc
@@ -21,7 +21,7 @@ #include "testing/gtest/include/gtest/gtest.h" namespace { -constexpr char install_switch[] = "--install="; +constexpr char tag_switch[] = "--tag="; constexpr char enable_logging_switch[] = "--enable-logging"; constexpr char logging_module_switch[] = "--vmodule="; @@ -91,7 +91,7 @@ std::wstring command_line_str(L"UpdaterSetup.exe"); // Add a tag switch to bypass attempting to parse a tag. command_line_str = base::SysUTF8ToWide( - base::StrCat({"UpdaterSetup.exe ", install_switch, "fake_tag"})); + base::StrCat({"UpdaterSetup.exe ", tag_switch, "fake_tag"})); updater::ProcessExitResult exit_result = updater::BuildInstallerCommandLineArguments(command_line_str.c_str(), cmd_line_args.get(), @@ -103,9 +103,8 @@ // Test that no --enable-logging switch is added if one is provided. cmd_line_args.clear(); // Add a tag switch to bypass attempting to parse a tag. - command_line_str = - base::SysUTF8ToWide(base::StrCat({"UpdaterSetup.exe ", install_switch, - "fake_tag ", enable_logging_switch})); + command_line_str = base::SysUTF8ToWide(base::StrCat( + {"UpdaterSetup.exe ", tag_switch, "fake_tag ", enable_logging_switch})); exit_result = updater::BuildInstallerCommandLineArguments( command_line_str.c_str(), cmd_line_args.get(), cmd_line_args.capacity()); EXPECT_EQ(exit_result.exit_code, updater::SUCCESS_EXIT_CODE); @@ -119,7 +118,7 @@ std::wstring command_line_str(L"UpdaterSetup.exe"); // Add a tag switch to bypass attempting to parse a tag. command_line_str = base::SysUTF8ToWide( - base::StrCat({"UpdaterSetup.exe ", install_switch, "fake_tag"})); + base::StrCat({"UpdaterSetup.exe ", tag_switch, "fake_tag"})); updater::ProcessExitResult exit_result = updater::BuildInstallerCommandLineArguments(command_line_str.c_str(), cmd_line_args.get(), @@ -132,7 +131,7 @@ cmd_line_args.clear(); // Add a tag switch to bypass attempting to parse a tag. command_line_str = base::SysUTF8ToWide( - base::StrCat({"UpdaterSetup.exe ", install_switch, "fake_tag ", + base::StrCat({"UpdaterSetup.exe ", tag_switch, "fake_tag ", logging_module_switch, "fake_module"})); exit_result = updater::BuildInstallerCommandLineArguments( command_line_str.c_str(), cmd_line_args.get(), cmd_line_args.capacity()); @@ -149,7 +148,7 @@ std::wstring command_line_str(L"UpdaterSetup.exe"); std::string long_tag(updater::kInstallerMaxCommandString + 1, 'A'); command_line_str = base::SysUTF8ToWide( - base::StrCat({"UpdaterSetup.exe ", install_switch, long_tag})); + base::StrCat({"UpdaterSetup.exe ", tag_switch, long_tag})); updater::ProcessExitResult exit_result = updater::BuildInstallerCommandLineArguments(command_line_str.c_str(), cmd_line_args.get(),
diff --git a/chrome/updater/win/signing/enterprise_standalone_installer.wxs.xml b/chrome/updater/win/signing/enterprise_standalone_installer.wxs.xml index 6e5905f..337a0818 100644 --- a/chrome/updater/win/signing/enterprise_standalone_installer.wxs.xml +++ b/chrome/updater/win/signing/enterprise_standalone_installer.wxs.xml
@@ -2,7 +2,7 @@ <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'> <?define Copyright = '$(var.ProductOriginalVersionString) Copyright $(var.ProductBuildYear) $(var.CompanyFullName)'?> <?define UpdateKeyPath = 'SOFTWARE\$(var.CompanyName)\Update'?> - <?define InstallCommandBase='--silent --install=[ProductTag] --installsource=enterprisemsi[OptOmahaArgs]'?> + <?define InstallCommandBase='--silent --tag=[ProductTag] --installsource enterprisemsi[OptOmahaArgs]'?> <Product Id='$(var.MsiProductId)'
diff --git a/chromecast/browser/cast_web_contents_impl.cc b/chromecast/browser/cast_web_contents_impl.cc index d7bf3e3..9a818ff 100644 --- a/chromecast/browser/cast_web_contents_impl.cc +++ b/chromecast/browser/cast_web_contents_impl.cc
@@ -45,6 +45,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "net/base/net_errors.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/navigation/navigation_params.h" #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h" #include "third_party/blink/public/mojom/autoplay/autoplay.mojom.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" @@ -735,6 +736,13 @@ navigation_handle->GetURL(), navigation_handle->GetRenderFrameHost()); } + // Always allow mixed content (https and http in the same page) for cast. + // TODO(https://crbug.com/333795270): Decide whether to use + // kKeyAllowInsecureContent to configure allowing mixed content. + auto content_settings = blink::CreateDefaultRendererContentSettings(); + content_settings->allow_mixed_content = true; + navigation_handle->SetContentSettings(std::move(content_settings)); + // Notifies observers that the navigation of the main frame is ready. for (Observer& observer : sync_observers_) { observer.MainFrameReadyToCommitNavigation(navigation_handle);
diff --git a/chromeos/ash/components/standalone_browser/browser_support.cc b/chromeos/ash/components/standalone_browser/browser_support.cc index a7ab25016..a12f5ee 100644 --- a/chromeos/ash/components/standalone_browser/browser_support.cc +++ b/chromeos/ash/components/standalone_browser/browser_support.cc
@@ -13,6 +13,7 @@ #include "base/metrics/histogram_functions.h" #include "base/system/sys_info.h" #include "chromeos/ash/components/standalone_browser/lacros_availability.h" +#include "chromeos/ash/components/standalone_browser/migrator_util.h" #include "chromeos/ash/components/standalone_browser/standalone_browser_features.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" @@ -52,6 +53,81 @@ } } +// Returns whether or not lacros is allowed for the Primary user, +// with given LacrosAvailability policy. +bool IsAllowedInternal(const user_manager::User* user, + LacrosAvailability lacros_availability) { + if (IsLacrosDisallowedByCommand() || !BrowserSupport::IsCpuSupported()) { + // This happens when Ash is restarted in multi-user session, meaning there + // are more than two users logged in to the device. This will not cause an + // accidental removal of Lacros data because for the primary user, the fact + // that the device is in multi-user session means that Lacros was not + // enabled beforehand. And for secondary users, data removal does not happen + // even if Lacros is disabled. + return false; + } + + if (!user) { + // User is not available. Practically, this is accidentally happening + // if related function is called before session, or in testing. + // TODO(crbug.com/1408962): We should limit this at least only for + // testing. + return false; + } + + if (!IsUserTypeAllowed(*user)) { + return false; + } + + switch (lacros_availability) { + case LacrosAvailability::kLacrosDisallowed: + return false; + case LacrosAvailability::kUserChoice: + case LacrosAvailability::kLacrosOnly: + return true; + } +} + +// Returns whether the standalone browser (a.k.a. Lacros) is enabled. +// Practically, before invoking this, BrowserSupport::IsAllowedInternal() +// needs to be called and make sure it returns true. +bool IsEnabledInternal(const user_manager::User* user, + LacrosAvailability lacros_availability, + bool check_migration_status) { + DCHECK(user); + + // If profile migration is enabled, the completion of it is necessary for + // Lacros to be enabled. + if (check_migration_status && + !base::FeatureList::IsEnabled( + features::kLacrosProfileMigrationForceOff)) { + PrefService* local_state = + user_manager::UserManager::Get()->GetLocalState(); + // Note that local_state can be nullptr in tests. + if (local_state && !migrator_util::IsProfileMigrationCompletedForUser( + local_state, user->username_hash())) { + // If migration has not been completed, do not enable lacros. + return false; + } + } + + switch (lacros_availability) { + case LacrosAvailability::kUserChoice: + break; + case LacrosAvailability::kLacrosDisallowed: + NOTREACHED(); // Guarded by IsLacrosAllowedInternal, called before. + return false; + case LacrosAvailability::kLacrosOnly: + return true; + } + + if (base::FeatureList::IsEnabled(features::kLacrosOnly)) { + return true; + } + + return false; +} + } // namespace BrowserSupport::BrowserSupport(bool is_allowed) : is_allowed_(is_allowed) { @@ -126,39 +202,15 @@ g_cpu_supported_override_ = value; } -// Returns whether or not lacros is allowed for the Primary user, -// with given LacrosAvailability policy. -bool BrowserSupport::IsAllowedInternal(const user_manager::User* user, - LacrosAvailability lacros_availability) { - if (IsLacrosDisallowedByCommand() || !IsCpuSupported()) { - // This happens when Ash is restarted in multi-user session, meaning there - // are more than two users logged in to the device. This will not cause an - // accidental removal of Lacros data because for the primary user, the fact - // that the device is in multi-user session means that Lacros was not - // enabled beforehand. And for secondary users, data removal does not happen - // even if Lacros is disabled. +bool BrowserSupport::IsEnabledInternal(const user_manager::User* user, + LacrosAvailability lacros_availability, + bool check_migration_status) { + if (!IsAllowedInternal(user, lacros_availability)) { return false; } - if (!user) { - // User is not available. Practically, this is accidentally happening - // if related function is called before session, or in testing. - // TODO(crbug.com/1408962): We should limit this at least only for - // testing. - return false; - } - - if (!IsUserTypeAllowed(*user)) { - return false; - } - - switch (lacros_availability) { - case LacrosAvailability::kLacrosDisallowed: - return false; - case LacrosAvailability::kUserChoice: - case LacrosAvailability::kLacrosOnly: - return true; - } + return ash::standalone_browser::IsEnabledInternal(user, lacros_availability, + check_migration_status); } } // namespace ash::standalone_browser
diff --git a/chromeos/ash/components/standalone_browser/browser_support.h b/chromeos/ash/components/standalone_browser/browser_support.h index b74a0b4..1859c716 100644 --- a/chromeos/ash/components/standalone_browser/browser_support.h +++ b/chromeos/ash/components/standalone_browser/browser_support.h
@@ -54,8 +54,9 @@ // Temporarily exposing internal function for transition period. // TODO(crbug.com/1494005): Hide the function along with refactoring. - static bool IsAllowedInternal(const user_manager::User* user, - LacrosAvailability lacros_availability); + static bool IsEnabledInternal(const user_manager::User* user, + LacrosAvailability lacros_availability, + bool check_migration_status); private: BrowserSupport(bool is_allowed);
diff --git a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc index f3d087cc..63d2317 100644 --- a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc +++ b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
@@ -1380,6 +1380,7 @@ case apps::PackageType::kUnknown: case apps::PackageType::kBorealis: case apps::PackageType::kChromeApp: + case apps::PackageType::kGeForceNow: return crosapi::mojom::PackageIdType::kUnknown; } }
diff --git a/clank b/clank index 64fe84c..1e8d9e0 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 64fe84c44408d892262ac3b64317ba9c697d267c +Subproject commit 1e8d9e0abee2cc46c667b23e3ccccceb50f9ac37
diff --git a/components/android_autofill/browser/autofill_provider_android.cc b/components/android_autofill/browser/autofill_provider_android.cc index 7335d07..12ac65a 100644 --- a/components/android_autofill/browser/autofill_provider_android.cc +++ b/components/android_autofill/browser/autofill_provider_android.cc
@@ -789,6 +789,8 @@ pw_form.password_element_renderer_id.value()); SCOPED_CRASH_KEY_NUMBER("crbug1523259", "fs.fields.size", form_structure.fields().size()); + SCOPED_CRASH_KEY_NUMBER("crbug1523259", "fs.form_signature", + form_structure.form_signature().value()); SCOPED_CRASH_KEY_STRING1024("crbug1523259", "fs.fields.global_ids", [&] { std::ostringstream ss; for (size_t i = 0;
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 23bc3726..932d653 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -1021,11 +1021,22 @@ } last_queried_element_ = FieldRef(element); - const bool is_address_or_payments_manual_fallback = - IsAddressAutofillManuallyTriggered(trigger_source) || - IsPaymentsAutofillManuallyTriggered(trigger_source); - if (!is_address_or_payments_manual_fallback && - form_util::IsAutofillableInputElement(input_element)) { + + // Manual fallbacks override any prioritization done based on the field type. + // TODO(b/333990908): Test manual fallback on different form types. + if (IsAddressAutofillManuallyTriggered(trigger_source) || + IsPaymentsAutofillManuallyTriggered(trigger_source)) { + QueryAutofillSuggestions(element, trigger_source); + return; + } + if (IsPasswordsAutofillManuallyTriggered(trigger_source)) { + is_popup_possibly_visible_ = password_autofill_agent_->ShowSuggestions( + input_element, trigger_source); + return; + } + + // Proceed with generating suggestions based on the field type. + if (form_util::IsAutofillableInputElement(input_element)) { if (password_generation_agent_ && password_generation_agent_->ShowPasswordGenerationSuggestions( input_element)) { @@ -1040,17 +1051,15 @@ } // Password field elements should only have suggestions shown by the password - // autofill agent. Unless an address or payments manual fallback option is - // chosen. The /*disable presubmit*/ comment below is used to disable a - // presubmit script that ensures that only IsPasswordFieldForAutofill() is + // autofill agent. The /*disable presubmit*/ comment below is used to disable + // a presubmit script that ensures that only IsPasswordFieldForAutofill() is // used in this code (it has to appear between the function name and the // parenthesis to not match a regex). In this specific case we are actually // interested in whether the field is currently a password field, not whether // it has ever been a password field. if (!input_element.IsNull() && input_element.IsPasswordField /*disable presubmit*/ () && - !config_.query_password_suggestions && - !is_address_or_payments_manual_fallback) { + !config_.query_password_suggestions) { return; }
diff --git a/components/autofill/core/browser/address_data_manager.cc b/components/autofill/core/browser/address_data_manager.cc index 7e90865..5b5d75e5 100644 --- a/components/autofill/core/browser/address_data_manager.cc +++ b/components/autofill/core/browser/address_data_manager.cc
@@ -295,6 +295,13 @@ return sync_service_->GetActiveDataTypes().Has(syncer::CONTACT_INFO); } +bool AddressDataManager::IsCountryEligibleForAccountStorage( + std::string_view country_code) const { + constexpr char const* kUnsupportedCountries[] = {"CU", "IR", "KP", "SD", + "SY"}; + return !base::Contains(kUnsupportedCountries, country_code); +} + void AddressDataManager::MigrateProfileToAccount( const AutofillProfile& profile) { CHECK_EQ(profile.source(), AutofillProfile::Source::kLocalOrSyncable);
diff --git a/components/autofill/core/browser/address_data_manager.h b/components/autofill/core/browser/address_data_manager.h index afaf573f..c3e3e65 100644 --- a/components/autofill/core/browser/address_data_manager.h +++ b/components/autofill/core/browser/address_data_manager.h
@@ -127,6 +127,11 @@ // Autofill address profiles to their account. virtual bool IsEligibleForAddressAccountStorage() const; + // Users based in unsupported countries and profiles with a country value set + // to an unsupported country are not eligible for account storage. This + // function determines if the `country_code` is eligible. + bool IsCountryEligibleForAccountStorage(std::string_view country_code) const; + // Migrates a given kLocalOrSyncable `profile` to source kAccount. This has // multiple side-effects for the profile: // - It is stored in a different backend.
diff --git a/components/autofill/core/browser/address_data_manager_unittest.cc b/components/autofill/core/browser/address_data_manager_unittest.cc index 053c1ae..6dab9bb 100644 --- a/components/autofill/core/browser/address_data_manager_unittest.cc +++ b/components/autofill/core/browser/address_data_manager_unittest.cc
@@ -650,6 +650,11 @@ EXPECT_FALSE(address_data_manager().IsEligibleForAddressAccountStorage()); } +TEST_F(AddressDataManagerTest, IsCountryEligibleForAccountStorage) { + EXPECT_TRUE(address_data_manager().IsCountryEligibleForAccountStorage("AT")); + EXPECT_FALSE(address_data_manager().IsCountryEligibleForAccountStorage("IR")); +} + TEST_F(AddressDataManagerTest, MigrateProfileToAccount) { const AutofillProfile kLocalProfile = test::GetFullProfile(); ASSERT_EQ(kLocalProfile.source(), AutofillProfile::Source::kLocalOrSyncable);
diff --git a/components/autofill/core/browser/autofill_profile_import_process.cc b/components/autofill/core/browser/autofill_profile_import_process.cc index 2891e16..8b88ab9 100644 --- a/components/autofill/core/browser/autofill_profile_import_process.cc +++ b/components/autofill/core/browser/autofill_profile_import_process.cc
@@ -261,8 +261,8 @@ CHECK(import_candidate_); if (personal_data_manager_->address_data_manager() .IsEligibleForAddressAccountStorage() && - personal_data_manager_->IsCountryEligibleForAccountStorage( - base::UTF16ToUTF8( + personal_data_manager_->address_data_manager() + .IsCountryEligibleForAccountStorage(base::UTF16ToUTF8( import_candidate_->GetRawInfo(ADDRESS_HOME_COUNTRY)))) { import_candidate_ = import_candidate_->ConvertToAccountProfile(); }
diff --git a/components/autofill/core/browser/heuristic_classification_unittests.cc b/components/autofill/core/browser/heuristic_classification_unittests.cc index 7f93a2437..258eca9 100644 --- a/components/autofill/core/browser/heuristic_classification_unittests.cc +++ b/components/autofill/core/browser/heuristic_classification_unittests.cc
@@ -626,13 +626,18 @@ // Replace \r\n on windows with \n to get a canonical representation. base::RemoveChars(*output_json_text, "\r", &(*output_json_text)); - // Write output if and only if it is different. - if (input_json_text != output_json_text) { base::FilePath output_file = GetParam().AddExtension(FILE_PATH_LITERAL(".new")); - LOG(ERROR) << "Classifications changed. Writing new file " << output_file; - EXPECT_TRUE(base::WriteFile(output_file, *output_json_text)); - } + if (input_json_text != output_json_text) { + // Write output if and only if it is different. + LOG(ERROR) << "Classifications changed. Writing new file " << output_file; + EXPECT_TRUE(base::WriteFile(output_file, *output_json_text)); + } else { + // If output is as expected, delete stale .new files. + if (base::PathExists(output_file)) { + base::DeleteFile(output_file); + } + } EXPECT_EQ(old_stats, new_stats);
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 5bad1cd5..6b23f5fa 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -10,7 +10,6 @@ #include <utility> #include "base/check_deref.h" -#include "base/containers/contains.h" #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/functional/callback.h" @@ -210,9 +209,8 @@ bool PersonalDataManager::IsCountryEligibleForAccountStorage( std::string_view country_code) const { - constexpr char const* kUnsupportedCountries[] = {"CU", "IR", "KP", "SD", - "SY"}; - return !base::Contains(kUnsupportedCountries, country_code); + return address_data_manager_->IsCountryEligibleForAccountStorage( + country_code); } void PersonalDataManager::MigrateProfileToAccount(
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 2ec970b7..ba66fecdf 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -208,9 +208,8 @@ // TODO(crbug.com/1487119): Change return type to const AutofillProfile* AutofillProfile* GetProfileByGUID(const std::string& guid) const; - // Users based in unsupported countries and profiles with a country value set - // to an unsupported country are not eligible for account storage. This - // function determines if the `country_code` is eligible. + // TODO(b/322170538): Deprecated. Use the functions in + // `address_data_manager()` instead. Migrate remaining callers. bool IsCountryEligibleForAccountStorage(std::string_view country_code) const; // Migrates a given kLocalOrSyncable `profile` to source kAccount. This has
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index 90e0839..ecd73e0 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -4,16 +4,9 @@ #include "components/autofill/core/browser/personal_data_manager.h" -#include <memory> -#include <string> -#include <utility> - -#include "base/strings/utf_string_conversions.h" #include "base/test/mock_callback.h" #include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/personal_data_manager_test_base.h" -#include "components/autofill/core/common/autofill_prefs.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,48 +15,29 @@ class PersonalDataManagerTest : public PersonalDataManagerTestBase, public testing::Test { protected: - PersonalDataManagerTest() = default; - ~PersonalDataManagerTest() override { - if (personal_data_) - personal_data_->Shutdown(); + personal_data_->Shutdown(); personal_data_.reset(); } void SetUp() override { SetUpTest(); - ResetPersonalDataManager(); - } - void TearDown() override { TearDownTest(); } - - void ResetPersonalDataManager(bool use_sync_transport_mode = false) { - if (personal_data_) - personal_data_->Shutdown(); personal_data_ = std::make_unique<PersonalDataManager>("EN", "US"); PersonalDataManagerTestBase::ResetPersonalDataManager( - use_sync_transport_mode, personal_data_.get()); + /*use_sync_transport_mode=*/false, personal_data_.get()); } - - void AddProfileToPersonalDataManager(const AutofillProfile& profile) { - PersonalDataChangedWaiter waiter(*personal_data_); - personal_data_->AddProfile(profile); - std::move(waiter).Wait(); - } + void TearDown() override { TearDownTest(); } std::unique_ptr<PersonalDataManager> personal_data_; }; -TEST_F(PersonalDataManagerTest, IsCountryEligibleForAccountStorage) { - EXPECT_TRUE(personal_data_->IsCountryEligibleForAccountStorage("AT")); - EXPECT_FALSE(personal_data_->IsCountryEligibleForAccountStorage("IR")); -} - TEST_F(PersonalDataManagerTest, ChangeCallbackIsTriggeredOnAddedProfile) { ::testing::StrictMock<base::MockOnceClosure> callback; EXPECT_CALL(callback, Run); - personal_data_->AddChangeCallback(callback.Get()); - AddProfileToPersonalDataManager(test::GetFullProfile()); + PersonalDataChangedWaiter waiter(*personal_data_); + personal_data_->AddProfile(test::GetFullProfile()); + std::move(waiter).Wait(); } } // namespace autofill
diff --git a/components/autofill/core/browser/profile_requirement_utils.cc b/components/autofill/core/browser/profile_requirement_utils.cc index 89a331c..77020ca5 100644 --- a/components/autofill/core/browser/profile_requirement_utils.cc +++ b/components/autofill/core/browser/profile_requirement_utils.cc
@@ -162,8 +162,9 @@ .IsEligibleForAddressAccountStorage() && !personal_data_manager.address_data_manager() .IsProfileMigrationBlocked(profile.guid()) && - personal_data_manager.IsCountryEligibleForAccountStorage( - base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))); + personal_data_manager.address_data_manager() + .IsCountryEligibleForAccountStorage( + base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))); } } // namespace autofill
diff --git a/components/feed/OWNERS b/components/feed/OWNERS index 89657b3..780f3a1c 100644 --- a/components/feed/OWNERS +++ b/components/feed/OWNERS
@@ -1,5 +1,4 @@ carlosk@chromium.org -chili@chromium.org dewittj@chromium.org harringtond@chromium.org iwells@chromium.org
diff --git a/components/neterror/OWNERS b/components/neterror/OWNERS index 4f7c650f..dc46f40 100644 --- a/components/neterror/OWNERS +++ b/components/neterror/OWNERS
@@ -3,5 +3,4 @@ file://net/OWNERS # Offline owners. -chili@chromium.org jianli@chromium.org
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc index 9b5bac2c..b08521c 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -9,8 +9,6 @@ #include <string> #include <utility> -#include "base/debug/crash_logging.h" -#include "base/debug/dump_without_crashing.h" #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" @@ -57,15 +55,17 @@ CHECK(navigation_handle->HasCommitted()); const net::HttpResponseHeaders* response_headers = navigation_handle->GetResponseHeaders(); - if (!response_headers) + if (!response_headers) { return -1; + } return response_headers->response_code(); } UserInitiatedInfo CreateUserInitiatedInfo( content::NavigationHandle* navigation_handle) { - if (!navigation_handle->IsRendererInitiated()) + if (!navigation_handle->IsRendererInitiated()) { return UserInitiatedInfo::BrowserInitiated(); + } return UserInitiatedInfo::RenderInitiated( navigation_handle->HasUserGesture(), @@ -93,8 +93,9 @@ for (auto web_feature : web_features) { CHECK_NE(web_feature, blink::mojom::WebFeature::kPageVisits) << "WebFeature::kPageVisits is a reserved feature."; - if (web_feature == blink::mojom::WebFeature::kPageVisits) + if (web_feature == blink::mojom::WebFeature::kPageVisits) { continue; + } features.emplace_back(blink::mojom::UseCounterFeatureType::kWebFeature, static_cast<uint32_t>(web_feature)); @@ -132,11 +133,13 @@ mojo::PendingAssociatedReceiver<mojom::PageLoadMetrics> receiver, content::RenderFrameHost* rfh) { auto* web_contents = content::WebContents::FromRenderFrameHost(rfh); - if (!web_contents) + if (!web_contents) { return; + } auto* observer = MetricsWebContentsObserver::FromWebContents(web_contents); - if (!observer) + if (!observer) { return; + } observer->page_load_metrics_receivers_.Bind(rfh, std::move(receiver)); } @@ -155,8 +158,9 @@ // Do this before clearing `primary_page_`, so that the observers don't hit // the CHECK in MetricsWebContentsObserver::GetDelegateForCommittedLoad. - for (auto& observer : lifecycle_observers_) + for (auto& observer : lifecycle_observers_) { observer.OnGoingAway(); + } UnregisterInputEventObserver(web_contents()->GetPrimaryMainFrame()); @@ -173,14 +177,16 @@ void MetricsWebContentsObserver::RegisterInputEventObserver( content::RenderFrameHost* host) { - if (host != nullptr) + if (host != nullptr) { host->GetRenderWidgetHost()->AddInputEventObserver(this); + } } void MetricsWebContentsObserver::UnregisterInputEventObserver( content::RenderFrameHost* host) { - if (host != nullptr) + if (host != nullptr) { host->GetRenderWidgetHost()->RemoveInputEventObserver(this); + } } void MetricsWebContentsObserver::RenderFrameHostChanged( @@ -197,8 +203,9 @@ void MetricsWebContentsObserver::FrameDeleted(int frame_tree_node_id) { content::RenderFrameHost* rfh = web_contents()->UnsafeFindFrameByFrameTreeNodeId(frame_tree_node_id); - if (!rfh) + if (!rfh) { return; + } // Deletion of FrameTreeNode follows deletion of RenderFrameHost. If the node // is root of the page, corresponding PageLoadTracker has gone at this timing. @@ -211,11 +218,13 @@ void MetricsWebContentsObserver::RenderFrameDeleted( content::RenderFrameHost* rfh) { - if (auto* memory_tracker = GetMemoryTracker()) + if (auto* memory_tracker = GetMemoryTracker()) { memory_tracker->OnRenderFrameDeleted(rfh, this); + } - if (PageLoadTracker* tracker = GetPageLoadTracker(rfh)) + if (PageLoadTracker* tracker = GetPageLoadTracker(rfh)) { tracker->RenderFrameDeleted(rfh); + } content::GlobalRenderFrameHostId rfh_id = rfh->GetGlobalId(); auto new_end_it = std::remove_if(queued_memory_updates_.begin(), @@ -227,8 +236,9 @@ // PageLoadTracker and smoothness data can be associated only with a main // frame. - if (rfh->GetParent()) + if (rfh->GetParent()) { return; + } active_pages_.erase(rfh); inactive_pages_.erase(rfh); ukm_smoothness_data_.erase(rfh); @@ -242,8 +252,9 @@ // Ignore media that starts playing in a page that was navigated away // from. - if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) + if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) { tracker->MediaStartedPlaying(video_type, render_frame_host); + } } void MetricsWebContentsObserver::WillStartNavigationRequest( @@ -252,8 +263,9 @@ // WillStartNavigationRequest. CHECK(!navigation_handle->IsSameDocument()); - if (!navigation_handle->IsInMainFrame()) + if (!navigation_handle->IsInMainFrame()) { return; + } WillStartNavigationRequestImpl(navigation_handle); has_navigated_ = true; @@ -271,8 +283,9 @@ page_load_metrics_receivers_(web_contents, this) { // NoStatePrefetch loads erroneously report that they are initially visible, // so we manually override visibility state for prerender. - if (embedder_interface_->IsNoStatePrefetch(web_contents)) + if (embedder_interface_->IsNoStatePrefetch(web_contents)) { in_foreground_ = false; + } RegisterInputEventObserver(web_contents->GetPrimaryMainFrame()); } @@ -285,8 +298,9 @@ NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle, user_initiated_info); - if (!ShouldTrackMainFrameNavigation(navigation_handle)) + if (!ShouldTrackMainFrameNavigation(navigation_handle)) { return; + } // Pass in the last committed url to the PageLoadTracker. If the MWCO has // never observed a committed load, use the last committed url from this @@ -336,8 +350,9 @@ // but reuse an existing one that was created for the initial prerendering // navigation so that the same instance will bee OnPrerenderStart and // DidActivatePrerenderedPage. - if (navigation_handle->IsPrerenderedPageActivation()) + if (navigation_handle->IsPrerenderedPageActivation()) { return; + } // Passing raw pointers to `embedder_interface_` is safe because the // MetricsWebContentsObserver owns them both list and they are torn down after @@ -351,15 +366,17 @@ parent_tracker))); CHECK(insertion_result.second) << "provisional_loads_ already contains NavigationHandle."; - for (auto& observer : lifecycle_observers_) + for (auto& observer : lifecycle_observers_) { observer.OnTrackerCreated(insertion_result.first->second.get()); + } } void MetricsWebContentsObserver::WillProcessNavigationResponse( content::NavigationHandle* navigation_handle) { auto it = provisional_loads_.find(navigation_handle); - if (it == provisional_loads_.end()) + if (it == provisional_loads_.end()) { return; + } it->second->WillProcessNavigationResponse(navigation_handle); } @@ -393,8 +410,9 @@ // load, `primary_page_` or `active_pages_`. If the resource // request was started before this navigation of them, then it should be // ignored. Check `primary_page_` here as its start time is the oldest one. - if (!primary_page_ || creation_time < primary_page_->navigation_start()) + if (!primary_page_ || creation_time < primary_page_->navigation_start()) { return nullptr; + } // Sub-frame resources have a null RFH when browser-side navigation is // enabled, so we can't perform the RFH check below for them. @@ -404,13 +422,15 @@ // for sub-frames similar to the main-frame lookup above. Now we have // `active_pages_` in addition to `primary_page_`, and the following code // cannot handle sub-frames inside FencedFrames. - if (blink::IsRequestDestinationFrame(request_destination)) + if (blink::IsRequestDestinationFrame(request_destination)) { return primary_page_.get(); + } // This was originally a CHECK but it fails when the document load happened // after client certificate selection. - if (!render_frame_host_or_null) + if (!render_frame_host_or_null) { return nullptr; + } // There is a race here: a completed resource for the previously committed // page can arrive after the new page has committed. In this case, we may @@ -465,22 +485,25 @@ void MetricsWebContentsObserver::FrameReceivedUserActivation( content::RenderFrameHost* render_frame_host) { - if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) + if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) { tracker->FrameReceivedUserActivation(render_frame_host); + } } void MetricsWebContentsObserver::FrameDisplayStateChanged( content::RenderFrameHost* render_frame_host, bool is_display_none) { - if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) + if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) { tracker->FrameDisplayStateChanged(render_frame_host, is_display_none); + } } void MetricsWebContentsObserver::FrameSizeChanged( content::RenderFrameHost* render_frame_host, const gfx::Size& frame_size) { - if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) + if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) { tracker->FrameSizeChanged(render_frame_host, frame_size); + } } void MetricsWebContentsObserver::OnCookiesAccessed( @@ -494,19 +517,22 @@ // For uncommitted main frame navigations, find a tracker from // `provisional_loads_`. auto it = provisional_loads_.find(navigation); - if (it != provisional_loads_.end()) + if (it != provisional_loads_.end()) { tracker = it->second.get(); + } } - if (tracker) + if (tracker) { OnCookiesAccessedImpl(*tracker, details); + } } void MetricsWebContentsObserver::OnCookiesAccessed( content::RenderFrameHost* rfh, const content::CookieAccessDetails& details) { - if (PageLoadTracker* tracker = GetPageLoadTracker(rfh)) + if (PageLoadTracker* tracker = GetPageLoadTracker(rfh)) { OnCookiesAccessedImpl(*tracker, details); + } } void MetricsWebContentsObserver::OnCookiesAccessedImpl( @@ -536,14 +562,9 @@ void MetricsWebContentsObserver::DidActivatePreviewedPage( base::TimeTicks activation_time) { + // TODO(b:334709645): Investigate how nullptr cases happen. if (primary_page_) { primary_page_->DidActivatePreviewedPage(activation_time); - } else { - // TODO(b:330324142): Speculative fix to avoid crash cases. Need extra - // investigation why this happens once we ensure the case. - SCOPED_CRASH_KEY_STRING32("b/330324142", "Null", - "MetricsWebContentsObserver::primary_page_"); - base::debug::DumpWithoutCrashing(); } } @@ -570,22 +591,25 @@ if (navigation_handle->IsInPrimaryMainFrame()) { // Notify `primary_page_` that we are ready to commit a navigation to a // new page in the primary main frame. - if (primary_page_) + if (primary_page_) { primary_page_->ReadyToCommitNavigation(navigation_handle); + } } else if (navigation_handle->IsInMainFrame()) { // For non-primary main frame, we notify the PageLoadTracker associated with // the RenderFrameHost that triggers the navigation. PageLoadTracker* tracker = GetPageLoadTracker(navigation_handle->GetRenderFrameHost()); - if (tracker) + if (tracker) { tracker->ReadyToCommitNavigation(navigation_handle); + } } else { // For subframe navigations, notify the PageLoadTracker associated with the // main frame. PageLoadTracker* tracker = GetPageLoadTracker(navigation_handle->GetParentFrame()); - if (tracker) + if (tracker) { tracker->ReadyToCommitNavigation(navigation_handle); + } } } @@ -616,17 +640,20 @@ CHECK(navigation_handle->IsInMainFrame()); if (navigation_handle->HasCommitted() && navigation_handle->IsSameDocument()) { - if (navigation_handle_tracker) + if (navigation_handle_tracker) { navigation_handle_tracker->StopTracking(); + } if (navigation_handle->IsInPrimaryMainFrame()) { - if (primary_page_) + if (primary_page_) { primary_page_->DidCommitSameDocumentNavigation(navigation_handle); + } } else { // Handle the event for non-primary main frames, i.e., FencedFrames. PageLoadTracker* tracker = GetPageLoadTracker(navigation_handle->GetRenderFrameHost()); - if (tracker) + if (tracker) { tracker->DidCommitSameDocumentNavigation(navigation_handle); + } } return; } @@ -667,12 +694,14 @@ // If `navigation_handle` already has an associated PageLoadTracker in // `inactive_pages_`, move it into `primary_page_`. - if (MaybeActivatePageLoadTracker(navigation_handle)) + if (MaybeActivatePageLoadTracker(navigation_handle)) { return; + } } - if (!navigation_handle_tracker) + if (!navigation_handle_tracker) { return; + } if (!ShouldTrackMainFrameNavigation(navigation_handle)) { navigation_handle_tracker->StopTracking(); @@ -714,8 +743,9 @@ is_aborted_provisional_load ? END_OTHER : END_PROVISIONAL_LOAD_FAILED, UserInitiatedInfo::NotUserInitiated(), now, true); - if (is_aborted_provisional_load) + if (is_aborted_provisional_load) { aborted_provisional_loads_.push_back(std::move(tracker)); + } } void MetricsWebContentsObserver::HandleCommittedNavigationForTrackedLoad( @@ -744,8 +774,9 @@ // just fails. It results in destructing the moved tracker unexpectedly. // To avoid this problem, we ensure destructing existing tracker beforehand. auto it = active_pages_.find(navigation_handle->GetRenderFrameHost()); - if (it != active_pages_.end()) + if (it != active_pages_.end()) { active_pages_.erase(it); + } active_pages_.emplace(navigation_handle->GetRenderFrameHost(), std::move(tracker)); @@ -753,8 +784,9 @@ raw_tracker->Commit(navigation_handle); CHECK(raw_tracker->did_commit()); - for (auto& observer : lifecycle_observers_) + for (auto& observer : lifecycle_observers_) { observer.OnCommit(raw_tracker); + } auto* render_frame_host = navigation_handle->GetRenderFrameHost(); const bool is_main_frame = @@ -791,8 +823,9 @@ "MaybeRestorePageLoadTrackerForBackForwardCache", "next_navigation", next_navigation_handle); - if (!previously_committed_load) + if (!previously_committed_load) { return; + } content::RenderFrameHost* previous_frame = content::RenderFrameHost::FromID( next_navigation_handle->GetPreviousRenderFrameHostId()); @@ -805,8 +838,9 @@ (previous_frame->GetLifecycleState() == content::RenderFrameHost::LifecycleState::kInBackForwardCache); - if (!is_back_forward_cache) + if (!is_back_forward_cache) { return; + } previously_committed_load->OnEnterBackForwardCache(); inactive_pages_.emplace(previous_frame, std::move(previously_committed_load)); @@ -830,8 +864,9 @@ // `navigation_handle` is served from the back/forward cache. For example, // if a page is put into the cache before MetricsWebContents is created, // `inactive_pages_` is empty. - if (it == inactive_pages_.end()) + if (it == inactive_pages_.end()) { return false; + } active_pages_.clear(); @@ -844,11 +879,13 @@ primary_main_frame->ForEachRenderFrameHost( [&](content::RenderFrameHost* rfh) { // Skip RenderFrameHosts that aren't main frames. - if (rfh != rfh->GetMainFrame()) + if (rfh != rfh->GetMainFrame()) { return; + } auto it = inactive_pages_.find(rfh); - if (it == inactive_pages_.end()) + if (it == inactive_pages_.end()) { return; + } PageLoadTracker* tracker; if (rfh == primary_main_frame) { primary_page_ = std::move(it->second); @@ -865,8 +902,9 @@ } }); - for (auto& observer : lifecycle_observers_) + for (auto& observer : lifecycle_observers_) { observer.OnActivate(primary_page_.get()); + } return true; } @@ -902,12 +940,14 @@ void MetricsWebContentsObserver::OnInputEvent( const blink::WebInputEvent& event) { // Ignore browser navigation or reload which comes with type Undefined. - if (event.GetType() == blink::WebInputEvent::Type::kUndefined) + if (event.GetType() == blink::WebInputEvent::Type::kUndefined) { return; + } // For now, we assume input events occur only in primary page. - if (primary_page_) + if (primary_page_) { primary_page_->OnInputEvent(event); + } } void MetricsWebContentsObserver::FlushMetricsOnAppEnterBackground() { @@ -917,8 +957,9 @@ // anything about foreground / background state of the associated tab as part // of this method call. - if (primary_page_) + if (primary_page_) { primary_page_->FlushMetricsOnAppEnterBackground(); + } for (const auto& kv : active_pages_) { kv.second->FlushMetricsOnAppEnterBackground(); } @@ -935,43 +976,53 @@ void MetricsWebContentsObserver::DidRedirectNavigation( content::NavigationHandle* navigation_handle) { - if (!navigation_handle->IsInMainFrame()) + if (!navigation_handle->IsInMainFrame()) { return; + } auto it = provisional_loads_.find(navigation_handle); - if (it == provisional_loads_.end()) + if (it == provisional_loads_.end()) { return; + } it->second->Redirect(navigation_handle); } void MetricsWebContentsObserver::OnVisibilityChanged( content::Visibility visibility) { - if (web_contents_will_soon_be_destroyed_) + if (web_contents_will_soon_be_destroyed_) { return; + } bool was_in_foreground = in_foreground_; in_foreground_ = visibility == content::Visibility::VISIBLE; - if (in_foreground_ == was_in_foreground) + if (in_foreground_ == was_in_foreground) { return; + } if (in_foreground_) { - if (primary_page_) + if (primary_page_) { primary_page_->PageShown(); - for (const auto& kv : active_pages_) + } + for (const auto& kv : active_pages_) { kv.second->PageShown(); + } for (const auto& kv : provisional_loads_) { // Prerendered pages are always invisible regardless of the WebContents' // visibility status. - if (!kv.first->IsInPrerenderedMainFrame()) + if (!kv.first->IsInPrerenderedMainFrame()) { kv.second->PageShown(); + } } } else { - if (primary_page_) + if (primary_page_) { primary_page_->PageHidden(); - for (const auto& kv : active_pages_) + } + for (const auto& kv : active_pages_) { kv.second->PageHidden(); + } for (const auto& kv : provisional_loads_) { - if (!kv.first->IsInPrerenderedMainFrame()) + if (!kv.first->IsInPrerenderedMainFrame()) { kv.second->PageHidden(); + } } } @@ -1053,16 +1104,19 @@ content::NavigationHandle* new_navigation, UserInitiatedInfo user_initiated_info) { // Prerendering navigations do not abort provisional loads in the active page. - if (new_navigation->IsInPrerenderedMainFrame()) + if (new_navigation->IsInPrerenderedMainFrame()) { return nullptr; + } // If there are multiple aborted loads that can be attributed to this one, // just count the latest one for simplicity. Other loads will fall into the // OTHER bucket, though there shouldn't be very many. - if (aborted_provisional_loads_.empty()) + if (aborted_provisional_loads_.empty()) { return nullptr; - if (aborted_provisional_loads_.size() > 1) + } + if (aborted_provisional_loads_.size() > 1) { RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); + } std::unique_ptr<PageLoadTracker> last_aborted_load = std::move(aborted_provisional_loads_.back()); @@ -1109,8 +1163,9 @@ const bool is_main_frame = (render_frame_host->GetParent() == nullptr); if (is_main_frame) { - if (DoesTimingUpdateHaveError(tracker)) + if (DoesTimingUpdateHaveError(tracker)) { return; + } } else if (!tracker) { RecordInternalError(ERR_SUBFRAME_IPC_WITH_NO_RELEVANT_LOAD); } @@ -1195,29 +1250,34 @@ } // Ignore NTP loads. - if (embedder_interface_->IsNewTabPageUrl(navigation_handle->GetURL())) + if (embedder_interface_->IsNewTabPageUrl(navigation_handle->GetURL())) { return false; + } // The navigation served from the back-forward cache will use the previously // created tracker for the document. - if (navigation_handle->IsServedFromBackForwardCache()) + if (navigation_handle->IsServedFromBackForwardCache()) { return false; + } // For a prerendering activation navigation, we will use a tracker in // `inactive_pages_` created in the initial prerendering navigation. - if (navigation_handle->IsPrerenderedPageActivation()) + if (navigation_handle->IsPrerenderedPageActivation()) { return false; + } if (navigation_handle->HasCommitted()) { // Ignore Chrome error pages (e.g. No Internet connection). - if (navigation_handle->IsErrorPage()) + if (navigation_handle->IsErrorPage()) { return false; + } // Ignore network error pages (e.g. 4xx, 5xx). int http_status_code = GetHttpStatusCode(navigation_handle); if (http_status_code > 0 && - (http_status_code < 200 || http_status_code >= 400)) + (http_status_code < 200 || http_status_code >= 400)) { return false; + } } return true; @@ -1236,8 +1296,9 @@ void MetricsWebContentsObserver::AddLifecycleObserver( MetricsLifecycleObserver* observer) { - if (!lifecycle_observers_.HasObserver(observer)) + if (!lifecycle_observers_.HasObserver(observer)) { lifecycle_observers_.AddObserver(observer); + } } void MetricsWebContentsObserver::RemoveLifecycleObserver( @@ -1249,8 +1310,9 @@ // Prefetching can be triggered by speculation rules (by SpeculationHostImpl:: // UpdateSpeculationCandidates()) or by NavigationPredictor, both of which // work only on behalf of a primary page. - if (primary_page_) + if (primary_page_) { primary_page_->OnPrefetchLikely(); + } } void MetricsWebContentsObserver::OnV8MemoryChanged( @@ -1259,8 +1321,9 @@ for (const MemoryUpdate& update : memory_updates) { content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(update.routing_id); - if (!rfh) + if (!rfh) { continue; + } PageLoadTracker* tracker = GetPageLoadTracker(rfh); if (tracker) { per_tracker_updates[tracker].push_back(update); @@ -1275,17 +1338,20 @@ } } - for (const auto& map_pair : per_tracker_updates) + for (const auto& map_pair : per_tracker_updates) { map_pair.first->OnV8MemoryChanged(map_pair.second); + } } void MetricsWebContentsObserver::OnSharedStorageWorkletHostCreated( content::RenderFrameHost* rfh) { - if (!rfh) + if (!rfh) { return; + } - if (PageLoadTracker* tracker = GetPageLoadTracker(rfh)) + if (PageLoadTracker* tracker = GetPageLoadTracker(rfh)) { tracker->OnSharedStorageWorkletHostCreated(); + } } base::TimeTicks MetricsWebContentsObserver::GetCreated() { @@ -1311,41 +1377,48 @@ // TODO(https://crbug.com/1301880): Use GetPageLoadTracker always. PageLoadTracker* MetricsWebContentsObserver::GetPageLoadTrackerLegacy( content::RenderFrameHost* rfh) { - if (!rfh) + if (!rfh) { return nullptr; + } if (rfh->GetMainFrame()->IsActive()) { auto it = active_pages_.find(rfh->GetMainFrame()); - if (it != active_pages_.end()) + if (it != active_pages_.end()) { return it->second.get(); + } return primary_page_.get(); } auto it = inactive_pages_.find(rfh->GetMainFrame()); - if (it != inactive_pages_.end()) + if (it != inactive_pages_.end()) { return it->second.get(); + } return nullptr; } PageLoadTracker* MetricsWebContentsObserver::GetPageLoadTracker( content::RenderFrameHost* rfh) { - if (!rfh) + if (!rfh) { return nullptr; + } - if (rfh->GetPage().IsPrimary()) + if (rfh->GetPage().IsPrimary()) { return primary_page_.get(); + } { auto it = active_pages_.find(rfh->GetMainFrame()); - if (it != active_pages_.end()) + if (it != active_pages_.end()) { return it->second.get(); + } } { auto it = inactive_pages_.find(rfh->GetMainFrame()); - if (it != inactive_pages_.end()) + if (it != inactive_pages_.end()) { return it->second.get(); + } } return nullptr;
diff --git a/components/services/app_service/public/cpp/app_types.cc b/components/services/app_service/public/cpp/app_types.cc index 7a39c97..239e94d 100644 --- a/components/services/app_service/public/cpp/app_types.cc +++ b/components/services/app_service/public/cpp/app_types.cc
@@ -22,7 +22,13 @@ kExtension, kStandaloneBrowserExtension, kBruschetta) -APP_ENUM_TO_STRING(PackageType, kUnknown, kArc, kChromeApp, kWeb, kBorealis) +APP_ENUM_TO_STRING(PackageType, + kUnknown, + kArc, + kBorealis, + kChromeApp, + kGeForceNow, + kWeb) APP_ENUM_TO_STRING(Readiness, kUnknown, kReady, @@ -94,12 +100,14 @@ return AppType::kUnknown; case PackageType::kArc: return AppType::kArc; - case PackageType::kChromeApp: - return AppType::kChromeApp; - case PackageType::kWeb: - return AppType::kWeb; case PackageType::kBorealis: return AppType::kBorealis; + case PackageType::kChromeApp: + return AppType::kChromeApp; + case PackageType::kGeForceNow: + return std::nullopt; + case PackageType::kWeb: + return AppType::kWeb; } }
diff --git a/components/services/app_service/public/cpp/app_types.h b/components/services/app_service/public/cpp/app_types.h index d6374059..988b6b30 100644 --- a/components/services/app_service/public/cpp/app_types.h +++ b/components/services/app_service/public/cpp/app_types.h
@@ -43,7 +43,7 @@ // // Used by PackageId mapping closely to corresponding values in AppType but // can contain other non-app values e.g. app shortcuts. -ENUM(PackageType, kUnknown, kArc, kChromeApp, kWeb, kBorealis) +ENUM(PackageType, kUnknown, kArc, kBorealis, kChromeApp, kGeForceNow, kWeb) // Whether an app is ready to launch, i.e. installed. // Note the enumeration is used in UMA histogram so entries should not be
diff --git a/components/services/app_service/public/cpp/package_id.cc b/components/services/app_service/public/cpp/package_id.cc index 07a7f8a..85e30de 100644 --- a/components/services/app_service/public/cpp/package_id.cc +++ b/components/services/app_service/public/cpp/package_id.cc
@@ -19,6 +19,7 @@ constexpr char kArcPlatformName[] = "android"; constexpr char kBorealisPlatformName[] = "steam"; constexpr char kChromeAppPlatformName[] = "chromeapp"; +constexpr char kGeForceNowPlatformName[] = "gfn"; constexpr char kWebPlatformName[] = "web"; PackageType PlatformNameToPackageType(std::string_view platform_name) { @@ -28,12 +29,15 @@ if (platform_name == kBorealisPlatformName) { return PackageType::kBorealis; } - if (platform_name == kWebPlatformName) { - return PackageType::kWeb; - } if (platform_name == kChromeAppPlatformName) { return PackageType::kChromeApp; } + if (platform_name == kGeForceNowPlatformName) { + return PackageType::kGeForceNow; + } + if (platform_name == kWebPlatformName) { + return PackageType::kWeb; + } return PackageType::kUnknown; } @@ -48,6 +52,8 @@ return kBorealisPlatformName; case PackageType::kChromeApp: return kChromeAppPlatformName; + case PackageType::kGeForceNow: + return kGeForceNowPlatformName; case PackageType::kWeb: return kWebPlatformName; default:
diff --git a/components/services/app_service/public/cpp/package_id.h b/components/services/app_service/public/cpp/package_id.h index a59bcc4..1f3b3056 100644 --- a/components/services/app_service/public/cpp/package_id.h +++ b/components/services/app_service/public/cpp/package_id.h
@@ -31,6 +31,7 @@ // kArc | "android" | package name | "android:com.foo.bar" // kBorealis | "steam" | Steam Game ID | "steam:123456" // kChromeApp | "chromeapp" | Extension ID | "chromeapp:mmfbcljfglbok" +// kGeForceNow | "gfn" | GeForce Game ID | "gfn:123456" // kWeb | "web" | processed manifest ID | "web:https://app.com/id" class COMPONENT_EXPORT(APP_TYPES) PackageId { public:
diff --git a/components/strings/components_strings_da.xtb b/components/strings/components_strings_da.xtb index 1f4faa0..aba81c54 100644 --- a/components/strings/components_strings_da.xtb +++ b/components/strings/components_strings_da.xtb
@@ -362,7 +362,7 @@ <translation id="1645368109819982629">Ikke-understøttet protokol</translation> <translation id="1650602712345345441">Administrer dine Chrome-indstillinger</translation> <translation id="1652415888492971589">JIS B8</translation> -<translation id="1652862280638399816">Hvis du vil bruge Adgangskodeadministrator sammen med macOS-nøgleringen, skal du genstarte Chromium og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="1652862280638399816">Hvis du vil bruge Adgangskodeadministrator sammen med macOS-nøgleringen, skal du genstarte Chromium og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="1656024727720460136">Chrome har forenklet denne side for at gøre den nemmere at læse. Chrome har hentet den oprindelige side via en sikker forbindelse.</translation> <translation id="1656489000284462475">Afhentning</translation> <translation id="1658111267661135323">Tv og video</translation> @@ -1200,7 +1200,7 @@ <translation id="3303872874382375219">Om en annonce, du ser, er personligt tilpasset, kan afhænge af mange ting, herunder denne indstilling, <ph name="BEGIN_LINK1" />annonceemner<ph name="LINK_END1" />, dine <ph name="BEGIN_LINK2" />cookieindstillinger<ph name="LINK_END2" />, og om det website, du besøger, foretager personlig tilpasning af annoncer. Se, hvordan du <ph name="BEGIN_LINK3" />administrerer privatliv vedrørende annoncering<ph name="LINK_END3" />.</translation> <translation id="3304073249511302126">Bluetooth-scanning</translation> <translation id="3304777285002411338">A2x3</translation> -<translation id="33073482541490531">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. Adgangskodeadministrator anbefaler, at du ændrer denne adgangskode nu.</translation> +<translation id="33073482541490531">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. Adgangskodeadministrator anbefaler, at du ændrer denne adgangskode nu.</translation> <translation id="3307649904964670439">Knappen Tilpas Chrome, aktivér for at tilpasse din browsers udseende</translation> <translation id="3308006649705061278">Organisationsenhed (OU)</translation> <translation id="3310047144791481950">Se oplysninger, der hjælper dig med at vælge, hvilket kort du skal betale med. <ph name="CARD_BENEFIT_HELP_LINK_BEGIN" />Få flere oplysninger om kortfordele<ph name="CARD_BENEFIT_HELP_LINK_END" /></translation> @@ -1267,7 +1267,7 @@ <translation id="3432601291244612633">Luk side</translation> <translation id="3433111389595862568">Software til samarbejde og kommunikation</translation> <translation id="3433144818443565002">Tale- og videochat</translation> -<translation id="3434025015623587566">Google Adgangskodeadministrator skal bruge mere omfattende adgang</translation> +<translation id="3434025015623587566">Google Adgangskodeadministrator skal bruge mere omfattende adgang</translation> <translation id="3434346831962601311">Der er ingen blokerede emner</translation> <translation id="343474037147570563">De filer, du uploader eller vedhæfter, sendes til Google Cloud eller tredjeparter, hvor de analyseres. De kan f.eks. blive scannet for følsomme oplysninger eller malware, og de kan blive gemt i henhold til virksomhedens politikker og være synlige for din administrator.</translation> <translation id="3435557549311968410">Kontinuerlig (kort)</translation> @@ -1445,7 +1445,7 @@ <translation id="372429172604983730">Apps, der kan forårsage denne fejl, er blandt andet antivirus-, firewall- og webfiltrerings- eller proxysoftware.</translation> <translation id="3727101516080730231"><ph name="CREATE_GOOGLE_SLIDE_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryk på Tab-tasten efterfulgt af Enter for hurtigt at oprette en ny Google-præsentation i Slides</translation> <translation id="3727309136762649052">Navneområde</translation> -<translation id="3727850735097852673">Hvis du vil bruge Google Adgangskodeadministrator med macOS-nøgleringen, skal du genstarte Chrome og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="3727850735097852673">Hvis du vil bruge Google Adgangskodeadministrator med macOS-nøgleringen, skal du genstarte Chrome og give adgang til nøgleringen. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="3736739313435669994">Du har blokeret websites, så de ikke kan bruge tredjepartscookies til at spore din aktivitet, mens du browser. Gå til indstillingerne for <ph name="LINK" />.</translation> <translation id="3738166223076830879">Din browser administreres af din administrator.</translation> <translation id="3739842843727261045">Hvis du giver et like, indsendes der feedback om, at du kan lide disse resultater</translation> @@ -1484,7 +1484,7 @@ <translation id="3807709094043295184">Klassisk rock og oldies</translation> <translation id="3807873520724684969">Skadeligt indhold blokeres.</translation> <translation id="380865868633614173">Gemmer kortoplysninger</translation> -<translation id="3810770279996899697">Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> +<translation id="3810770279996899697">Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> <translation id="3810973564298564668">Administrer</translation> <translation id="3812398568375898177">Dette er en vigtig opdatering, som forbedrer ydeevnen for Android-apps i ChromeOS.</translation> <translation id="3815434930383843058">8 x 12 tommer</translation> @@ -1814,7 +1814,7 @@ <translation id="4449116177348980384">Knappen Administrer indstillinger for websites, aktivér for at administrere tilladelser og data, der gemmes på websites, i Chrome-indstillingerne</translation> <translation id="4451135742916150903">Websitet kan anmode om tilladelse til at oprette forbindelse til HID-enheder</translation> <translation id="4451684391620232683">Tekst, der vises til brugeren:</translation> -<translation id="4452328064229197696">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Google Adgangskodeadministrator, at du tjekker dine gemte adgangskoder.</translation> +<translation id="4452328064229197696">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Google Adgangskodeadministrator, at du tjekker dine gemte adgangskoder.</translation> <translation id="4456937135469235202">Oplevelsesrejser</translation> <translation id="4464826014807964867">Websites med oplysninger fra din organisation</translation> <translation id="4466576951214254884">Studielån og finansiering af uddannelse</translation> @@ -2040,7 +2040,7 @@ <translation id="4918221908152712722">Installer <ph name="APP_NAME" /> (kræver ikke download)</translation> <translation id="4920457992177678649">Ferieboliger og korttidslejemål</translation> <translation id="4920710383559189047">Omslag</translation> -<translation id="4922104989726031751">Hvis du vil bruge Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chromium og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="4922104989726031751">Hvis du vil bruge Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chromium og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="4923459931733593730">Betaling</translation> <translation id="4926049483395192435">Skal angives.</translation> <translation id="4926159001844873046"><ph name="SITE" /> siger</translation> @@ -2121,7 +2121,7 @@ <translation id="507130231501693183">Postkasse 4</translation> <translation id="5074134429918579056">Bukser og shorts</translation> <translation id="5077767274537436092">Brug en anden adgangsnøgle</translation> -<translation id="5078060223219502807">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Adgangskodeadministrator, at du ændrer den nu og derefter tjekker dine gemte adgangskoder.</translation> +<translation id="5078060223219502807">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Adgangskodeadministrator, at du ændrer den nu og derefter tjekker dine gemte adgangskoder.</translation> <translation id="5087286274860437796">Serverens certifikatet er ikke gyldigt i øjeblikket.</translation> <translation id="5087580092889165836">Tilføj kort</translation> <translation id="5088142053160410913">Meddelelse til operator</translation> @@ -2573,7 +2573,7 @@ <translation id="5992805036496113940">Se de oplysninger, der bruges til at vise dig annoncer</translation> <translation id="5995727681868049093">Administrer din konto, dit privatliv og beskyttelsen på din Google-konto</translation> <translation id="5996255674476750320">Biludstillinger</translation> -<translation id="5997247540087773573">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Google Adgangskodeadministrator, at du ændrer det nu og tjekker dine gemte adgangskoder.</translation> +<translation id="5997247540087773573">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Google Adgangskodeadministrator, at du ændrer det nu og tjekker dine gemte adgangskoder.</translation> <translation id="5999271311987646952">Chrome har indbyggede sikkerhedsfunktioner, der beskytter dig, når du er på nettet, f.eks. Google Beskyttet browsing. Denne funktion har <ph name="BEGIN_LINK" />for nylig fundet malware<ph name="END_LINK" /> på det website, du forsøger at besøge.</translation> <translation id="6000528814684428358">Hård rock og progressiv rock</translation> <translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultater for "<ph name="SEARCH_TEXT" />"</translation> @@ -2703,7 +2703,7 @@ <translation id="6236290670123303279">Administrer indstillinger</translation> <translation id="623825323736974198">Administrer websites, der altid forbliver aktive, så der ikke frigøres hukommelse</translation> <translation id="6240447795304464094">Google Pay-logo</translation> -<translation id="6240964651812394252">Hvis du vil bruge Google Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chrome og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> +<translation id="6240964651812394252">Hvis du vil bruge Google Adgangskodeadministrator sammen med dit operativsystem, skal du genstarte Chrome og give adgang til Adgangskodeadministrator på din computer. Dine faner åbnes igen, når du har genstartet.</translation> <translation id="6241121617266208201">Skjul forslag</translation> <translation id="624499991300733384">Tjeneste til udskriftssammensætning</translation> <translation id="6250932670816326647">Produkter til badeværelset og kropspleje</translation> @@ -2715,7 +2715,7 @@ <translation id="6263376278284652872"><ph name="DOMAIN" />-bogmærker</translation> <translation id="6264376385120300461">Download alligevel</translation> <translation id="6264485186158353794">Tilbage i sikkerhed</translation> -<translation id="6264636978858465832">Adgangskodeadministrator skal bruge mere omfattende adgang</translation> +<translation id="6264636978858465832">Adgangskodeadministrator skal bruge mere omfattende adgang</translation> <translation id="6265794661083428563">Kopiér værdien fra <ph name="POLICY_NAME" />-politikken</translation> <translation id="6266934640124581640">Lys grønblå</translation> <translation id="6270066318535733958">Med båd</translation> @@ -2979,7 +2979,7 @@ <translation id="6770747695101757579">Papir (bomuld)</translation> <translation id="677257480647123231">Børns sikkerhed på internettet</translation> <translation id="6775759552199460396">JIS B2</translation> -<translation id="6779348349813025131">Google Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> +<translation id="6779348349813025131">Google Adgangskodeadministrator skal have adgang til macOS-nøgleringen</translation> <translation id="6782656837469339439">Udløbsår</translation> <translation id="6785990323398321538">Du kan til enhver tid ændre din søgemaskine i Chrome-indstillingerne.</translation> <translation id="6786145470008421571">Konvolut 6 x 9 tommer</translation> @@ -3050,7 +3050,7 @@ <translation id="691024665142758461">Download flere filer</translation> <translation id="6915804003454593391">Bruger:</translation> <translation id="6916193791494646625">Angiv årsag til download (påkrævet)</translation> -<translation id="6917795328362592458">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Adgangskodeadministrator, at du tjekker dine gemte adgangskoder.</translation> +<translation id="6917795328362592458">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler Adgangskodeadministrator, at du tjekker dine gemte adgangskoder.</translation> <translation id="6925267999184670015">Nordamerika B+</translation> <translation id="6926216138694948720">Kropskunst</translation> <translation id="692638818576287323">Erhvervskøretøjer</translation> @@ -3455,7 +3455,7 @@ <translation id="7637586430889951925">{COUNT,plural, =0{Ingen}=1{1 adgangskode på din konto (til <ph name="DOMAIN_LIST" />)}one{# adgangskode på din konto (til <ph name="DOMAIN_LIST" />)}other{# adgangskoder på din konto (til <ph name="DOMAIN_LIST" />)}}</translation> <translation id="7638605456503525968">Serieporte</translation> <translation id="7639968568612851608">Mørkegrå</translation> -<translation id="7646681339175747202">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. Google Adgangskodeadministrator anbefaler, at du ændrer din adgangskode med det samme.</translation> +<translation id="7646681339175747202">Den adgangskode, du lige har brugt, er blevet lækket i forbindelse med et brud på datasikkerheden. Google Adgangskodeadministrator anbefaler, at du ændrer din adgangskode med det samme.</translation> <translation id="7647206758853451655">Udskriftskvalitet</translation> <translation id="7648992873808071793">Gemme filer på denne enhed</translation> <translation id="7653957176542370971">Regnearket for betalingshandler er lukket</translation>
diff --git a/components/sync/protocol/web_app_specifics.proto b/components/sync/protocol/web_app_specifics.proto index b7f363d0..27df156c 100644 --- a/components/sync/protocol/web_app_specifics.proto +++ b/components/sync/protocol/web_app_specifics.proto
@@ -37,6 +37,9 @@ // WebApp data. This is a synced part of // chrome/browser/web_applications/proto/web_app.proto data. +// Note: Pre-M125 clients will incorrectly drop any unrecognized new fields +// added to the proto. Handling should be added to ApplySyncDataToApp in +// web_app_sync_bridge.cc if new fields need to be preserved. message WebAppSpecifics { // This enum should be a subset of the DisplayMode enum in // chrome/browser/web_applications/proto/web_app.proto and
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index 50de77d9..b1fd8fe 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -741,15 +741,9 @@ if (!host()) return; - // Ensure the event is not routed to a prerendered page. This is now - // DUMP_WILL_BE_NOTREACHED_NORETURN() as this could actually happen for - // crbug.com/326509142. This static variable makes sure to record it only one - // time. - static bool is_prerendering_check_recorded = false; - if (!is_prerendering_check_recorded && host()->frame_tree() && - host()->frame_tree()->is_prerendering()) { - is_prerendering_check_recorded = true; - DUMP_WILL_BE_NOTREACHED_NORETURN(); + // Ensure the event is not routed to a prerendered page. + if (host()->frame_tree() && host()->frame_tree()->is_prerendering()) { + NOTREACHED_NORETURN(); } PreProcessMouseEvent(event); @@ -762,15 +756,9 @@ if (!host()) return; - // Ensure the event is not routed to a prerendered page. This is now - // DUMP_WILL_BE_NOTREACHED_NORETURN() as this could actually happen for - // crbug.com/326509142. This static variable makes sure to record it only one - // time. - static bool is_prerendering_check_recorded = false; - if (!is_prerendering_check_recorded && host()->frame_tree() && - host()->frame_tree()->is_prerendering()) { - is_prerendering_check_recorded = true; - DUMP_WILL_BE_NOTREACHED_NORETURN(); + // Ensure the event is not routed to a prerendered page. + if (host()->frame_tree() && host()->frame_tree()->is_prerendering()) { + NOTREACHED_NORETURN(); } host()->ForwardWheelEventWithLatencyInfo(event, latency); @@ -782,15 +770,9 @@ if (!host()) return; - // Ensure the event is not routed to a prerendered page. This is now - // DUMP_WILL_BE_NOTREACHED_NORETURN() as this could actually happen for - // crbug.com/326509142. This static variable makes sure to record it only one - // time. - static bool is_prerendering_check_recorded = false; - if (!is_prerendering_check_recorded && host()->frame_tree() && - host()->frame_tree()->is_prerendering()) { - is_prerendering_check_recorded = true; - DUMP_WILL_BE_NOTREACHED_NORETURN(); + // Ensure the event is not routed to a prerendered page. + if (host()->frame_tree() && host()->frame_tree()->is_prerendering()) { + NOTREACHED_NORETURN(); } PreProcessTouchEvent(event); @@ -803,15 +785,9 @@ if (!host()) return; - // Ensure the event is not routed to a prerendered page. This is now - // DUMP_WILL_BE_NOTREACHED_NORETURN() as this could actually happen for - // crbug.com/326509142. This static variable makes sure to record it only one - // time. - static bool is_prerendering_check_recorded = false; - if (!is_prerendering_check_recorded && host()->frame_tree() && - host()->frame_tree()->is_prerendering()) { - is_prerendering_check_recorded = true; - DUMP_WILL_BE_NOTREACHED_NORETURN(); + // Ensure the event is not routed to a prerendered page. + if (host()->frame_tree() && host()->frame_tree()->is_prerendering()) { + NOTREACHED_NORETURN(); } host()->ForwardGestureEventWithLatencyInfo(event, latency);
diff --git a/content/test/data/forms/form_controls_browsertest_button_win.png b/content/test/data/forms/form_controls_browsertest_button_win.png index d86595b7..b425e0f 100644 --- a/content/test/data/forms/form_controls_browsertest_button_win.png +++ b/content/test/data/forms/form_controls_browsertest_button_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_checkbox_win.png b/content/test/data/forms/form_controls_browsertest_checkbox_win.png index f4a364c..27342a78 100644 --- a/content/test/data/forms/form_controls_browsertest_checkbox_win.png +++ b/content/test/data/forms/form_controls_browsertest_checkbox_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_color_input_win.png b/content/test/data/forms/form_controls_browsertest_color_input_win.png index 57cadb7..d02f2852 100644 --- a/content/test/data/forms/form_controls_browsertest_color_input_win.png +++ b/content/test/data/forms/form_controls_browsertest_color_input_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_dark_mode_text_selection_win.png b/content/test/data/forms/form_controls_browsertest_dark_mode_text_selection_win.png index e8985d2d..0193e49 100644 --- a/content/test/data/forms/form_controls_browsertest_dark_mode_text_selection_win.png +++ b/content/test/data/forms/form_controls_browsertest_dark_mode_text_selection_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_input_win.png b/content/test/data/forms/form_controls_browsertest_input_win.png index 2790f738c..a58c8f14 100644 --- a/content/test/data/forms/form_controls_browsertest_input_win.png +++ b/content/test/data/forms/form_controls_browsertest_input_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_meter_win.png b/content/test/data/forms/form_controls_browsertest_meter_win.png index 73b8845..1b00a8b 100644 --- a/content/test/data/forms/form_controls_browsertest_meter_win.png +++ b/content/test/data/forms/form_controls_browsertest_meter_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_multi_select_win.png b/content/test/data/forms/form_controls_browsertest_multi_select_win.png index e867deb8..7e7984a 100644 --- a/content/test/data/forms/form_controls_browsertest_multi_select_win.png +++ b/content/test/data/forms/form_controls_browsertest_multi_select_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_progress_win.png b/content/test/data/forms/form_controls_browsertest_progress_win.png index 8fb3cd950..3197f23 100644 --- a/content/test/data/forms/form_controls_browsertest_progress_win.png +++ b/content/test/data/forms/form_controls_browsertest_progress_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_radio_win.png b/content/test/data/forms/form_controls_browsertest_radio_win.png index 172fbf9..00576c64 100644 --- a/content/test/data/forms/form_controls_browsertest_radio_win.png +++ b/content/test/data/forms/form_controls_browsertest_radio_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_range_win.png b/content/test/data/forms/form_controls_browsertest_range_win.png index d90da00..9eb052c 100644 --- a/content/test/data/forms/form_controls_browsertest_range_win.png +++ b/content/test/data/forms/form_controls_browsertest_range_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_select_win.png b/content/test/data/forms/form_controls_browsertest_select_win.png index 225667d4..51ca511 100644 --- a/content/test/data/forms/form_controls_browsertest_select_win.png +++ b/content/test/data/forms/form_controls_browsertest_select_win.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_textarea_win.png b/content/test/data/forms/form_controls_browsertest_textarea_win.png index 26083754..1940e9d 100644 --- a/content/test/data/forms/form_controls_browsertest_textarea_win.png +++ b/content/test/data/forms/form_controls_browsertest_textarea_win.png Binary files differ
diff --git a/docs/updater/design_doc.md b/docs/updater/design_doc.md index cc7a480..1ca76fd 100644 --- a/docs/updater/design_doc.md +++ b/docs/updater/design_doc.md
@@ -449,7 +449,7 @@ For example, here is a command line for the Updater on Windows that includes: ``` -UpdaterSetup.exe --install="appguid=YourAppID&needsadmin=False" +UpdaterSetup.exe --install --tag="appguid=YourAppID&needsadmin=False" ``` In this case, the updater client understands that the application installer
diff --git a/docs/updater/functional_spec.md b/docs/updater/functional_spec.md index 74fd731..2105f6d7 100644 --- a/docs/updater/functional_spec.md +++ b/docs/updater/functional_spec.md
@@ -243,22 +243,23 @@ The updater's functionality is split between several processes. The mode of a process is determined by command-line arguments: -* --install[=tag] [--app-id=...] +* --install [--app-id=...] * Install and activate this version of the updater if there is no active updater. - * If a tag argument is specified instead of `--app-id`, this supplies - the install metadata needed when installing an application. - Typically, a tagged metainstaller invokes the updater with the tag. - For example: `--install="appguid=foo&appname=Foo&needsadmin=False"`. * --app-id=... * Also install the given application. - * --handoff[=tag] - * A tag argument can be specified, similar to `--install`. + * --tag=... + * Supplies the install metadata needed when installing an + application. Typically, a tagged metainstaller invokes the updater + with this command line argument. + * If --tag is specified, --install is assumed. + * --handoff=... + * As --tag. * --appargs="appguid=...&installerdata=..." * Allows extra data (`installerdata`) to be communicated to the application installer. One per application. * `appguid` must be the first arg followed by the `installerdata`. The - same `appguid` must appear in `--install=` or `--handoff=`. + same `appguid` must appear in `tag` value or `handoff` value. * This is an alternative to using `installdataindex` in the tag. Where `installdataindex` selects from a pre-defined set of `installerdata` options, this value specifies the exact `installerdata` to use. @@ -772,9 +773,9 @@ metainstaller with the following parameters: ``` --silent ---install=appguid={8237E44A-0054-442C-B6B6-EA0509993955}& - appname=GoogleChromeBeta&needsAdmin=True&brand=GCEA ---installsource=enterprisemsi +--tag=appguid={8237E44A-0054-442C-B6B6-EA0509993955}&appname=GoogleChromeBeta& + needsAdmin=True&brand=GCEA +--installsource enterprisemsi --appargs=appguid={8237E44A-0054-442C-B6B6-EA0509993955}& installerdata=%7B%22dis%22%3A%7B%22msi%22%3Atrue%7D%7D ``` @@ -795,8 +796,8 @@ the following parameters: ``` --silent ---install=appguid={8237E44A-0054-442C-B6B6-EA0509993955}& - appname=Google%20Chrome%20Beta&needsAdmin=True&brand=GGLL +--tag=appguid={8237E44A-0054-442C-B6B6-EA0509993955}&appname=Google%20Chrome%20 + Beta&needsAdmin=True&brand=GGLL --installsource enterprisemsi --appargs=appguid={8237E44A-0054-442C-B6B6-EA0509993955}& installerdata=%7B%22dis%22%3A%7B%22msi%22%3Atrue%7D%7D @@ -995,7 +996,7 @@ For example, here is a command line for the Updater on Windows that includes: ``` -UpdaterSetup.exe --install="appguid=YourAppID&needsadmin=False" +UpdaterSetup.exe --install --tag="appguid=YourAppID&needsadmin=False" ``` In this case, the updater client understands that the application installer
diff --git a/docs/updater/user_manual.md b/docs/updater/user_manual.md index 72a4d23..46ad32ec 100644 --- a/docs/updater/user_manual.md +++ b/docs/updater/user_manual.md
@@ -97,7 +97,7 @@ The updater will uninstall itself automatically when it has no applications to manage, but it may need some help to do so in a timely manner. -On Windows, when an application is uninstalled, it should delete the +On Windows, when an application is uninstalled, it should delete the `(HKCU or HKLM)\SOFTWARE\{Company}\Update\Clients\{AppID}` key and then run the command line in `(HKCU or HKLM)\SOFTWARE\{Company}\Updater` → `UninstallCmdLine`. This will @@ -106,7 +106,7 @@ On macOS, it is assumed that users uninstall software by deleting the app bundle. The updater will notice this on its own in a few hours. However, it can be notified earlier by running any -`{Company}Updater.app/Contents/MacOS/{Company}Updater --wake-all` (with +`{Company}Updater.app/Contents/MacOS/{Company}Updater --wake-all` (with `--system` for system-scope installs). ## Additional Updater Command Lines @@ -133,7 +133,7 @@ For example, here is a command line for the Updater on Windows that includes: ``` -UpdaterSetup.exe --install="appguid=YourAppID&needsadmin=False" +UpdaterSetup.exe --install --tag="appguid=YourAppID&needsadmin=False" ``` In this case, the updater client understands that the application installer
diff --git a/docs/website b/docs/website index 0fa768e2..192b4c1 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit 0fa768e21e9cb653d0957201899713a86adafa8f +Subproject commit 192b4c1fca9c092343459067d75ba65fbc6ea856
diff --git "a/infra/config/generated/builders/ci/Mac Builder \050reclient compare\051/gn-args.json" "b/infra/config/generated/builders/ci/Mac Builder \050reclient compare\051/gn-args.json" index e1a1b3b..137ae77f 100644 --- "a/infra/config/generated/builders/ci/Mac Builder \050reclient compare\051/gn-args.json" +++ "b/infra/config/generated/builders/ci/Mac Builder \050reclient compare\051/gn-args.json"
@@ -6,6 +6,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 1, + "target_cpu": "x64", "use_remoteexec": true } } \ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index cdb1585b..8c3f711e 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -19572,7 +19572,7 @@ name: "Mac Builder (reclient compare)" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "cpu:x86-64" + dimensions: "cpu:arm64" dimensions: "free_space:standard" dimensions: "os:Mac-13|Mac-14" dimensions: "pool:luci.chromium.ci"
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index 73b1a98..5c528813 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -267,16 +267,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 125.0.6418.0', + 'description': 'Run with ash-chrome version 125.0.6420.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v125.0.6418.0', - 'revision': 'version:125.0.6418.0', + 'location': 'lacros_version_skew_tests_v125.0.6420.0', + 'revision': 'version:125.0.6420.0', }, ], },
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 3ff68b0..2220051 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -1685,10 +1685,12 @@ "release_builder", "reclient", "minimal_symbols", + "x64", ], ), builderless = True, cores = None, # crbug.com/1245114 + cpu = cpu.ARM64, console_view_entry = consoles.console_view_entry( category = "mac", short_name = "cmp",
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index e838026a..2420159 100644 --- a/infra/config/targets/lacros-version-skew-variants.json +++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@ { "LACROS_VERSION_SKEW_CANARY": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "identifier": "Lacros version skew testing ash canary", "swarming": { "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ] }
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_da.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_da.xtb index edfee4bb..7ec2cae 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_da.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_da.xtb
@@ -103,7 +103,7 @@ Du kan ændre denne indstilling ved at <ph name="BEGIN_LINK" />rydde Chromium-dataene på din konto<ph name="END_LINK" />.</translation> <translation id="4005283307739974863">Åbner og kører et sikkerhedstjek i Chromium.</translation> -<translation id="4043291146360695975">Adgangskoder gemmes kun i Adgangskodeadministrator på denne enhed.</translation> +<translation id="4043291146360695975">Adgangskoder gemmes kun i Adgangskodeadministrator på denne enhed.</translation> <translation id="4076589763479456892">Hvis du glemmer din adgangssætning eller vil ændre denne indstilling, skal du <ph name="BEGIN_LINK" />rydde Chromium-dataene på din konto<ph name="END_LINK" />.</translation> <translation id="4099085513035183040">Understøttes ikke i Chromium Beta</translation> <translation id="4106512142782407609">Logget ind som <ph name="EMAIL" />. @@ -141,7 +141,7 @@ <translation id="5131565040785979529">Din organisation, <ph name="DOMAIN" />, administrerer den konto, du er logget ind på, og hvordan Chromium bruges.</translation> <translation id="5146749061471423558">Føj bogmærker til Chromium</translation> <translation id="5171868502429358653">Log ind på Chromium</translation> -<translation id="5213683223491576284">Åbner Adgangskodeadministrator i Chromium.</translation> +<translation id="5213683223491576284">Åbner Adgangskodeadministrator i Chromium.</translation> <translation id="5224391634244552924">Der er ingen gemte adgangskoder. Chromium kan tjekke dine adgangskoder, når du gemmer dem.</translation> <translation id="5242782538551259282">Nogle af dine Chromium-data er endnu ikke gemt på din Google-konto. @@ -187,7 +187,7 @@ <translation id="6170619162539716595">Tillad, at Chromium bruger Google Maps til at vise dig rutevejledning og lokale oplysninger om registrerede adresser.</translation> <translation id="6175967839221456271">Del Chromium</translation> <translation id="6197255575340902638">Hvis du skjuler "<ph name="MODULE_NAME" />", sporer Chromium ikke længere automatisk dine fremtidige pakker, og alle dine tidligere pakkesporingsdata slettes.</translation> -<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> +<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> <translation id="6268381023930128611">Vil du logge ud af Chromium?</translation> <translation id="6324041800010509197">Gå til fanegitteret i Chromium</translation> <translation id="6325378625795868881">Brug Chromium, hver gang du trykker på links i meddelelser og andre apps.</translation> @@ -211,14 +211,14 @@ <translation id="6852799557929001644">Få adgang til dine Chromium-adgangskoder m.m. i andre apps på denne enhed.</translation> <translation id="6887138405044152640">Hvis du vil sende denne fane til en anden enhed, skal du logge ind i Chromium på den pågældende enhed.</translation> <translation id="6911341667534646387">Fortsæt med at bruge Chromium-dataene på din Google-konto</translation> -<translation id="7006920032187763988">Du kan bruge de adgangskoder, du har gemt i Adgangskodeadministrator, i andre apps på din iPad.</translation> +<translation id="7006920032187763988">Du kan bruge de adgangskoder, du har gemt i Adgangskodeadministrator, i andre apps på din iPad.</translation> <translation id="7018284295775193585">Chromium kan ikke opdateres</translation> <translation id="7045244423563602563">Tilpas Chromium</translation> <translation id="7055269218854630176">Din organisation, <ph name="DOMAIN" />, administrerer den konto, du logger ind på, og hvordan Chromium kan bruges. Din administrator kan konfigurere eller begrænse visse funktioner.</translation> <translation id="7099326575020694068">Chromium kan ikke bruge dit kamera i tilstanden Opdelt visning</translation> <translation id="7163483974919055112">Søg efter visuelle elementer i Chromium.</translation> <translation id="7165402419892018581">Vælg Chromium for Autofyld</translation> -<translation id="7175400662502680481">Din adgangskode er blevet offentliggjort i forbindelse med et brud på datasikkerheden. Adgangskodeadministrator anbefaler, at du ændrer det nu.</translation> +<translation id="7175400662502680481">Din adgangskode er blevet offentliggjort i forbindelse med et brud på datasikkerheden. Adgangskodeadministrator anbefaler, at du ændrer det nu.</translation> <translation id="7192111075364461693">Chromium-notifikationer er i øjeblikket deaktiveret i enhedsindstillingerne.</translation> <translation id="7222001353246886083">Søg efter ${searchphrase} i Chromium</translation> <translation id="725427773388857052">Chromium kan hjælpe med at beskytte dig mod brud på datasikkerheden, usikre websites og meget mere.</translation> @@ -227,7 +227,7 @@ <translation id="7337881442233988129">Chromium</translation> <translation id="7357211569052832586">De valgte data er fjernet fra Chromium og synkroniserede enheder. Din Google-konto kan have andre former for browserhistorik, f.eks. søgninger og aktivitet fra andre Google-tjenester, på history.google.com.</translation> <translation id="7387082980875012885">Åbn en ny fane i Chromium</translation> -<translation id="7395825497086981028">Din adgangskode gemmes i Adgangskodeadministrator for <ph name="EMAIL" />.</translation> +<translation id="7395825497086981028">Din adgangskode gemmes i Adgangskodeadministrator for <ph name="EMAIL" />.</translation> <translation id="7400689562045506105">Brug Chromium, uanset hvor du er</translation> <translation id="7523464085759699266">Aktivér "Lås inkognitofaner, når du lukker Chromium".</translation> <translation id="7601597633134889942">Besøg et website, og klik på Følg i Chromium-menuen</translation> @@ -263,7 +263,7 @@ <translation id="8386869251364507178">Chromium-handlinger</translation> <translation id="8409374867500149834">Du har Chromiums stærkeste beskyttelse mod skadelige websites</translation> <translation id="8458950033462118672">Du kan åbne links i Chromium automatisk ved at angive Chromium som din standardapp til browsing.</translation> -<translation id="858114650497379505">Du kan bruge de adgangskoder, du har gemt i Adgangskodeadministrator, i andre apps på din iPhone.</translation> +<translation id="858114650497379505">Du kan bruge de adgangskoder, du har gemt i Adgangskodeadministrator, i andre apps på din iPhone.</translation> <translation id="8586442755830160949">Copyright <ph name="YEAR" /> Forfatterne bag Chromium. Alle rettigheder forbeholdes.</translation> <translation id="8618440443578628179">Kryptering med adgangssætning omfatter ikke betalingsmetoder og adresser fra Google Pay. @@ -289,7 +289,7 @@ Dine data blev krypteret med din adgangssætning <ph name="TIME" />. Angiv adgangssætningen for at bruge og gemme Chromium-data på din Google-konto.</translation> <translation id="9022552996538154597">Log ind på Chromium</translation> <translation id="9050790730841755540">Brug Chromium, hver gang du trykker på links i andre apps.</translation> -<translation id="9059693977935746710">Du behøver ikke at huske denne adgangskode. Den gemmes i Adgangskodeadministrator for <ph name="EMAIL" /></translation> +<translation id="9059693977935746710">Du behøver ikke at huske denne adgangskode. Den gemmes i Adgangskodeadministrator for <ph name="EMAIL" /></translation> <translation id="9089354809943900324">Chromium er forældet</translation> <translation id="9110075932708282655">Brug Chromium som standard</translation> <translation id="921174536258924340">Chromium kunne ikke tjekke alle adgangskoder. Prøv igen i morgen, eller <ph name="BEGIN_LINK" />tjek adgangskoder på din Google-konto<ph name="END_LINK" />.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_zu.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_zu.xtb index 237c9be..3f58340 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_zu.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_zu.xtb
@@ -50,7 +50,7 @@ <translation id="2236584955986023187">Lokhu kusho ukuthi i-Chromium izocela isayithi yedeskithophu ngaso sonke isikhathi.</translation> <translation id="2313870531055795960">Kuhlola ama-URL anohlu lwamasayithi angaphephile agcinwe ku-Chromium. Uma isayithi lizama ukuntshontsha iphasiwedi yakho, noma uma ulanda ifayela eliyingozi, i-Chromium ingathumela nama-URL, kuhlanganise nokuthile okuqukethwe kulelo khasi, Ekuphequluleni Okuphephile.</translation> <translation id="231828342043114302">Ukuze uthole okuqukethwe okwenzelwe wena ngokusekelwe kokuthandayo, ngena ngemvume ku-Chromium.</translation> -<translation id="2374627437126809292">I-Chromium isebenzisa i-Google Maps ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> +<translation id="2374627437126809292">I-Chromium isebenzisa Amamephu eGoogle ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> <translation id="2386292341327187942">Ebhokisini elithi Amawijethi Okusesha, faka i-Chromium</translation> <translation id="2426113998523353159">Inhlangano yakho idinga ukuba ungene ngemvume ukuze usebenzise i-Chromium.</translation> <translation id="2450140762465183767">Manje ungasebenzisa i-Chromium noma nini uma uthepha ama-app kumilayezo, amadokhumenti, namanye ama-app.</translation> @@ -133,8 +133,8 @@ <translation id="4985291216379576555">Ayixhunyiwe kwi-inthanethi, i-Chromium ayikwazi ukuhlola izibuyekezo</translation> <translation id="4996471330284142407">Yenza okuningi nge-Chromium elula, evikelekile, nesheshayo kunangaphambilini.</translation> <translation id="4999538639245140991">Ngoba uphuma ku-akhawunti ephethwe ngu-<ph name="SIGNOUT_MANAGED_DOMAIN" />, idatha yakho ye-Chromium izosuswa kusuka kule divayisi. Idatha yakho izohlala ku-akhawunti yakho ye-Google.</translation> -<translation id="5042011327527167688">Thepha okuthi “Buka nge-Google Maps ku-Chromium.”</translation> -<translation id="5044871537677053278">I-Chromium ithola amakheli bese isebenzisa i-Google Maps ukuze ikunikeze izikhombisi-ndlela kanye nolwazi lwendawo.</translation> +<translation id="5042011327527167688">Thepha okuthi “Buka nge-Amamephu eGoogle ku-Chromium.”</translation> +<translation id="5044871537677053278">I-Chromium ithola amakheli bese isebenzisa Amamephu eGoogle ukuze ikunikeze izikhombisi-ndlela kanye nolwazi lwendawo.</translation> <translation id="5048795749726991615">Ukuze uthole kalula amaphasiwedi akho alondoloziwe kwamanye ama-app, sebenzisa i-Chromium Yokugcwalisa Okuzenzakalelayo</translation> <translation id="5076601183701536878">Sula Idatha Yokubhrawuza ku-Chromium</translation> <translation id="5124429847818367226">Manje usungasebenzisa i-Chromium noma kunini uma ubhrawuza noma uthepha amalinki emilayezweni, kumadokhumenti, nakwamanye ama-app.</translation> @@ -184,7 +184,7 @@ 3. Khetha i-Chromium.</translation> <translation id="6132149203299792222">Ngena ngemvume nge-Google Account yakho ukuze uvumelanise amaphasiwedi wakho, amabhukhimakhi, nokuningi.</translation> <translation id="6154098560469640583">Sebenzisa i-Chromium noma nini lapho uchofoza amalinki emiyalezweni, kumadokhumenti, nakwamanye ama-app.</translation> -<translation id="6170619162539716595">Vumela i-Chromium isebenzise i-Google Maps ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> +<translation id="6170619162539716595">Vumela i-Chromium isebenzise Amamephu eGoogle ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> <translation id="6175967839221456271">Yabelana nge-Chromium</translation> <translation id="6197255575340902638">Uma ufihla "i-<ph name="MODULE_NAME" />", i-Chromium ngeke isalandelela ngokuzenzakalelayo amaphakheji akho esikhathi esizayo futhi izosusa yonke idatha yakho yokulandela yephakheji edlule.</translation> <translation id="6247557882553405851">Umphathi Wephasiwedi ye-Google</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_da.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_da.xtb index f5b73fa..1b516a6 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_da.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_da.xtb
@@ -5,7 +5,7 @@ <translation id="1066101356081285416">Chrome registrerer sporingsnumre på de websites, du besøger, og viser dig pakkeopdateringer på siden Ny fane. Pakkesporingsnummeret og websitets navn sendes til Google for at levere denne funktion og forbedre Googles shoppingfunktioner for alle. Du kan til enhver tid opdatere dette i <ph name="BEGIN_LINK" />indstillingerne for pakkesporing<ph name="END_LINK" />.</translation> <translation id="1085696779717592361">Brug Chrome som standard</translation> <translation id="1105362920864247682">Ryd browserdata i Chrome.</translation> -<translation id="1143896152279775643">Din adgangskode gemmes i Google Adgangskodeadministrator for <ph name="EMAIL" />.</translation> +<translation id="1143896152279775643">Din adgangskode gemmes i Google Adgangskodeadministrator for <ph name="EMAIL" />.</translation> <translation id="1177414119866731261">Åbn Chrome-menuen</translation> <translation id="1180362651362502943">Fortsæt med at bruge Chrome-dataene på din Google-konto.</translation> <translation id="1200396280085622191">Brug Chrome, hver gang du trykker på links i meddelelser og andre apps.</translation> @@ -14,7 +14,7 @@ <translation id="1282031177488366470">Hjælp med at forbedre Chromes funktioner og effektivitet</translation> <translation id="1320619893013575407">Du har deaktiveret login via Chrome.</translation> <translation id="1333745675627230582">Spil Chrome Dino-spillet</translation> -<translation id="1352919863522755794">Google Adgangskodeadministrator kunne ikke tjekke dine adgangskoder. Prøv at tjekke din internetforbindelse.</translation> +<translation id="1352919863522755794">Google Adgangskodeadministrator kunne ikke tjekke dine adgangskoder. Prøv at tjekke din internetforbindelse.</translation> <translation id="1407843355326180937">Log ind på dette website og i Chrome for at få adgang til dine bogmærker og meget mere på alle dine enheder.</translation> <translation id="1436059927646026729">Åbn min seneste fane i Chrome</translation> <translation id="1449241544691504574">Føj bogmærker til Chrome</translation> @@ -68,14 +68,14 @@ <translation id="2576431527583832481">Chrome er lige blevet bedre! Der er en ny tilgængelig version.</translation> <translation id="257708665678654955">Skal Google Chrome tilbyde at oversætte sider på <ph name="LANGUAGE_NAME" /> fra dette website næste gang?</translation> <translation id="2650286135394207535">Få hjælp af Chrome til at spore dine pakker</translation> -<translation id="2671426118752779020">Du kan bruge de adgangskoder, du har gemt i Google Adgangskodeadministrator, i andre apps på din iPhone.</translation> +<translation id="2671426118752779020">Du kan bruge de adgangskoder, du har gemt i Google Adgangskodeadministrator, i andre apps på din iPhone.</translation> <translation id="2689064829982324496">Hvis du vil logge ud af din Google-konto på alle websites, skal du <ph name="BEGIN_LINK" />logge ud af Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome kunne ikke søge efter opdateringer. Prøv igen senere.</translation> <translation id="2702250627063295552">Føj et element til læselisten i Chrome</translation> <translation id="2703746758996815929">Aktivér notifikationer i iOS-indstillingerne for at få nyttige tips til Chrome.</translation> <translation id="2736805085127235148">Chrome-notifikationer er i øjeblikket deaktiveret i enhedsindstillingerne.</translation> <translation id="2750626042242931740">Du kan til enhver tid opdatere dine valg i Chrome-indstillingerne.</translation> -<translation id="2767464022270041271">Der er ingen gemte adgangskoder. Google Adgangskodeadministrator kan tjekke dine adgangskoder, når du gemmer dem.</translation> +<translation id="2767464022270041271">Der er ingen gemte adgangskoder. Google Adgangskodeadministrator kan tjekke dine adgangskoder, når du gemmer dem.</translation> <translation id="2789947168960170215">Hvis du glemmer din adgangssætning eller vil ændre denne indstilling, skal du <ph name="BEGIN_LINK" />rydde Chrome-dataene på din konto<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Ryd browserdata i Chrome</translation> <translation id="2869959624320573933">Log ind i Chrome</translation> @@ -130,7 +130,7 @@ Prøv at vente et par minutter, før du logger ud. Hvis du logger ud nu, slettes disse data.</translation> <translation id="484033449593719797">Understøttes ikke i Chrome Beta</translation> -<translation id="4840404732697892756">Google Adgangskodeadministrator kan tjekke dine adgangskoder, når du logger ind med din Google-konto.</translation> +<translation id="4840404732697892756">Google Adgangskodeadministrator kan tjekke dine adgangskoder, når du logger ind med din Google-konto.</translation> <translation id="4860330141789125848">{COUNT,plural, =1{Chrome kan hjælpe dig med at spore denne pakke på siden Ny fane.}one{Chrome kan hjælpe dig med at spore denne pakke på siden Ny fane.}other{Chrome kan hjælpe dig med at spore disse pakker på siden Ny fane.}}</translation> <translation id="4903674399067644695">Dette kort viser dig forslag til, hvordan du får mest muligt ud af Chrome.</translation> <translation id="49200511069271369">Din organisation, <ph name="DOMAIN" />, administrerer den konto, du logger ind på, og hvordan Chrome kan bruges. Din administrator kan konfigurere eller begrænse visse funktioner.</translation> @@ -151,7 +151,7 @@ <translation id="5442013002200339429">Hvis du skjuler "<ph name="MODULE_NAME" />", sporer Chrome ikke længere automatisk dine fremtidige pakker, og alle dine tidligere pakkesporingsdata slettes.</translation> <translation id="5460571915754665838">4. Vælg Chrome</translation> <translation id="546541279759910616">{COUNT,plural, =1{Chrome hjælper med at spore denne pakke på siden Ny fane.}one{Chrome hjælper med at spore denne pakke på siden Ny fane.}other{Chrome hjælper med at spore disse pakker på siden Ny fane.}}</translation> -<translation id="5492504007368565877">Google Adgangskodeadministrator kan ikke tjekke dine adgangskoder.</translation> +<translation id="5492504007368565877">Google Adgangskodeadministrator kan ikke tjekke dine adgangskoder.</translation> <translation id="5525095647255982834">Hvis du vil sende denne fane til en anden enhed, skal du logge ind på Chrome på den pågældende enhed.</translation> <translation id="5527026824954593399">Tryk på "Se med Google Maps i Chrome".</translation> <translation id="5552137475244467770">Chrome tjekker regelmæssigt, om dine adgangskoder er på nogen lister over adgangskoder, der er blevet afsløret online. Dine adgangskoder og brugernavne krypteres under disse tjek, så de kan ikke læses af nogen, heller ikke Google.</translation> @@ -159,14 +159,14 @@ <translation id="5601180634394228718">Du kan finde flere indstillinger, der bruger data til at forbedre din Chrome-oplevelse, ved at gå til <ph name="BEGIN_LINK" />Google-tjenester<ph name="END_LINK" />.</translation> <translation id="5639704535586432836">Åbn Indstillinger > Privatliv > Kamera > Google Chrome, og slå kameraet til.</translation> <translation id="5642200033778930880">Google Chrome kan ikke bruge dit kamera i tilstanden Opdelt visning</translation> -<translation id="5661521615548540542">Google Adgangskodeadministrator kunne ikke tjekke alle adgangskoder. Prøv igen senere.</translation> +<translation id="5661521615548540542">Google Adgangskodeadministrator kunne ikke tjekke alle adgangskoder. Prøv igen senere.</translation> <translation id="5690398455483874150">{count,plural, =1{Viser nu 1 Chrome-vindue}one{Viser nu {count} Chrome-vindue}other{Viser nu {count} Chrome-vinduer}}</translation> <translation id="5690427481109656848">Google LLC</translation> <translation id="571296537125272375">Offline – Chrome kan ikke søge efter opdateringer</translation> <translation id="5716154293141027663">Åbn Chrome, hver gang du trykker på links i andre apps</translation> <translation id="5733084997078800044">Tip til Chrome</translation> <translation id="5808435672482059465">Se din Chrome-historik</translation> -<translation id="589695154992054845">Åbner Adgangskodeadministrator i Chrome.</translation> +<translation id="589695154992054845">Åbner Adgangskodeadministrator i Chrome.</translation> <translation id="5998675059699164418">Din organisation kræver, at du logger ind for at bruge Chrome.</translation> <translation id="6054613632208573261">Brug Chrome som standard</translation> <translation id="6063091872902370735">Tillad login via Chrome</translation> @@ -174,7 +174,7 @@ <translation id="6132149203299792222">Log ind med din Google-konto for at synkronisere dine adgangskoder, bogmærker m.m.</translation> <translation id="6177442314419606057">Søg i Chrome</translation> <translation id="6238746320622508509">Lad Chrome låse dine inkognitofaner.</translation> -<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> +<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> <translation id="6272822675004864999">Hvis du vil modtage notifikationer fra Chrome, skal du aktivere notifikationer i iOS-indstillingerne.</translation> <translation id="630693926528731525">Din adgangskode blev ikke delt. Tjek din internetforbindelse, og sørg for, at du er logget ind i Chrome. Prøv derefter igen.</translation> <translation id="6348855835728304880">Få adgang til dine Chrome-adgangskoder m.m. i andre apps på denne enhed.</translation> @@ -190,7 +190,7 @@ <translation id="6646696210740573446">Sender en sløret del af webadressen til Google via en privatlivsbeskyttende server, som skjuler din IP-adresse. Hvis et website forsøger at stjæle din adgangskode, eller når du downloader en skadelig fil, sender Chrome muligvis også webadresser, bl.a. mindre mængder sideindhold, til Google.</translation> <translation id="6648150602980899529">Du er ved at logge ind med en konto, der administreres af <ph name="DOMAIN" />, hvilket giver administratoren kontrol over dine Chrome-data. Dine data tilknyttes denne konto permanent. Hvis du logger ud af Chrome, slettes dine data fra denne enhed, men de forbliver gemt på din Google-konto.</translation> <translation id="6683891932310469419">Åbner siden med din Chrome-historik.</translation> -<translation id="6709398533399187136">Din adgangskode er blevet offentliggjort i forbindelse med et brud på datasikkerheden. Google Adgangskodeadministrator anbefaler, at du ændrer det nu.</translation> +<translation id="6709398533399187136">Din adgangskode er blevet offentliggjort i forbindelse med et brud på datasikkerheden. Google Adgangskodeadministrator anbefaler, at du ændrer det nu.</translation> <translation id="6815466750807582739">Betalingsmetoder og adresser krypteres ikke. Browserhistorik fra Chrome synkroniseres ikke. Kun personer med din adgangssætning kan læse dine krypterede data. Adgangssætningen bliver ikke sendt til eller gemt af Google. Hvis du glemmer din adgangssætning eller vil ændre denne indstilling, skal du <ph name="BEGIN_LINK" />rydde Chrome-dataene på din konto<ph name="END_LINK" />.</translation> @@ -210,7 +210,7 @@ <translation id="7187993566681480880">Beskytter dig i Chrome og kan bruges til at forbedre din sikkerhed i andre Google-apps, når du er logget ind.</translation> <translation id="7200524487407690471">Chrome kører automatisk et sikkerhedstjek hver dag for at beskytte dig mod brud på datasikkerheden, usikre websites og meget mere. Du kan få flere oplysninger om Sikkerhedstjek i Indstillinger.</translation> <translation id="7203324561587388418">Hold dig opdateret om indhold og nyttige Chrome-tips.</translation> -<translation id="72119412072970160">Du kan bruge de adgangskoder, du har gemt i Google Adgangskodeadministrator, i andre apps på din iPad.</translation> +<translation id="72119412072970160">Du kan bruge de adgangskoder, du har gemt i Google Adgangskodeadministrator, i andre apps på din iPad.</translation> <translation id="722167379782941918">Chrome anbefaler forbedret beskyttelse</translation> <translation id="723787869754590019">Brug Chrome til Autofyld</translation> <translation id="7254380941803999489">Angiv Chrome som standardbrowser</translation> @@ -268,13 +268,13 @@ <translation id="8540666473246803645">Google Chrome</translation> <translation id="8558480467877843976">Du kan nu bruge Chrome, hver gang du browser eller trykker på links i meddelelser, dokumenter og andre apps.</translation> <translation id="8577978202917232774">Forslagene er baseret på browseraktiviteten på dine andre enheder. Log ind i Chrome på alle dine enheder for at få forslag.</translation> -<translation id="8603022514504485810">Google Adgangskodeadministrator kunne ikke tjekke alle adgangskoder. Prøv igen i morgen, eller <ph name="BEGIN_LINK" />tjek adgangskoder på din Google-konto<ph name="END_LINK" />.</translation> +<translation id="8603022514504485810">Google Adgangskodeadministrator kunne ikke tjekke alle adgangskoder. Prøv igen i morgen, eller <ph name="BEGIN_LINK" />tjek adgangskoder på din Google-konto<ph name="END_LINK" />.</translation> <translation id="8727043961453758442">Få mest muligt ud af Chrome</translation> <translation id="8736550665979974340">Vær sikker med Google Chrome</translation> <translation id="8760668027640688122">Åbn en ny fane i Chrome</translation> <translation id="8765470054473112089">Når du indtaster noget i adresselinjen eller søgefeltet, sender Chrome det, du skriver, til din standardsøgemaskine for at få bedre forslag. Dette er deaktiveret i inkognitotilstand.</translation> <translation id="8772179140489533211">Viser anmodninger om at logge ind i Chrome.</translation> -<translation id="8788269841521769222">Du behøver ikke at huske denne adgangskode. Den gemmes i Googles Adgangskodeadministrator for <ph name="EMAIL" /></translation> +<translation id="8788269841521769222">Du behøver ikke at huske denne adgangskode. Den gemmes i Googles Adgangskodeadministrator for <ph name="EMAIL" /></translation> <translation id="878917453316810648">Tip til Chrome: Brug Chrome som standard</translation> <translation id="8808828119384186784">Indstillinger for Chrome</translation> <translation id="8850736900032787670">Log ind i Chrome for at få personligt tilpasset indhold baseret på dine interesser.</translation> @@ -282,11 +282,11 @@ <translation id="8856877214925961642">Kryptering med adgangssætning omfatter ikke betalingsmetoder og adresser. Du kan ændre denne indstilling ved at <ph name="BEGIN_LINK" />rydde Chrome-dataene på din konto<ph name="END_LINK" />.</translation> -<translation id="8857676124663337448">Google Adgangskodeadministrator kunne ikke tjekke alle adgangskoder. Prøv igen i morgen.</translation> +<translation id="8857676124663337448">Google Adgangskodeadministrator kunne ikke tjekke alle adgangskoder. Prøv igen i morgen.</translation> <translation id="8865415417596392024">Chrome-data på din konto</translation> <translation id="8874688701962049679">Tips til at få mest muligt ud af Chrome.</translation> <translation id="8891935667620843985">Du kan åbne links i Chrome automatisk ved at angive Chrome som din standardapp til browsing.</translation> -<translation id="8897749957032330183">Adgangskoder gemmes i Google Adgangskodeadministrator på denne enhed.</translation> +<translation id="8897749957032330183">Adgangskoder gemmes i Google Adgangskodeadministrator på denne enhed.</translation> <translation id="8949681853939555434">Angiv Chrome som din standardbrowser</translation> <translation id="9068336935206019333">Åbn i inkognitotilstand i Chrome</translation> <translation id="9071207983537882274">Åbner Indstillinger i Chrome.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zu.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zu.xtb index 7f4e4b26..36eec0f 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zu.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zu.xtb
@@ -94,7 +94,7 @@ <translation id="3360031466389132716">{THRESHOLD,plural, =1{Lokhu kwenzeka lapho i-Chrome ingasetshenziswa umzuzu ongu-{THRESHOLD}}one{Lokhu kwenzeka lapho i-Chrome ingasetshenziswa imizuzu engu-{THRESHOLD}}other{Lokhu kwenzeka lapho i-Chrome ingasetshenziswa imizuzu engu-{THRESHOLD}}}</translation> <translation id="3399930248910934354">Vula Amasethingi e-Chrome</translation> <translation id="344736123700721678">Finyelela ku-Chrome ngokushesha ukusuka kudokhu yakho yesikrini sasekhaya</translation> -<translation id="3472587960215700950">I-Chrome isebenzisa i-Google Maps ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> +<translation id="3472587960215700950">I-Chrome isebenzisa Amamephu eGoogle ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> <translation id="3503014945441706099">Thola Ukubhrawuza Okuphephile Okuthuthukisiwe kwale phrofayela ye-Chrome, futhi</translation> <translation id="3522659714780527202">Ukuze ubone amathebhu wakho noma kuphi lapho usebenzisa i-Chrome, vula ukuvumelanisa</translation> <translation id="3577555362230509265">Sebenzisa i-Chrome kwamanye ama-app.</translation> @@ -153,7 +153,7 @@ <translation id="546541279759910616">{COUNT,plural, =1{I-Chrome izokusiza ukulandelela le phakheji Ekhasini Lethebhu Entsha.}one{I-Chrome izokusiza ukulandelela le phakheji Ekhasini Lethebhu Entsha.}other{I-Chrome izokusiza ukulandelela le phakheji Ekhasini Lethebhu Entsha.}}</translation> <translation id="5492504007368565877">Umphathi Wephasiwedi Ye-Google akakwazi ukuhlola amaphasiwedi wakho.</translation> <translation id="5525095647255982834">Ukuze uthumele le thebhu kwenye idivayisi, ngena ngemvume ku-Chrome lapho.</translation> -<translation id="5527026824954593399">Thepha okuthi “Buka nge-Google Maps ku-Chrome.”</translation> +<translation id="5527026824954593399">Thepha okuthi “Buka nge-Amamephu eGoogle ku-Chrome.”</translation> <translation id="5552137475244467770">I-Chrome ngezikhathi ezithile ihlola amaphasiwedi akho ngokuwaqhathanisa nohlu olushicilelwe ku-inthanethi. Uma kwenziwa lokhu, amaphasiwedi akho namagama abasebenzisi abethelwe, ngakho-ke awakwazi ukufundwa inoma ubani, okufaka i-Google.</translation> <translation id="5554520618550346933">Uma usebenzisa iphasiwedi, i-Chrome iyakuxwayisa uma ishicilelwe ku-inthanethi. Uma yenza lokhu, amaphasiwedi akho namagama abasebenzisi ayabethelwa, ngakho awakwazi ukufundwa yinoma ubani, kubandakanya ne-Google.</translation> <translation id="5601180634394228718">Ukuze uthole amasethingi engeziwe asebenzisa idatha ukuthuthukisa ukuzizwisa kwakho kwe-Chrome, iya <ph name="BEGIN_LINK" />Kumasevisi e-Google<ph name="END_LINK" />.</translation> @@ -185,7 +185,7 @@ Idatha yakho ibethelwe ngomushwana wokungena. Ifake ukuze usebenzise futhi wonge idatha ye-Chrome ku-akhawunti yakho ye-Google.</translation> <translation id="6540120577248033958">Vakashela isayithi bese uchofoza okuthi Landela kumenyu ye-Chrome</translation> -<translation id="6545449117344801102">I-Chrome ithola amakheli futhi isebenzise i-Google Maps ukuze ikunikeze izikhombisi-ndlela nolwazi lwendawo.</translation> +<translation id="6545449117344801102">I-Chrome ithola amakheli futhi isebenzise Amamephu eGoogle ukuze ikunikeze izikhombisi-ndlela nolwazi lwendawo.</translation> <translation id="6634107063912726160">Lapho uphuma ngemvume, i-Chrome ngeke ivumelanise noma iyiphi idatha entsha kwi-akhawunti yakho ye-Google. Idatha evumelaniswe ngaphambilini ihlala kwi-akhawunti.</translation> <translation id="6646696210740573446">Ithumela ingxenye engaqondakali ye-URL ku-Google isebenzisa iseva eyimfihlo efihla ikheli lakho lasesizindeni se-inthanethi. Uma isayithi lizama ukuntshontsha iphasiwedi yakho, noma uma udawuniloda ifayela eliyingozi, i-Chrome ingathumela nama-URL, kuhlanganise nokuthile okuqukethwe kulelo khasi, ku-Google.</translation> <translation id="6648150602980899529">Ungena ngemvume nge-akhawunti ephethwe yi-<ph name="DOMAIN" /> futhi unikeza umlawuli ulawulo olungaphezulu kwedatha yakho ye-Chrome. Idatha yakho izohlanganiswa ngunaphakade kule akhawunti. Ukuphuma ngemvume ku-Chrome kuzosusa idatha yakho kusukela kule divayisi, kodwa kuzohlala kugcinwe ku-akhawunti yakho ye-Google.</translation> @@ -219,7 +219,7 @@ <translation id="7275945473750112644">I-akhawunti yakho iphethwe yi-<ph name="HOSTED_DOMAIN" />, ngakho idatha yakho ye-Chrome izosulwa kule divayisi</translation> <translation id="7304491752269485262">Ukubuka Okunwetshiwe Kokugcwalisa Okuzenzakalelayo kwe-Chrome</translation> <translation id="7344094882820374540">Thola ukuvikeleka okunamandla kakhulu kwe-Chrome kumasayithi ayingozi</translation> -<translation id="7349129508108954623">Vumela i-Chrome ukuthi isebenzise i-Google Maps ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> +<translation id="7349129508108954623">Vumela i-Chrome ukuthi isebenzise Amamephu eGoogle ukuze ikunikeze izikhombisi-ndlela nolwazi lwasendaweni kumakheli atholiwe.</translation> <translation id="7394108421562933108">I-Maps ku-Chrome</translation> <translation id="7400722733683201933">Mayelana ne-Google Chrome</translation> <translation id="7466693328838535498">Ebhokisini elithi Amawijethi Okusesha, faka i-Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_da.xtb b/ios/chrome/app/strings/resources/ios_strings_da.xtb index 9323af4..74802e0 100644 --- a/ios/chrome/app/strings/resources/ios_strings_da.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_da.xtb
@@ -94,7 +94,7 @@ <ph name="BEGIN_LINK" />Få flere oplysninger<ph name="END_LINK" /></translation> <translation id="1491277525950327607">Tryk to gange for at skifte indstilling</translation> <translation id="1492417797159476138">Du har allerede gemt dette brugernavn for dette website</translation> -<translation id="1497590942294823549">Menu → Adgangskodeadministrator</translation> +<translation id="1497590942294823549">Menu → Adgangskodeadministrator</translation> <translation id="1498283581832036924">Din <ph name="WEBSITE" />-konto slettes ikke.</translation> <translation id="1506063256525392513">Det giver dig mulighed for at tage og uploade billeder samt scanne QR-koder</translation> <translation id="1509486075633541495">Log ind på website</translation> @@ -158,7 +158,7 @@ <translation id="1832848789136765277">Verificer din identitet for at sikre, at du altid har adgang til dine synkroniserede data</translation> <translation id="1836891464494477513">{count,plural, =1{Bogmærket er gemt på din Google-konto, {email}}one{Bogmærket er gemt på din Google-konto, {email}}other{Bogmærkerne er gemt på din Google-konto, {email}}}</translation> <translation id="183878838231635348">Dette kort viser eventuelle privatlivs- eller sikkerhedsproblemer, som Sikkerhedstjek automatisk registrerer for dig.</translation> -<translation id="1847795903283049083">Du kan også se og administrere disse elementer i dine bogmærker, på din læseliste eller via Adgangskodeadministrator.</translation> +<translation id="1847795903283049083">Du kan også se og administrere disse elementer i dine bogmærker, på din læseliste eller via Adgangskodeadministrator.</translation> <translation id="1870148520156231997">Vis adgangskode</translation> <translation id="1872096359983322073">Lommelygte</translation> <translation id="1875733418125333939"><ph name="FILENAME" />.</translation> @@ -243,7 +243,7 @@ <translation id="2286505070150039482">Fremhævet tekst</translation> <translation id="2287614783861766820">{count,plural, =1{Adressen slettes fra denne enhed.}one{Adressen slettes fra denne enhed.}other{Adresserne slettes fra denne enhed.}}</translation> <translation id="2297989278479054870">Når du er logget ud, fjernes bogmærkerne, adgangskoderne m.m. på din Google-konto fra denne enhed.</translation> -<translation id="2299218006564889602">Dine adgangskoder krypteres på din enhed, inden de gemmes i Googles Adgangskodeadministrator.</translation> +<translation id="2299218006564889602">Dine adgangskoder krypteres på din enhed, inden de gemmes i Googles Adgangskodeadministrator.</translation> <translation id="2299515531293777561"><ph name="CARRIER_NAME" /> • #<ph name="PARCEL_IDENTIFIER" /></translation> <translation id="2302742851632557585">Skift adgangskode på website</translation> <translation id="230956208401264723">Se alle dine sporede pakker her i denne karrusel</translation> @@ -287,7 +287,7 @@ <translation id="2500374554657206846">Valgmuligheder for at gemme adgangskode</translation> <translation id="2511117522375201202">Du har <ph name="NUMBER_OF_PASSWORDS" /> kompromitterede adgangskoder, hvilket kan udgøre en sikkerhedsrisiko.</translation> <translation id="2529021024822217800">Åbn alle</translation> -<translation id="2536991091671391962">Du kan bruge gemte adgangskoder på alle enheder. De er gemt i Google Adgangskodeadministrator for <ph name="EMAIL" />.</translation> +<translation id="2536991091671391962">Du kan bruge gemte adgangskoder på alle enheder. De er gemt i Google Adgangskodeadministrator for <ph name="EMAIL" />.</translation> <translation id="2542268842667970959">Skjul "Sikkerhedstjek"</translation> <translation id="2547458583188611426">Synkronisering fungerer ikke. Angiv din adgangssætning for at starte synkroniseringen.</translation> <translation id="2551153019974022505">Kontofejl</translation> @@ -628,7 +628,7 @@ <translation id="4293080268407233932">Søg</translation> <translation id="4302248187517737842">Der er intet brugernavn ••••••••</translation> <translation id="4302415908542657649">Deler adgangskode</translation> -<translation id="4304713468139749426">Adgangskodeadministrator</translation> +<translation id="4304713468139749426">Adgangskodeadministrator</translation> <translation id="430793432425771671">Synkroniser alt</translation> <translation id="4309403553630140242">Tryk to gange for at få flere oplysninger</translation> <translation id="430967081421617822">Altid</translation> @@ -820,7 +820,7 @@ <translation id="5234764350956374838">Luk</translation> <translation id="5235389474593199952">Skjul historik</translation> <translation id="5238301240406177137">Gem på din konto</translation> -<translation id="5238596603078743134"><ph name="BEGIN_BOLD" /><ph name="USERNAME" /><ph name="END_BOLD" /> kan nu benytte dit brugernavn og din adgangskode, når vedkommende bruger Google Adgangskodeadministrator til at logge ind på <ph name="BEGIN_BOLD" /><ph name="WEBSITE" /><ph name="END_BOLD" />.</translation> +<translation id="5238596603078743134"><ph name="BEGIN_BOLD" /><ph name="USERNAME" /><ph name="END_BOLD" /> kan nu benytte dit brugernavn og din adgangskode, når vedkommende bruger Google Adgangskodeadministrator til at logge ind på <ph name="BEGIN_BOLD" /><ph name="WEBSITE" /><ph name="END_BOLD" />.</translation> <translation id="5245322853195994030">Annuller synkronisering</translation> <translation id="5248640482715684545">Dette website forsøger at åbne en anden app.</translation> <translation id="5256661381001734217">Dette website forsøger at åbne en app. Dette fjerner dig fra inkognitotilstand.</translation> @@ -899,7 +899,7 @@ <translation id="5684761169742812828">Denne adgangskode er blevet offentliggjort i forbindelse med et brud på datasikkerheden på internettet. Hvis du ikke har tid til at ændre den lige nu, anbefaler Google, at du gemmer denne advarsel for at minde dig selv om det senere.</translation> <translation id="5694848685995373177">Gemt i Drev for <ph name="USER_EMAIL" />.</translation> <translation id="5701270923492462699">Der er givet adgang til kameraet</translation> -<translation id="5702108177581350218">Når du deler en kopi af dit brugernavn og din adgangskode, kan dine familiemedlemmer udfylde dem ved hjælp af Google Adgangskodeadministrator.</translation> +<translation id="5702108177581350218">Når du deler en kopi af dit brugernavn og din adgangskode, kan dine familiemedlemmer udfylde dem ved hjælp af Google Adgangskodeadministrator.</translation> <translation id="5704908597376970822">Det lykkedes ikke at logge ind.</translation> <translation id="5706552126692816153">Aktiv for 1 dag siden</translation> <translation id="5718049162805123412">Du bør ændre disse med det samme</translation> @@ -926,7 +926,7 @@ <translation id="581659025233126501">Aktivér synkronisering</translation> <translation id="5817176759448082654">Adgangskodetjek</translation> <translation id="5819208479324046259">Administreres af <ph name="MANAGER" /> <ph name="BEGIN_LINK" />Få flere oplysninger<ph name="END_LINK" /></translation> -<translation id="5827650163984030263">Skjul Adgangskodeadministrator</translation> +<translation id="5827650163984030263">Skjul Adgangskodeadministrator</translation> <translation id="5834415013958049700">Lens-billede, du har kopieret</translation> <translation id="5844284118433003733">Når du er logget ind, knyttes disse data til din Google-konto for at beskytte dig i Google-tjenester, f.eks. ved at øge beskyttelsen i Gmail efter en sikkerhedshændelse.</translation> <translation id="5846482154967366008">Søgemaskine</translation> @@ -1012,7 +1012,7 @@ <translation id="6231782223312638214">Foreslået</translation> <translation id="6232329973559504466">Søgning i inkognitotilstand</translation> <translation id="6236952928980352967">Gendan advarsel</translation> -<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> +<translation id="6247557882553405851">Google Adgangskodeadministrator</translation> <translation id="6254066287920239840">Åbn links i appen i stedet for i browseren.</translation> <translation id="6255097610484507482">Rediger kreditkort</translation> <translation id="6266039999629596120">Kræver handling</translation> @@ -1046,7 +1046,7 @@ <translation id="6374469231428023295">Prøv igen</translation> <translation id="6377118281273296434">Sikkerhed på websitet</translation> <translation id="6383719166112032471">Åbn lokation…</translation> -<translation id="6387994324662817823">Adgangskoder gemmes kun i Adgangskodeadministrator på denne enhed.</translation> +<translation id="6387994324662817823">Adgangskoder gemmes kun i Adgangskodeadministrator på denne enhed.</translation> <translation id="6389470377220713856">Navn på kort</translation> <translation id="6404422529625928907">Åbn i Google Drev</translation> <translation id="6406506848690869874">Synkronisering</translation> @@ -1189,7 +1189,7 @@ <translation id="7069695992271320873">Fjern fra denne enhed</translation> <translation id="7080806333218412752">Sender webadresser til tjek i Beskyttet browsing. Der sendes også et mindre antal sider, downloads, udvidelsesaktivitet og systemoplysninger for at identificere nye trusler. Disse data knyttes midlertidigt til din Google-konto, når du er logget ind, for at beskytte dig i Google-apps.</translation> <translation id="7082853213442715471">Når denne funktion er aktiveret, blokeres visse webteknologier, hvilket kan medføre, at nogle websites indlæses langsommere eller ikke fungerer korrekt.</translation> -<translation id="7095110968493193530">I Google Adgangskodeadministrator for <ph name="EMAIL" /></translation> +<translation id="7095110968493193530">I Google Adgangskodeadministrator for <ph name="EMAIL" /></translation> <translation id="7101580180124131336">Du kan nu se indhold fra og om <ph name="CHANNEL_NAME" /> i Følger.</translation> <translation id="7102005569666697658">Downloader… <ph name="FILE_SIZE" /></translation> <translation id="7108338896283013870">Skjul</translation> @@ -1225,7 +1225,7 @@ <translation id="734758817008927353">Valgmuligheder for at gemme kort</translation> <translation id="7352651011704765696">Noget gik galt</translation> <translation id="7353432112255316844">Verificer din identitet</translation> -<translation id="7367530036083223701">Få sikker adgang til dine adgangskoder fra startskærmen med widgetten Adgangskodeadministrator.</translation> +<translation id="7367530036083223701">Få sikker adgang til dine adgangskoder fra startskærmen med widgetten Adgangskodeadministrator.</translation> <translation id="7380220816562673297">Indtil videre kan du kun dele adgangskoder med familiemedlemmer. <ph name="BEGIN_LINK" />Opret en familiegruppe<ph name="END_LINK" /> med op til 6 medlemmer for at få mere ud af dine produkter og abonnementer fra Google.</translation> <translation id="739101637685146669">Hvilken webadresse vil du tilføje som bogmærke?</translation> <translation id="7396331865858820922">Adgangskoden blev ikke delt</translation> @@ -1320,12 +1320,12 @@ <translation id="7788868432173225918">Luk udvidet visning</translation> <translation id="7791543448312431591">Tilføj</translation> <translation id="7792549458069452436">HENT APPEN</translation> -<translation id="7800723706644914607">Adgangskodeadministrator</translation> +<translation id="7800723706644914607">Adgangskodeadministrator</translation> <translation id="7807060072011926525">Leveret af Google</translation> <translation id="7812377703891978671">Du kan få adgang til hele din browserhistorik ved at vælge <ph name="HISTORY_BUTTON_ACCESSIBILITY_LABEL" />.</translation> <translation id="78146569776629510">Downloads</translation> <translation id="7839985698273989086">Offlineside</translation> -<translation id="7839994177130598711">Dine familiemedlemmer kan nu benytte dit brugernavn og din adgangskode, når de bruger Google Adgangskodeadministrator til at logge ind på <ph name="BEGIN_BOLD" /><ph name="WEBSITE" /><ph name="END_BOLD" />.</translation> +<translation id="7839994177130598711">Dine familiemedlemmer kan nu benytte dit brugernavn og din adgangskode, når de bruger Google Adgangskodeadministrator til at logge ind på <ph name="BEGIN_BOLD" /><ph name="WEBSITE" /><ph name="END_BOLD" />.</translation> <translation id="7840771868269352570">De valgte elementer fjernes.</translation> <translation id="7845466610722898">Vis læselisten</translation> <translation id="784551991304901159">Vælg Aktivér i menuen for at se indhold</translation> @@ -1341,7 +1341,7 @@ <translation id="7884694604461143138">Søgehistorik (<ph name="COUNT" /> blev fundet)</translation> <translation id="7887174313503389866">Få en rundvisning i vigtige privatlivs- og sikkerhedsindstillinger. Gå til de individuelle indstillinger for at se flere valgmuligheder.</translation> <translation id="7887198238286927132">Af hensyn til beskyttelsen af dine personlige oplysninger autofylder Chrome ikke dette felt.</translation> -<translation id="7889910613639381518">Nem og sikker adgang med widgetten Google Adgangskodeadministrator.</translation> +<translation id="7889910613639381518">Nem og sikker adgang med widgetten Google Adgangskodeadministrator.</translation> <translation id="7911190106180361398">Din organisation tillader ikke, at du synkroniserer alt.</translation> <translation id="7920949005883349320">Privatliv og sikkerhed</translation> <translation id="792357691529995513">Der blev ikke fundet nogen problemer</translation> @@ -1359,10 +1359,10 @@ <translation id="7977451675950311423">Advarer dig, hvis du bruger en adgangskode, der er blevet kompromitteret som følge af et brud på datasikkerheden.</translation> <translation id="7978018860671536736">3. Tryk på Autoudfyld adgangskoder</translation> <translation id="7982789257301363584">Netværk</translation> -<translation id="7987685713885608670">For at beskytte adgangskoderne yderligere krypteres de på din enhed, inden de gemmes i Googles Adgangskodeadministrator.</translation> +<translation id="7987685713885608670">For at beskytte adgangskoderne yderligere krypteres de på din enhed, inden de gemmes i Googles Adgangskodeadministrator.</translation> <translation id="7993619969781047893">Funktioner på visse websites fungerer muligvis ikke</translation> <translation id="800361585186029508">Åbner de angivne webadresser i Google Chrome.</translation> -<translation id="8005666035647241369">I Google Adgangskodeadministrator på denne enhed</translation> +<translation id="8005666035647241369">I Google Adgangskodeadministrator på denne enhed</translation> <translation id="8009225694047762179">Administrer adgangskoder</translation> <translation id="8011489434346330032">Web Inspector</translation> <translation id="8016714545083187120">Brug altid sikre forbindelser</translation> @@ -1548,7 +1548,7 @@ <translation id="8898822736010347272">Sender webadresser på visse sider, du besøger, begrænsede systemoplysninger og indhold fra visse sider til Google med henblik på at opdage nye trusler og beskytte brugerne på nettet.</translation> <translation id="890565330728586731">Tilbage</translation> <translation id="8909135823018751308">Del…</translation> -<translation id="8909459547399237818">Vælg Adgangskodeadministrator, og tryk derefter på Tilføj widget</translation> +<translation id="8909459547399237818">Vælg Adgangskodeadministrator, og tryk derefter på Tilføj widget</translation> <translation id="891282356902782456">Denne adgangskode gemmes kun på denne enhed. Hvis du vil bruge den på dine andre enheder, skal du gemme den på din Google-konto, <ph name="EMAIL" />.</translation> <translation id="8917490105272468696">Ja tak</translation> <translation id="8928133177108699615">Computer</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zu.xtb b/ios/chrome/app/strings/resources/ios_strings_zu.xtb index a2c73633..acbe9845 100644 --- a/ios/chrome/app/strings/resources/ios_strings_zu.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_zu.xtb
@@ -1538,7 +1538,7 @@ <translation id="8849001918648564819">Ifihliwe</translation> <translation id="8855242995793521265">Ayinensisi ibhrawuza yakho noma idivayisi yakho.</translation> <translation id="886335568110896118">Fihla Isicelo Sesayithi Yeselula</translation> -<translation id="8863431381414769983">Thola izikhombisi-ndlela nolwazi lwendawo ku-Google Maps</translation> +<translation id="8863431381414769983">Thola izikhombisi-ndlela nolwazi lwendawo ku-Amamephu eGoogle</translation> <translation id="8868471676553493380">{count,plural, =1{Ithebhu engu-{count}}one{Amathebhu angu-{count}}other{Amathebhu angu-{count}}}</translation> <translation id="8870413625673593573">Okuvalwe kamuva</translation> <translation id="8876882697946675716">Gcina Amadivayisi Akho Ekuvumelaniseni</translation>
diff --git a/ios/chrome/browser/ui/whats_new/strings/resources/ios_whats_new_strings_da.xtb b/ios/chrome/browser/ui/whats_new/strings/resources/ios_whats_new_strings_da.xtb index 48bffe0..8faeca7 100644 --- a/ios/chrome/browser/ui/whats_new/strings/resources/ios_whats_new_strings_da.xtb +++ b/ios/chrome/browser/ui/whats_new/strings/resources/ios_whats_new_strings_da.xtb
@@ -12,11 +12,11 @@ <translation id="4497631794981705027">Hold fingeren på startskærmen.</translation> <translation id="463279609093232564">Tryk på + øverst til venstre på skærmen.</translation> <translation id="5604467549230434026">Skriv Chrome i feltet Søgewidgets.</translation> -<translation id="5639067007765618198">Widgetten Google Adgangskodeadministrator</translation> +<translation id="5639067007765618198">Widgetten Google Adgangskodeadministrator</translation> <translation id="5922999516621365983">Træk fanen hertil for at fastgøre den.</translation> <translation id="5979837087407522202">Søg i adgangskoder</translation> <translation id="6109989197058801417">Hold fingeren på den fane, du vil fastgøre.</translation> -<translation id="639614003069108254">Vælg Adgangskodeadministrator, og tryk derefter på Tilføj widget.</translation> +<translation id="639614003069108254">Vælg Adgangskodeadministrator, og tryk derefter på Tilføj widget.</translation> <translation id="6905308710260460250">Fastgjorte faner</translation> <translation id="720206380500582061">Administrer indstillinger for inaktive faner under Indstillinger > Faner.</translation> <translation id="8077675488769462025">Inaktive faner</translation>
diff --git a/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_da.xtb b/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_da.xtb index 2843e62..cf90c1a 100644 --- a/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_da.xtb +++ b/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_da.xtb
@@ -8,18 +8,18 @@ <translation id="1706288056912586527">Vis adgangskode</translation> <translation id="1870148520156231997">Vis adgangskode</translation> <translation id="1977167321677356409">Adgangskode</translation> -<translation id="2211969839027957773">Google Adgangskodeadministrator</translation> +<translation id="2211969839027957773">Google Adgangskodeadministrator</translation> <translation id="2320166752086256636">Skjul tastaturet</translation> -<translation id="2489483078139081050">Du kan bruge gemte adgangskoder i andre apps på din enhed. De er kun gemt i Google Adgangskodeadministrator på denne enhed.</translation> +<translation id="2489483078139081050">Du kan bruge gemte adgangskoder i andre apps på din enhed. De er kun gemt i Google Adgangskodeadministrator på denne enhed.</translation> <translation id="2677128368066534822">Fravælg iCloud keychain for at få hurtigere adgang til dine adgangskoder</translation> <translation id="2712586044587587728">Dine Chrome-adgangskoder kan bruges i andre apps. Du kan altid deaktivere dette i appen Indstillinger.</translation> <translation id="2747003861858887689">Forrige felt</translation> <translation id="3280734926621805458">Brug</translation> <translation id="3580107423202590938">Der er ingen Chrome-adgangskoder</translation> <translation id="368844171100841558">Erstat</translation> -<translation id="3739920431472254679">Adgangskoder gemmes i Google Adgangskodeadministrator, så du kan bruge dem på alle enheder.</translation> +<translation id="3739920431472254679">Adgangskoder gemmes i Google Adgangskodeadministrator, så du kan bruge dem på alle enheder.</translation> <translation id="3789385946721385622">Brugernavn</translation> -<translation id="3830647155781949426">Din adgangskode gemmes i Google Adgangskodeadministrator for <ph name="EMAIL" />, når du vender tilbage til Chrome.</translation> +<translation id="3830647155781949426">Din adgangskode gemmes i Google Adgangskodeadministrator for <ph name="EMAIL" />, når du vender tilbage til Chrome.</translation> <translation id="4241076354893135477">Der er ingen Chrome-adgangskoder</translation> <translation id="4253168017788158739">Note</translation> <translation id="4452240207605337349">Adgangskoden kan ikke gemmes</translation> @@ -28,10 +28,10 @@ <translation id="5118084770294029567">Alle adgangskoder</translation> <translation id="5148402015874782921">Annuller</translation> <translation id="5824290706342306555">Kom godt i gang ved at gemme adgangskoder i Chrome eller logge ind med din Google-konto.</translation> -<translation id="6002340317268558779">Du kan bruge gemte adgangskoder i andre apps på din enhed. De er gemt i Google Adgangskodeadministrator for <ph name="EMAIL" />.</translation> +<translation id="6002340317268558779">Du kan bruge gemte adgangskoder i andre apps på din enhed. De er gemt i Google Adgangskodeadministrator for <ph name="EMAIL" />.</translation> <translation id="6159839020698489198">valgfrit</translation> <translation id="6216401132953873625">Tilføj ny adgangskode</translation> -<translation id="6387994324662817823">Adgangskoder gemmes kun i Adgangskodeadministrator på denne enhed.</translation> +<translation id="6387994324662817823">Adgangskoder gemmes kun i Adgangskodeadministrator på denne enhed.</translation> <translation id="6539092367496845964">Noget gik galt. Prøv igen senere.</translation> <translation id="6657585470893396449">Adgangskode</translation> <translation id="666236282349601348">Autofyld er aktiveret</translation> @@ -54,5 +54,5 @@ <translation id="8730621377337864115">Udfør</translation> <translation id="8877181643142698531">Webadresse</translation> <translation id="9069288651897538648">For <ph name="URL" /></translation> -<translation id="9168839987494597225">Adgangskoder gemmes kun i Google Adgangskodeadministrator på denne enhed.</translation> +<translation id="9168839987494597225">Adgangskoder gemmes kun i Google Adgangskodeadministrator på denne enhed.</translation> </translationbundle> \ No newline at end of file
diff --git a/ios/chrome/widget_kit_extension/strings/resources/ios_widget_kit_extension_strings_da.xtb b/ios/chrome/widget_kit_extension/strings/resources/ios_widget_kit_extension_strings_da.xtb index 1997a5d9..c75d2283 100644 --- a/ios/chrome/widget_kit_extension/strings/resources/ios_widget_kit_extension_strings_da.xtb +++ b/ios/chrome/widget_kit_extension/strings/resources/ios_widget_kit_extension_strings_da.xtb
@@ -5,7 +5,7 @@ <translation id="2513892053093488070">Stemmesøgning</translation> <translation id="2535710892645968259">Hop ind i Chrome Dino-spillet via din låseskærm.</translation> <translation id="2542770169955243077">Chrome Dino-spillet</translation> -<translation id="2922313168575194078">Søg sikkert efter dine gemte adgangskoder i Google Adgangskodeadministrator</translation> +<translation id="2922313168575194078">Søg sikkert efter dine gemte adgangskoder i Google Adgangskodeadministrator</translation> <translation id="302608144225178783">Hop ind i Chrome Dino-spillet via din startskærm.</translation> <translation id="3296938369177810197">Stemmesøgning</translation> <translation id="3464120926993669599">Søgning i inkognitotilstand</translation> @@ -24,12 +24,12 @@ <translation id="6179961764474023795">Genvejsmenu</translation> <translation id="6330929932864892436">Søg, eller angiv en webadresse</translation> <translation id="6336802729091778259">Chrome Dino-spillet</translation> -<translation id="6400175403219850910">Adgangskodeadministrator</translation> +<translation id="6400175403219850910">Adgangskodeadministrator</translation> <translation id="6663288906398689853">Søg</translation> <translation id="6691821786147477657">Start en ny søgning, eller åbn dine mest besøgte websites via din iPads startside.</translation> <translation id="6721566127904256183">Dine mest besøgte websites vises her.</translation> <translation id="6855322554930231468">Søgning</translation> -<translation id="6973491011026415905">Søg efter adgangskoder i Google Adgangskodeadministrator</translation> +<translation id="6973491011026415905">Søg efter adgangskoder i Google Adgangskodeadministrator</translation> <translation id="7010831364920321713">Søgning i inkognitotilstand</translation> <translation id="7048549665319929185">Søg, eller angiv en webadresse</translation>
diff --git a/ios_internal b/ios_internal index 53de667..4f440ef 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 53de6672bc3762c361e52d3df3555ff6fd5e5aac +Subproject commit 4f440ef57481bc0d056679d87cf6d4f6f1e8658f
diff --git a/net/base/features.cc b/net/base/features.cc index 4516dd1..7647810 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -81,6 +81,10 @@ "UseHostResolverCache", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kUseServiceEndpointRequest, + "UseServiceEndpointRequest", + base::FEATURE_DISABLED_BY_DEFAULT); + const base::FeatureParam<int> kAlternativePortForGloballyReachableCheck{ &kUseAlternativePortForGloballyReachableCheck, "AlternativePortForGloballyReachableCheck", 443};
diff --git a/net/base/features.h b/net/base/features.h index aec4fc4b..814a36f 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -97,6 +97,11 @@ // transactions complete. NET_EXPORT BASE_DECLARE_FEATURE(kUseHostResolverCache); +// Enables the DNS ServiceEndpointRequest API, which provides intermediate +// service endpoints in the middle of a DNS transaction so that clients of this +// API can attempt connections as soon as candidate endpoints are available. +NET_EXPORT BASE_DECLARE_FEATURE(kUseServiceEndpointRequest); + // If the `kUseAlternativePortForGloballyReachableCheck` flag is enabled, the // globally reachable check will use the port number specified by // `kAlternativePortForGloballyReachableCheck` flag. Otherwise, the globally
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index b175b9a..8d32558 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h
@@ -830,6 +830,11 @@ // The compression dictionary cannot be loaded. NET_ERROR(DICTIONARY_LOAD_FAILED, -387) +// The "content-dictionary" response header is unexpected. This is used both +// when there is no "content-dictionary" response header and when the received +// "content-dictionary" response header does not match the expected value. +NET_ERROR(UNEXPECTED_CONTENT_DICTIONARY_HEADER, -388) + // The cache does not have the requested entry. NET_ERROR(CACHE_MISS, -400)
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn index 9c10bfed..19a205a3 100644 --- a/net/dns/BUILD.gn +++ b/net/dns/BUILD.gn
@@ -76,6 +76,8 @@ "host_resolver_manager_job.h", "host_resolver_manager_request_impl.cc", "host_resolver_manager_request_impl.h", + "host_resolver_manager_service_endpoint_request_impl.cc", + "host_resolver_manager_service_endpoint_request_impl.h", "host_resolver_mdns_listener_impl.cc", "host_resolver_mdns_listener_impl.h", "host_resolver_mdns_task.cc", @@ -425,6 +427,7 @@ "host_resolver_internal_result_unittest.cc", "host_resolver_manager_ipv6_reachability_override_unittest.cc", "host_resolver_manager_unittest.cc", + "host_resolver_service_endpoint_request_unittest.cc", "https_record_rdata_unittest.cc", "httpssvc_metrics_unittest.cc", "loopback_only_unittest.cc",
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index f13340e..674e7a0 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h
@@ -194,6 +194,57 @@ virtual void ChangeRequestPriority(RequestPriority priority) {} }; + // Handler for a service endpoint resolution request. Unlike + // ResolveHostRequest, which waits for all responses, this could provide + // intermediate endpoint candidates in the middle of the resolution. + // + // A client owns an instance of this class. Destruction cancels the request. + class ServiceEndpointRequest { + public: + class Delegate { + public: + virtual ~Delegate() = default; + + // Called when the request has updated endpoints. + virtual void OnServiceEndpointsUpdated() = 0; + + // Called when all queries are responded or an error occurred. + // Note that this can be called without OnServiceEndpointsUpdated(). + virtual void OnServiceEndpointRequestFinished(int rv) = 0; + }; + + virtual ~ServiceEndpointRequest() = default; + + // Starts resolving service endpoints. `delegate` is used only when this + // method returns ERR_IO_PENDING. When the return value is other than + // ERR_IO_PENDING, resolution completed (or an error occurred) + // synchronously, and GetEndpointResults() will return finalized results. + virtual int Start(Delegate* delegate) = 0; + + // The current available service endpoints. These can be changed over time + // while resolution is still ongoing. Changes are signaled by a call to the + // delegate's OnServiceEndpointsUpdated(). Results are finalized when + // Start() finished synchronously (returning other than ERR_IO_PENDING), or + // delegate's OnServiceEndpointRequestFinished() is called. + virtual const std::vector<ServiceEndpoint>& GetEndpointResults() = 0; + + // Any DNS record aliases, such as CNAME aliases, found as a result of + // addresses and HTTPS queries. These can be changed over time while + // resolution is still ongoing. See also the comment on + // Request::GetDnsAliasResults() for details. + virtual const std::set<std::string>& GetDnsAliasResults() = 0; + + // True if the client of this request can attempt cryptographic handshakes. + // If false, the provided service endpoints via GetEndpointResults() are not + // finalized to the point to allow completing transactions, and data or + // cryptographic handshakes must not be sent. This can be changed over time + // while resolution is still ongoing. + // TODO(crbug.com/41493696): Consider renaming this to + // `IsSvcbResolutionCompleted()` when Chrome supports HTTPS follow-up + // queries. + virtual bool EndpointsCryptoReady() = 0; + }; + // Handler for an activation of probes controlled by a HostResolver. Created // by HostResolver::CreateDohProbeRequest(). class ProbeRequest {
diff --git a/net/dns/host_resolver_dns_task.cc b/net/dns/host_resolver_dns_task.cc index cde346bb..5360865e3 100644 --- a/net/dns/host_resolver_dns_task.cc +++ b/net/dns/host_resolver_dns_task.cc
@@ -535,7 +535,8 @@ break; } - if (base::FeatureList::IsEnabled(features::kUseHostResolverCache)) { + if (base::FeatureList::IsEnabled(features::kUseHostResolverCache) || + base::FeatureList::IsEnabled(features::kUseServiceEndpointRequest)) { SortTransactionAndHandleResults(std::move(transaction_info), std::move(results).value()); } else {
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index d67c41e..0635fe7 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -88,6 +88,7 @@ #include "net/dns/host_resolver_internal_result.h" #include "net/dns/host_resolver_manager_job.h" #include "net/dns/host_resolver_manager_request_impl.h" +#include "net/dns/host_resolver_manager_service_endpoint_request_impl.h" #include "net/dns/host_resolver_mdns_listener_impl.h" #include "net/dns/host_resolver_mdns_task.h" #include "net/dns/host_resolver_nat64_task.h" @@ -535,6 +536,24 @@ return listener; } +std::unique_ptr<HostResolver::ServiceEndpointRequest> +HostResolverManager::CreateServiceEndpointRequest( + url::SchemeHostPort scheme_host_port, + NetworkAnonymizationKey network_anonymization_key, + NetLogWithSource net_log, + ResolveHostParameters parameters, + ResolveContext* resolve_context) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!invalidation_in_progress_); + DCHECK_EQ(resolve_context->GetTargetNetwork(), target_network_); + DCHECK(registered_contexts_.HasObserver(resolve_context)); + + return std::make_unique<ServiceEndpointRequestImpl>( + std::move(scheme_host_port), std::move(network_anonymization_key), + std::move(net_log), std::move(parameters), resolve_context->GetWeakPtr(), + weak_ptr_factory_.GetWeakPtr(), tick_clock_); +} + void HostResolverManager::SetInsecureDnsClientEnabled( bool enabled, bool additional_dns_types_enabled) { @@ -893,6 +912,24 @@ return job.get(); } +void HostResolverManager::CreateAndStartJobForServiceEndpointRequest( + JobKey key, + std::deque<TaskType> tasks, + ServiceEndpointRequestImpl* request) { + CHECK(!tasks.empty()); + + auto jobit = jobs_.find(key); + if (jobit == jobs_.end()) { + Job* job = AddJobWithoutRequest(key, request->parameters().cache_usage, + request->host_cache(), std::move(tasks), + request->priority(), request->net_log()); + job->AddServiceEndpointRequest(request); + job->RunNextTask(); + } else { + jobit->second->AddServiceEndpointRequest(request); + } +} + HostCache::Entry HostResolverManager::ResolveAsIP(DnsQueryTypeSet query_types, bool resolve_canonname, const IPAddress& ip_address) {
diff --git a/net/dns/host_resolver_manager.h b/net/dns/host_resolver_manager.h index 8ede7e5..89f730c 100644 --- a/net/dns/host_resolver_manager.h +++ b/net/dns/host_resolver_manager.h
@@ -109,6 +109,7 @@ struct NET_EXPORT_PRIVATE JobKey; class NET_EXPORT_PRIVATE Job; class NET_EXPORT_PRIVATE RequestImpl; + class NET_EXPORT_PRIVATE ServiceEndpointRequestImpl; // Creates a HostResolver as specified by |options|. Blocking tasks are run in // ThreadPool. @@ -169,6 +170,15 @@ std::unique_ptr<MdnsListener> CreateMdnsListener(const HostPortPair& host, DnsQueryType query_type); + // Creates a service endpoint resolution request. + std::unique_ptr<HostResolver::ServiceEndpointRequest> + CreateServiceEndpointRequest( + url::SchemeHostPort scheme_host_port, + NetworkAnonymizationKey network_anonymization_key, + NetLogWithSource net_log, + ResolveHostParameters parameters, + ResolveContext* resolve_context); + // Enables or disables the built-in asynchronous DnsClient. If enabled, by // default (when no |ResolveHostParameters::source| is specified), the // DnsClient will be used for resolves and, in case of failure, resolution @@ -351,6 +361,12 @@ RequestPriority priority, const NetLogWithSource& source_net_log); + // Similar to CreateAndStartJob(), but for a ServiceEndpointRequest. + void CreateAndStartJobForServiceEndpointRequest( + JobKey key, + std::deque<TaskType> tasks, + ServiceEndpointRequestImpl* request); + // Resolves the IP literal hostname represented by `ip_address`. HostCache::Entry ResolveAsIP(DnsQueryTypeSet query_types, bool resolve_canonname,
diff --git a/net/dns/host_resolver_manager_job.cc b/net/dns/host_resolver_manager_job.cc index 0d2daeb..8498ccc3 100644 --- a/net/dns/host_resolver_manager_job.cc +++ b/net/dns/host_resolver_manager_job.cc
@@ -11,21 +11,26 @@ #include "base/containers/linked_list.h" #include "base/memory/raw_ptr.h" +#include "base/memory/safe_ref.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "net/base/address_family.h" +#include "net/base/features.h" #include "net/base/network_anonymization_key.h" #include "net/base/network_handle.h" #include "net/base/prioritized_dispatcher.h" #include "net/base/url_util.h" #include "net/dns/dns_client.h" +#include "net/dns/dns_task_results_manager.h" #include "net/dns/host_cache.h" #include "net/dns/host_resolver.h" #include "net/dns/host_resolver_dns_task.h" #include "net/dns/host_resolver_manager.h" #include "net/dns/host_resolver_manager_request_impl.h" +#include "net/dns/host_resolver_manager_service_endpoint_request_impl.h" #include "net/dns/host_resolver_mdns_task.h" #include "net/dns/host_resolver_nat64_task.h" #include "net/dns/public/dns_query_type.h" @@ -192,6 +197,13 @@ CHECK(key_ == req->GetJobKey()); req->OnJobCancelled(key_); } + + while (!service_endpoint_requests_.empty()) { + ServiceEndpointRequestImpl* request = + service_endpoint_requests_.head()->value(); + request->RemoveFromList(); + request->OnJobCancelled(); + } } void HostResolverManager::Job::Schedule(bool at_head) { @@ -224,20 +236,8 @@ request->AssignJob(weak_ptr_factory_.GetSafeRef()); - priority_tracker_.Add(request->priority()); - - request->source_net_log().AddEventReferencingSource( - NetLogEventType::HOST_RESOLVER_MANAGER_JOB_ATTACH, net_log_.source()); - - net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB_REQUEST_ATTACH, - [&] { - return NetLogJobAttachParams( - request->source_net_log().source(), priority()); - }); - - if (!request->parameters().is_speculative) { - had_non_speculative_request_ = true; - } + AddRequestCommon(request->priority(), request->source_net_log(), + request->parameters().is_speculative); requests_.Append(request); @@ -258,12 +258,7 @@ DCHECK_EQ(key_.host, request->request_host()); DCHECK(!requests_.empty()); - priority_tracker_.Remove(request->priority()); - net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB_REQUEST_DETACH, - [&] { - return NetLogJobAttachParams( - request->source_net_log().source(), priority()); - }); + CancelRequestCommon(request->priority(), request->source_net_log()); if (num_active_requests() > 0) { UpdatePriority(); @@ -277,6 +272,34 @@ } } +void HostResolverManager::Job::AddServiceEndpointRequest( + ServiceEndpointRequestImpl* request) { + CHECK_EQ(host_cache_, request->host_cache()); + + request->AssignJob(weak_ptr_factory_.GetSafeRef()); + + AddRequestCommon(request->priority(), request->net_log(), + request->parameters().is_speculative); + + service_endpoint_requests_.Append(request); + + UpdatePriority(); +} + +void HostResolverManager::Job::CancelServiceEndpointRequest( + ServiceEndpointRequestImpl* request) { + CancelRequestCommon(request->priority(), request->net_log()); + + if (num_active_requests() > 0) { + UpdatePriority(); + request->RemoveFromList(); + } else { + // See comments in CancelRequest(). + CompleteRequestsWithError(ERR_DNS_REQUEST_CANCELLED, + /*task_type=*/std::nullopt); + } +} + void HostResolverManager::Job::Abort() { CompleteRequestsWithError(ERR_NETWORK_CHANGED, /*task_type=*/std::nullopt); } @@ -495,6 +518,7 @@ } dns_task_.reset(); } + dns_task_results_manager_.reset(); } void HostResolverManager::Job::ReduceByOneJobSlot() { @@ -515,6 +539,32 @@ } } +void HostResolverManager::Job::AddRequestCommon( + RequestPriority request_priority, + const NetLogWithSource& request_net_log, + bool is_speculative) { + priority_tracker_.Add(request_priority); + request_net_log.AddEventReferencingSource( + NetLogEventType::HOST_RESOLVER_MANAGER_JOB_ATTACH, net_log_.source()); + net_log_.AddEvent( + NetLogEventType::HOST_RESOLVER_MANAGER_JOB_REQUEST_ATTACH, [&] { + return NetLogJobAttachParams(request_net_log.source(), priority()); + }); + if (!is_speculative) { + had_non_speculative_request_ = true; + } +} + +void HostResolverManager::Job::CancelRequestCommon( + RequestPriority request_priority, + const NetLogWithSource& request_net_log) { + priority_tracker_.Remove(request_priority); + net_log_.AddEvent( + NetLogEventType::HOST_RESOLVER_MANAGER_JOB_REQUEST_DETACH, [&] { + return NetLogJobAttachParams(request_net_log.source(), priority()); + }); +} + void HostResolverManager::Job::UpdatePriority() { if (is_queued()) { handle_ = resolver_->dispatcher_->ChangePriority(handle_, priority()); @@ -629,6 +679,13 @@ DCHECK_EQ(secure, !dispatched_); DCHECK_EQ(dispatched_ ? 1 : 0, num_occupied_job_slots_); DCHECK(!resolver_->ShouldForceSystemResolverDueToTestOverride()); + + CHECK(!dns_task_results_manager_); + if (base::FeatureList::IsEnabled(features::kUseServiceEndpointRequest)) { + dns_task_results_manager_ = std::make_unique<DnsTaskResultsManager>( + this, key_.host, key_.query_types, net_log_); + } + // Need to create the task even if we're going to post a failure instead of // running it, as a "started" job needs a task to be properly cleaned up. dns_task_ = std::make_unique<HostResolverDnsTask>( @@ -773,9 +830,12 @@ dns_task_->StartNextTransaction(); } - // TODO(crbug.com/41493696): Use `single_transaction_results` for the - // ServiceEndpointRequest API. Be sure to handle the case where `this` was - // deleted while processing the intermediate results. + if (dns_task_results_manager_ && single_transaction_results.has_value()) { + dns_task_results_manager_->ProcessDnsTransactionResults( + single_transaction_results->query_type, + single_transaction_results->results); + // `this` may be deleted. Do not add code below. + } } void HostResolverManager::Job::AddTransactionTimeQueued( @@ -783,6 +843,19 @@ total_transaction_time_queued_ += time_queued; } +void HostResolverManager::Job::OnServiceEndpointsUpdated() { + // Requests could be destroyed while executing callbacks. Post tasks + // instead of calling callbacks synchronously to prevent requests from being + // destroyed in the following for loop. + for (auto* request = service_endpoint_requests_.head(); + request != service_endpoint_requests_.end(); request = request->next()) { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(&ServiceEndpointRequestImpl::OnServiceEndpointsChanged, + request->value()->GetWeakPtr())); + } +} + void HostResolverManager::Job::StartMdnsTask() { // No flags are supported for MDNS except // HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6 (which is not actually an @@ -984,6 +1057,16 @@ } } + while (!service_endpoint_requests_.empty()) { + ServiceEndpointRequestImpl* request = + service_endpoint_requests_.head()->value(); + request->RemoveFromList(); + request->OnJobCompleted(results, secure); + if (!resolver_.get()) { + return; + } + } + // TODO(crbug.com/1200908): Call StartBootstrapFollowup() if any of the // requests have the Bootstrap policy. Note: A naive implementation could // cause an infinite loop if the bootstrap result has TTL=0.
diff --git a/net/dns/host_resolver_manager_job.h b/net/dns/host_resolver_manager_job.h index 3055e39..860ad90 100644 --- a/net/dns/host_resolver_manager_job.h +++ b/net/dns/host_resolver_manager_job.h
@@ -12,12 +12,14 @@ #include "base/containers/linked_list.h" #include "base/memory/raw_ptr.h" +#include "base/memory/safe_ref.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "net/base/address_family.h" #include "net/base/network_anonymization_key.h" #include "net/base/network_handle.h" #include "net/base/prioritized_dispatcher.h" +#include "net/dns/dns_task_results_manager.h" #include "net/dns/host_cache.h" #include "net/dns/host_resolver.h" #include "net/dns/host_resolver_dns_task.h" @@ -60,7 +62,8 @@ // Aggregates all Requests for the same Key. Dispatched via // PrioritizedDispatcher. class HostResolverManager::Job : public PrioritizedDispatcher::Job, - public HostResolverDnsTask::Delegate { + public HostResolverDnsTask::Delegate, + public DnsTaskResultsManager::Delegate { public: // Creates new job for |key| where |request_net_log| is bound to the // request that spawned it. @@ -87,6 +90,12 @@ // this Job. void CancelRequest(RequestImpl* request); + void AddServiceEndpointRequest(ServiceEndpointRequestImpl* request); + + // Similar to CancelRequest(), if `request` was the last active one, finishes + // this job. + void CancelServiceEndpointRequest(ServiceEndpointRequestImpl* request); + // Called from AbortJobsWithoutTargetNetwork(). Completes all requests and // destroys the job. This currently assumes the abort is due to a network // change. @@ -131,6 +140,10 @@ return key_.GetTargetNetwork() != handles::kInvalidNetworkHandle; } + DnsTaskResultsManager* dns_task_results_manager() const { + return dns_task_results_manager_.get(); + } + private: // Keeps track of the highest priority. class PriorityTracker { @@ -184,6 +197,13 @@ // so signals it is complete. void ReduceByOneJobSlot(); + // Common helper methods for adding and canceling a request. + void AddRequestCommon(RequestPriority request_priority, + const NetLogWithSource& request_net_log, + bool is_speculative); + void CancelRequestCommon(RequestPriority request_priority, + const NetLogWithSource& request_net_log); + void UpdatePriority(); // PrioritizedDispatcher::Job: @@ -222,6 +242,9 @@ single_transaction_results) override; void AddTransactionTimeQueued(base::TimeDelta time_queued) override; + // DnsTaskResultsManager::Delegate implementation: + void OnServiceEndpointsUpdated() override; + void StartMdnsTask(); void OnMdnsTaskComplete(); void OnMdnsImmediateFailure(int rv); @@ -324,6 +347,14 @@ // All Requests waiting for the result of this Job. Some can be canceled. base::LinkedList<RequestImpl> requests_; + // All ServiceEndpointRequests waiting for the result of this Job. Some can + // be canceled. + base::LinkedList<ServiceEndpointRequestImpl> service_endpoint_requests_; + + // Builds and updates intermediate service endpoints while executing + // a DnsTransaction. + std::unique_ptr<DnsTaskResultsManager> dns_task_results_manager_; + // A handle used for |dispatcher_|. PrioritizedDispatcher::Handle handle_;
diff --git a/net/dns/host_resolver_manager_service_endpoint_request_impl.cc b/net/dns/host_resolver_manager_service_endpoint_request_impl.cc new file mode 100644 index 0000000..556860c --- /dev/null +++ b/net/dns/host_resolver_manager_service_endpoint_request_impl.cc
@@ -0,0 +1,268 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/dns/host_resolver_manager_service_endpoint_request_impl.h" + +#include "base/memory/safe_ref.h" +#include "base/no_destructor.h" +#include "base/notreached.h" +#include "base/types/optional_util.h" +#include "net/base/net_errors.h" +#include "net/dns/dns_alias_utility.h" +#include "net/dns/dns_task_results_manager.h" +#include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_manager.h" +#include "url/scheme_host_port.h" + +namespace net { + +HostResolverManager::ServiceEndpointRequestImpl::FinalizedResult:: + FinalizedResult(std::vector<ServiceEndpoint> endpoints, + std::set<std::string> dns_aliases) + : endpoints(std::move(endpoints)), dns_aliases(std::move(dns_aliases)) {} + +HostResolverManager::ServiceEndpointRequestImpl::FinalizedResult:: + ~FinalizedResult() = default; + +HostResolverManager::ServiceEndpointRequestImpl::FinalizedResult:: + FinalizedResult(FinalizedResult&&) = default; +HostResolverManager::ServiceEndpointRequestImpl::FinalizedResult& +HostResolverManager::ServiceEndpointRequestImpl::FinalizedResult::operator=( + FinalizedResult&&) = default; + +HostResolverManager::ServiceEndpointRequestImpl::ServiceEndpointRequestImpl( + url::SchemeHostPort scheme_host_port, + NetworkAnonymizationKey network_anonymization_key, + NetLogWithSource net_log, + ResolveHostParameters parameters, + base::WeakPtr<ResolveContext> resolve_context, + base::WeakPtr<HostResolverManager> manager, + const base::TickClock* tick_clock) + : host_(std::move(scheme_host_port)), + network_anonymization_key_( + NetworkAnonymizationKey::IsPartitioningEnabled() + ? std::move(network_anonymization_key) + : NetworkAnonymizationKey()), + net_log_(std::move(net_log)), + parameters_(std::move(parameters)), + resolve_context_(std::move(resolve_context)), + manager_(std::move(manager)), + tick_clock_(tick_clock), + priority_(parameters_.initial_priority) {} + +HostResolverManager::ServiceEndpointRequestImpl::~ServiceEndpointRequestImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!job_.has_value()) { + return; + } + + LogCancelRequest(); + + // Clear the delegate to avoid calling delegate's callback after destruction. + // The following CancelServiceEndpointRequest() could result in calling + // OnJobCancelled() synchronously. + delegate_ = nullptr; + + job_.value()->CancelServiceEndpointRequest(this); +} + +int HostResolverManager::ServiceEndpointRequestImpl::Start(Delegate* delegate) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(!delegate_); + CHECK(resolve_context_); + CHECK(manager_); + + delegate_ = delegate; + + JobKey job_key(host_, resolve_context_.get()); + IPAddress ip_address; + manager_->InitializeJobKeyAndIPAddress( + network_anonymization_key_, parameters_, net_log_, job_key, ip_address); + + // Try to resolve locally first. + std::optional<HostCache::EntryStaleness> stale_info; + std::deque<TaskType> tasks; + HostCache::Entry results = manager_->ResolveLocally( + /*only_ipv6_reachable=*/false, job_key, ip_address, + parameters_.cache_usage, parameters_.secure_dns_policy, + parameters_.source, net_log_, host_cache(), &tasks, &stale_info); + if (results.error() != ERR_DNS_CACHE_MISS || + parameters_.source == HostResolverSource::LOCAL_ONLY || tasks.empty()) { + SetFinalizedResultFromLegacyResults(results); + return results.error(); + } + + manager_->CreateAndStartJobForServiceEndpointRequest(std::move(job_key), + std::move(tasks), this); + return ERR_IO_PENDING; +} + +const std::vector<ServiceEndpoint>& +HostResolverManager::ServiceEndpointRequestImpl::GetEndpointResults() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (finalized_result_.has_value()) { + return finalized_result_->endpoints; + } + + if (job_) { + CHECK(job_.value()->dns_task_results_manager()); + return job_.value()->dns_task_results_manager()->GetCurrentEndpoints(); + } + + NOTREACHED_NORETURN(); +} + +const std::set<std::string>& +HostResolverManager::ServiceEndpointRequestImpl::GetDnsAliasResults() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (finalized_result_.has_value()) { + return finalized_result_->dns_aliases; + } + + if (job_) { + CHECK(job_.value()->dns_task_results_manager()); + // TODO(crbug.com/41493696): Call dns_alias_utility::FixUpDnsAliases(). + return job_.value()->dns_task_results_manager()->GetAliases(); + } + + NOTREACHED_NORETURN(); +} + +bool HostResolverManager::ServiceEndpointRequestImpl::EndpointsCryptoReady() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (finalized_result_.has_value()) { + return true; + } + + if (job_) { + CHECK(job_.value()->dns_task_results_manager()); + return job_.value()->dns_task_results_manager()->IsMetadataReady(); + } + + NOTREACHED_NORETURN(); +} + +void HostResolverManager::ServiceEndpointRequestImpl::AssignJob( + base::SafeRef<Job> job) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(!job_.has_value()); + job_ = job; +} + +void HostResolverManager::ServiceEndpointRequestImpl::OnJobCompleted( + const HostCache::Entry& results, + bool obtained_securely) { + CHECK(job_); + CHECK(delegate_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + job_.reset(); + SetFinalizedResultFromLegacyResults(results); + + const bool is_secure_network_error = + obtained_securely && results.error() != OK; + error_info_ = ResolveErrorInfo(results.error(), is_secure_network_error); + delegate_->OnServiceEndpointRequestFinished(results.error()); + // Do not add code below. `this` may be deleted at this point. +} + +void HostResolverManager::ServiceEndpointRequestImpl::OnJobCancelled() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(job_); + + job_.reset(); + + // The owner of `this` has already destroyed `this`. + if (!delegate_) { + return; + } + + LogCancelRequest(); + + finalized_result_ = FinalizedResult(/*endpoints=*/{}, /*dns_aliases=*/{}); + error_info_ = ResolveErrorInfo(ERR_DNS_REQUEST_CANCELLED, + /*is_secure_network_error=*/false); + delegate_->OnServiceEndpointRequestFinished(ERR_DNS_REQUEST_CANCELLED); + // Do not add code below. `this` may be deleted at this point. +} + +void HostResolverManager::ServiceEndpointRequestImpl:: + OnServiceEndpointsChanged() { + // This method is called asynchronously via a posted task. `job_` could + // be completed or cancelled before executing the task. + if (finalized_result_.has_value()) { + return; + } + + CHECK(job_); + CHECK(job_.value()->dns_task_results_manager()); + CHECK(delegate_); + delegate_->OnServiceEndpointsUpdated(); + // Do not add code below. `this` may be deleted at this point. +} + +base::WeakPtr<HostResolverManager::ServiceEndpointRequestImpl> +HostResolverManager::ServiceEndpointRequestImpl::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +void HostResolverManager::ServiceEndpointRequestImpl:: + SetFinalizedResultFromLegacyResults(const HostCache::Entry& results) { + CHECK(!finalized_result_); + if (results.error() == OK && !parameters_.is_speculative) { + std::vector<IPEndPoint> ipv4_endpoints; + std::vector<IPEndPoint> ipv6_endpoints; + for (const auto& ip_endpoint : results.ip_endpoints()) { + std::vector<IPEndPoint>& ip_endpoints = + ip_endpoint.address().IsIPv6() ? ipv6_endpoints : ipv4_endpoints; + if (ip_endpoint.port() == 0) { + ip_endpoints.emplace_back(ip_endpoint.address(), host_.GetPort()); + } else { + ip_endpoints.emplace_back(ip_endpoint); + } + } + + // See HostCache::Entry::GetEndpoints. + std::vector<ServiceEndpoint> endpoints; + if (!ipv4_endpoints.empty() || !ipv6_endpoints.empty()) { + for (const auto& metadata : results.GetMetadatas()) { + if (!base::Contains(results.canonical_names(), metadata.target_name)) { + continue; + } + + ServiceEndpoint endpoint; + endpoint.ipv4_endpoints = ipv4_endpoints; + endpoint.ipv6_endpoints = ipv6_endpoints; + endpoint.metadata = metadata; + endpoints.emplace_back(std::move(endpoint)); + } + + // Append Non-SVCB endpoints at the end for fallback. + // TODO(crbug.com/41493696): Revisit how to handle non-SVCB endpoints once + // the connection layer starts using this API. Adding non-SVCB endpoints + // here might be inconsistent with intermediate results generated by + // DnsTaskResultsManager, which doesn't append non-SVCB endpoints. + ServiceEndpoint non_alternative_endpoint; + non_alternative_endpoint.ipv4_endpoints = ipv4_endpoints; + non_alternative_endpoint.ipv6_endpoints = ipv6_endpoints; + endpoints.emplace_back(std::move(non_alternative_endpoint)); + } + + finalized_result_ = + FinalizedResult(std::move(endpoints), + dns_alias_utility::FixUpDnsAliases(results.aliases())); + } else { + finalized_result_ = FinalizedResult(/*endpoints=*/{}, /*dns_aliases=*/{}); + } +} + +void HostResolverManager::ServiceEndpointRequestImpl::LogCancelRequest() { + net_log_.AddEvent(NetLogEventType::CANCELLED); + net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_MANAGER_REQUEST); +} + +} // namespace net
diff --git a/net/dns/host_resolver_manager_service_endpoint_request_impl.h b/net/dns/host_resolver_manager_service_endpoint_request_impl.h new file mode 100644 index 0000000..f1843c4 --- /dev/null +++ b/net/dns/host_resolver_manager_service_endpoint_request_impl.h
@@ -0,0 +1,121 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_DNS_HOST_RESOLVER_MANAGER_SERVICE_ENDPOINT_REQUEST_IMPL_H_ +#define NET_DNS_HOST_RESOLVER_MANAGER_SERVICE_ENDPOINT_REQUEST_IMPL_H_ + +#include <optional> +#include <set> +#include <string> +#include <vector> + +#include "base/containers/linked_list.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/safe_ref.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/time/tick_clock.h" +#include "net/base/network_anonymization_key.h" +#include "net/base/request_priority.h" +#include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_manager.h" +#include "net/dns/host_resolver_manager_job.h" +#include "net/dns/resolve_context.h" +#include "net/log/net_log_with_source.h" +#include "url/scheme_host_port.h" + +namespace net { + +// Implementation of HostResolver::ServiceEndpointRequest. +class HostResolverManager::ServiceEndpointRequestImpl + : public HostResolver::ServiceEndpointRequest, + public base::LinkNode<HostResolverManager::ServiceEndpointRequestImpl> { + public: + ServiceEndpointRequestImpl(url::SchemeHostPort scheme_host_port, + NetworkAnonymizationKey network_anonymization_key, + NetLogWithSource net_log, + ResolveHostParameters parameters, + base::WeakPtr<ResolveContext> resolve_context, + base::WeakPtr<HostResolverManager> manager, + const base::TickClock* tick_clock); + + ServiceEndpointRequestImpl(const ServiceEndpointRequestImpl&) = delete; + ServiceEndpointRequestImpl& operator=(const ServiceEndpointRequestImpl&) = + delete; + + ~ServiceEndpointRequestImpl() override; + + // HostResolver::ServiceEndpointRequest implementations: + int Start(Delegate* delegate) override; + const std::vector<ServiceEndpoint>& GetEndpointResults() override; + const std::set<std::string>& GetDnsAliasResults() override; + bool EndpointsCryptoReady() override; + + // These should only be called from HostResolver::Job. + void AssignJob(base::SafeRef<Job> job); + void OnJobCompleted(const HostCache::Entry& results, bool obtained_securely); + void OnJobCancelled(); + void OnServiceEndpointsChanged(); + + const NetLogWithSource& net_log() const { return net_log_; } + + const ResolveHostParameters& parameters() const { return parameters_; } + + // TODO(crbug.com/41493696): Support setting priority. + RequestPriority priority() const { return priority_; } + + HostCache* host_cache() const { + return resolve_context_ ? resolve_context_->host_cache() : nullptr; + } + + base::WeakPtr<ServiceEndpointRequestImpl> GetWeakPtr(); + + private: + void SetFinalizedResultFromLegacyResults(const HostCache::Entry& results); + + void LogCancelRequest(); + + const HostResolver::Host host_; + const NetworkAnonymizationKey network_anonymization_key_; + const NetLogWithSource net_log_; + ResolveHostParameters parameters_; + base::WeakPtr<ResolveContext> resolve_context_; + base::WeakPtr<HostResolverManager> manager_; + const raw_ptr<const base::TickClock> tick_clock_; + RequestPriority priority_; + + // `delegate_` must outlive `this` unless `resolve_context_` becomes invalid. + raw_ptr<Delegate> delegate_; + + // Holds the finalized results. + struct FinalizedResult { + FinalizedResult(std::vector<ServiceEndpoint> endpoints, + std::set<std::string> dns_aliases); + ~FinalizedResult(); + + FinalizedResult(FinalizedResult&&); + FinalizedResult& operator=(FinalizedResult&&); + + std::vector<ServiceEndpoint> endpoints; + std::set<std::string> dns_aliases; + }; + + // Set when the endpoint results are finalized. + std::optional<FinalizedResult> finalized_result_; + + // Set when a job is associated with `this`. Must be valid unless + // `resolve_context_` becomes invalid. Cleared when the endpoints are + // finalized to ensure that `job_` doesn't become a dangling pointer. + std::optional<base::SafeRef<Job>> job_; + + ResolveErrorInfo error_info_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<ServiceEndpointRequestImpl> weak_ptr_factory_{this}; +}; + +} // namespace net + +#endif // NET_DNS_HOST_RESOLVER_MANAGER_SERVICE_ENDPOINT_REQUEST_IMPL_H_
diff --git a/net/dns/host_resolver_service_endpoint_request_unittest.cc b/net/dns/host_resolver_service_endpoint_request_unittest.cc new file mode 100644 index 0000000..9c3bf2e --- /dev/null +++ b/net/dns/host_resolver_service_endpoint_request_unittest.cc
@@ -0,0 +1,933 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <algorithm> +#include <memory> +#include <optional> +#include <string> +#include <string_view> +#include <vector> + +#include "base/functional/callback.h" +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "base/time/time.h" +#include "net/base/address_family.h" +#include "net/base/features.h" +#include "net/base/net_errors.h" +#include "net/base/network_anonymization_key.h" +#include "net/dns/address_sorter.h" +#include "net/dns/dns_task_results_manager.h" +#include "net/dns/dns_test_util.h" +#include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_manager_service_endpoint_request_impl.h" +#include "net/dns/host_resolver_manager_unittest.h" +#include "net/dns/host_resolver_results_test_util.h" +#include "net/dns/public/host_resolver_results.h" +#include "net/dns/public/host_resolver_source.h" +#include "net/dns/resolve_context.h" +#include "net/log/net_log_with_source.h" +#include "net/test/gtest_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/scheme_host_port.h" + +using ::testing::ElementsAre; +using ::testing::IsEmpty; +using ::testing::UnorderedElementsAre; + +using net::test::IsError; +using net::test::IsOk; + +namespace net { + +using ServiceEndpointRequest = HostResolver::ServiceEndpointRequest; +using ResolveHostRequest = HostResolver::ResolveHostRequest; +using ResolveHostParameters = HostResolver::ResolveHostParameters; + +namespace { + +IPEndPoint MakeIPEndPoint(std::string_view ip_literal, uint16_t port = 0) { + std::optional<IPAddress> ip = IPAddress::FromIPLiteral(std::move(ip_literal)); + return IPEndPoint(*ip, port); +} + +// Sorts endpoints using IPAddress's comparator. +class FakeAddressSorter : public AddressSorter { + public: + void Sort(const std::vector<IPEndPoint>& endpoints, + CallbackType callback) const override { + std::vector<IPEndPoint> sorted = endpoints; + std::sort(sorted.begin(), sorted.end(), + [](const IPEndPoint& a, const IPEndPoint& b) { + return a.address() < b.address(); + }); + std::move(callback).Run(true, sorted); + } +}; + +class Requester : public ServiceEndpointRequest::Delegate { + public: + explicit Requester(std::unique_ptr<ServiceEndpointRequest> request) + : request_(std::move(request)) {} + + ~Requester() override = default; + + // ServiceEndpointRequest::Delegate overrides: + + void OnServiceEndpointsUpdated() override { + if (on_updated_callback_) { + std::move(on_updated_callback_).Run(); + } + } + + void OnServiceEndpointRequestFinished(int rv) override { + SetFinishedResult(rv); + + if (on_finished_callback_) { + std::move(on_finished_callback_).Run(); + } + + if (wait_for_finished_callback_) { + std::move(wait_for_finished_callback_).Run(); + } + } + + int Start() { + int rv = request_->Start(this); + if (rv != ERR_IO_PENDING) { + SetFinishedResult(rv); + } + return rv; + } + + void CancelRequest() { request_.reset(); } + + void CancelRequestOnUpdated() { + SetOnUpdatedCallback(base::BindLambdaForTesting([&] { CancelRequest(); })); + } + + void CancelRequestOnFinished() { + SetOnFinishedCallback(base::BindLambdaForTesting([&] { CancelRequest(); })); + } + + void SetOnUpdatedCallback(base::OnceClosure callback) { + CHECK(!finished_result_); + CHECK(!on_updated_callback_); + on_updated_callback_ = std::move(callback); + } + + void SetOnFinishedCallback(base::OnceClosure callback) { + CHECK(!finished_result_); + CHECK(!on_finished_callback_); + on_finished_callback_ = std::move(callback); + } + + void WaitForFinished() { + CHECK(!finished_result_); + CHECK(!wait_for_finished_callback_); + base::RunLoop run_loop; + wait_for_finished_callback_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + ServiceEndpointRequest* request() const { return request_.get(); } + + std::optional<int> finished_result() const { return finished_result_; } + + const std::vector<ServiceEndpoint>& finished_endpoints() const { + CHECK(finished_result_.has_value()); + return finished_endpoints_; + } + + private: + void SetFinishedResult(int rv) { + CHECK(!finished_result_); + finished_result_ = rv; + + if (request_) { + finished_endpoints_ = request_->GetEndpointResults(); + } + } + + std::unique_ptr<ServiceEndpointRequest> request_; + + std::optional<int> finished_result_; + std::vector<ServiceEndpoint> finished_endpoints_; + + base::OnceClosure wait_for_finished_callback_; + base::OnceClosure on_updated_callback_; + base::OnceClosure on_finished_callback_; +}; + +class LegacyRequester { + public: + explicit LegacyRequester(std::unique_ptr<ResolveHostRequest> request) + : request_(std::move(request)) {} + + ~LegacyRequester() = default; + + int Start() { + return request_->Start( + base::BindOnce(&LegacyRequester::OnComplete, base::Unretained(this))); + } + + void CancelRequest() { request_.reset(); } + + std::optional<int> complete_result() const { return complete_result_; } + + private: + void OnComplete(int rv) { complete_result_ = rv; } + + std::unique_ptr<ResolveHostRequest> request_; + std::optional<int> complete_result_; +}; + +} // namespace + +class HostResolverServiceEndpointRequestTest + : public HostResolverManagerDnsTest { + public: + HostResolverServiceEndpointRequestTest() { + feature_list_.InitAndEnableFeature(features::kUseServiceEndpointRequest); + } + + ~HostResolverServiceEndpointRequestTest() override = default; + + protected: + void SetUp() override { + HostResolverManagerDnsTest::SetUp(); + + // MockHostResolverProc resolves all requests to "127.0.0.1" when there is + // no rule. Add a rule to prevent the default behavior. + proc_->AddRule(std::string(), ADDRESS_FAMILY_UNSPECIFIED, "192.0.2.1"); + } + + void SetDnsRules(MockDnsClientRuleList rules) { + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + } + + void UseNoDomanDnsRules(const std::string& host) { + MockDnsClientRuleList rules; + AddDnsRule(&rules, host, dns_protocol::kTypeA, + MockDnsClientRule::ResultType::kNoDomain, /*delay=*/false); + AddDnsRule(&rules, host, dns_protocol::kTypeAAAA, + MockDnsClientRule::ResultType::kNoDomain, /*delay=*/false); + SetDnsRules(std::move(rules)); + } + + void UseNonDelayedDnsRules(const std::string& host) { + MockDnsClientRuleList rules; + AddDnsRule(&rules, host, dns_protocol::kTypeA, + MockDnsClientRule::ResultType::kOk, /*delay=*/false); + AddDnsRule(&rules, host, dns_protocol::kTypeAAAA, + MockDnsClientRule::ResultType::kOk, /*delay=*/false); + SetDnsRules(std::move(rules)); + } + + void UseIpv4DelayedDnsRules(const std::string& host) { + MockDnsClientRuleList rules; + AddDnsRule(&rules, host, dns_protocol::kTypeA, + MockDnsClientRule::ResultType::kOk, /*delay=*/true); + AddDnsRule(&rules, host, dns_protocol::kTypeAAAA, + MockDnsClientRule::ResultType::kOk, /*delay=*/false); + SetDnsRules(std::move(rules)); + } + + void UseIpv6DelayedDnsRules(const std::string& host) { + MockDnsClientRuleList rules; + AddDnsRule(&rules, host, dns_protocol::kTypeA, + MockDnsClientRule::ResultType::kOk, /*delay=*/false); + AddDnsRule(&rules, host, dns_protocol::kTypeAAAA, + MockDnsClientRule::ResultType::kOk, /*delay=*/true); + SetDnsRules(std::move(rules)); + } + + void UseHttpsDelayedDnsRules(const std::string& host) { + MockDnsClientRuleList rules; + AddDnsRule(&rules, host, dns_protocol::kTypeA, + MockDnsClientRule::ResultType::kOk, /*delay=*/false); + AddDnsRule(&rules, host, dns_protocol::kTypeAAAA, + MockDnsClientRule::ResultType::kOk, /*delay=*/false); + + std::vector<DnsResourceRecord> records = { + BuildTestHttpsServiceRecord(host, /*priority=*/1, /*service_name=*/".", + /*params=*/{})}; + rules.emplace_back(host, dns_protocol::kTypeHttps, + /*secure=*/false, + MockDnsClientRule::Result(BuildTestDnsResponse( + host, dns_protocol::kTypeHttps, records)), + /*delay=*/true); + SetDnsRules(std::move(rules)); + } + + std::unique_ptr<ServiceEndpointRequest> CreateRequest( + std::string_view host, + ResolveHostParameters parameters = ResolveHostParameters()) { + return resolver_->CreateServiceEndpointRequest( + url::SchemeHostPort(GURL(host)), NetworkAnonymizationKey(), + NetLogWithSource(), std::move(parameters), resolve_context_.get()); + } + + Requester CreateRequester( + std::string_view host, + ResolveHostParameters parameters = ResolveHostParameters()) { + return Requester(CreateRequest(host, std::move(parameters))); + } + + LegacyRequester CreateLegacyRequester(std::string_view host) { + return LegacyRequester(resolver_->CreateRequest( + url::SchemeHostPort(GURL(host)), NetworkAnonymizationKey(), + NetLogWithSource(), ResolveHostParameters(), resolve_context_.get())); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(HostResolverServiceEndpointRequestTest, NameNotResolved) { + UseNoDomanDnsRules("nodomain"); + + proc_->SignalMultiple(1u); + Requester requester = CreateRequester("https://nodomain"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + requester.WaitForFinished(); + EXPECT_THAT(*requester.finished_result(), IsError(ERR_NAME_NOT_RESOLVED)); +} + +TEST_F(HostResolverServiceEndpointRequestTest, Ok) { + UseNonDelayedDnsRules("ok"); + + Requester requester = CreateRequester("https://ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + requester.WaitForFinished(); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, ResolveLocally) { + UseNonDelayedDnsRules("ok"); + + // The first local only request should complete synchronously with a cache + // miss. + { + ResolveHostParameters parameters; + parameters.source = HostResolverSource::LOCAL_ONLY; + Requester requester = CreateRequester("https://ok", std::move(parameters)); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_DNS_CACHE_MISS)); + } + + // Populate the cache. + { + Requester requester = CreateRequester("https://ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + requester.WaitForFinished(); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + } + + // The second local only request should complete synchronously with a cache + // hit. + { + ResolveHostParameters parameters; + parameters.source = HostResolverSource::LOCAL_ONLY; + Requester requester = CreateRequester("https://ok", std::move(parameters)); + int rv = requester.Start(); + EXPECT_THAT(rv, IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + } +} + +TEST_F(HostResolverServiceEndpointRequestTest, EndpointsAreSorted) { + MockDnsClientRuleList rules; + constexpr const char* kHost = "multiple"; + + DnsResponse a_response = BuildTestDnsResponse( + kHost, dns_protocol::kTypeA, + {BuildTestAddressRecord(kHost, *IPAddress::FromIPLiteral("192.0.2.2")), + BuildTestAddressRecord(kHost, *IPAddress::FromIPLiteral("192.0.2.1"))}); + DnsResponse aaaa_response = BuildTestDnsResponse( + kHost, dns_protocol::kTypeAAAA, + {BuildTestAddressRecord(kHost, *IPAddress::FromIPLiteral("2001:db8::2")), + BuildTestAddressRecord(kHost, + *IPAddress::FromIPLiteral("2001:db8::1"))}); + AddDnsRule(&rules, kHost, dns_protocol::kTypeA, std::move(a_response), + /*delay=*/false); + AddDnsRule(&rules, kHost, dns_protocol::kTypeAAAA, std::move(aaaa_response), + /*delay=*/false); + + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + mock_dns_client_->SetAddressSorterForTesting( + std::make_unique<FakeAddressSorter>()); + + Requester requester = CreateRequester("https://multiple"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + requester.WaitForFinished(); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("192.0.2.1", 443), + MakeIPEndPoint("192.0.2.2", 443)), + ElementsAre(MakeIPEndPoint("2001:db8::1", 443), + MakeIPEndPoint("2001:db8::2", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, CancelRequestOnUpdated) { + UseIpv4DelayedDnsRules("4slow_ok"); + + Requester requester = CreateRequester("https://4slow_ok"); + requester.CancelRequestOnUpdated(); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + RunUntilIdle(); + // The finished callback should not be called because the request was + // already cancelled. + ASSERT_FALSE(requester.finished_result().has_value()); + ASSERT_FALSE(requester.request()); +} + +TEST_F(HostResolverServiceEndpointRequestTest, CancelRequestOnFinished) { + UseIpv4DelayedDnsRules("4slow_ok"); + + Requester requester = CreateRequester("https://4slow_ok"); + requester.CancelRequestOnFinished(); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + mock_dns_client_->CompleteDelayedTransactions(); + requester.WaitForFinished(); + // The result should be OK because we cancel the request after completing the + // associated Job. + EXPECT_THAT(*requester.finished_result(), IsOk()); +} + +TEST_F(HostResolverServiceEndpointRequestTest, Ipv4Slow) { + UseIpv4DelayedDnsRules("4slow_ok"); + + Requester requester = CreateRequester("https://4slow_ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // AAAA and HTTPS should complete. + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + ASSERT_FALSE(requester.finished_result().has_value()); + ASSERT_TRUE(requester.request()->EndpointsCryptoReady()); + EXPECT_THAT(requester.request()->GetEndpointResults(), + ElementsAre(ExpectServiceEndpoint( + IsEmpty(), ElementsAre(MakeIPEndPoint("::1", 443))))); + EXPECT_THAT(requester.request()->GetDnsAliasResults(), + UnorderedElementsAre("4slow_ok")); + + // Complete A request, which finishes the request synchronously. + mock_dns_client_->CompleteDelayedTransactions(); + ASSERT_TRUE(requester.request()->EndpointsCryptoReady()); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + EXPECT_THAT(requester.request()->GetDnsAliasResults(), + UnorderedElementsAre("4slow_ok")); +} + +TEST_F(HostResolverServiceEndpointRequestTest, Ipv6Slow) { + UseIpv6DelayedDnsRules("6slow_ok"); + + Requester requester = CreateRequester("https://6slow_ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // A and HTTPS should complete, but no endpoints should be available since + // waiting for AAAA response. + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + ASSERT_FALSE(requester.finished_result().has_value()); + ASSERT_TRUE(requester.request()->EndpointsCryptoReady()); + EXPECT_THAT(requester.request()->GetEndpointResults(), IsEmpty()); + + // Complete AAAA request, which finishes the request synchronously. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, Ipv6SlowResolutionDelayPassed) { + UseIpv6DelayedDnsRules("6slow_ok"); + + Requester requester = CreateRequester("https://6slow_ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // A and HTTPS should complete, but no endpoints should be available since + // waiting for AAAA response. + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + ASSERT_FALSE(requester.finished_result().has_value()); + ASSERT_TRUE(requester.request()->EndpointsCryptoReady()); + EXPECT_THAT(requester.request()->GetEndpointResults(), IsEmpty()); + + // The resolution delay timer fired, IPv4 endpoints should be available. + FastForwardBy(DnsTaskResultsManager::kResolutionDelay + + base::Milliseconds(1)); + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + ASSERT_FALSE(requester.finished_result().has_value()); + EXPECT_THAT(requester.request()->GetEndpointResults(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), IsEmpty()))); + + // Complete AAAA request, which finishes the request synchronously. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, HttpsSlow) { + UseHttpsDelayedDnsRules("https_slow_ok"); + + Requester requester = CreateRequester("https://https_slow_ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // A and AAAA should complete. + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + ASSERT_FALSE(requester.finished_result().has_value()); + ASSERT_FALSE(requester.request()->EndpointsCryptoReady()); + EXPECT_THAT(requester.request()->GetEndpointResults(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + + // Complete HTTPS request, which finishes the request synchronously. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT( + requester.finished_endpoints(), + ElementsAre( + ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443)), + ConnectionEndpointMetadata( + /*supported_protocol_alpns=*/{"http/1.1"}, + /*ech_config_list=*/{}, std::string("https_slow_ok"))), + // Non-SVCB endpoints. + ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, DestroyResolverWhileUpdating) { + // Using 4slow_ok not to complete transactions at once. + UseIpv4DelayedDnsRules("4slow_ok"); + + Requester requester = CreateRequester("https://4slow_ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + requester.SetOnUpdatedCallback( + base::BindLambdaForTesting([&]() { DestroyResolver(); })); + + RunUntilIdle(); + EXPECT_THAT(*requester.finished_result(), IsError(ERR_DNS_REQUEST_CANCELLED)); +} + +TEST_F(HostResolverServiceEndpointRequestTest, DestroyResolverWhileFinishing) { + UseNonDelayedDnsRules("ok"); + + Requester requester = CreateRequester("https://ok"); + int rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + requester.SetOnFinishedCallback( + base::BindLambdaForTesting([&]() { DestroyResolver(); })); + + RunUntilIdle(); + EXPECT_THAT(*requester.finished_result(), IsOk()); +} + +TEST_F(HostResolverServiceEndpointRequestTest, MultipleRequestsOk) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + Requester requester1 = CreateRequester(kHost); + EXPECT_THAT(requester1.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester2 = CreateRequester(kHost); + EXPECT_THAT(requester2.Start(), IsError(ERR_IO_PENDING)); + // The second request should share the same job with the first request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Complete the delayed transaction, which finishes requests synchronously. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(*requester1.finished_result(), IsOk()); + EXPECT_THAT(requester1.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + + EXPECT_THAT(*requester2.finished_result(), IsOk()); + EXPECT_THAT(requester2.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + MultipleRequestsAddRequestInTheMiddleOfResolution) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + Requester requester1 = CreateRequester(kHost); + EXPECT_THAT(requester1.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Partially complete transactions. Only IPv6 endpoints should be available. + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + ASSERT_FALSE(requester1.finished_result().has_value()); + EXPECT_THAT(requester1.request()->GetEndpointResults(), + ElementsAre(ExpectServiceEndpoint( + IsEmpty(), ElementsAre(MakeIPEndPoint("::1", 443))))); + + // Add a new request in the middle of resolution. The request should be + // attached to the ongoing job. + Requester requester2 = CreateRequester(kHost); + requester2.CancelRequestOnFinished(); + EXPECT_THAT(requester2.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // The second request should have the same intermediate results as the first + // request. + ASSERT_FALSE(requester2.finished_result().has_value()); + EXPECT_THAT(requester2.request()->GetEndpointResults(), + ElementsAre(ExpectServiceEndpoint( + IsEmpty(), ElementsAre(MakeIPEndPoint("::1", 443))))); + + // Complete all transactions. Both requests should finish and have the same + // results. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_EQ(0u, resolver_->num_running_dispatcher_jobs_for_tests()); + + EXPECT_THAT(*requester1.finished_result(), IsOk()); + EXPECT_THAT(requester1.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + + EXPECT_THAT(*requester2.finished_result(), IsOk()); + EXPECT_THAT(requester2.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + MultipleRequestsAddAndCancelRequestInUpdatedCallback) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + Requester requester1 = CreateRequester(kHost); + Requester requester2 = CreateRequester(kHost); + + requester1.SetOnUpdatedCallback(base::BindLambdaForTesting([&] { + EXPECT_THAT(requester2.Start(), IsError(ERR_IO_PENDING)); + requester1.CancelRequest(); + })); + + EXPECT_THAT(requester1.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Partially complete transactions. The update callback of the first request + // should start the second request and then cancel the first request. + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + + ASSERT_FALSE(requester1.finished_result().has_value()); + ASSERT_FALSE(requester1.request()); + + ASSERT_FALSE(requester2.finished_result().has_value()); + EXPECT_THAT(requester2.request()->GetEndpointResults(), + ElementsAre(ExpectServiceEndpoint( + IsEmpty(), ElementsAre(MakeIPEndPoint("::1", 443))))); + + // Complete all transactions. The second request should finish successfully. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_EQ(0u, resolver_->num_running_dispatcher_jobs_for_tests()); + + ASSERT_FALSE(requester1.finished_result().has_value()); + ASSERT_FALSE(requester1.request()); + + EXPECT_THAT(*requester2.finished_result(), IsOk()); + EXPECT_THAT(requester2.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + MultipleRequestsAddRequestInFinishedCallback) { + UseNonDelayedDnsRules("ok"); + + constexpr std::string_view kHost = "https://ok"; + Requester requester1 = CreateRequester(kHost); + Requester requester2 = CreateRequester(kHost); + + requester1.SetOnFinishedCallback(base::BindLambdaForTesting([&] { + // The second request should finish synchronously because it should + // share the same job as the first one and the job has finished already. + EXPECT_THAT(requester2.Start(), IsOk()); + })); + + EXPECT_THAT(requester1.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + RunUntilIdle(); + EXPECT_EQ(0u, resolver_->num_running_dispatcher_jobs_for_tests()); + + EXPECT_THAT(*requester1.finished_result(), IsOk()); + EXPECT_THAT(requester1.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + + EXPECT_THAT(*requester2.finished_result(), IsOk()); + EXPECT_THAT(requester2.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + MultipleRequestsCancelOneRequestOnUpdated) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + Requester requester1 = CreateRequester(kHost); + EXPECT_THAT(requester1.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester2 = CreateRequester(kHost); + // The second request destroys self when notified an update. + requester2.CancelRequestOnUpdated(); + EXPECT_THAT(requester2.Start(), IsError(ERR_IO_PENDING)); + // The second request should share the same job with the first request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Complete the delayed transaction, which finishes the first request + // synchronously. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(*requester1.finished_result(), IsOk()); + EXPECT_THAT(requester1.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); + // The second request was destroyed so it didn't get notified. + ASSERT_FALSE(requester2.finished_result().has_value()); + ASSERT_FALSE(requester2.request()); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + MultipleRequestsCancelAllRequestOnUpdated) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + Requester requester1 = CreateRequester(kHost); + requester1.CancelRequestOnUpdated(); + EXPECT_THAT(requester1.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester2 = CreateRequester(kHost); + requester2.CancelRequestOnUpdated(); + EXPECT_THAT(requester2.Start(), IsError(ERR_IO_PENDING)); + // The second request should share the same job with the first request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Complete non-delayed transactions and invoke update callbacks, which + // destroy all requests. + RunUntilIdle(); + EXPECT_EQ(0u, resolver_->num_running_dispatcher_jobs_for_tests()); + + ASSERT_FALSE(requester1.finished_result().has_value()); + ASSERT_FALSE(requester1.request()); + ASSERT_FALSE(requester2.finished_result().has_value()); + ASSERT_FALSE(requester2.request()); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + MultipleRequestsCancelAllRequestOnFinished) { + UseNonDelayedDnsRules("ok"); + + constexpr std::string_view kHost = "https://ok"; + Requester requester1 = CreateRequester(kHost); + requester1.CancelRequestOnFinished(); + EXPECT_THAT(requester1.Start(), IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester2 = CreateRequester(kHost); + requester2.CancelRequestOnFinished(); + EXPECT_THAT(requester2.Start(), IsError(ERR_IO_PENDING)); + // The second request should share the same job with the first request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + RunUntilIdle(); + EXPECT_EQ(0u, resolver_->num_running_dispatcher_jobs_for_tests()); + EXPECT_THAT(*requester1.finished_result(), IsOk()); + EXPECT_THAT(*requester2.finished_result(), IsOk()); +} + +TEST_F(HostResolverServiceEndpointRequestTest, WithLegacyRequestOk) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + LegacyRequester legacy_requester = CreateLegacyRequester(kHost); + int rv = legacy_requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester = CreateRequester(kHost); + rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + // The request should share the same job with the legacy request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Partially complete transactions. Requests should not complete but + // the non-legacy request should provide intermediate endpoints. + RunUntilIdle(); + EXPECT_EQ(1u, resolver_->num_running_dispatcher_jobs_for_tests()); + ASSERT_FALSE(legacy_requester.complete_result().has_value()); + ASSERT_FALSE(requester.finished_result().has_value()); + ASSERT_TRUE(requester.request()->EndpointsCryptoReady()); + EXPECT_THAT(requester.request()->GetEndpointResults(), + ElementsAre(ExpectServiceEndpoint( + IsEmpty(), ElementsAre(MakeIPEndPoint("::1", 443))))); + + // Complete delayed transactions, which finish requests synchronously. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(*legacy_requester.complete_result(), IsOk()); + EXPECT_THAT(*requester.finished_result(), IsOk()); + EXPECT_THAT(requester.finished_endpoints(), + ElementsAre(ExpectServiceEndpoint( + ElementsAre(MakeIPEndPoint("127.0.0.1", 443)), + ElementsAre(MakeIPEndPoint("::1", 443))))); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + WithLegacyRequestDestroyResolverOnUpdated) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + LegacyRequester legacy_requester = CreateLegacyRequester(kHost); + int rv = legacy_requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester = CreateRequester(kHost); + rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + // The request should share the same job with the legacy request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + requester.SetOnUpdatedCallback( + base::BindLambdaForTesting([&]() { DestroyResolver(); })); + + RunUntilIdle(); + // DestroyResolver() removed the corresponding job and the legacy reqquest + // didn't get notified, but the non-legacy request got notified via the + // update callback. + ASSERT_FALSE(legacy_requester.complete_result().has_value()); + EXPECT_THAT(*requester.finished_result(), IsError(ERR_DNS_REQUEST_CANCELLED)); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + WithLegacyRequestCancelRequestOnUpdated) { + UseIpv4DelayedDnsRules("4slow_ok"); + + constexpr std::string_view kHost = "https://4slow_ok"; + LegacyRequester legacy_requester = CreateLegacyRequester(kHost); + int rv = legacy_requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester = CreateRequester(kHost); + requester.CancelRequestOnUpdated(); + rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + // The request should share the same job with the legacy request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Partially complete transactions to trigger the update callback on + // non-legacy request, which cancels the request itself. + RunUntilIdle(); + ASSERT_FALSE(legacy_requester.complete_result().has_value()); + ASSERT_FALSE(requester.request()); + + // Complete delayed transactions, which finish the legacy request + // synchronously. Non-legacy request was already destroyed. + mock_dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(*legacy_requester.complete_result(), IsOk()); +} + +TEST_F(HostResolverServiceEndpointRequestTest, + WithLegacyRequestCancelLegacyRequest) { + UseNonDelayedDnsRules("ok"); + + constexpr std::string_view kHost = "https://ok"; + + LegacyRequester legacy_requester = CreateLegacyRequester(kHost); + int rv = legacy_requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + Requester requester = CreateRequester(kHost); + requester.CancelRequestOnUpdated(); + rv = requester.Start(); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + // The request should share the same job with the legacy request. + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + // Cancelling legacy request should not cancel non-legacy request. + legacy_requester.CancelRequest(); + ASSERT_FALSE(requester.finished_result().has_value()); + EXPECT_EQ(3u, resolver_->num_running_dispatcher_jobs_for_tests()); + + requester.WaitForFinished(); + EXPECT_EQ(0u, resolver_->num_running_dispatcher_jobs_for_tests()); + EXPECT_THAT(*requester.finished_result(), IsOk()); +} + +} // namespace net
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index 00b20a6..ab70e6d 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2024-04-12 12:55 UTC +# Last updated: 2024-04-14 12:56 UTC PinsListTimestamp -1712926524 +1713099385 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json index c68c6b3..ce07e2b 100644 --- a/net/http/transport_security_state_static_pins.json +++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@ // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets' // refer to, and the timestamp at which the pins list was last updated. // -// Last updated: 2024-04-12 12:55 UTC +// Last updated: 2024-04-14 12:56 UTC // { "pinsets": [
diff --git a/services/network/shared_dictionary/shared_dictionary_network_transaction.cc b/services/network/shared_dictionary/shared_dictionary_network_transaction.cc index b7a7aa2..aee05bc5 100644 --- a/services/network/shared_dictionary/shared_dictionary_network_transaction.cc +++ b/services/network/shared_dictionary/shared_dictionary_network_transaction.cc
@@ -163,7 +163,7 @@ shared_dictionary::kContentDictionaryHeaderName, &content_dictionary) || dictionary_hash_base64_ != content_dictionary) { - return base::unexpected(net::ERR_DICTIONARY_LOAD_FAILED); + return base::unexpected(net::ERR_UNEXPECTED_CONTENT_DICTIONARY_HEADER); } }
diff --git a/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc b/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc index 3397e63..ab9fdafe 100644 --- a/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc +++ b/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc
@@ -787,8 +787,9 @@ ASSERT_THAT(transaction.Start(&request, start_callback.callback(), net::NetLogWithSource()), net::test::IsError(net::ERR_IO_PENDING)); - EXPECT_THAT(start_callback.WaitForResult(), - net::test::IsError(net::ERR_DICTIONARY_LOAD_FAILED)); + EXPECT_THAT( + start_callback.WaitForResult(), + net::test::IsError(net::ERR_UNEXPECTED_CONTENT_DICTIONARY_HEADER)); } TEST_F(SharedDictionaryNetworkTransactionTest, WrongContentDictionary) { @@ -816,8 +817,9 @@ ASSERT_THAT(transaction.Start(&request, start_callback.callback(), net::NetLogWithSource()), net::test::IsError(net::ERR_IO_PENDING)); - EXPECT_THAT(start_callback.WaitForResult(), - net::test::IsError(net::ERR_DICTIONARY_LOAD_FAILED)); + EXPECT_THAT( + start_callback.WaitForResult(), + net::test::IsError(net::ERR_UNEXPECTED_CONTENT_DICTIONARY_HEADER)); } TEST_F(SharedDictionaryNetworkTransactionTest, MultipleContentEncodingWithSbr) {
diff --git a/services/webnn/tflite/graph_builder.cc b/services/webnn/tflite/graph_builder.cc index 14ca56ae..dccaee07 100644 --- a/services/webnn/tflite/graph_builder.cc +++ b/services/webnn/tflite/graph_builder.cc
@@ -211,6 +211,8 @@ } case mojom::Activation::Tag::kRelu: return ::tflite::ActivationFunctionType_RELU; + case mojom::Activation::Tag::kTanh: + return ::tflite::ActivationFunctionType_TANH; case mojom::Activation::Tag::kElu: return base::unexpected("Elu activation is not supported."); case mojom::Activation::Tag::kHardSigmoid: @@ -227,8 +229,6 @@ return base::unexpected("Softplus activation is not supported."); case mojom::Activation::Tag::kSoftsign: return base::unexpected("Softsign activation is not supported."); - case mojom::Activation::Tag::kTanh: - return base::unexpected("Tanh activation is not supported."); } } @@ -380,6 +380,9 @@ ASSIGN_OR_RETURN(operator_offset, SerializeSplit(*op.get_split())); break; } + case mojom::Operation::Tag::kTanh: + operator_offset = SerializeTanh(*op.get_tanh()); + break; case mojom::Operation::Tag::kTranspose: operator_offset = SerializeTranspose(*op.get_transpose()); break; @@ -411,8 +414,6 @@ return base::unexpected("softplus is not implemented"); case mojom::Operation::Tag::kSoftsign: return base::unexpected("softsign is not implemented"); - case mojom::Operation::Tag::kTanh: - return base::unexpected("tanh is not implemented"); case mojom::Operation::Tag::kTriangular: return base::unexpected("triangular is not implemented"); case mojom::Operation::Tag::kWhere: @@ -1580,6 +1581,11 @@ ::tflite::BuiltinOptions_SplitVOptions, split_options.Union()); } +auto GraphBuilder::SerializeTanh(const mojom::Tanh& tanh) -> OperatorOffset { + return SerializeUnaryOperation(::tflite::BuiltinOperator_TANH, + tanh.input_operand_id, tanh.output_operand_id); +} + auto GraphBuilder::SerializeTranspose(const mojom::Transpose& transpose) -> OperatorOffset { return SerializeTransposeOperation(
diff --git a/services/webnn/tflite/graph_builder.h b/services/webnn/tflite/graph_builder.h index 0ce04c1c..786dc00 100644 --- a/services/webnn/tflite/graph_builder.h +++ b/services/webnn/tflite/graph_builder.h
@@ -184,6 +184,7 @@ OperatorOffset SerializeSoftmax(const mojom::Softmax& softmax); base::expected<OperatorOffset, std::string> SerializeSplit( const mojom::Split& split); + OperatorOffset SerializeTanh(const mojom::Tanh& tanh); OperatorOffset SerializeTranspose(const mojom::Transpose& transpose); // No further methods may be called on this class after calling this method
diff --git a/services/webnn/tflite/op_resolver.cc b/services/webnn/tflite/op_resolver.cc index be4be1c..3aa8fce 100644 --- a/services/webnn/tflite/op_resolver.cc +++ b/services/webnn/tflite/op_resolver.cc
@@ -189,6 +189,9 @@ ::tflite::ops::builtin::Register_SUM(), /* min_version = */ 1, /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_TANH, + ::tflite::ops::builtin::Register_TANH(), /* min_version = */ 1, + /* max_version = */ 3); AddBuiltin(::tflite::BuiltinOperator_TRANSPOSE, ::tflite::ops::builtin::Register_TRANSPOSE(), /* min_version = */ 1,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index d4870b0..167ec81 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5484,9 +5484,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5496,8 +5496,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -5640,9 +5640,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5652,8 +5652,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index c5deb369a..1982f5f 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -19715,9 +19715,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19727,8 +19727,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -19865,9 +19865,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19877,8 +19877,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 55b3368..64d68c2 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -41738,9 +41738,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41749,8 +41749,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -41888,9 +41888,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41899,8 +41899,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -43237,9 +43237,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43249,8 +43249,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -43393,9 +43393,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43405,8 +43405,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -44718,9 +44718,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44729,8 +44729,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -44868,9 +44868,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44879,8 +44879,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 9c502e4c..bb86160 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -15765,12 +15765,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15780,8 +15780,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": { @@ -15941,12 +15941,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 125.0.6418.0", + "description": "Run with ash-chrome version 125.0.6420.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15956,8 +15956,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6418.0", - "revision": "version:125.0.6418.0" + "location": "lacros_version_skew_tests_v125.0.6420.0", + "revision": "version:125.0.6420.0" } ], "dimensions": {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 73b1a98..5c528813 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -267,16 +267,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 125.0.6418.0', + 'description': 'Run with ash-chrome version 125.0.6420.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6418.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6420.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v125.0.6418.0', - 'revision': 'version:125.0.6418.0', + 'location': 'lacros_version_skew_tests_v125.0.6420.0', + 'revision': 'version:125.0.6420.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 2446c0b..70619d64 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2100,6 +2100,27 @@ ] } ], + "AvoidLoadingPredictorPrefetchDuringBrowserStartup": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "fuchsia", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AvoidLoadingPredictorPrefetchDuringBrowserStartup" + ] + } + ] + } + ], "AvoidResourceRequestCopies": [ { "platforms": [ @@ -18352,8 +18373,7 @@ "SkiaGraphite": [ { "platforms": [ - "mac", - "windows" + "mac" ], "experiments": [ { @@ -22472,6 +22492,21 @@ ] } ], + "WebViewAsyncDns": [ + { + "platforms": [ + "android_webview" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "WebViewAsyncDns" + ] + } + ] + } + ], "WebViewExitReasonMetric": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 505438c..c77573e 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1381,6 +1381,9 @@ "LCPPDeferUnusedPreload", base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam<double> kLCPPDeferUnusedPreloadFrequencyThreshold{ + &kLCPPDeferUnusedPreload, "lcpp_unused_preload_frequency_threshold", 0.5}; + BASE_FEATURE(kLCPPFontURLPredictor, "LCPPFontURLPredictor", base::FEATURE_DISABLED_BY_DEFAULT); @@ -1457,6 +1460,10 @@ &kHttpDiskCachePrewarming, "http_disk_cache_prewarming_use_read_and_discard_body_option", false}; +const base::FeatureParam<bool> kHttpDiskCachePrewarmingSkipDuringBrowserStartup{ + &kHttpDiskCachePrewarming, + "http_disk_cache_prewarming_skip_during_browser_startup", true}; + BASE_FEATURE(kLegacyParsingOfXContentTypeOptions, "LegacyParsingOfXContentTypeOptions", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 6d17853..95e1614 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -803,6 +803,10 @@ // If enabled, unused preload requests are deferred to the timing on LCP. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLCPPDeferUnusedPreload); +// Unused preload requests are deferred if frequencies are above this threshold. +BLINK_COMMON_EXPORT extern const base::FeatureParam<double> + kLCPPDeferUnusedPreloadFrequencyThreshold; + // If enabled, fetched font URLs are observed to predict font usage in the // future navigation. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLCPPFontURLPredictor); @@ -883,6 +887,10 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> kHttpDiskCachePrewarmingUseReadAndDiscardBodyOption; +// If true, avoid prewarming HttpDiskCache during the browser startup. +BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> + kHttpDiskCachePrewarmingSkipDuringBrowserStartup; + // Kill-switch for new parsing behaviour of the X-Content-Type-Options header. // (Should be removed after the new behaviour has been launched.) BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLegacyParsingOfXContentTypeOptions);
diff --git a/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom b/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom index d849d16..8c8ca35 100644 --- a/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom +++ b/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom
@@ -61,4 +61,7 @@ // Preconnectable origins that affected the LCP element. array<url.mojom.Url> preconnect_origins; + + // Unused preloaded URLs in the past loads. + array<url.mojom.Url> unused_preloads; };
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 5b38e18..3a835b91 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -3236,6 +3236,14 @@ preconnect_origins.emplace_back(url::Origin::Create(origin_url)); } lcpp->set_preconnected_origins(preconnect_origins); + + Vector<KURL> unused_preloads; + unused_preloads.reserve( + base::checked_cast<wtf_size_t>(hint->unused_preloads.size())); + for (const auto& url : hint->unused_preloads) { + unused_preloads.emplace_back(url); + } + lcpp->set_unused_preloads(std::move(unused_preloads)); } void WebLocalFrameImpl::AddHitTestOnTouchStartCallback(
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc index a8323f7..f47611cd 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -353,7 +353,8 @@ network::mojom::ReferrerPolicy document_referrer_policy = network::mojom::ReferrerPolicy::kDefault, bool use_secure_document_url = false, - Vector<ElementLocator> locators = {}) { + Vector<ElementLocator> locators = {}, + bool disable_preload_scanning = false) { HTMLParserOptions options(&GetDocument()); KURL document_url = KURL("http://whatever.test/"); if (use_secure_document_url) @@ -372,7 +373,8 @@ CreateMediaValuesData(), TokenPreloadScanner::ScannerType::kMainDocument, /* script_token_scanner=*/nullptr, - /* take_preload=*/HTMLPreloadScanner::TakePreloadFn(), locators); + /* take_preload=*/HTMLPreloadScanner::TakePreloadFn(), locators, + disable_preload_scanning); } void SetUp() override { @@ -1899,4 +1901,20 @@ } } +TEST_F(HTMLPreloadScannerTest, PreloadScanDisabled_NoPreloads) { + PreloadScannerTestCase test_cases[] = { + {"http://example.test", "<img src='bla.gif'>", /* preloaded_url=*/nullptr, + "http://example.test/", ResourceType::kImage, 0}, + {"http://example.test", "<script src='test.js'></script>", + /* preloaded_url=*/nullptr, "http://example.test/", + ResourceType::kScript, 0}}; + + for (const auto& test_case : test_cases) { + RunSetUp(kViewportDisabled, kPreloadEnabled, + network::mojom::ReferrerPolicy::kDefault, true, {}, + /* disable_preload_scanning=*/true); + Test(test_case); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/block_node.cc b/third_party/blink/renderer/core/layout/block_node.cc index fb3ecb9..7ca1ffb 100644 --- a/third_party/blink/renderer/core/layout/block_node.cc +++ b/third_party/blink/renderer/core/layout/block_node.cc
@@ -1148,25 +1148,17 @@ if (UNLIKELY(!is_last_fragment)) return; - bool needs_full_invalidation = false; - if (LayoutBlock* block = DynamicTo<LayoutBlock>(box_.Get())) { - if (UNLIKELY(flow_thread && Style().HasColumnRule())) { - // Issue full invalidation, in case the number of column rules have - // changed. - needs_full_invalidation = true; - } - - block->SetNeedsOverflowRecalc( - LayoutObject::OverflowRecalcType::kOnlyVisualOverflowRecalc); - } - + box_->SetNeedsOverflowRecalc( + LayoutObject::OverflowRecalcType::kOnlyVisualOverflowRecalc); box_->SetScrollableOverflowFromLayoutResults(); box_->UpdateAfterLayout(); - if (needs_full_invalidation) + if (UNLIKELY(flow_thread && Style().HasColumnRule())) { + // Issue full invalidation, in case the number of column rules have changed. box_->ClearNeedsLayoutWithFullPaintInvalidation(); - else + } else { box_->ClearNeedsLayout(); + } // We should notify the display lock that we've done layout on self, and if // it's not blocked, on children.
diff --git a/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc b/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc index 46ae8b4..c8234f7f9 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc +++ b/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc
@@ -715,7 +715,8 @@ // LayoutBR does not set preserve_newline, but should be preserved. if (UNLIKELY(space_run_has_newline && string.length() == 1 && layout_object && layout_object->IsBR())) { - if (UNLIKELY(is_text_combine_)) { + // https://drafts.csswg.org/css-ruby/#anon-gen-unbreak + if (UNLIKELY(is_text_combine_ || ruby_text_nesting_level_ > 0)) { AppendTextItem(TransformedString(" "), layout_object); } else { AppendForcedBreakCollapseWhitespace(layout_object); @@ -1412,6 +1413,7 @@ has_ruby_ = has_ruby_ || node->IsInlineRubyText(); if (node->IsInlineRubyText()) { + ++ruby_text_nesting_level_; if (!node->Parent()->IsInlineRuby()) { // This creates a ruby column with a placeholder-only ruby-base. AppendOpaque(InlineItem::kOpenRubyColumn, @@ -1513,6 +1515,7 @@ AppendOpaque(InlineItem::kCloseTag, node); if (node->IsInlineRubyText()) { + --ruby_text_nesting_level_; if (node->Parent()->IsInlineRuby()) { LayoutObject* ruby_container = node->Parent(); AppendOpaque(InlineItem::kCloseRubyColumn,
diff --git a/third_party/blink/renderer/core/layout/inline/inline_items_builder.h b/third_party/blink/renderer/core/layout/inline/inline_items_builder.h index 0fe8adb7..0f9c939b 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_items_builder.h +++ b/third_party/blink/renderer/core/layout/inline/inline_items_builder.h
@@ -193,6 +193,7 @@ const SvgTextChunkOffsets* text_chunk_offsets_; + uint32_t ruby_text_nesting_level_ = 0; const bool is_text_combine_; bool has_bidi_controls_ = false; bool has_floats_ = false;
diff --git a/third_party/blink/renderer/core/layout/inline/inline_node_test.cc b/third_party/blink/renderer/core/layout/inline/inline_node_test.cc index cec8fcc..b18c58c9 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_node_test.cc +++ b/third_party/blink/renderer/core/layout/inline/inline_node_test.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" +#include "third_party/blink/renderer/core/testing/mock_hyphenation.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" @@ -486,80 +487,83 @@ TEST_ITEM_OFFSET_DIR(items[8], 22u, 28u, TextDirection::kLtr); } -TEST_F(InlineNodeTest, MinMaxSizes) { - LoadAhem(); - SetupHtml("t", "<div id=t style='font:10px Ahem'>AB CDEF</div>"); - InlineNodeForTest node = CreateInlineNode(); - MinMaxSizes sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(40, sizes.min_size); - EXPECT_EQ(70, sizes.max_size); +struct MinMaxData { + const char* content; + int min_max[2]; + const char* target_style = ""; + const char* style = ""; + const char* lang = nullptr; +} min_max_data[] = { + {"AB CDEF", {40, 70}}, + // Element boundary is at the middle of a word. + {"A B<span>C D</span>", {20, 60}}, + // A close tag after a forced break. + {"<span>12<br></span>", {80, 80}, "", "span { border: 30px solid blue; }"}, + // `pre-wrap` with trailing spaces. + {"12345 6789 ", {50, 110}, "white-space: pre-wrap;"}, + // `word-break: break-word` can break a space run. + {"M):\n<span> </span>p", + {10, 90}, + "white-space: pre-wrap; word-break: break-word;", + "span { font-size: 200%; }"}, + // Tabulation characters with `break-word`. + {"		<span>X</span>", + {10, 170}, + "white-space: pre-wrap; word-break: break-word;"}, + // Soft Hyphens. + {"abcd­ef xx", {50, 90}}, + {"abcd­ef xx", {60, 90}, "hyphens: none;"}, + {"abcd­ ef xx", {50, 100}, "hyphens: none;"}, + // Hyphenations. + {"zz hyphenation xx", {50, 170}, "hyphens: auto;", "", "en-us"}, + // Floats. + {"XXX <div id=left></div> XXXX", + {50, 130}, + "", + "#left { float: left; width: 50px; }"}, + // Floats with clearances. + {"XXX <div id=left></div><div id=right></div><div id=left></div> XXX", + {50, 160}, + "", + "#left { float: left; width: 40px; }" + "#right { float: right; clear: left; width: 50px; }"}, +}; + +std::ostream& operator<<(std::ostream& os, const MinMaxData& data) { + return os << data.content << std::endl << data.style; } -TEST_F(InlineNodeTest, MinMaxSizesElementBoundary) { - LoadAhem(); - SetupHtml("t", "<div id=t style='font:10px Ahem'>A B<span>C D</span></div>"); - InlineNodeForTest node = CreateInlineNode(); - MinMaxSizes sizes = ComputeMinMaxSizes(node); - // |min_content| should be the width of "BC" because there is an element - // boundary between "B" and "C" but no break opportunities. - EXPECT_EQ(20, sizes.min_size); - EXPECT_EQ(60, sizes.max_size); -} +class MinMaxTest : public InlineNodeTest, + public testing::WithParamInterface<MinMaxData> {}; -TEST_F(InlineNodeTest, MinMaxSizesFloats) { +INSTANTIATE_TEST_SUITE_P(InlineNodeTest, + MinMaxTest, + testing::ValuesIn(min_max_data)); + +TEST_P(MinMaxTest, Data) { + const MinMaxData& data = GetParam(); LoadAhem(); - SetupHtml("t", R"HTML( + StringBuilder html; + html.AppendFormat(R"HTML(" + <!DOCTYPE html> <style> - #left { float: left; width: 50px; } + #target { font: 10px Ahem;%s } + %s </style> - <div id=t style="font: 10px Ahem"> - XXX <div id="left"></div> XXXX - </div> - )HTML"); - + <div id="target")HTML", + data.target_style, data.style); + if (data.lang) { + html.AppendFormat(" lang='%s'", data.lang); + LayoutLocale::SetHyphenationForTesting(AtomicString(data.lang), + MockHyphenation::Create()); + } + html.AppendFormat(">%s</div>", data.content); + SetupHtml("target", html.ToString()); InlineNodeForTest node = CreateInlineNode(); - MinMaxSizes sizes = ComputeMinMaxSizes(node); - - EXPECT_EQ(50, sizes.min_size); - EXPECT_EQ(130, sizes.max_size); -} - -TEST_F(InlineNodeTest, MinMaxSizesCloseTagAfterForcedBreak) { - LoadAhem(); - SetupHtml("t", R"HTML( - <style> - span { border: 30px solid blue; } - </style> - <div id=t style="font: 10px Ahem"> - <span>12<br></span> - </div> - )HTML"); - - InlineNodeForTest node = CreateInlineNode(); - MinMaxSizes sizes = ComputeMinMaxSizes(node); - // The right border of the `</span>` is included in the line even if it - // appears after `<br>`. crbug.com/991320. - EXPECT_EQ(80, sizes.min_size); - EXPECT_EQ(80, sizes.max_size); -} - -TEST_F(InlineNodeTest, MinMaxSizesFloatsClearance) { - LoadAhem(); - SetupHtml("t", R"HTML( - <style> - #left { float: left; width: 40px; } - #right { float: right; clear: left; width: 50px; } - </style> - <div id=t style="font: 10px Ahem"> - XXX <div id="left"></div><div id="right"></div><div id="left"></div> XXX - </div> - )HTML"); - - InlineNodeForTest node = CreateInlineNode(); - MinMaxSizes sizes = ComputeMinMaxSizes(node); - - EXPECT_EQ(50, sizes.min_size); - EXPECT_EQ(160, sizes.max_size); + const MinMaxSizes actual_sizes = ComputeMinMaxSizes(node); + const MinMaxSizes expected_sizezs{LayoutUnit(data.min_max[0]), + LayoutUnit(data.min_max[1])}; + EXPECT_EQ(actual_sizes, expected_sizezs); } // For http://crbug.com/1112560 @@ -585,25 +589,6 @@ // Note: |sizes.max_size.Round()| isn't |LayoutUnit::Max()| on some platform. } -TEST_F(InlineNodeTest, MinMaxSizesTabulationWithBreakWord) { - LoadAhem(); - SetupHtml("t", R"HTML( - <style> - #t { - font: 10px Ahem; - white-space: pre-wrap; - word-break: break-word; - } - </style> - <div id=t>		<span>X</span></div> - )HTML"); - - InlineNodeForTest node = CreateInlineNode(); - MinMaxSizes sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(10, sizes.min_size); - EXPECT_EQ(170, sizes.max_size); -} - // For http://crbug.com/1116713 TEST_F(InlineNodeTest, MinMaxSizesNeedsLayout) { LoadAhem();
diff --git a/third_party/blink/renderer/core/layout/inline/justification_utils.cc b/third_party/blink/renderer/core/layout/inline/justification_utils.cc index dfbda8c..f371833 100644 --- a/third_party/blink/renderer/core/layout/inline/justification_utils.cc +++ b/third_party/blink/renderer/core/layout/inline/justification_utils.cc
@@ -97,7 +97,8 @@ return line_text_builder.ReleaseString(); } -void JustifyResults(String line_text, +void JustifyResults(const String& text_content, + String line_text, unsigned line_text_start_offset, ShapeResultSpacing<String>& spacing, InlineItemResults& results) { @@ -107,6 +108,19 @@ break; } if (item_result.shape_result) { +#if DCHECK_IS_ON() + // This `if` is necessary for external/wpt/css/css-text/text-justify/ + // text-justify-and-trailing-spaces-*.html. + if (item_result.StartOffset() - line_text_start_offset + + item_result.Length() <= + line_text.length()) { + DCHECK_EQ(StringView(text_content, item_result.StartOffset(), + item_result.Length()), + StringView(line_text, + item_result.StartOffset() - line_text_start_offset, + item_result.Length())); + } +#endif ShapeResult* shape_result = item_result.shape_result->CreateShapeResult(); DCHECK_GE(item_result.StartOffset(), line_text_start_offset); DCHECK_EQ(shape_result->NumCharacters(), item_result.Length()); @@ -141,7 +155,7 @@ item_result.ruby_column) { LineInfo& base_line = item_result.ruby_column->base_line; if (item_result.inline_size == base_line.Width()) { - JustifyResults(line_text, line_text_start_offset, spacing, + JustifyResults(text_content, line_text, line_text_start_offset, spacing, *base_line.MutableResults()); base_line.SetWidth(base_line.AvailableWidth(), base_line.ComputeWidth()); @@ -206,18 +220,18 @@ item_result.spacing_before += leading_expansion; } -} // namespace - -std::optional<LayoutUnit> ApplyJustification(LayoutUnit space, - JustificationTarget target, - LineInfo* line_info) { +std::optional<LayoutUnit> ApplyJustificationInternal( + LayoutUnit space, + JustificationTarget target, + const LineInfo& line_info, + InlineItemResults* results) { // Empty lines should align to start. - if (line_info->IsEmptyLine()) { + if (line_info.IsEmptyLine()) { return std::nullopt; } // Justify the end of visible text, ignoring preserved trailing spaces. - unsigned end_offset = line_info->EndOffsetForJustify(); + unsigned end_offset = line_info.EndOffsetForJustify(); // If this line overflows, fallback to 'text-align: start'. if (space <= 0) { @@ -225,7 +239,7 @@ } // Can't justify an empty string. - if (end_offset == line_info->StartOffset()) { + if (end_offset == line_info.StartOffset()) { return std::nullopt; } @@ -233,13 +247,13 @@ // |ItemsResults[0].StartOffset()|, e.g. <b><input> <input></b> when // line break before space (leading space). See http://crbug.com/1240791 const unsigned line_text_start_offset = - line_info->Results().front().StartOffset(); + line_info.Results().front().StartOffset(); // Construct the line text to compute spacing for. + String text_content = line_info.ItemsData().text_content; String line_text = BuildJustificationText( - line_info->ItemsData().text_content, line_info->Results(), - line_text_start_offset, end_offset, - line_info->MayHaveTextCombineOrRubyItem()); + text_content, line_info.Results(), line_text_start_offset, end_offset, + line_info.MayHaveTextCombineOrRubyItem()); if (line_text.empty()) { return std::nullopt; } @@ -247,7 +261,7 @@ // Compute the spacing to justify. ShapeResultSpacing<String> spacing(line_text, target == JustificationTarget::kSvgText); - spacing.SetExpansion(space, line_info->BaseDirection()); + spacing.SetExpansion(space, line_info.BaseDirection()); const bool is_ruby = target == JustificationTarget::kRubyText || target == JustificationTarget::kRubyBase; if (!spacing.HasExpansion()) { @@ -266,17 +280,35 @@ // For ruby text, inset it by no more than a full-width ruby character on // each side. if (target == JustificationTarget::kRubyText) { - inset = - std::min(LayoutUnit(2 * line_info->LineStyle().FontSize()), inset); + inset = std::min(LayoutUnit(2 * line_info.LineStyle().FontSize()), inset); } - spacing.SetExpansion(space - inset, line_info->BaseDirection()); + spacing.SetExpansion(space - inset, line_info.BaseDirection()); } - JustifyResults(line_text, line_text_start_offset, spacing, - *line_info->MutableResults()); + if (results) { + DCHECK_EQ(&line_info.Results(), results); + JustifyResults(text_content, line_text, line_text_start_offset, spacing, + *results); + } return inset / 2; } +} // namespace + +std::optional<LayoutUnit> ApplyJustification(LayoutUnit space, + JustificationTarget target, + LineInfo* line_info) { + return ApplyJustificationInternal(space, target, *line_info, + line_info->MutableResults()); +} + +std::optional<LayoutUnit> ComputeRubyBaseInset(LayoutUnit space, + const LineInfo& line_info) { + DCHECK(line_info.IsRubyBase()); + return ApplyJustificationInternal(space, JustificationTarget::kRubyBase, + line_info, nullptr); +} + bool ApplyLeadingAndTrailingExpansion(LayoutUnit leading_expansion, LayoutUnit trailing_expansion, LineInfo& line_info) {
diff --git a/third_party/blink/renderer/core/layout/inline/justification_utils.h b/third_party/blink/renderer/core/layout/inline/justification_utils.h index 481a994..46626fe 100644 --- a/third_party/blink/renderer/core/layout/inline/justification_utils.h +++ b/third_party/blink/renderer/core/layout/inline/justification_utils.h
@@ -27,6 +27,11 @@ JustificationTarget target, LineInfo* line_info); +// Compute `inset` value without applying justification. +// `line_info.IsRubyBase()` must be true. +std::optional<LayoutUnit> ComputeRubyBaseInset(LayoutUnit space, + const LineInfo& line_info); + // Add spaces to the line. This works only for ruby-base and ruby-text for now. // Returns false if we couldn't expand the line. bool ApplyLeadingAndTrailingExpansion(LayoutUnit leading_expansion,
diff --git a/third_party/blink/renderer/core/layout/inline/line_breaker.cc b/third_party/blink/renderer/core/layout/inline/line_breaker.cc index 06d5d992..4e787be 100644 --- a/third_party/blink/renderer/core/layout/inline/line_breaker.cc +++ b/third_party/blink/renderer/core/layout/inline/line_breaker.cc
@@ -3058,7 +3058,24 @@ if (base_line_info.Width() < ruby_size) { may_have_ruby_overhang_ = true; + + AnnotationOverhang overhang = GetOverhang(*column_result); + if (overhang.end > LayoutUnit()) { + column_result->pending_end_overhang = overhang.end; + maybe_have_end_overhang_ = true; + } + + if (CanApplyStartOverhang(line_info, overhang.start)) { + DCHECK_EQ(column_result->margins.inline_start, LayoutUnit()); + DCHECK_EQ((*column_result->ruby_column->base_line.MutableResults())[0] + .item->Type(), + InlineItem::kRubyLinePlaceholder); + (*column_result->ruby_column->base_line.MutableResults())[0] + .margins.inline_start = -overhang.start; + position_ -= overhang.start; + } } + trailing_whitespace_ = WhitespaceState::kNone; return column_result; }
diff --git a/third_party/blink/renderer/core/layout/inline/line_breaker_test.cc b/third_party/blink/renderer/core/layout/inline/line_breaker_test.cc index 7890ee9..a871abe 100644 --- a/third_party/blink/renderer/core/layout/inline/line_breaker_test.cc +++ b/third_party/blink/renderer/core/layout/inline/line_breaker_test.cc
@@ -15,7 +15,6 @@ #include "third_party/blink/renderer/core/layout/layout_ng_block_flow.h" #include "third_party/blink/renderer/core/layout/positioned_float.h" #include "third_party/blink/renderer/core/layout/unpositioned_float.h" -#include "third_party/blink/renderer/core/testing/mock_hyphenation.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" @@ -755,122 +754,6 @@ EXPECT_FALSE(space_text->NeedsLayout()); } -TEST_F(LineBreakerTest, MinMaxWithTrailingSpaces) { - LoadAhem(); - InlineNode node = CreateInlineNode(R"HTML( - <!DOCTYPE html> - <style> - #container { - font: 10px/1 Ahem; - white-space: pre-wrap; - } - </style> - <div id=container>12345 6789 </div> - )HTML"); - - const auto sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(sizes.min_size, LayoutUnit(50)); - EXPECT_EQ(sizes.max_size, LayoutUnit(110)); -} - -// `word-break: break-word` can break a space run. -TEST_F(LineBreakerTest, MinMaxBreakSpaces) { - LoadAhem(); - InlineNode node = CreateInlineNode(R"HTML( - <!DOCTYPE html> - <style> - div { - font: 10px/1 Ahem; - white-space: pre-wrap; - word-break: break-word; - } - span { - font-size: 200%; - } - </style> - <div id=container>M): -<span> </span>p</div> - )HTML"); - - const auto sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(sizes.min_size, LayoutUnit(10)); - EXPECT_EQ(sizes.max_size, LayoutUnit(90)); -} - -TEST_F(LineBreakerTest, MinMaxWithSoftHyphen) { - LoadAhem(); - InlineNode node = CreateInlineNode(R"HTML( - <!DOCTYPE html> - <style> - #container { - font: 10px/1 Ahem; - } - </style> - <div id=container>abcd­ef xx</div> - )HTML"); - - const auto sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(sizes.min_size, LayoutUnit(50)); - EXPECT_EQ(sizes.max_size, LayoutUnit(90)); -} - -TEST_F(LineBreakerTest, MinMaxWithHyphensDisabled) { - LoadAhem(); - InlineNode node = CreateInlineNode(R"HTML( - <!DOCTYPE html> - <style> - #container { - font: 10px/1 Ahem; - hyphens: none; - } - </style> - <div id=container>abcd­ef xx</div> - )HTML"); - - const auto sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(sizes.min_size, LayoutUnit(60)); - EXPECT_EQ(sizes.max_size, LayoutUnit(90)); -} - -TEST_F(LineBreakerTest, MinMaxWithHyphensDisabledWithTrailingSpaces) { - LoadAhem(); - InlineNode node = CreateInlineNode(R"HTML( - <!DOCTYPE html> - <style> - #container { - font: 10px/1 Ahem; - hyphens: none; - } - </style> - <div id=container>abcd­ ef xx</div> - )HTML"); - - const auto sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(sizes.min_size, LayoutUnit(50)); - EXPECT_EQ(sizes.max_size, LayoutUnit(100)); -} - -TEST_F(LineBreakerTest, MinMaxWithHyphensAuto) { - LoadAhem(); - LayoutLocale::SetHyphenationForTesting(AtomicString("en-us"), - MockHyphenation::Create()); - InlineNode node = CreateInlineNode(R"HTML( - <!DOCTYPE html> - <style> - #container { - font: 10px/1 Ahem; - hyphens: auto; - } - </style> - <div id=container lang="en-us">zz hyphenation xx</div> - )HTML"); - - const auto sizes = ComputeMinMaxSizes(node); - EXPECT_EQ(sizes.min_size, LayoutUnit(50)); - EXPECT_EQ(sizes.max_size, LayoutUnit(170)); - LayoutLocale::SetHyphenationForTesting(AtomicString("en-us"), nullptr); -} - // For http://crbug.com/1104534 TEST_F(LineBreakerTest, SplitTextZero) { // Note: |V8TestingScope| is needed for |Text::splitText()|.
diff --git a/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc b/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc index 3460f4a..bf4eba04 100644 --- a/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc +++ b/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc
@@ -166,12 +166,18 @@ line_box->AddChild(item.BidiLevel()); } else if (item.Type() == InlineItem::kRubyLinePlaceholder) { DCHECK(RuntimeEnabledFeatures::RubyLineBreakableEnabled()); + // Overhang values are zero or negative. + LayoutUnit start_overhang = item_result.margins.inline_start; + LayoutUnit end_overhang = item_result.margins.inline_end; // Adds a LogicalLineItem with an InlineItem to check its // InlineItemType later. - line_box->AddChild(item, item_result, item_result.TextOffset(), - /* block_offset */ LayoutUnit(), - item_result.inline_size, - /* text_height */ LayoutUnit(), item.BidiLevel()); + line_box->AddChild( + item, item_result, item_result.TextOffset(), + /* block_offset */ LayoutUnit(), + item_result.inline_size + start_overhang + end_overhang, + /* text_height */ LayoutUnit(), item.BidiLevel()); + (*line_box)[line_box->size() - 1].rect.offset.inline_offset = + start_overhang; } else if (item.Type() == InlineItem::kListMarker) { PlaceListMarker(item, &item_result); } else if (item.Type() == InlineItem::kOutOfFlowPositioned) {
diff --git a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc index 07239ae..0b23370 100644 --- a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc +++ b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/layout/inline/inline_box_state.h" #include "third_party/blink/renderer/core/layout/inline/inline_cursor.h" #include "third_party/blink/renderer/core/layout/inline/inline_item_result.h" +#include "third_party/blink/renderer/core/layout/inline/inline_item_result_ruby_column.h" #include "third_party/blink/renderer/core/layout/inline/justification_utils.h" #include "third_party/blink/renderer/core/layout/inline/line_info.h" #include "third_party/blink/renderer/core/layout/inline/logical_line_container.h" @@ -134,6 +135,30 @@ AnnotationOverhang GetOverhang(const InlineItemResult& item) { AnnotationOverhang overhang; + if (item.item->Type() == InlineItem::kOpenRubyColumn && item.ruby_column) { + DCHECK(RuntimeEnabledFeatures::RubyLineBreakableEnabled()); + const InlineItemResultRubyColumn& column = *item.ruby_column; + LayoutUnit half_width_of_annotation_font; + for (const auto& annotation_line : column.annotation_line_list) { + if (annotation_line.Width() == item.inline_size) { + half_width_of_annotation_font = + LayoutUnit(annotation_line.LineStyle().FontSize() / 2); + break; + } + } + if (half_width_of_annotation_font == LayoutUnit()) { + return overhang; + } + std::optional<LayoutUnit> inset = ComputeRubyBaseInset( + item.inline_size - column.base_line.Width(), column.base_line); + if (!inset) { + return overhang; + } + overhang.start = std::min(*inset, half_width_of_annotation_font); + overhang.end = overhang.start; + return overhang; + } + if (!item.layout_result) return overhang; @@ -236,6 +261,43 @@ } DCHECK_EQ(text_item.Type(), InlineItem::kText); wtf_size_t i = items->size() - 1; + if (RuntimeEnabledFeatures::RubyLineBreakableEnabled()) { + while ((*items)[i].item->Type() != InlineItem::kOpenRubyColumn || + !(*items)[i].ruby_column) { + const auto type = (*items)[i].item->Type(); + if (type != InlineItem::kOpenTag && type != InlineItem::kCloseTag && + type != InlineItem::kCloseRubyColumn && + type != InlineItem::kOpenRubyColumn && + type != InlineItem::kRubyLinePlaceholder) { + return LayoutUnit(); + } + if (i-- == 0) { + return LayoutUnit(); + } + } + InlineItemResult& column_item = (*items)[i]; + if (column_item.pending_end_overhang <= LayoutUnit()) { + return LayoutUnit(); + } + if (column_item.ruby_column->base_line.LineStyle().FontSize() < + text_item.Style()->FontSize()) { + return LayoutUnit(); + } + // Ideally we should refer to inline_size of |text_item| instead of the + // width of the InlineItem's ShapeResult. However it's impossible to compute + // inline_size of |text_item| before calling BreakText(), and BreakText() + // requires precise |position_| which takes |end_overhang| into account. + LayoutUnit end_overhang = + std::min(column_item.pending_end_overhang, + LayoutUnit(text_item.TextShapeResult()->Width())); + InlineItemResult& end_item = + column_item.ruby_column->base_line.MutableResults()->back(); + DCHECK_EQ(end_item.item->Type(), InlineItem::kRubyLinePlaceholder); + DCHECK_EQ(end_item.margins.inline_end, LayoutUnit()); + end_item.margins.inline_end = -end_overhang; + column_item.pending_end_overhang = LayoutUnit(); + return end_overhang; + } while ((*items)[i].item->Type() != InlineItem::kAtomicInline) { const auto type = (*items)[i].item->Type(); if (type != InlineItem::kOpenTag && type != InlineItem::kCloseTag) {
diff --git a/third_party/blink/renderer/core/layout/layout_image_test.cc b/third_party/blink/renderer/core/layout/layout_image_test.cc index 3a670a6f..afdffbe8 100644 --- a/third_party/blink/renderer/core/layout/layout_image_test.cc +++ b/third_party/blink/renderer/core/layout/layout_image_test.cc
@@ -28,4 +28,21 @@ EXPECT_EQ(target, result.InnerNode()); } +TEST_F(LayoutImageTest, NeedsVisualOverflowRecalc) { + SetBodyInnerHTML(R"HTML( + <div id="target" style="position: relative; width: 100px;"> + <img id="img" style="position: absolute; width: 100%;"> + </div> + )HTML"); + UpdateAllLifecyclePhasesForTest(); + + const auto* img_layer = GetLayoutBoxByElementId("img")->Layer(); + GetElementById("target")->SetInlineStyleProperty(CSSPropertyID::kWidth, "200px"); + EXPECT_FALSE(img_layer->NeedsVisualOverflowRecalc()); + + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + EXPECT_TRUE(img_layer->NeedsVisualOverflowRecalc()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc index f464af2..de8ea79 100644 --- a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc +++ b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc
@@ -78,6 +78,10 @@ preconnected_origins_ = std::move(origins); } +void LCPCriticalPathPredictor::set_unused_preloads(Vector<KURL> preloads) { + unused_preloads_ = std::move(preloads); +} + void LCPCriticalPathPredictor::Reset() { lcp_element_locators_.clear(); lcp_element_locator_strings_.clear();
diff --git a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h index 581f5d7..4d731b9 100644 --- a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h +++ b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h
@@ -60,8 +60,12 @@ void set_preconnected_origins(const Vector<url::Origin>& origins); + void set_unused_preloads(Vector<KURL> preloads); + const Vector<KURL>& fetched_fonts() { return fetched_fonts_; } + const Vector<KURL>& unused_preloads() { return unused_preloads_; } + void Reset(); bool IsLcpInfluencerScript(const KURL& url); @@ -97,6 +101,7 @@ HashSet<KURL> lcp_influencer_scripts_; Vector<KURL> fetched_fonts_; Vector<url::Origin> preconnected_origins_; + Vector<KURL> unused_preloads_; // Callbacks are called when predicted LCP is painted. Never called if // prediction is incorrect.
diff --git a/third_party/blink/renderer/core/paint/box_fragment_painter.cc b/third_party/blink/renderer/core/paint/box_fragment_painter.cc index a5430a1..f1fa3db 100644 --- a/third_party/blink/renderer/core/paint/box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/box_fragment_painter.cc
@@ -2599,9 +2599,9 @@ DCHECK(item->GetLayoutObject()->IsLayoutInline()); } else if (item->Type() == FragmentItem::kLine) { const PhysicalLineBoxFragment* child_line = item->LineBoxFragment(); - DCHECK(child_line); - if (!child_line->HasFloatingDescendantsForPaint()) + if (child_line && !child_line->HasFloatingDescendantsForPaint()) { continue; + } } else { continue; }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index a479000f..10e9bcc 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2668,9 +2668,6 @@ crbug.com/332933144 [ Mac11 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/response/response-clone.any.html [ Failure Timeout ] crbug.com/332933144 [ Win11 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/response/response-clone.any.serviceworker.html [ Failure Timeout ] crbug.com/332933144 [ Mac11 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/response/response-clone.any.serviceworker.html [ Failure Timeout ] -crbug.com/332933144 [ Mac14 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https.html [ Failure Timeout ] -crbug.com/333406327 [ Mac13 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https.html [ Failure Timeout ] -crbug.com/332933144 [ Mac14 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-decompression.tentative.https.html [ Failure Timeout ] crbug.com/332741532 [ Mac12 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/metadata/generated/audioworklet.https.sub.html [ Timeout ] crbug.com/332572646 external/wpt/wasm/webapi/esm-integration/worker-import-source-phase.tentative.html [ Timeout ] crbug.com/332572643 external/wpt/css/css-transforms/transform-iframe-scroll-position.html [ Failure ] @@ -7242,7 +7239,6 @@ # RubyLineBreakable crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/br-clear-all-002.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/empty-ruby-text-container-abs.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/empty-ruby-text-container-float.html [ Crash ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/line-break-around-ruby-001.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/line-spacing.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/nested-ruby-pairing-001.html [ Crash Failure Timeout ] @@ -7252,42 +7248,37 @@ crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-align-002a.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-base-container-float.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-bidi-003.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-float-handling-001.html [ Crash Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-intra-level-whitespace-001.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-line-breaking-002.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/after-doesnt-crash.html [ Crash Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/before-doesnt-crash.html [ Crash Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/float-overhang-from-ruby-text.html [ Crash Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/float-overhang-from-ruby-text.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/line-break-ruby.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/nested-ruby.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-horizontal-no-overlap1.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-horizontal-no-overlap2.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-horizontal.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-vertical-no-overlap1.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-vertical-no-overlap2.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-vertical.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/percentage-height-child-crash.html [ Crash ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/position-after.html [ Crash ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-columns-spans.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-columns.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-illegal-7.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-illegal-combined.html [ Crash Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-length.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-position-modern-japanese-fonts.html [ Crash Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-trailing.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/select-ruby.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/fast/ruby/split-ruby-column-percentage-height-descendant.html [ Failure ] # RubyLineBreakable; NeedsRebaseline crbug.com/324111880 virtual/ruby-lb/fast/ruby/float-object-doesnt-crash.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/modify-positioned-ruby-text-crash.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/position-after.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-column-break.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-columns-spans.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-columns.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-empty-rt.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-first-letter.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-length.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-text-before-after-content.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-trailing.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-rt-block-1.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-rt-block-2.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-rt-block-3.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-text2.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/split-ruby-column-percentage-height-descendant.html [ Failure ] # line-clamp crbug.com/40336192 external/wpt/css/css-overflow/line-clamp-001.tentative.html [ Failure ]
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 db4e5f0..dd5adf07 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
@@ -352024,7 +352024,7 @@ [] ], "compression-dictionary-util.js": [ - "46d95041d8c48d71752543d8c8be3a0b752f7e22", + "7d86f594a802c221077ce471393f6c9fabba7f2e", [] ], "echo-headers.py": [ @@ -392193,7 +392193,7 @@ [] ], "setters_tests.json": [ - "82adf4cdce270b5b60a45a3845446be7faf14f64", + "3850606d660bbb54cfc52e4dd43e2d7577b3363e", [] ], "toascii.json": [ @@ -512788,39 +512788,67 @@ } }, "compression-dictionary": { - "dictionary-clear-site-data.tentative.https.html": [ - "b583834831f86102b3135e01499178d9dcbe09b3", + "dictionary-clear-site-data-cache.tentative.https.html": [ + "c8bcf7fdf1299519e51f84568b984310706710f2", [ null, - {} + { + "timeout": "long" + } + ] + ], + "dictionary-clear-site-data-cookies.tentative.https.html": [ + "aa1673e88c80922553ff59cb2114d35d6ff37942", + [ + null, + { + "timeout": "long" + } + ] + ], + "dictionary-clear-site-data-storage.tentative.https.html": [ + "22747eb65657e53a4900769fa77d9f35c70093a7", + [ + null, + { + "timeout": "long" + } ] ], "dictionary-decompression.tentative.https.html": [ - "cd2062581603101fc94b095f329420f536b6cbdb", + "c7b3b7c3a5a697f5bc2adcd3123793f8a363b5d5", [ null, - {} + { + "timeout": "long" + } ] ], "dictionary-fetch-with-link-element.tentative.https.html": [ - "71a9b1c0509c95e0422849590190bd5385b50d9d", + "23a271d481873dfe2f7c96fa2616cd46b7f28ad4", [ null, - {} + { + "timeout": "long" + } ] ], "dictionary-fetch-with-link-header.tentative.https.html": [ - "a3ffd8ba74a394d4d0324b3c54918369345bcf1e", + "6f6a792ade6416b0b5cacee4097c9af2a4921947", [ null, - {} + { + "timeout": "long" + } ] ], "dictionary-registration.tentative.https.html": [ - "7921b1294663c0032725a649bb375b4f32e87a3e", + "f0782aff3bd3e640e62463f2aa8154f993b73d35", [ null, - {} + { + "timeout": "long" + } ] ] }, @@ -583244,6 +583272,13 @@ } ] ], + "inline-async-inserted-execorder.html": [ + "0f51fd318b42233a113c16a2cb649f2880328c1e", + [ + null, + {} + ] + ], "inline-async-onload.html": [ "314abc98dc71cc42b81e6ba19086e65186665133", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-001.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-001.html index 7e47d18c..4496786 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-001.html
@@ -12,7 +12,7 @@ </style> <div id="host"><span id="in-document">1234567890</span></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> @font-face { @@ -27,6 +27,8 @@ <span id="in-shadow">0123456789</span> `; + await document.fonts.ready; + assert_not_equals(document.getElementById('in-document').offsetWidth, 160); assert_equals(host.shadowRoot.getElementById('in-shadow').offsetWidth, 160); }, "@font-face applies in the shadow tree")
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-002-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-002-expected.txt deleted file mode 100644 index 840e9666..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-002-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] @font-face from the document applies in the shadow tree - assert_equals: expected 160 but got 80 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-002.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-002.html index 2e3272c..3a20d0b8 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-002.html
@@ -13,7 +13,7 @@ </style> <div id="host"><span id="in-document">1234567890</span></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> #in-shadow { @@ -24,6 +24,8 @@ <span id="in-shadow">0123456789</span> `; + await document.fonts.ready; + assert_not_equals(document.getElementById('in-document').offsetWidth, 160); assert_equals(host.shadowRoot.getElementById('in-shadow').offsetWidth, 160); }, "@font-face from the document applies in the shadow tree");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-003-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-003-expected.txt deleted file mode 100644 index da2aa2a4..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-003-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] @font-face from document applies to :host - assert_equals: expected 160 but got 80 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-003.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-003.html index d3f83e4ec..adf0bba 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-003.html
@@ -13,7 +13,7 @@ </style> <div id="host"><span id="in-document">1234567890</span></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> :host { @@ -24,6 +24,8 @@ <span id="in-shadow">0123456789</span> `; + await document.fonts.ready; + assert_equals(document.getElementById('in-document').offsetWidth, 160); assert_equals(host.shadowRoot.getElementById('in-shadow').offsetWidth, 160); }, "@font-face from document applies to :host");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-004-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-004-expected.txt deleted file mode 100644 index 865903e..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-004-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] @font-face from document applies to a slotted element - assert_equals: expected 160 but got 80 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-004.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-004.html index 6ac50bd..957f4805 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-004.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-004.html
@@ -14,7 +14,7 @@ </style> <div id="host"><span id="in-document">1234567890</span></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> ::slotted(#in-document) { @@ -25,6 +25,8 @@ <span id="in-shadow">0123456789</span> `; + await document.fonts.ready; + assert_equals(document.getElementById('in-document').offsetWidth, 160); assert_not_equals(host.shadowRoot.getElementById('in-shadow').offsetWidth, 160); }, "@font-face from document applies to a slotted element");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-005.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-005.html index fdf86fb5..de102f2 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-005.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-005.html
@@ -12,7 +12,7 @@ </style> <div id="host"><span id="in-document">1234567890</span></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> @font-face { @@ -27,6 +27,8 @@ <span id="in-shadow">0123456789</span> `; + await document.fonts.ready; + assert_not_equals(document.getElementById('in-document').offsetWidth, 160); assert_equals(host.shadowRoot.getElementById('in-shadow').offsetWidth, 160); }, "@font-face should not leak out of shadow tree.");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-006.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-006.html index 8c6e3417..e72d4ec 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-006.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-006.html
@@ -16,7 +16,7 @@ </style> <div id="host"></div> <script> -promise_test(async function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> :host::before, :host::after {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-007.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-007.html index ae669f6..c644a549 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-007.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-007.html
@@ -7,7 +7,7 @@ <div id="host"><span id="in-document">1234567890</span></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> @font-face { @@ -22,6 +22,8 @@ <span id="in-shadow">0123456789</span> `; + await document.fonts.ready; + assert_equals(document.getElementById('in-document').offsetWidth, 160); assert_equals(host.shadowRoot.getElementById('in-shadow').offsetWidth, 160); }, "@font-face from shadow applies to :host");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-008.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-008.html index a40b024..52c7869 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-008.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-008.html
@@ -8,7 +8,7 @@ <div id="host"><span id="in-document">1234567890</span></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> @font-face { @@ -23,6 +23,8 @@ <span id="in-shadow">0123456789</span> `; + await document.fonts.ready; + assert_equals(document.getElementById('in-document').offsetWidth, 160); assert_not_equals(host.shadowRoot.getElementById('in-shadow').offsetWidth, 160); }, "@font-face from shadow applies to a slotted element");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-009.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-009.html index 5d77092..4e08162 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-009.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/font-face-009.html
@@ -12,7 +12,7 @@ </style> <div id="host"></div> <script> -test(function() { +promise_test(async () => { host.attachShadow({ mode: "open" }).innerHTML = ` <style> @font-face { @@ -27,6 +27,8 @@ <slot></slot> `; + await document.fonts.ready; + //shrinkwrapped size for a default font will be a bit more than 80-90 //if the font is applied, it will be a bit more than 160 assert_greater_than(document.getElementById('host').offsetWidth, 160);
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-cache.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-cache.tentative.https.html new file mode 100644 index 0000000..c8bcf7f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-cache.tentative.https.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<head> +<meta charset="utf-8"> +<meta name="timeout" content="long"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/compression-dictionary-util.js"></script> +</head> +<body> +<script> + +compression_dictionary_promise_test(async (t) => { + const dict = await (await fetch(kRegisterDictionaryPath)).text(); + // Wait until `available-dictionary` header is available. + assert_equals( + await waitUntilAvailableDictionaryHeader(t, {}), + kDefaultDictionaryHashBase64); + // Clear site data. + assert_equals(await clearSiteData(/*directive=*/'cache'), 'OK'); + // Check if `available-dictionary` header is not available. + assert_equals( + await waitUntilAvailableDictionaryHeader(t, {max_retry: 0}), + '"available-dictionary" header is not available'); +}, 'Clear-Site-Data with "cache" directive must unregister dictionary'); + +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-cookies.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-cookies.tentative.https.html new file mode 100644 index 0000000..aa1673e8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-cookies.tentative.https.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<head> +<meta charset="utf-8"> +<meta name="timeout" content="long"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/compression-dictionary-util.js"></script> +</head> +<body> +<script> + +compression_dictionary_promise_test(async (t) => { + const dict = await (await fetch(kRegisterDictionaryPath)).text(); + // Wait until `available-dictionary` header is available. + assert_equals( + await waitUntilAvailableDictionaryHeader(t, {}), + kDefaultDictionaryHashBase64); + // Clear site data. + assert_equals(await clearSiteData(/*directive=*/'cookies'), 'OK'); + // Check if `available-dictionary` header is not available. + assert_equals( + await waitUntilAvailableDictionaryHeader(t, {max_retry: 0}), + '"available-dictionary" header is not available'); +}, 'Clear-Site-Data with "cookies" directive must unregister dictionary'); + +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-storage.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-storage.tentative.https.html new file mode 100644 index 0000000..22747eb6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data-storage.tentative.https.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<head> +<meta charset="utf-8"> +<meta name="timeout" content="long"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/compression-dictionary-util.js"></script> +</head> +<body> +<script> + +compression_dictionary_promise_test(async (t) => { + const dict = await (await fetch(kRegisterDictionaryPath)).text(); + // Wait until `available-dictionary` header is available. + assert_equals( + await waitUntilAvailableDictionaryHeader(t, {}), + kDefaultDictionaryHashBase64); + // Clear site data. + assert_equals(await clearSiteData(/*directive=*/'storage'), 'OK'); + // Check if `available-dictionary` header is not available. + assert_equals( + await waitUntilAvailableDictionaryHeader(t, {max_retry: 0}), + kDefaultDictionaryHashBase64); +}, 'Clear-Site-Data with "storage" directive must not unregister dictionary'); + +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https.html deleted file mode 100644 index b583834..0000000 --- a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https.html +++ /dev/null
@@ -1,54 +0,0 @@ -<!DOCTYPE html> -<head> -<meta charset="utf-8"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="./resources/compression-dictionary-util.js"></script> -</head> -<body> -<script> - -compression_dictionary_promise_test(async (t) => { - const dict = await (await fetch(kRegisterDictionaryPath)).text(); - // Wait until `available-dictionary` header is available. - assert_equals( - await waitUntilAvailableDictionaryHeader(t, {}), - kDefaultDictionaryHashBase64); - // Clear site data. - assert_equals(await clearSiteData(/*directive=*/'cache'), 'OK'); - // Check if `available-dictionary` header is not available. - assert_equals( - await waitUntilAvailableDictionaryHeader(t, {max_retry: 0}), - '"available-dictionary" header is not available'); -}, 'Clear-Site-Data with "cache" directive must unregister dictionary'); - -compression_dictionary_promise_test(async (t) => { - const dict = await (await fetch(kRegisterDictionaryPath)).text(); - // Wait until `available-dictionary` header is available. - assert_equals( - await waitUntilAvailableDictionaryHeader(t, {}), - kDefaultDictionaryHashBase64); - // Clear site data. - assert_equals(await clearSiteData(/*directive=*/'cookies'), 'OK'); - // Check if `available-dictionary` header is not available. - assert_equals( - await waitUntilAvailableDictionaryHeader(t, {max_retry: 0}), - '"available-dictionary" header is not available'); -}, 'Clear-Site-Data with "cookies" directive must unregister dictionary'); - -compression_dictionary_promise_test(async (t) => { - const dict = await (await fetch(kRegisterDictionaryPath)).text(); - // Wait until `available-dictionary` header is available. - assert_equals( - await waitUntilAvailableDictionaryHeader(t, {}), - kDefaultDictionaryHashBase64); - // Clear site data. - assert_equals(await clearSiteData(/*directive=*/'storage'), 'OK'); - // Check if `available-dictionary` header is not available. - assert_equals( - await waitUntilAvailableDictionaryHeader(t, {max_retry: 0}), - kDefaultDictionaryHashBase64); -}, 'Clear-Site-Data with "storage" directive must not unregister dictionary'); - -</script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-decompression.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-decompression.tentative.https.html index cd20625..c7b3b7c 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-decompression.tentative.https.html +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-decompression.tentative.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <head> <meta charset="utf-8"> +<meta name="timeout" content="long"/> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/get-host-info.sub.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-element.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-element.tentative.https.html index 71a9b1c..23a271d 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-element.tentative.https.html +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-element.tentative.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <head> <meta charset="utf-8"> +<meta name="timeout" content="long"/> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/get-host-info.sub.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-header.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-header.tentative.https.html index a3ffd8b..6f6a792 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-header.tentative.https.html +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-fetch-with-link-header.tentative.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <head> <meta charset="utf-8"> +<meta name="timeout" content="long"/> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/get-host-info.sub.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-registration.tentative.https.html b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-registration.tentative.https.html index 7921b12..f0782af 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-registration.tentative.https.html +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/dictionary-registration.tentative.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <head> <meta charset="utf-8"> +<meta name="timeout" content="long"/> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="./resources/compression-dictionary-util.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/resources/compression-dictionary-util.js b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/resources/compression-dictionary-util.js index 46d9504..7d86f59 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/resources/compression-dictionary-util.js +++ b/third_party/blink/web_tests/external/wpt/fetch/compression-dictionary/resources/compression-dictionary-util.js
@@ -6,8 +6,8 @@ const kCompressedDataPath = './resources/compressed-data.py'; const kExpectedCompressedData = `This is compressed test data using a test dictionary`; -const kCheckAvailableDictionaryHeaderMaxRetry = 5; -const kCheckAvailableDictionaryHeaderRetryTimeout = 100; +const kCheckAvailableDictionaryHeaderMaxRetry = 10; +const kCheckAvailableDictionaryHeaderRetryTimeout = 200; const kCheckPreviousRequestHeadersMaxRetry = 5; const kCheckPreviousRequestHeadersRetryTimeout = 250;
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/inline-async-inserted-execorder.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/inline-async-inserted-execorder.html new file mode 100644 index 0000000..0f51fd31 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/inline-async-inserted-execorder.html
@@ -0,0 +1,70 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Inline async="" module scripts execute or throw parse errors asynchronously</title> +<link rel="help" href="https://github.com/whatwg/html/issues/9864"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +"use strict"; +setup({ allow_uncaught_exception: true }); + +promise_test(async t => { + window.log = ["before any script execution"]; + + window.addEventListener("error", ev => { + window.log.push("error event on Window"); + }); + + const noErrorScript = document.createElement("script"); + noErrorScript.type = "module"; + noErrorScript.async = true; + noErrorScript.textContent = "window.log.push('no error script executed');"; + + // This should queue a task to run the script, but not run it immediately. + document.head.append(noErrorScript); + + log.push("after inserting noErrorScript"); + assert_array_equals(window.log, [ + "before any script execution", + "after inserting noErrorScript" + ]); + + const parseErrorScript = document.createElement("script"); + parseErrorScript.type = "module"; + parseErrorScript.async = true; + parseErrorScript.textContent = "+++++"; + + // This should queue a task to fire the error event, but not fire it immediately. + document.head.append(parseErrorScript); + + log.push("after inserting parseErrorScript"); + assert_array_equals(window.log, [ + "before any script execution", + "after inserting noErrorScript", + "after inserting parseErrorScript" + ]); + + // After a microtask, the script run / error event must not happen. + queueMicrotask(t.step_func(() => { + assert_array_equals(window.log, [ + "before any script execution", + "after inserting noErrorScript", + "after inserting parseErrorScript" + ]); + })); + + // But it must eventually happen, after a full task. + await t.step_wait(() => window.log.length == 5, "5 items must eventually be logged"); + + // And when it does the order must be correct. + assert_array_equals(window.log, [ + "before any script execution", + "after inserting noErrorScript", + "after inserting parseErrorScript", + "no error script executed", + "error event on Window" + ]); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json b/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json index 82adf4c..3850606 100644 --- a/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json +++ b/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json
@@ -826,6 +826,17 @@ } }, { + "comment": "Stuff after a ? delimiter is ignored, trailing 'port'", + "href": "http://example.net/path", + "new_value": "example.com?stuff:8080", + "expected": { + "href": "http://example.com/path", + "host": "example.com", + "hostname": "example.com", + "port": "" + } + }, + { "comment": "Stuff after a ? delimiter is ignored", "href": "http://example.net/path", "new_value": "example.com:8080?stuff", @@ -925,6 +936,39 @@ } }, { + "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", + "href": "http://example.net:8080", + "new_value": "example.com:invalid", + "expected": { + "href": "http://example.com:8080/", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080" + } + }, + { + "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", + "href": "http://example.net:8080/test", + "new_value": "[::1]:invalid", + "expected": { + "href": "http://[::1]:8080/test", + "host": "[::1]:8080", + "hostname": "[::1]", + "port": "8080" + } + }, + { + "comment": "IPv6 without port", + "href": "http://example.net:8080/test", + "new_value": "[::1]", + "expected": { + "href": "http://[::1]:8080/test", + "host": "[::1]:8080", + "hostname": "[::1]", + "port": "8080" + } + }, + { "comment": "Port numbers are 16 bit integers", "href": "http://example.net/path", "new_value": "example.com:65535",
diff --git a/third_party/blink/web_tests/fast/url/mailto-expected.txt b/third_party/blink/web_tests/fast/url/mailto-expected.txt index 332be52..b29bdf7 100644 --- a/third_party/blink/web_tests/fast/url/mailto-expected.txt +++ b/third_party/blink/web_tests/fast/url/mailto-expected.txt
@@ -7,8 +7,8 @@ PASS canonicalize('mailto:addr1 ') is 'mailto:addr1' PASS canonicalize('mailto:addr1?to=jon') is 'mailto:addr1?to=jon' PASS canonicalize('mailto:addr1,addr2') is 'mailto:addr1,addr2' -PASS canonicalize('mailto:addr1, addr2') is 'mailto:addr1,%20addr2' -PASS canonicalize('mailto:addr1,"addr2"') is 'mailto:addr1,%22addr2%22' +FAIL canonicalize('mailto:addr1, addr2') should be mailto:addr1, addr2. Was mailto:addr1,%20addr2. +FAIL canonicalize('mailto:addr1,"addr2"') should be mailto:addr1,"addr2". Was mailto:addr1,%22addr2%22. PASS canonicalize('mailto:addr1%2caddr2') is 'mailto:addr1%2caddr2' PASS canonicalize('mailto:𐌀') is 'mailto:%F0%90%8C%80' PASS canonicalize('mailto:addr1?') is 'mailto:addr1?'
diff --git a/third_party/blink/web_tests/fast/url/script-tests/mailto.js b/third_party/blink/web_tests/fast/url/script-tests/mailto.js index f809333..c61d4d76 100644 --- a/third_party/blink/web_tests/fast/url/script-tests/mailto.js +++ b/third_party/blink/web_tests/fast/url/script-tests/mailto.js
@@ -8,8 +8,10 @@ ["addr1 \t ", "addr1"], ["addr1?to=jon", "addr1?to=jon"], ["addr1,addr2", "addr1,addr2"], - ["addr1, addr2", "addr1,%20addr2"], - ['addr1,"addr2"', "addr1,%22addr2%22"], + // Fails unless kStandardCompliantNonSpecialSchemeURLParsing is enabled. + // See crbug.com/40063064. + ["addr1, addr2", "addr1, addr2"], + ['addr1,"addr2"', "addr1,\"addr2\""], ["addr1%2caddr2", "addr1%2caddr2"], // U+10300 input as UTF-16 surrogate pair, expected as escaped UTF-8
diff --git a/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/mailto-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/mailto-expected.txt index b12bdad5..e0cbfa6 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/mailto-expected.txt +++ b/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/mailto-expected.txt
@@ -7,8 +7,8 @@ PASS canonicalize('mailto:addr1 ') is 'mailto:addr1' PASS canonicalize('mailto:addr1?to=jon') is 'mailto:addr1?to=jon' PASS canonicalize('mailto:addr1,addr2') is 'mailto:addr1,addr2' -FAIL canonicalize('mailto:addr1, addr2') should be mailto:addr1,%20addr2. Was mailto:addr1, addr2. -FAIL canonicalize('mailto:addr1,"addr2"') should be mailto:addr1,%22addr2%22. Was mailto:addr1,"addr2". +PASS canonicalize('mailto:addr1, addr2') is 'mailto:addr1, addr2' +PASS canonicalize('mailto:addr1,"addr2"') is 'mailto:addr1,"addr2"' PASS canonicalize('mailto:addr1%2caddr2') is 'mailto:addr1%2caddr2' PASS canonicalize('mailto:𐌀') is 'mailto:%F0%90%8C%80' PASS canonicalize('mailto:addr1?') is 'mailto:addr1?'
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any-expected.txt deleted file mode 100644 index fea6b512..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -This is a testharness.js-based test. -[FAIL] tanh float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any.worker-expected.txt deleted file mode 100644 index fea6b512..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any.worker-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -This is a testharness.js-based test. -[FAIL] tanh float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -[FAIL] tanh float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': tanh is not implemented" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac12/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac12/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt deleted file mode 100644 index 5b37deb..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. -Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt deleted file mode 100644 index 5b37deb..0000000 --- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. -Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac13/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac13/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt deleted file mode 100644 index f0e73454..0000000 --- a/third_party/blink/web_tests/platform/mac-mac13/virtual/keepalive-in-browser-migration/external/wpt/fetch/compression-dictionary/dictionary-clear-site-data.tentative.https-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] Clear-Site-Data with "cache" directive must unregister dictionary - assert_equals: expected ":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:" but got "\\"available-dictionary\\" header is not available" -Harness: the test ran to completion. -
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index 5951e69..0a3f868 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit 5951e69a2333e36fbd7912bd160f4686347e6c5f +Subproject commit 0a3f86862cfd84e4ec1a2fc43acfc5091d8923dc
diff --git a/third_party/depot_tools b/third_party/depot_tools index 609288a..495b23b 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 609288a46b37758cbbfd82aefc01359631aec81f +Subproject commit 495b23b39aaba2ca3b55dd27cadc523f1cb17ee6
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index e01752b..af2d230 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit e01752b3743faf0896f5c4b32deee5980c7f1cbd +Subproject commit af2d230f71174076f1668b20d3ec2b7a05dcb53f
diff --git a/third_party/skia b/third_party/skia index 625637f..fbc5b8b 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 625637fb612de63f127c57ca00783b2ecc66e3c8 +Subproject commit fbc5b8bb532a84c88a5d393d3849c171be6392eb
diff --git a/third_party/webrtc b/third_party/webrtc index 352bfe3..1261863 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 352bfe3c44c3baf1f16a18f912b8b162ca581c54 +Subproject commit 1261863f87ff0f6c7910a039012d3469ee8ee2fb
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 5fbaa7f..813650e 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3120,6 +3120,7 @@ <int value="-402" label="CACHE_WRITE_FAILURE"/> <int value="-401" label="CACHE_READ_FAILURE"/> <int value="-400" label="CACHE_MISS"/> + <int value="-388" label="UNEXPECTED_CONTENT_DICTIONARY_HEADER"/> <int value="-387" label="DICTIONARY_LOAD_FAILED"/> <int value="-386" label="ZSTD_WINDOW_SIZE_TOO_BIG"/> <int value="-385" label="BLOCKED_BY_PRIVATE_NETWORK_ACCESS_CHECKS"/> @@ -27613,6 +27614,7 @@ <int value="385" label="BLOCKED_BY_PRIVATE_NETWORK_ACCESS_CHECKS"/> <int value="386" label="ZSTD_WINDOW_SIZE_TOO_BIG"/> <int value="387" label="DICTIONARY_LOAD_FAILED"/> + <int value="388" label="UNEXPECTED_CONTENT_DICTIONARY_HEADER"/> <int value="400" label="CACHE_MISS"/> <int value="401" label="CACHE_READ_FAILURE"/> <int value="402" label="CACHE_WRITE_FAILURE"/>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index b5f208b..18fac77 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -4843,6 +4843,16 @@ </summary> </histogram> +<histogram name="Ash.Mahi.QuestionCountPerMahiSession" units="count" + expires_after="2025-02-01"> + <owner>andrewxu@chromium.org</owner> + <owner>cros-status-area-eng@google.com</owner> + <summary> + Record the count of questions in each Mahi session. Emitted when a Mahi + session ends, including: 1. Content is refreshed. 2. Mahi UI is closed. + </summary> +</histogram> + <histogram name="Ash.Mahi.QuestionSource" enum="MahiQuestionSource" expires_after="2025-02-01"> <owner>andrewxu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/file/enums.xml b/tools/metrics/histograms/metadata/file/enums.xml index 1c78240..1b5df1c 100644 --- a/tools/metrics/histograms/metadata/file/enums.xml +++ b/tools/metrics/histograms/metadata/file/enums.xml
@@ -438,6 +438,10 @@ <int value="35" label="HTTP_CONFLICT"/> <int value="36" label="HTTP_TOO_MANY_REQUESTS"/> <int value="37" label="HTTP_SERVICE_UNAVAILABLE"/> + <int value="38" label="THROTTLING_TENANT_APPLICATION"/> + <int value="39" label="THROTTLING_TENANT"/> + <int value="40" label="THROTTLING_APPLICATION"/> + <int value="41" label="THROTTLING_UNKNOWN"/> </enum> <enum name="FileSystemProviderMountType">
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 8272bce..d3056507 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -7207,6 +7207,17 @@ </summary> </histogram> +<histogram name="LoadingPredictor.PredictorDatabaseFileSize" units="KB" + expires_after="2024-07-09"> + <owner>yoichio@chromium.org</owner> + <owner>chrome-loading@chromium.org</owner> + <component>Internals>Preload</component> + <summary> + The size, in kilobytes, of the database used for the loading prediction. + Values can range from 1KiB to 1GiB. Logged at browser startup and daily. + </summary> +</histogram> + <histogram name="LoadingPredictor.PreresolveCount" units="hosts" expires_after="2023-12-12"> <owner>spelchat@chromium.org</owner>
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc index acb3c494..bb2837ac 100644 --- a/ui/aura/test/aura_test_helper.cc +++ b/ui/aura/test/aura_test_helper.cc
@@ -164,9 +164,6 @@ void AuraTestHelper::TearDown() { g_instance = nullptr; - if (test_screen_ && (display::Screen::GetScreen() == GetTestScreen())) - display::Screen::SetScreenInstance(nullptr); - if (!env_) Env::GetInstance()->set_context_factory(context_factory_to_restore_); @@ -184,7 +181,12 @@ capture_client_.reset(); focus_client_.reset(); host_.reset(); + + if (test_screen_ && (display::Screen::GetScreen() == GetTestScreen())) { + display::Screen::SetScreenInstance(nullptr); + } test_screen_.reset(); + context_factories_.reset(); env_.reset(); zero_duration_mode_.reset();
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 532065f..533cde5 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -172,10 +172,6 @@ "host/wayland_window_manager.h", "host/wayland_window_observer.cc", "host/wayland_window_observer.h", - "host/wayland_zaura_output.cc", - "host/wayland_zaura_output.h", - "host/wayland_zaura_output_manager.cc", - "host/wayland_zaura_output_manager.h", "host/wayland_zaura_output_manager_v2.cc", "host/wayland_zaura_output_manager_v2.h", "host/wayland_zaura_shell.cc",
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc index d03e308..d6f061f 100644 --- a/ui/ozone/platform/wayland/host/wayland_connection.cc +++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -53,7 +53,6 @@ #include "ui/ozone/platform/wayland/host/wayland_shm.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" #include "ui/ozone/platform/wayland/host/wayland_window_drag_controller.h" -#include "ui/ozone/platform/wayland/host/wayland_zaura_output_manager.h" #include "ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.h" #include "ui/ozone/platform/wayland/host/wayland_zaura_shell.h" #include "ui/ozone/platform/wayland/host/wayland_zcr_color_management_output.h" @@ -150,8 +149,6 @@ &SinglePixelBuffer::Instantiate); RegisterGlobalObjectFactory(SurfaceAugmenter::kInterfaceName, &SurfaceAugmenter::Instantiate); - RegisterGlobalObjectFactory(WaylandZAuraOutputManager::kInterfaceName, - &WaylandZAuraOutputManager::Instantiate); RegisterGlobalObjectFactory(WaylandZAuraOutputManagerV2::kInterfaceName, &WaylandZAuraOutputManagerV2::Instantiate); RegisterGlobalObjectFactory(WaylandDataDeviceManager::kInterfaceName, @@ -525,8 +522,8 @@ out << std::endl; } - if (zaura_output_manager_) { - zaura_output_manager_->DumpState(out); + if (zaura_output_manager_v2_) { + zaura_output_manager_v2_->DumpState(out); out << std::endl; } } @@ -553,10 +550,7 @@ } bool WaylandConnection::IsUsingZAuraOutputManager() const { - // TODO(crbug.com/324111902): Remove zaura_output_manager after - // zaura_output_manager_v2 has landed and existed for sufficient version - // skew. - return zaura_output_manager_ || zaura_output_manager_v2_; + return !!zaura_output_manager_v2_; } // static
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h index 526f6727..049362c 100644 --- a/ui/ozone/platform/wayland/host/wayland_connection.h +++ b/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -53,7 +53,6 @@ class WaylandOutputManager; class WaylandSeat; class WaylandZAuraShell; -class WaylandZAuraOutputManager; class WaylandZAuraOutputManagerV2; class WaylandZcrColorManager; class WaylandZcrCursorShapes; @@ -201,10 +200,6 @@ return buffer_manager_host_.get(); } - WaylandZAuraOutputManager* zaura_output_manager() const { - return zaura_output_manager_.get(); - } - WaylandZAuraOutputManagerV2* zaura_output_manager_v2() const { return zaura_output_manager_v2_.get(); } @@ -383,7 +378,6 @@ friend class WaylandDataDeviceManager; friend class WaylandOutput; friend class WaylandSeat; - friend class WaylandZAuraOutputManager; friend class WaylandZAuraOutputManagerV2; friend class WaylandZAuraShell; friend class WaylandZcrTouchpadHaptics; @@ -489,7 +483,6 @@ std::unique_ptr<WaylandDataDeviceManager> data_device_manager_; std::unique_ptr<WaylandOutputManager> output_manager_; std::unique_ptr<WaylandCursorPosition> cursor_position_; - std::unique_ptr<WaylandZAuraOutputManager> zaura_output_manager_; std::unique_ptr<WaylandZAuraOutputManagerV2> zaura_output_manager_v2_; std::unique_ptr<WaylandZAuraShell> zaura_shell_; std::unique_ptr<WaylandZcrColorManager> zcr_color_manager_;
diff --git a/ui/ozone/platform/wayland/host/wayland_output.cc b/ui/ozone/platform/wayland/host/wayland_output.cc index cb75f33f..fdd00ce0 100644 --- a/ui/ozone/platform/wayland/host/wayland_output.cc +++ b/ui/ozone/platform/wayland/host/wayland_output.cc
@@ -15,7 +15,6 @@ #include "ui/ozone/platform/wayland/host/dump_util.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_output_manager.h" -#include "ui/ozone/platform/wayland/host/wayland_zaura_output.h" #include "ui/ozone/platform/wayland/host/wayland_zcr_color_management_output.h" #include "ui/ozone/platform/wayland/host/wayland_zcr_color_manager.h" #include "ui/ozone/platform/wayland/host/xdg_output.h" @@ -131,13 +130,6 @@ zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, output_.get())); } -void WaylandOutput::InitializeZAuraOutput(zaura_shell* aura_shell) { - // TODO(oshima): remove zaura_output_. - DCHECK(!aura_output_); - aura_output_ = std::make_unique<WaylandZAuraOutput>( - zaura_shell_get_aura_output(aura_shell, output_.get())); -} - void WaylandOutput::InitializeColorManagementOutput( WaylandZcrColorManager* zcr_color_manager) { DCHECK(!color_management_output_); @@ -189,16 +181,7 @@ return metrics_.output_id == output_id_; } - // The aura output requires both the logical size and the display ID - // to become ready. If a client that uses xdg_output but not aura_output - // needs different condition for readiness, this needs to be updated. - return is_ready_ && - (!aura_output_ || - (xdg_output_ && xdg_output_->IsReady() && aura_output_->IsReady())); -} - -zaura_output* WaylandOutput::get_zaura_output() { - return aura_output_ ? aura_output_->wl_object() : nullptr; + return is_ready_; } void WaylandOutput::SetScaleFactorForTesting(float scale_factor) { @@ -219,7 +202,6 @@ } void WaylandOutput::UpdateMetrics() { - CHECK(!aura_output_); metrics_.output_id = output_id_; // For the non-aura case we map the global output "name" to the display_id. metrics_.display_id = output_id_; @@ -284,8 +266,6 @@ return; } - CHECK(!self->aura_output_); - self->is_ready_ = true; if (auto& xdg_output = self->xdg_output_) {
diff --git a/ui/ozone/platform/wayland/host/wayland_output.h b/ui/ozone/platform/wayland/host/wayland_output.h index 1c70a6a..2583001c 100644 --- a/ui/ozone/platform/wayland/host/wayland_output.h +++ b/ui/ozone/platform/wayland/host/wayland_output.h
@@ -21,7 +21,6 @@ class WaylandZcrColorManager; class WaylandZcrColorManagementOutput; class WaylandConnection; -class WaylandZAuraOutput; // WaylandOutput objects keep track of wl_output information received through // the Wayland protocol, along with other related protocol extensions, such as, @@ -107,7 +106,6 @@ void Initialize(Delegate* delegate); void InitializeXdgOutput(zxdg_output_manager_v1* manager); - void InitializeZAuraOutput(zaura_shell* aura_shell); void InitializeColorManagementOutput(WaylandZcrColorManager* manager); float GetUIScaleFactor() const; @@ -128,7 +126,6 @@ bool IsReady() const; wl_output* get_output() { return output_.get(); } - zaura_output* get_zaura_output(); void SetScaleFactorForTesting(float scale_factor); @@ -138,7 +135,6 @@ void set_delegate_for_testing(Delegate* delegate) { delegate_ = delegate; } XDGOutput* xdg_output_for_testing() { return xdg_output_.get(); } - WaylandZAuraOutput* aura_output_for_testing() { return aura_output_.get(); } private: FRIEND_TEST_ALL_PREFIXES(WaylandOutputTest, NameAndDescriptionFallback); @@ -187,7 +183,6 @@ const Id output_id_ = 0; wl::Object<wl_output> output_; std::unique_ptr<XDGOutput> xdg_output_; - std::unique_ptr<WaylandZAuraOutput> aura_output_; std::unique_ptr<WaylandZcrColorManagementOutput> color_management_output_; float scale_factor_ = kDefaultScaleFactor;
diff --git a/ui/ozone/platform/wayland/host/wayland_output_manager.cc b/ui/ozone/platform/wayland/host/wayland_output_manager.cc index 44884f1..e7af458 100644 --- a/ui/ozone/platform/wayland/host/wayland_output_manager.cc +++ b/ui/ozone/platform/wayland/host/wayland_output_manager.cc
@@ -12,7 +12,6 @@ #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_output.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" -#include "ui/ozone/platform/wayland/host/wayland_zaura_output_manager.h" #include "ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.h" #include "ui/ozone/platform/wayland/host/wayland_zaura_shell.h" @@ -56,10 +55,6 @@ if (connection_->xdg_output_manager_v1()) { wayland_output->InitializeXdgOutput(connection_->xdg_output_manager_v1()); } - if (connection_->zaura_shell()) { - wayland_output->InitializeZAuraOutput( - connection_->zaura_shell()->wl_object()); - } } // TODO(tluk): Update zaura_output_manager to support the capabilities of @@ -91,11 +86,6 @@ wayland_screen_->OnOutputRemoved(output_id); DCHECK(output_list_.find(output_id) != output_list_.end()); - if (auto* output_manager = connection_->zaura_output_manager()) { - output_manager->RemoveOutputMetrics(output_id); - DCHECK(!output_manager->GetOutputMetrics(output_id)); - } - output_list_.erase(output_id); } @@ -105,14 +95,6 @@ output.second->InitializeXdgOutput(connection_->xdg_output_manager_v1()); } -void WaylandOutputManager::InitializeAllZAuraOutputs() { - DCHECK(connection_->zaura_shell()); - for (const auto& output : output_list_) { - output.second->InitializeZAuraOutput( - connection_->zaura_shell()->wl_object()); - } -} - void WaylandOutputManager::InitializeAllColorManagementOutputs() { DCHECK(connection_->zcr_color_manager()); for (const auto& output : output_list_)
diff --git a/ui/ozone/platform/wayland/host/wayland_output_manager.h b/ui/ozone/platform/wayland/host/wayland_output_manager.h index 588ea26..99cb70cd 100644 --- a/ui/ozone/platform/wayland/host/wayland_output_manager.h +++ b/ui/ozone/platform/wayland/host/wayland_output_manager.h
@@ -42,7 +42,6 @@ void RemoveWaylandOutput(WaylandOutput::Id output_id); void InitializeAllXdgOutputs(); - void InitializeAllZAuraOutputs(); void InitializeAllColorManagementOutputs(); // Creates a platform screen.
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output.cc deleted file mode 100644 index 4972a7e0..0000000 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output.cc +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/ozone/platform/wayland/host/wayland_zaura_output.h" - -#include <aura-shell-client-protocol.h> - -#include "base/check.h" -#include "base/logging.h" -#include "ui/base/wayland/wayland_display_util.h" -#include "ui/display/screen.h" - -namespace ui { - -WaylandZAuraOutput::WaylandZAuraOutput(zaura_output* aura_output) - : obj_(aura_output) { - DCHECK(obj_); - static constexpr zaura_output_listener kAuraOutputListener = { - .scale = &OnScale, - .connection = &OnConnection, - .device_scale_factor = &OnDeviceScaleFactor, - .insets = &OnInsets, - .logical_transform = &OnLogicalTransform, - .display_id = &OnDisplayId, - .activated = &OnActivated}; - zaura_output_add_listener(obj_.get(), &kAuraOutputListener, this); -} - -WaylandZAuraOutput::WaylandZAuraOutput() : obj_(nullptr) {} - -WaylandZAuraOutput::~WaylandZAuraOutput() = default; - -bool WaylandZAuraOutput::IsReady() const { - return is_ready_; -} - -void WaylandZAuraOutput::OnDone() { - // If `display_id_` has been set the server must have propagated all the - // necessary state events for this zaura_output. - is_ready_ = display_id_.has_value(); -} - -void WaylandZAuraOutput::UpdateMetrics(WaylandOutput::Metrics& metrics) { - if (!IsReady()) { - return; - } - - metrics.insets = insets_; - metrics.logical_transform = logical_transform_.value(); - metrics.display_id = display_id_.value(); -} - -void WaylandZAuraOutput::OnScale(void* data, - zaura_output* output, - uint32_t flags, - uint32_t scale) {} - -void WaylandZAuraOutput::OnConnection(void* data, - zaura_output* output, - uint32_t connection) {} - -void WaylandZAuraOutput::OnDeviceScaleFactor(void* data, - zaura_output* output, - uint32_t scale) {} - -void WaylandZAuraOutput::OnInsets(void* data, - zaura_output* output, - int32_t top, - int32_t left, - int32_t bottom, - int32_t right) { - if (auto* self = static_cast<WaylandZAuraOutput*>(data)) { - self->insets_ = gfx::Insets::TLBR(top, left, bottom, right); - } -} - -void WaylandZAuraOutput::OnLogicalTransform(void* data, - zaura_output* output, - int32_t transform) { - if (auto* self = static_cast<WaylandZAuraOutput*>(data)) { - self->logical_transform_ = transform; - } -} - -void WaylandZAuraOutput::OnDisplayId(void* data, - zaura_output* output, - uint32_t display_id_hi, - uint32_t display_id_lo) { - if (auto* self = static_cast<WaylandZAuraOutput*>(data)) { - self->display_id_ = - ui::wayland::FromWaylandDisplayIdPair({display_id_hi, display_id_lo}); - } -} - -void WaylandZAuraOutput::OnActivated(void* data, zaura_output* output) { - auto* self = static_cast<WaylandZAuraOutput*>(data); - if (self && self->IsReady()) { - DCHECK(display::Screen::GetScreen()); - display::Screen::GetScreen()->SetDisplayForNewWindows( - self->display_id_.value()); - } -} - -} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager.cc deleted file mode 100644 index f32f5d9c..0000000 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager.cc +++ /dev/null
@@ -1,295 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/ozone/platform/wayland/host/wayland_zaura_output_manager.h" - -#include <components/exo/wayland/protocol/aura-shell-client-protocol.h> - -#include "base/check.h" -#include "base/containers/contains.h" -#include "base/logging.h" -#include "ui/base/wayland/wayland_display_util.h" -#include "ui/display/screen.h" -#include "ui/ozone/platform/wayland/host/wayland_connection.h" -#include "ui/ozone/platform/wayland/host/wayland_output_manager.h" - -namespace ui { - -namespace { -// To support all existing use cases of zaura_output and xdg_output, -// zaura_output_manager must be version 2+. -constexpr uint32_t kMinVersion = 2; -constexpr uint32_t kMaxVersion = 2; -} // namespace - -// static -constexpr char WaylandZAuraOutputManager::kInterfaceName[]; - -// static -void WaylandZAuraOutputManager::Instantiate(WaylandConnection* connection, - wl_registry* registry, - uint32_t name, - const std::string& interface, - uint32_t version) { - CHECK_EQ(interface, kInterfaceName) << "Expected \"" << kInterfaceName - << "\" but got \"" << interface << "\""; - - if (connection->zaura_output_manager_ || - !wl::CanBind(interface, version, kMinVersion, kMaxVersion)) { - return; - } - - // zaura_output_manager_v2 will be advertised first by the server. If - // supported and bound by this client skip binding the older interface. - if (connection->zaura_output_manager_v2_) { - LOG(WARNING) << "Skipping bind to zaura_output_manager, " - "zaura_output_manager_v2 has already been bound."; - return; - } - - auto output_manager = wl::Bind<struct zaura_output_manager>( - registry, name, std::min(version, kMaxVersion)); - if (!output_manager) { - return; - } - connection->zaura_output_manager_ = - std::make_unique<WaylandZAuraOutputManager>(output_manager.release(), - connection); -} - -WaylandZAuraOutputManager::WaylandZAuraOutputManager( - zaura_output_manager* output_manager, - WaylandConnection* connection) - : obj_(output_manager), connection_(connection) { - DCHECK(obj_); - DCHECK(connection_); - static constexpr zaura_output_manager_listener kAuraOutputManagerListener = { - .done = &OnDone, - .display_id = &OnDisplayId, - .logical_position = &OnLogicalPosition, - .logical_size = &OnLogicalSize, - .physical_size = &OnPhysicalSize, - .insets = &OnInsets, - .device_scale_factor = &OnDeviceScaleFactor, - .logical_transform = &OnLogicalTransform, - .panel_transform = &OnPanelTransform, - .name = &OnName, - .description = &OnDescription, - .activated = &OnActivated, - .overscan_insets = &OnOverscanInsets}; - zaura_output_manager_add_listener(obj_.get(), &kAuraOutputManagerListener, - this); -} - -WaylandZAuraOutputManager::~WaylandZAuraOutputManager() = default; - -const WaylandOutput::Metrics* WaylandZAuraOutputManager::GetOutputMetrics( - WaylandOutput::Id output_id) const { - // Only return the output metrics if all state has arrived from the server. - return IsReady(output_id) ? &output_metrics_map_.at(output_id) : nullptr; -} - -void WaylandZAuraOutputManager::RemoveOutputMetrics( - WaylandOutput::Id output_id) { - pending_output_metrics_map_.erase(output_id); - output_metrics_map_.erase(output_id); -} - -void WaylandZAuraOutputManager::DumpState(std::ostream& out) const { - out << "AuraOutputManager:" << std::endl; - int i = 0; - for (const auto& pair : pending_output_metrics_map_) { - out << " pending output metrics[" << i++ << "]:"; - pair.second.DumpState(out); - out << std::endl; - } - i = 0; - for (const auto& pair : output_metrics_map_) { - out << " output metrics[" << i++ << "]:"; - pair.second.DumpState(out); - out << std::endl; - } -} - -WaylandOutput::Id WaylandZAuraOutputManager::GetId(wl_output* output) const { - WaylandOutputManager* output_manager = connection_->wayland_output_manager(); - // The WaylandOutputManager should have been instantiated when the first - // wl_output was bound. - DCHECK(output_manager); - return output_manager->GetOutputId(output); -} - -WaylandOutput* WaylandZAuraOutputManager::GetWaylandOutput( - WaylandOutput::Id output_id) { - WaylandOutputManager* output_manager = connection_->wayland_output_manager(); - CHECK(output_manager); - return output_manager->GetOutput(output_id); -} - -bool WaylandZAuraOutputManager::IsReady(WaylandOutput::Id output_id) const { - return base::Contains(output_metrics_map_, output_id); -} - -// static -void WaylandZAuraOutputManager::OnDone(void* data, - zaura_output_manager* output_manager, - wl_output* output) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - const WaylandOutput::Id output_id = self->GetId(output); - self->pending_output_metrics_map_[output_id].output_id = output_id; - - self->output_metrics_map_[output_id] = - self->pending_output_metrics_map_[output_id]; - - if (auto* wayland_output = self->GetWaylandOutput(output_id)) { - // Update the metrics on the corresponding WaylandOutput. - wayland_output->SetMetrics(self->output_metrics_map_[output_id]); - - // TODO(tluk): In the case of multiple outputs we should wait until we - // receive state updates for all outputs before propagating notifications. - wayland_output->TriggerDelegateNotifications(); - } -} - -// static -void WaylandZAuraOutputManager::OnDisplayId( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - uint32_t display_id_hi, - uint32_t display_id_lo) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].display_id = - ui::wayland::FromWaylandDisplayIdPair({display_id_hi, display_id_lo}); -} - -// static -void WaylandZAuraOutputManager::OnLogicalPosition( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t x, - int32_t y) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].origin.SetPoint(x, y); -} - -// static -void WaylandZAuraOutputManager::OnLogicalSize( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t width, - int32_t height) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].logical_size.SetSize( - width, height); -} - -// static -void WaylandZAuraOutputManager::OnPhysicalSize( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t width, - int32_t height) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].physical_size.SetSize( - width, height); -} - -// static -void WaylandZAuraOutputManager::OnInsets(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t top, - int32_t left, - int32_t bottom, - int32_t right) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].insets = - gfx::Insets::TLBR(top, left, bottom, right); -} - -// static -void WaylandZAuraOutputManager::OnDeviceScaleFactor( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - uint32_t scale_as_uint) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].scale_factor = - base::bit_cast<float>(scale_as_uint); -} - -// static -void WaylandZAuraOutputManager::OnLogicalTransform( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t transform) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].logical_transform = - transform; -} - -// static -void WaylandZAuraOutputManager::OnPanelTransform( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t transform) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].panel_transform = - transform; -} - -// static -void WaylandZAuraOutputManager::OnName(void* data, - zaura_output_manager* output_manager, - wl_output* output, - const char* name) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].name = name; -} - -// static -void WaylandZAuraOutputManager::OnDescription( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - const char* description) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)].description = - description; -} - -// static -void WaylandZAuraOutputManager::OnActivated( - void* data, - zaura_output_manager* output_manager, - wl_output* output) { - CHECK(display::Screen::GetScreen()); - - const auto* self = static_cast<WaylandZAuraOutputManager*>(data); - const WaylandOutput::Id output_id = self->GetId(output); - display::Screen::GetScreen()->SetDisplayForNewWindows( - self->GetOutputMetrics(output_id)->display_id); -} - -// static -void WaylandZAuraOutputManager::OnOverscanInsets( - void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t top, - int32_t left, - int32_t bottom, - int32_t right) { - auto* self = static_cast<WaylandZAuraOutputManager*>(data); - self->pending_output_metrics_map_[self->GetId(output)] - .physical_overscan_insets = gfx::Insets::TLBR(top, left, bottom, right); -} - -} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager.h b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager.h deleted file mode 100644 index 1eedd6b..0000000 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager.h +++ /dev/null
@@ -1,142 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_OUTPUT_MANAGER_H_ -#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_OUTPUT_MANAGER_H_ - -#include <ostream> - -#include "base/containers/flat_map.h" -#include "base/containers/flat_set.h" -#include "base/memory/raw_ptr.h" -#include "ui/display/tablet_state.h" -#include "ui/ozone/platform/wayland/common/wayland_object.h" -#include "ui/ozone/platform/wayland/host/wayland_output.h" - -namespace ui { - -class WaylandConnection; - -// Wraps the zaura_output_manager object. Responsible for receiving -// output state from the server and associating the state with the -// appropriate WaylandOutput. -class WaylandZAuraOutputManager - : public wl::GlobalObjectRegistrar<WaylandZAuraOutputManager> { - public: - static constexpr char kInterfaceName[] = "zaura_output_manager"; - - using OutputMetricsMap = - base::flat_map<WaylandOutput::Id, WaylandOutput::Metrics>; - - static void Instantiate(WaylandConnection* connection, - wl_registry* registry, - uint32_t name, - const std::string& interface, - uint32_t version); - - WaylandZAuraOutputManager(zaura_output_manager* output_manager, - WaylandConnection* connection); - WaylandZAuraOutputManager(const WaylandZAuraOutputManager&) = delete; - WaylandZAuraOutputManager& operator=(const WaylandZAuraOutputManager&) = - delete; - ~WaylandZAuraOutputManager(); - - // Gets the complete Metrics object for the `output_id`. Returns a valid - // object only if the zaura_output_manager is supported and has been - // bound by the client. - const WaylandOutput::Metrics* GetOutputMetrics( - WaylandOutput::Id output_id) const; - - // Removes the stored Metrics for the `output_id`. If no output exists the - // operation will no-op. - void RemoveOutputMetrics(WaylandOutput::Id output_id); - - zaura_output_manager* wl_object() { return obj_.get(); } - - void DumpState(std::ostream& out) const; - - private: - WaylandOutput::Id GetId(wl_output* output) const; - WaylandOutput* GetWaylandOutput(WaylandOutput::Id output_id); - - // Returns true once the output manager has received the done event. At this - // point all mandatory state for the output has been received. - bool IsReady(WaylandOutput::Id output_id) const; - - // zaura_output_manager_listener callbacks: - static void OnDone(void* data, - zaura_output_manager* output_manager, - wl_output* output); - static void OnDisplayId(void* data, - zaura_output_manager* output_manager, - wl_output* output, - uint32_t display_id_hi, - uint32_t display_id_lo); - static void OnLogicalPosition(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t x, - int32_t y); - static void OnLogicalSize(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t width, - int32_t height); - static void OnPhysicalSize(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t width, - int32_t height); - static void OnInsets(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t top, - int32_t left, - int32_t bottom, - int32_t right); - static void OnDeviceScaleFactor(void* data, - zaura_output_manager* output_manager, - wl_output* output, - uint32_t scale_as_uint); - static void OnLogicalTransform(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t transform); - static void OnPanelTransform(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t transform); - static void OnName(void* data, - zaura_output_manager* output_manager, - wl_output* output, - const char* name); - static void OnDescription(void* data, - zaura_output_manager* output_manager, - wl_output* output, - const char* description); - static void OnActivated(void* data, - zaura_output_manager* output_manager, - wl_output* output); - static void OnOverscanInsets(void* data, - zaura_output_manager* output_manager, - wl_output* output, - int32_t top, - int32_t left, - int32_t bottom, - int32_t right); - - // `pending_output_metrics_map_` holds Metrics objects that are updated - // incrementally as events arrive from the server. These Metrics objects are - // copied into the `output_metrics_map_` once clients receive the done event. - // This ensures atomic updates to the client's view of output metrics. - OutputMetricsMap pending_output_metrics_map_; - OutputMetricsMap output_metrics_map_; - - wl::Object<zaura_output_manager> obj_; - const raw_ptr<WaylandConnection> connection_; -}; - -} // namespace ui - -#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_OUTPUT_MANAGER_H_
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.cc index 2f9fd95..3f03926 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.cc +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.cc
@@ -6,8 +6,12 @@ #include <components/exo/wayland/protocol/aura-output-management-client-protocol.h> +#include <algorithm> + #include "base/check.h" #include "base/containers/contains.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "ui/base/wayland/wayland_display_util.h" #include "ui/display/screen.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" @@ -78,6 +82,36 @@ pending_removed_outputs_.push_back(output_id); } +void WaylandZAuraOutputManagerV2::DumpState(std::ostream& out) const { + out << "AuraOutputManagerv2:" << std::endl; + int i = 0; + for (const auto& pair : pending_output_metrics_map_) { + out << " pending output metrics[" << i++ << "]:"; + pair.second.DumpState(out); + out << std::endl; + } + i = 0; + for (const auto& pair : output_metrics_map_) { + out << " output metrics[" << i++ << "]:"; + pair.second.DumpState(out); + out << std::endl; + } + + std::vector<std::string> values; + std::transform(pending_outputs_.begin(), pending_outputs_.end(), + values.begin(), + static_cast<std::string (*)(int)>(base::NumberToString)); + out << " pending_changed outputs: [" << base::JoinString(values, ",") << "]" + << std::endl; + + values.clear(); + std::transform(pending_removed_outputs_.begin(), + pending_removed_outputs_.end(), values.begin(), + static_cast<std::string (*)(int)>(base::NumberToString)); + out << " pending_removed outputs: [" << base::JoinString(values, ",") << "]" + << std::endl; +} + WaylandOutput* WaylandZAuraOutputManagerV2::GetWaylandOutput( WaylandOutput::Id output_id) { WaylandOutputManager* output_manager = connection_->wayland_output_manager();
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.h b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.h index ac6857d..fcfefe4 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.h +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_v2.h
@@ -54,6 +54,8 @@ return pending_output_metrics_map_; } + void DumpState(std::ostream& out) const; + private: WaylandOutput* GetWaylandOutput(WaylandOutput::Id output_id);
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc b/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc index 8263627..9135333 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc +++ b/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc
@@ -58,13 +58,6 @@ connection->zaura_shell_ = std::make_unique<WaylandZAuraShell>(zaura_shell.release(), connection); ReportShellUMA(UMALinuxWaylandShell::kZauraShell); - - // Usually WaylandOutputManager is instantiated first, so any ZAuraOutputs it - // created wouldn't have been initialized, since the zaura_shell didn't exist - // yet. So initialize them now. - if (connection->wayland_output_manager()) { - connection->wayland_output_manager()->InitializeAllZAuraOutputs(); - } } WaylandZAuraShell::WaylandZAuraShell(zaura_shell* aura_shell,
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc index 8734e70..c27bccaf 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
@@ -242,9 +242,6 @@ void TestWaylandServerThread::OnTestOutputFlush( TestOutput* test_output, const TestOutputMetrics& metrics) { - if (zaura_output_manager_.resource()) { - zaura_output_manager_.SendOutputMetrics(test_output, metrics); - } if (zaura_output_manager_v2_.resource()) { zaura_output_manager_v2_.SendOutputMetrics(test_output, metrics); }
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h index 53a1b5e..c1f0e98 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
@@ -33,7 +33,6 @@ #include "ui/ozone/platform/wayland/test/test_surface_augmenter.h" #include "ui/ozone/platform/wayland/test/test_viewporter.h" #include "ui/ozone/platform/wayland/test/test_wp_pointer_gestures.h" -#include "ui/ozone/platform/wayland/test/test_zaura_output_manager.h" #include "ui/ozone/platform/wayland/test/test_zaura_output_manager_v2.h" #include "ui/ozone/platform/wayland/test/test_zaura_shell.h" #include "ui/ozone/platform/wayland/test/test_zcr_stylus.h" @@ -149,9 +148,6 @@ TestDataDeviceManager* data_device_manager() { return &data_device_manager_; } TestSeat* seat() { return &seat_; } MockXdgShell* xdg_shell() { return &xdg_shell_; } - TestZAuraOutputManager* zaura_output_manager() { - return &zaura_output_manager_; - } TestZAuraOutputManagerV2* zaura_output_manager_v2() { return &zaura_output_manager_v2_; } @@ -244,7 +240,6 @@ TestSeat seat_; TestZXdgOutputManager zxdg_output_manager_; MockXdgShell xdg_shell_; - TestZAuraOutputManager zaura_output_manager_; TestZAuraOutputManagerV2 zaura_output_manager_v2_; TestZAuraShell zaura_shell_; ::testing::NiceMock<MockZcrColorManagerV1> zcr_color_manager_v1_;