diff --git a/DEPS b/DEPS index 041e350..12766e88 100644 --- a/DEPS +++ b/DEPS
@@ -310,11 +310,11 @@ # 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': 'c29a20702356a118d09d173755d66315b16127cf', + 'skia_revision': '7bba745c06f2b61b147716b112a9f8b565212113', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'f243ba1bf4f7673ff645e31af0370f22e968d19d', + 'v8_revision': '19ff14d2f82c8ff9c1d66265486ec2be7bcbe3c6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -385,7 +385,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': 'a7a1e5eaa6ed285b51271a665bfda91bc8fe7a3f', + 'chromium_variations_revision': 'dfd5d19b1692bb48558f9ee13f1248aed2251886', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -401,7 +401,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '3a113586c2d333056dc944e92db447ddaa492762', + 'devtools_frontend_revision': '7128b4c8c6619ee48f9dd33a4ed13be79b107a26', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -501,7 +501,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '3c2f3884e62e17b137ede3e2f3e7214ef294e2c9', + 'libcxx_revision': '6024b26887625fef52ea0f227d888c4b815488be', # GN CIPD package version. 'gn_version': 'git_revision:a2e2717ea670249a34b0de4b3e54f268d320bdfa', @@ -825,7 +825,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '923f628b8e7644a1c009747dafe7bf61e12896b6', + 'ffa3dc27fca10f8fc147f85437851f73327551f5', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1203,7 +1203,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'd27a6b83a969ae8c9a02df0e03e5756a1f4c521a', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'ecca9b5d5bc1e729ccb20fc4c3ca68da163bcb06', 'condition': 'checkout_src_internal', }, @@ -1302,7 +1302,7 @@ }, 'src/third_party/cardboard/src' : { - 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + '5c9f3066dc14962d1dec9a32ec9d3668641c408d', + 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + 'c8842698f4a9d63cce865e7d6cb75773a4673496', 'condition': 'checkout_android', }, @@ -1663,7 +1663,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '786ec3a414ad41aa627a88b83c7fd9bae5d59136', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '5cafd5f37c15d474540c4a3439129381f4184f39', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '8ef97ff3b7332e38e61b347a2fbed425a4617151', @@ -1703,7 +1703,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'yr6NtXUFlwC0IMXpA-KKdgva5QQ8ME9lm0LD3wz3lSQC', + 'version': 'Wpuxcm9gcq_RziIlCD0O_dgjRUr75g61LfP2iXo4FTsC', }, ], 'condition': 'checkout_android', @@ -1848,7 +1848,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e082b08475761a2ba6a3349dfea72f704c8b68d4', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '1188d0849f18baf91ab0061781ea1a521363b8bd', + Var('webrtc_git') + '/src.git' + '@' + '310c9d4cbe0f3d7bbf3e5bcc2a2a92c8c350372f', # 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. @@ -1971,7 +1971,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'Z7MhyEea5gXSXfae41N_o4Mn5NxF4kf_oyAnOvipQoMC', + 'version': 'CKWXyPQR_GYDuwSEnDkAzqiJmrxJV9wMxpv6Jpqq7ZoC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2015,7 +2015,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'sdWslyJdc24I9dFH2Gy2M5HSGFBVRFSOKfOELvr3T7MC', + 'version': '4JlG30OSbHen6vXN7bNcKjd1XFKUcnZ8xmDaW1kzfa4C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4033,7 +4033,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - 'a2e9e8cfd9bd77d59fc632ddb10190e30514189d', + 'd7d7b06b764310290cab652eeb2701c6c515881f', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index a926c9f..0707747 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2530,8 +2530,8 @@ "wm/desks/desk_name_view.h", "wm/desks/desk_preview_view.cc", "wm/desks/desk_preview_view.h", - "wm/desks/desk_profiles_view.cc", - "wm/desks/desk_profiles_view.h", + "wm/desks/desk_profiles_button.cc", + "wm/desks/desk_profiles_button.h", "wm/desks/desk_textfield.cc", "wm/desks/desk_textfield.h", "wm/desks/desks_animations.cc",
diff --git a/ash/app_list/views/folder_header_view.cc b/ash/app_list/views/folder_header_view.cc index 95992b3..6d043ab 100644 --- a/ash/app_list/views/folder_header_view.cc +++ b/ash/app_list/views/folder_header_view.cc
@@ -298,7 +298,6 @@ void OnFocus() override { starting_name_ = GetText(); SystemTextfield::OnFocus(); - SetActive(true); } void OnBlur() override { @@ -314,6 +313,14 @@ } SystemTextfield::OnBlur(); + + // OnBlur updates background ONLY if the ActiveState is changed. Since the + // SystemTextField component does not clear focus after changing the + // ActiveState, there are some instances where removing focus will not + // trigger a background update. + // TODO(b/323054951): Clean this code once the SystemTextfield has + // implemented clearing focus. + UpdateBackground(); } bool DoesMouseEventActuallyIntersect(const ui::MouseEvent& event) { @@ -357,6 +364,7 @@ SystemTextfield* textfield, const ContentsChangedCallback& contents_changed_callback) : SystemTextfieldController(textfield), + textfield_(textfield), contents_changed_callback_(contents_changed_callback) {} FolderNameViewController(const FolderNameViewController&) = delete; @@ -372,6 +380,16 @@ bool HandleKeyEvent(views::Textfield* sender, const ui::KeyEvent& key_event) override { if (SystemTextfieldController::HandleKeyEvent(sender, key_event)) { + // TODO(b/323054951): Clean this code once the SystemTextfield has + // implemented clearing focus. + const bool should_clear_focus = + key_event.type() == ui::ET_KEY_PRESSED && + (key_event.key_code() == ui::VKEY_RETURN || + key_event.key_code() == ui::VKEY_ESCAPE); + + if (should_clear_focus) { + textfield_->GetFocusManager()->ClearFocus(); + } return true; } @@ -383,6 +401,7 @@ } private: + raw_ptr<SystemTextfield> textfield_ = nullptr; const ContentsChangedCallback contents_changed_callback_; };
diff --git a/ash/app_list/views/folder_header_view_unittest.cc b/ash/app_list/views/folder_header_view_unittest.cc index a4b3117f..62f0b84 100644 --- a/ash/app_list/views/folder_header_view_unittest.cc +++ b/ash/app_list/views/folder_header_view_unittest.cc
@@ -242,7 +242,7 @@ // Make sure the return press unfocused the text and registered the name // change. - EXPECT_EQ(IsJellyEnabled(), HasTextFocus()); + EXPECT_EQ(false, HasTextFocus()); EXPECT_EQ("ret", folder_item->name()); } @@ -266,7 +266,7 @@ SendKey(ui::VKEY_ESCAPE); // Make sure the escape press unfocused the text and reverted the name change. - EXPECT_EQ(IsJellyEnabled(), HasTextFocus()); + EXPECT_EQ(false, HasTextFocus()); EXPECT_EQ("", folder_item->name()); }
diff --git a/ash/clipboard/clipboard_history_controller_unittest.cc b/ash/clipboard/clipboard_history_controller_unittest.cc index dc46c19a3d..3092740 100644 --- a/ash/clipboard/clipboard_history_controller_unittest.cc +++ b/ash/clipboard/clipboard_history_controller_unittest.cc
@@ -490,10 +490,11 @@ TEST_F(ClipboardHistoryControllerTest, EncodeMultipleImages) { // Write a bunch of bitmaps to the clipboard. - std::vector<const SkBitmap> test_bitmaps; - test_bitmaps.emplace_back(gfx::test::CreateBitmap(2, 1)); - test_bitmaps.emplace_back(gfx::test::CreateBitmap(3, 2)); - test_bitmaps.emplace_back(gfx::test::CreateBitmap(4, 3)); + const std::vector<SkBitmap> test_bitmaps{ + gfx::test::CreateBitmap(2, 1), + gfx::test::CreateBitmap(3, 2), + gfx::test::CreateBitmap(4, 3), + }; for (const auto& test_bitmap : test_bitmaps) { WriteImageToClipboardAndConfirm(test_bitmap); } @@ -513,9 +514,10 @@ TEST_F(ClipboardHistoryControllerTest, WriteBitmapWhileEncodingImage) { // Write a bitmap to the clipboard. - std::vector<const SkBitmap> test_bitmaps; - test_bitmaps.emplace_back(gfx::test::CreateBitmap(3, 2)); - test_bitmaps.emplace_back(gfx::test::CreateBitmap(4, 3)); + const std::vector<SkBitmap> test_bitmaps{ + gfx::test::CreateBitmap(3, 2), + gfx::test::CreateBitmap(4, 3), + }; WriteImageToClipboardAndConfirm(test_bitmaps[0]); // Write another bitmap to the clipboard while encoding the first bitmap.
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 7b0089d2..3ac0f25c 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -2619,11 +2619,6 @@ "DemoModeGMSCoreWindowCloser", base::FEATURE_ENABLED_BY_DEFAULT); -// Enables the shutdown confirmation bubble from the login shelf view. -BASE_FEATURE(kShutdownConfirmationBubble, - "ShutdownConfirmationBubble", - base::FEATURE_ENABLED_BY_DEFAULT); - // Moves toasts to the bottom-side corner where the status area is instead of // the center when enabled. BASE_FEATURE(kSideAlignedToasts, @@ -2759,12 +2754,6 @@ "UseAndroidStagingSmds", base::FEATURE_DISABLED_BY_DEFAULT); -// When enabled, the login shelf view is placed in its own widget instead of -// sharing the shelf widget with other components. -BASE_FEATURE(kUseLoginShelfWidget, - "UseLoginShelfWidget", - base::FEATURE_ENABLED_BY_DEFAULT); - // Use the staging URL as part of the "Messages" feature under "Connected // Devices" settings. BASE_FEATURE(kUseMessagesStagingUrl, @@ -4410,10 +4399,6 @@ kUnmanagedDeviceDeviceTrustConnectorEnabled); } -bool IsUseLoginShelfWidgetEnabled() { - return base::FeatureList::IsEnabled(kUseLoginShelfWidget); -} - bool ShouldUseAndroidStagingSmds() { return base::FeatureList::IsEnabled(kUseAndroidStagingSmds); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 3f92e95..33363a0 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -798,8 +798,6 @@ BASE_DECLARE_FEATURE(kFeatureManagementFeatureAwareDeviceDemoMode); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kDemoModeGMSCoreWindowCloser); -COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kShutdownConfirmationBubble); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kSideAlignedToasts); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kSmartDimExperimentalComponent); @@ -848,7 +846,6 @@ BASE_DECLARE_FEATURE(kUpstreamTrustedReportsFirmware); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kUseAndroidStagingSmds); -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kUseLoginShelfWidget); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kUseMessagesStagingUrl); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kUseOneSharedImageForFastInkHostResources); @@ -1286,7 +1283,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsTrilinearFilteringEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsUnmanagedDeviceDeviceTrustConnectorFeatureEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsUseLoginShelfWidgetEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsUserEducationEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsVideoConferenceEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsStopAllScreenShareEnabled();
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc index ee062bc..d26d429 100644 --- a/ash/login/login_screen_controller.cc +++ b/ash/login/login_screen_controller.cc
@@ -326,14 +326,9 @@ Shell::Get()->focus_cycler()->FocusWidget(shelf->GetStatusAreaWidget()); } else if (shelf->shelf_widget()->GetLoginShelfView()->IsFocusable()) { // Otherwise focus goes to login shelf buttons when there is any. - if (features::IsUseLoginShelfWidgetEnabled()) { - LoginShelfWidget* login_shelf_widget = shelf->login_shelf_widget(); - login_shelf_widget->SetDefaultLastFocusableChild(reverse); - Shell::Get()->focus_cycler()->FocusWidget(login_shelf_widget); - } else { - shelf->shelf_widget()->set_default_last_focusable_child(reverse); - Shell::Get()->focus_cycler()->FocusWidget(shelf->shelf_widget()); - } + LoginShelfWidget* login_shelf_widget = shelf->login_shelf_widget(); + login_shelf_widget->SetDefaultLastFocusableChild(reverse); + Shell::Get()->focus_cycler()->FocusWidget(login_shelf_widget); } else { // No elements to focus on the shelf. //
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 5cd7212..a62797c1 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -1328,12 +1328,9 @@ ->status_area_widget_delegate() ->set_default_last_focusable_child(reverse); Shell::Get()->focus_cycler()->FocusWidget(shelf->GetStatusAreaWidget()); - } else if (features::IsUseLoginShelfWidgetEnabled()) { + } else { shelf->login_shelf_widget()->SetDefaultLastFocusableChild(reverse); Shell::Get()->focus_cycler()->FocusWidget(shelf->login_shelf_widget()); - } else { - shelf->shelf_widget()->set_default_last_focusable_child(reverse); - Shell::Get()->focus_cycler()->FocusWidget(shelf->shelf_widget()); } }
diff --git a/ash/login/ui/lock_screen_sanity_unittest.cc b/ash/login/ui/lock_screen_sanity_unittest.cc index 0d641d3c..dd5c7ff 100644 --- a/ash/login/ui/lock_screen_sanity_unittest.cc +++ b/ash/login/ui/lock_screen_sanity_unittest.cc
@@ -39,14 +39,8 @@ // Returns the widget contents view that contains login shelf in the same root // window as `native_window`. views::View* GetLoginShelfContentsView(gfx::NativeWindow native_window) { - // TODO(https://crbug.com/1343114): refactor the code below after the login - // shelf widget is ready. Shelf* shelf = Shelf::ForWindow(native_window); - if (features::IsUseLoginShelfWidgetEnabled()) { - return shelf->login_shelf_widget()->GetContentsView(); - } - - return shelf->shelf_widget()->GetContentsView(); + return shelf->login_shelf_widget()->GetContentsView(); } class LockScreenAppFocuser {
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index 3a765551..8ba1975 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -207,25 +207,21 @@ return; } base::RecordAction(base::UserMetricsAction("Shelf_ShutDown")); - if (base::FeatureList::IsEnabled(features::kShutdownConfirmationBubble)) { - Shelf* shelf = Shelf::ForWindow(GetWidget()->GetNativeWindow()); - // When the created ShelfShutdownConfirmationBubble is destroyed, it would - // call LoginShelfView::OnRequestShutdownCancelled() in the destructor to - // ensure that the pointer test_shutdown_confirmation_bubble_ here is - // cleaned up. - // And ShelfShutdownConfirmationBubble would be destroyed when it's - // dismissed or its buttons were presses. - shutdown_confirmation_button_->SetIsActive(true); + Shelf* shelf = Shelf::ForWindow(GetWidget()->GetNativeWindow()); + // When the created ShelfShutdownConfirmationBubble is destroyed, it would + // call LoginShelfView::OnRequestShutdownCancelled() in the destructor to + // ensure that the pointer test_shutdown_confirmation_bubble_ here is + // cleaned up. + // And ShelfShutdownConfirmationBubble would be destroyed when it's + // dismissed or its buttons were presses. + shutdown_confirmation_button_->SetIsActive(true); - test_shutdown_confirmation_bubble_ = new ShelfShutdownConfirmationBubble( - shutdown_confirmation_button_, shelf->alignment(), - base::BindOnce(&LoginShelfView::OnRequestShutdownConfirmed, - weak_ptr_factory_.GetWeakPtr()), - base::BindOnce(&LoginShelfView::OnRequestShutdownCancelled, - weak_ptr_factory_.GetWeakPtr())); - } else { - OnRequestShutdownConfirmed(); - } + test_shutdown_confirmation_bubble_ = new ShelfShutdownConfirmationBubble( + shutdown_confirmation_button_, shelf->alignment(), + base::BindOnce(&LoginShelfView::OnRequestShutdownConfirmed, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&LoginShelfView::OnRequestShutdownCancelled, + weak_ptr_factory_.GetWeakPtr())); } LoginShelfView::LoginShelfView( @@ -723,11 +719,10 @@ SetFocusBehavior(is_anything_focusable ? views::View::FocusBehavior::ALWAYS : views::View::FocusBehavior::NEVER); - // When the login shelf view is moved to its own widget, the login shelf + // The login shelf view lives in its own widget, therefore the login shelf // widget needs to change the size according to the login shelf view's // preferred size. - if (old_preferred_size != GetPreferredSize() && - features::IsUseLoginShelfWidgetEnabled()) { + if (old_preferred_size != GetPreferredSize()) { PreferredSizeChanged(); } else { DeprecatedLayoutImmediately();
diff --git a/ash/shelf/login_shelf_view_unittest.cc b/ash/shelf/login_shelf_view_unittest.cc index 8cf18c5..28f9f83 100644 --- a/ash/shelf/login_shelf_view_unittest.cc +++ b/ash/shelf/login_shelf_view_unittest.cc
@@ -164,18 +164,8 @@ } void FocusOnLoginShelfButton() { - // TODO(https://crbug.com/1343114): refactor the code below after the login - // shelf widget is ready. - - views::Widget* login_shelf_widget = GetLoginShelfWidget(); - if (features::IsUseLoginShelfWidgetEnabled()) { - static_cast<LoginShelfWidget*>(login_shelf_widget) - ->SetDefaultLastFocusableChild(/*reverse=*/false); - } else { - static_cast<ShelfWidget*>(login_shelf_widget) - ->set_default_last_focusable_child( - /*default_last_focusable_child=*/false); - } + LoginShelfWidget* login_shelf_widget = GetLoginShelfWidget(); + login_shelf_widget->SetDefaultLastFocusableChild(/*reverse=*/false); Shell::Get()->focus_cycler()->FocusWidget(login_shelf_widget); ExpectFocused(login_shelf_widget->GetContentsView()); @@ -197,15 +187,10 @@ } // Returns the widget where the login shelf view lives. - views::Widget* GetLoginShelfWidget() { - // TODO(https://crbug.com/1343114): refactor the code below after the login - // shelf widget is ready. - + LoginShelfWidget* GetLoginShelfWidget() { Shelf* shelf = Shelf::ForWindow(login_shelf_view_->GetWidget()->GetNativeWindow()); - return features::IsUseLoginShelfWidgetEnabled() - ? static_cast<views::Widget*>(shelf->login_shelf_widget()) - : shelf->shelf_widget(); + return shelf->login_shelf_widget(); } TestTrayActionClient tray_action_client_; @@ -1075,11 +1060,6 @@ ~LoginShelfViewWithShutdownConfirmationTest() override = default; - void SetUp() override { - LoginShelfViewTest::SetUp(); - feature_list_.InitAndEnableFeature(features::kShutdownConfirmationBubble); - } - base::HistogramTester& histograms() { return histograms_; } protected: @@ -1131,8 +1111,6 @@ private: // Histogram value verifier. base::HistogramTester histograms_; - - base::test::ScopedFeatureList feature_list_; }; // Checks that shutdown confirmation bubble appears after pressing the
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc index 478ea42..31e6eca4 100644 --- a/ash/shelf/shelf.cc +++ b/ash/shelf/shelf.cc
@@ -470,10 +470,8 @@ if (ash::features::IsDeskButtonEnabled()) { CreateDeskButtonWidget(shelf_container); } - if (features::IsUseLoginShelfWidgetEnabled()) { - login_shelf_widget_ = - std::make_unique<LoginShelfWidget>(/*shelf=*/this, shelf_container); - } + login_shelf_widget_ = + std::make_unique<LoginShelfWidget>(/*shelf=*/this, shelf_container); // Must occur after |shelf_widget_| is constructed because the system tray // constructors call back into Shelf::shelf_widget().
diff --git a/ash/shelf/shelf_focus_cycler.cc b/ash/shelf/shelf_focus_cycler.cc index e5d935e..8b85179 100644 --- a/ash/shelf/shelf_focus_cycler.cc +++ b/ash/shelf/shelf_focus_cycler.cc
@@ -103,18 +103,9 @@ void ShelfFocusCycler::FocusShelf(bool last_element) { if (shelf_->shelf_widget()->GetLoginShelfView()->GetVisible()) { - // TODO(https://crbug.com/1343114): refactor the code below after the login - // shelf widget is ready. - - if (features::IsUseLoginShelfWidgetEnabled()) { - LoginShelfWidget* login_shelf_widget = shelf_->login_shelf_widget(); - login_shelf_widget->SetDefaultLastFocusableChild(last_element); - Shell::Get()->focus_cycler()->FocusWidget(login_shelf_widget); - } else { - ShelfWidget* shelf_widget = shelf_->shelf_widget(); - shelf_widget->set_default_last_focusable_child(last_element); - Shell::Get()->focus_cycler()->FocusWidget(shelf_widget); - } + LoginShelfWidget* login_shelf_widget = shelf_->login_shelf_widget(); + login_shelf_widget->SetDefaultLastFocusableChild(last_element); + Shell::Get()->focus_cycler()->FocusWidget(login_shelf_widget); } else { HotseatWidget* hotseat_widget = shelf_->hotseat_widget(); hotseat_widget->scrollable_shelf_view()->set_default_last_focusable_child(
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 33147e7b..cfbd2df 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -1447,10 +1447,7 @@ } void ShelfLayoutManager::OnLocaleChanged() { - if (features::IsUseLoginShelfWidgetEnabled()) - shelf_->login_shelf_widget()->HandleLocaleChange(); - else - shelf_->shelf_widget()->HandleLocaleChange(); + shelf_->login_shelf_widget()->HandleLocaleChange(); shelf_->status_area_widget()->HandleLocaleChange(); shelf_->navigation_widget()->HandleLocaleChange(); if (features::IsDeskButtonEnabled()) { @@ -1881,10 +1878,7 @@ AnimateOpacity(GetLayer(shelf_->status_area_widget()), target_opacity_, dim_animation_duration, dim_animation_tween); - if (features::IsUseLoginShelfWidgetEnabled()) - shelf_->login_shelf_widget()->SetLoginShelfButtonOpacity(target_opacity_); - else - shelf_widget_->SetLoginShelfButtonOpacity(target_opacity_); + shelf_->login_shelf_widget()->SetLoginShelfButtonOpacity(target_opacity_); return true; } @@ -1919,9 +1913,7 @@ if (features::IsDeskButtonEnabled()) { shelf_widget_->desk_button_widget()->UpdateLayout(animate); } - if (features::IsUseLoginShelfWidgetEnabled()) { - shelf_->login_shelf_widget()->UpdateLayout(animate); - } + shelf_->login_shelf_widget()->UpdateLayout(animate); phase_ = ShelfLayoutPhase::kAtRest; } @@ -1965,8 +1957,7 @@ shelf_->hotseat_widget()->CalculateTargetBounds(); } - if (features::IsUseLoginShelfWidgetEnabled()) - shelf_->login_shelf_widget()->CalculateTargetBounds(); + shelf_->login_shelf_widget()->CalculateTargetBounds(); target_opacity_ = ComputeTargetOpacity(state); @@ -2407,13 +2398,10 @@ GetDragHandleNudgeWindow(shelf_widget_); // Calculate whether `window` is contained by the login shelf widget. - bool window_in_login_shelf_widget = false; - if (features::IsUseLoginShelfWidgetEnabled()) { - const aura::Window* login_shelf_window = - shelf_->login_shelf_widget()->GetNativeWindow(); - window_in_login_shelf_widget = - (login_shelf_window && login_shelf_window->Contains(window)); - } + const aura::Window* login_shelf_window = + shelf_->login_shelf_widget()->GetNativeWindow(); + bool window_in_login_shelf_widget = + (login_shelf_window && login_shelf_window->Contains(window)); // Calculate whether `window` is contained by the desk button widget. bool window_in_desk_button_widget = false;
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc index 19972fc..826a7bd 100644 --- a/ash/shelf/shelf_widget.cc +++ b/ash/shelf/shelf_widget.cc
@@ -69,23 +69,6 @@ constexpr int kShelfMaxOvershootHeight = 60; constexpr int kDragHandleCornerRadius = 2; -// Return the first or last focusable child of |root|. -views::View* FindFirstOrLastFocusableChild(views::View* root, - bool find_last_child) { - views::FocusSearch search(root, find_last_child /*cycle*/, - false /*accessibility_mode*/); - views::FocusTraversable* dummy_focus_traversable; - views::View* dummy_focus_traversable_view; - return search.FindNextFocusableView( - root, - find_last_child ? views::FocusSearch::SearchDirection::kBackwards - : views::FocusSearch::SearchDirection::kForwards, - views::FocusSearch::TraversalDirection::kDown, - views::FocusSearch::StartingViewPolicy::kSkipStartingView, - views::FocusSearch::AnchoredDialogPolicy::kCanGoIntoAnchoredDialog, - &dummy_focus_traversable, &dummy_focus_traversable_view); -} - // Sets the shelf opacity to 0 when the shelf is done hiding to avoid getting // rid of blur. class HideAnimationObserver : public ui::ImplicitAnimationObserver { @@ -145,10 +128,6 @@ layer()->SchedulePaint(gfx::Rect(layer()->size())); } - void SetLoginShelfFromShelfWidget(LoginShelfView* view) { - login_shelf_from_shelf_widget_ = view; - } - SkColor background_color() const { return background_color_; } private: @@ -166,9 +145,7 @@ // Don't draw highlight border in login screen. LoginShelfView* login_shelf_view = - features::IsUseLoginShelfWidgetEnabled() - ? shelf_->login_shelf_widget()->login_shelf_view() - : login_shelf_from_shelf_widget_.get(); + shelf_->login_shelf_widget()->login_shelf_view(); if (login_shelf_view && login_shelf_view->GetVisible()) return; @@ -262,12 +239,6 @@ const raw_ptr<Shelf> shelf_; const raw_ptr<views::View> owner_view_; - // The pointer to the login shelf view that resides in the shelf widget. Set - // only when the login shelf widget is not in use. - // TODO(https://crbug.com/1343114): remove this data member and its related - // code after the login shelf widget is ready. - raw_ptr<LoginShelfView> login_shelf_from_shelf_widget_ = nullptr; - SkColor background_color_; float corner_radius_ = 0.0f; views::HighlightBorder::Type highlight_border_type_ = @@ -301,21 +272,6 @@ void SetParentLayer(ui::Layer* layer); - // Adds the login shelf view as a child of this view. - // Returns a pointer to the login shelf view passed in as an argument. - LoginShelfView* AddLoginShelfView( - std::unique_ptr<LoginShelfView> login_shelf_view) { - DCHECK(!features::IsUseLoginShelfWidgetEnabled()); - - login_shelf_view_ = AddChildView(std::move(login_shelf_view)); - opaque_background_.SetLoginShelfFromShelfWidget(login_shelf_view_); - return login_shelf_view_; - } - - void set_default_last_focusable_child(bool default_last_focusable_child) { - default_last_focusable_child_ = default_last_focusable_child; - } - // Immediately hides the layer used to draw the shelf background. void HideOpaqueBackground(); @@ -341,7 +297,6 @@ void OnBoundsChanged(const gfx::Rect& old_bounds) override; // views::AccessiblePaneView: - views::View* GetDefaultFocusableChild() override; void Layout(PassKey) override; // ShelfBackgroundAnimatorObserver: @@ -375,13 +330,6 @@ const raw_ptr<ShelfWidget> shelf_widget_; raw_ptr<FocusCycler> focus_cycler_ = nullptr; - // Pointer to the login shelf view - visible only when the session is - // inactive. The view is owned by this view's hierarchy. - // Set only when the login shelf widget is not in use. - // TODO(https://crbug.com/1343114): remove this data member when the login - // shelf widget is in use. - raw_ptr<LoginShelfView> login_shelf_view_ = nullptr; - // A background layer that may be visible depending on a // ShelfBackgroundAnimator. ShelfBackgroundLayerDelegate opaque_background_; @@ -396,9 +344,6 @@ // Owned by the view hierarchy. raw_ptr<DragHandle> drag_handle_ = nullptr; - // When true, the default focus of the shelf is the last focusable child. - bool default_last_focusable_child_ = false; - // Cache the state of the background blur so that it can be updated only // when necessary. bool background_is_currently_blurred_ = false; @@ -476,14 +421,7 @@ } bool ShelfWidget::DelegateView::CanActivate() const { - if (features::IsUseLoginShelfWidgetEnabled()) - return false; - - // This widget only contains anything interesting to activate in login/lock - // screen mode. Only allow activation from the focus cycler, not from mouse - // events, etc. - return login_shelf_view_->GetVisible() && focus_cycler_ && - focus_cycler_->widget_activating() == GetWidget(); + return false; } void ShelfWidget::DelegateView::ReorderChildLayers(ui::Layer* parent_layer) { @@ -612,22 +550,7 @@ shelf_widget_->status_area_widget()->UpdateCollapseState(); } -views::View* ShelfWidget::DelegateView::GetDefaultFocusableChild() { - DCHECK(!features::IsUseLoginShelfWidgetEnabled()); - - if (login_shelf_view_->GetVisible()) { - return FindFirstOrLastFocusableChild(login_shelf_view_, - default_last_focusable_child_); - } - // If the login shelf view is not visible, there is nothing else to focus - // in this view. - return nullptr; -} - void ShelfWidget::DelegateView::Layout(PassKey) { - if (!features::IsUseLoginShelfWidgetEnabled()) - login_shelf_view_->SetBoundsRect(GetLocalBounds()); - // Center drag handle within the expected in-app shelf bounds - it's safe to // assume bottom shelf, given that the drag handle is only shown within the // bottom shelf (either in tablet mode, or on login/lock screen) @@ -675,30 +598,6 @@ return opaque_background_.background_color(); } -bool ShelfWidget::GetHitTestRects(aura::Window* target, - gfx::Rect* hit_test_rect_mouse, - gfx::Rect* hit_test_rect_touch) { - // TODO(https://crbug.com/1343114): refactor the code below after the login - // shelf widget is ready. - DCHECK(!features::IsUseLoginShelfWidgetEnabled()); - - // This should only get called when the login shelf is visible, i.e. not - // during an active session. In an active session, hit test rects should be - // calculated higher up in the class hierarchy by |EasyResizeWindowTargeter|. - // When in OOBE or locked/login screen, let events pass through empty parts of - // the shelf. - DCHECK(login_shelf_view_->GetVisible()); - gfx::Rect login_view_button_bounds = - login_shelf_view_->ConvertRectToWidget(login_shelf_view_->GetMirroredRect( - login_shelf_view_->get_button_union_bounds())); - aura::Window* source = login_shelf_view_->GetWidget()->GetNativeWindow(); - aura::Window::ConvertRectToTarget(source, target->parent(), - &login_view_button_bounds); - *hit_test_rect_mouse = login_view_button_bounds; - *hit_test_rect_touch = login_view_button_bounds; - return true; -} - base::ScopedClosureRunner ShelfWidget::ForceShowHotseatInTabletMode() { ++force_show_hotseat_count_; @@ -738,14 +637,6 @@ delegate_view_->drag_handle()->HideDragHandleNudge(context, /*animate=*/true); } -void ShelfWidget::SetLoginShelfButtonOpacity(float target_opacity) { - // TODO(https://crbug.com/1343114): remove this function after the login shelf - // widget is ready. - DCHECK(!features::IsUseLoginShelfWidgetEnabled()); - if (login_shelf_view_->GetVisible()) - login_shelf_view_->SetButtonOpacity(target_opacity); -} - ShelfWidget::ShelfWidget(Shelf* shelf) : shelf_(shelf), background_animator_(shelf_, Shell::Get()->wallpaper_controller()), @@ -765,15 +656,6 @@ void ShelfWidget::Initialize(aura::Window* shelf_container) { DCHECK(shelf_container); - // TODO(https://crbug.com/1343114): remove it after the login shelf view is - // moved to its own widget. - if (!features::IsUseLoginShelfWidgetEnabled()) { - login_shelf_view_ = - delegate_view_->AddLoginShelfView(std::make_unique<LoginShelfView>( - RootWindowController::ForWindow(shelf_container) - ->lock_screen_action_background_controller())); - } - views::Widget::InitParams params( views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.name = "ShelfWidget"; @@ -893,33 +775,12 @@ return hotseat_widget()->GetShelfView(); } -void ShelfWidget::set_default_last_focusable_child( - bool default_last_focusable_child) { - delegate_view_->set_default_last_focusable_child( - default_last_focusable_child); -} - LoginShelfView* ShelfWidget::GetLoginShelfView() { - if (features::IsUseLoginShelfWidgetEnabled()) - return shelf_->login_shelf_widget()->login_shelf_view(); - - return login_shelf_view_; + return shelf_->login_shelf_widget()->login_shelf_view(); } bool ShelfWidget::OnNativeWidgetActivationChanged(bool active) { - // TODO(https://crbug.com/1343114): remove this function after the login shelf - // widget is ready. - if (features::IsUseLoginShelfWidgetEnabled()) - return false; - - if (!Widget::OnNativeWidgetActivationChanged(active)) - return false; - if (active) { - // This widget should not get activated in an active session. - DCHECK(login_shelf_view_->GetVisible()); - delegate_view_->SetPaneFocusAndFocusDefault(); - } - return true; + return false; } void ShelfWidget::WillDeleteShelfLayoutManager() { @@ -1071,13 +932,6 @@ } } -void ShelfWidget::HandleLocaleChange() { - // TODO(https://crbug.com/1343114): remove this function when the login shelf - // widget is ready. - DCHECK(!features::IsUseLoginShelfWidgetEnabled()); - login_shelf_view_->HandleLocaleChange(); -} - gfx::Rect ShelfWidget::GetTargetBounds() const { return target_bounds_; } @@ -1106,11 +960,6 @@ if (show_hotseat && IsActive()) wm::DeactivateWindow(shelf_window); - // TODO(https://crbug.com/1343114): remove it when the login shelf widget is - // used as default. - if (!features::IsUseLoginShelfWidgetEnabled()) - GetLoginShelfView()->SetVisible(!show_hotseat); - ShowIfHidden(); // The shelf widget can get activated when login shelf view is shown, which @@ -1131,20 +980,10 @@ // Update drag handle's color on session state changes since the color mode // might change on session state changes. delegate_view_->drag_handle()->UpdateColor(); - - // TODO(https://crbug.com/1343114): remove it when the login shelf widget is - // ready. - if (!features::IsUseLoginShelfWidgetEnabled()) - login_shelf_view_->UpdateAfterSessionChange(); } void ShelfWidget::OnUserSessionAdded(const AccountId& account_id) { shelf_layout_manager_->SetDimmed(false); - - // TODO(https://crbug.com/1343114): remove it when the login shelf widget is - // ready. - if (!features::IsUseLoginShelfWidgetEnabled()) - login_shelf_view_->UpdateAfterSessionChange(); } SkColor ShelfWidget::GetShelfBackgroundColor() const {
diff --git a/ash/shelf/shelf_widget.h b/ash/shelf/shelf_widget.h index e300a32..534efcb 100644 --- a/ash/shelf/shelf_widget.h +++ b/ash/shelf/shelf_widget.h
@@ -102,8 +102,6 @@ // is moved to its own widget. LoginShelfView* GetLoginShelfView(); - void set_default_last_focusable_child(bool default_last_focusable_child); - // views::Widget: void OnMouseEvent(ui::MouseEvent* event) override; void OnGestureEvent(ui::GestureEvent* event) override; @@ -116,9 +114,6 @@ void UpdateLayout(bool animate) override; void UpdateTargetBoundsForGesture(int shelf_position) override; - // Called when shelf layout manager detects a locale change. - void HandleLocaleChange(); - // TODO(manucornet): Remove this method when all this widget's layout // logic is part of this class. void set_target_bounds(gfx::Rect target_bounds) { @@ -139,9 +134,6 @@ void OnUserSessionAdded(const AccountId& account_id) override; SkColor GetShelfBackgroundColor() const; - bool GetHitTestRects(aura::Window* target, - gfx::Rect* hit_test_rect_mouse, - gfx::Rect* hit_test_rect_touch); // Force to show hotseat in tablet mode. When the returned closure runner is // called or goes out of scope, it removes the caller as an instance to force
diff --git a/ash/shelf/shelf_window_targeter.cc b/ash/shelf/shelf_window_targeter.cc index c37e284..d465ead 100644 --- a/ash/shelf/shelf_window_targeter.cc +++ b/ash/shelf/shelf_window_targeter.cc
@@ -57,25 +57,8 @@ aura::Window* target, gfx::Rect* hit_test_rect_mouse, gfx::Rect* hit_test_rect_touch) const { - // We only want to special case a very specific situation where we are not - // currently in an active session (or unknown session state) and change only - // the behavior of the login shelf. On secondary displays, the login shelf - // will not be visible. - // TODO(https://crbug.com/1343114): remove this code block after the login - // shelf widget is in use. bool target_is_shelf_widget = target == shelf_->shelf_widget()->GetNativeWindow(); - if (target_is_shelf_widget && - Shell::Get()->session_controller()->GetSessionState() != - session_manager::SessionState::ACTIVE && - Shell::Get()->session_controller()->GetSessionState() != - session_manager::SessionState::UNKNOWN && - !features::IsUseLoginShelfWidgetEnabled()) { - // When this is the case, let events pass through the "empty" part of - // the shelf. - return shelf_->shelf_widget()->GetHitTestRects(target, hit_test_rect_mouse, - hit_test_rect_touch); - } *hit_test_rect_mouse = *hit_test_rect_touch = target->bounds(); if (ShouldUseExtendedBounds(target)) {
diff --git a/ash/strings/ash_strings_ar.xtb b/ash/strings/ash_strings_ar.xtb index 9a476ba..6db5cd0 100644 --- a/ash/strings/ash_strings_ar.xtb +++ b/ash/strings/ash_strings_ar.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">مساء الخير <ph name="GIVEN_NAME" />،</translation> <translation id="1088231044944504242">يمكنك البحث في <ph name="CATEGORY" /> والملفات والتطبيقات وغير ذلك. ويمكنك استخدام مفاتيح الأسهم للتنقّل بين التطبيقات.</translation> <translation id="1093645050124056515">ctrl + alt + السهم المتّجه للأسفل</translation> +<translation id="1094756674036064790">هل تريد إيقاف البلوتوث؟</translation> <translation id="109942774857561566">أشعر بالملل</translation> <translation id="1104084341931202936">عرض إعدادات تسهيل الاستخدام</translation> <translation id="1104621072296271835">تعمل أجهزتك بشكل أفضل وهي مرتبطة معًا</translation> @@ -661,6 +662,7 @@ <translation id="3660860940251915011">إيقاف أو تفعيل وضع الظهور العالي لميزة "<ph name="FEATURE_NAME" />"</translation> <translation id="366222428570480733">المستخدِم المُدار <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">مرِّر سريعًا لإخفاء النافذة العائمة.</translation> +<translation id="3673898235958558034">عند إيقاف البلوتوث، سيتم إلغاء ربط "<ph name="DEVICE_NAME_1" />" و"<ph name="DEVICE_NAME_2" />" بجهاز Chromebook.</translation> <translation id="367531336287639526">اختيار الرمز الأول على يمين شريط العناوين</translation> <translation id="3677931086890821290">يتيح هذا الإجراء لجميع التطبيقات والمواقع الإلكترونية التي لديها إذن تحديد الموقع الجغرافي ونظام التشغيل ChromeOS استخدام الموقع الجغرافي لشبكة Wi-Fi وشبكات الجوّال.</translation> <translation id="3679827876008292680">الانتقال إلى علامة التبويب الأخيرة في النافذة</translation> @@ -917,6 +919,7 @@ <translation id="4666911709726371538">المزيد من التطبيقات</translation> <translation id="4667099493359681081">جارٍ تنزيل <ph name="FILENAME" /></translation> <translation id="4672539464599646374">وضع "توفير شحن البطارية" مُفعَّل.</translation> +<translation id="4673427585974421255">عدم الإيقاف</translation> <translation id="468293128311738995">تطبيقات من هاتفك</translation> <translation id="4690510401873698237">الرف في الجزء السفلي</translation> <translation id="4696813013609194136">فتح قفل الجهاز باستخدام رمز الوالدين</translation> @@ -1217,6 +1220,7 @@ <translation id="5802516411616338943">فتح "الإعدادات السريعة"</translation> <translation id="5804651031882187592">إيقاف الإعداد "قفل شريحة SIM"</translation> <translation id="5805809050170488595">انقر لتفعيل <ph name="NETWORK_NAME" />.</translation> +<translation id="5816222150329690597">عند إيقاف البلوتوث، سيتم إلغاء ربط "<ph name="DEVICE_NAME_1" />" و"<ph name="DEVICE_NAME_2" />" و<ph name="DEVICE_COUNT" /> جهاز آخر بجهاز Chromebook.</translation> <translation id="5823239091726045201">"مهام Google" على الويب</translation> <translation id="5825969630400862129">إعدادات الأجهزة المتّصلة</translation> <translation id="5837036133683224804">إيقاف <ph name="ROUTE_TITLE" /> في <ph name="RECEIVER_NAME" /></translation> @@ -1397,6 +1401,7 @@ <translation id="6539852571005954999">جارٍ فحص الملف <ph name="FILENAME" /> لتنزيله</translation> <translation id="6542521951477560771">البث على <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">البحث عن الصور حسب المحتوى ومعاينات الصور</translation> +<translation id="6547795021703527064">عند إيقاف البلوتوث، سيتم إلغاء ربط "<ph name="DEVICE_NAME" />" بجهاز Chromebook.</translation> <translation id="6555373427270923730">اكتب عنوان الويب في شريط العناوين، ثم اضغط على <ph name="MODIFIER" /><ph name="KEY" />.</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> مثبَّت حديثًا</translation>
diff --git a/ash/strings/ash_strings_as.xtb b/ash/strings/ash_strings_as.xtb index 29bea1af..95d9c49 100644 --- a/ash/strings/ash_strings_as.xtb +++ b/ash/strings/ash_strings_as.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">শুভ অপৰাহ্ন <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">আপোনাৰ <ph name="CATEGORY" />, ফাইল, এপ্ আৰু আন বহুতো সন্ধান কৰক। আপোনাৰ এপ্সমূহ নেভিগে’ট কৰিবলৈ এৰ’ কীসমূহ ব্যৱহাৰ কৰক।</translation> <translation id="1093645050124056515">ctrl + alt + তলমুৱা কাঁড়</translation> +<translation id="1094756674036064790">ব্লুটুথ অফ কৰিবনে?</translation> <translation id="109942774857561566">মই বিৰক্ত হৈছোঁ</translation> <translation id="1104084341931202936">সাধ্য সুবিধাৰ ছেটিংসমূহ দেখুৱাওক</translation> <translation id="1104621072296271835">আপোনাৰ ডিভাইচসমূহে একেলগে আৰু ভালকৈ কাম কৰে</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" />ৰ উচ্চ দৃশ্যমানতা ট’গল কৰক</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" />এ পৰিচালনা কৰা ব্যৱহাৰকাৰী</translation> <translation id="3666266999138159418">আপোনাৰ উপঙি থকা ৱিণ্ড’ লুকুৱাবলৈ ছোৱাইপ কৰক</translation> +<translation id="3673898235958558034">আপুনি ব্লুটুথ অফ কৰিলে আপোনাৰ Chromebookৰ পৰা "<ph name="DEVICE_NAME_1" />" আৰু "<ph name="DEVICE_NAME_2" />"ৰ সংযোগ বিচ্ছিন্ন হ’ব।</translation> <translation id="367531336287639526">ঠিকনাৰ বাৰৰ বাওঁফালে থকা প্ৰথম চিহ্নটো বাছনি কৰক</translation> <translation id="3677931086890821290">এইটোৱে অৱস্থানৰ অনুমতি থকা আটাইবোৰ এপ্ আৰু ৱেবছাইট আৰু ChromeOSক ৱাই-ফাই আৰু ম’বাইল নেটৱৰ্কৰ অৱস্থান ব্যৱহাৰ কৰাৰ অনুমতি দিয়ে।</translation> <translation id="3679827876008292680">ৱিণ্ড’ত থকা শেষৰ টেবটোলৈ যাওক</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">অধিক এপ্</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> ডাউনল’ড কৰি থকা হৈছে</translation> <translation id="4672539464599646374">বেটাৰী সঞ্চয়কাৰী অন কৰা হৈছে</translation> +<translation id="4673427585974421255">অন কৰি ৰাখক</translation> <translation id="468293128311738995">আপোনাৰ ফ’ন থকা এপ্</translation> <translation id="4690510401873698237">শ্বেল্ফ একেবাৰে তলিত আছে</translation> <translation id="4696813013609194136">অভিভাৱকৰ এক্সেছ ক'ডৰ সহায়ত ডিভাইচ আনলক কৰক</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">ক্ষিপ্ৰ ছেটিং খোলক</translation> <translation id="5804651031882187592">"ছিম লক কৰক" ছেটিংটো অফ কৰক</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> সক্ৰিয় কৰিবলৈ টিপক</translation> +<translation id="5816222150329690597">আপুনি ব্লুটুথ অফ কৰিলে আপোনাৰ Chromebookৰ পৰা "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" আৰু অন্য <ph name="DEVICE_COUNT" /> টা ডিভাইচৰ সংযোগ বিচ্ছিন্ন হ’ব।</translation> <translation id="5823239091726045201">ৱেবত Google কার্য</translation> <translation id="5825969630400862129">সংযুক্ত হৈ থকা ডিভাইচৰ ছেটিংসমূহ</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />ত <ph name="ROUTE_TITLE" /> বন্ধ কৰক</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999"><ph name="FILENAME" /> স্কেনিং ডাউনল’ড কৰক</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> লৈ কাষ্ট কৰি থকা হৈছে</translation> <translation id="6546062506073634094">সমল আৰু প্ৰতিচ্ছবিৰ পূৰ্বদৰ্শন অনুসৰি প্ৰতিচ্ছবিৰ সন্ধান</translation> +<translation id="6547795021703527064">আপুনি ব্লুটুথ অফ কৰিলে আপোনাৰ Chromebookৰ পৰা "<ph name="DEVICE_NAME" />"ৰ সংযোগ বিচ্ছিন্ন হ’ব।</translation> <translation id="6555373427270923730">ঠিকনাৰ বাৰত এটা ৱেব ঠিকনা এটা টাইপ কৰক, তাৰ পাছত <ph name="MODIFIER" /><ph name="KEY" /> টিপক</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> নতুনকৈ ইনষ্টল কৰা</translation>
diff --git a/ash/strings/ash_strings_az.xtb b/ash/strings/ash_strings_az.xtb index f535f0f..983d252 100644 --- a/ash/strings/ash_strings_az.xtb +++ b/ash/strings/ash_strings_az.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Günortanız xeyir, <ph name="GIVEN_NAME" /></translation> <translation id="1088231044944504242"><ph name="CATEGORY" />, fayllar, tətbiqlər və s. axtarın. Tətbiqləri axtarmaq üçün ox düymələrindən istifadə edin.</translation> <translation id="1093645050124056515">ctrl + alt + aşağı ox</translation> +<translation id="1094756674036064790">Bluetooth deaktiv edilsin?</translation> <translation id="109942774857561566">Darıxıram</translation> <translation id="1104084341931202936">Əlçatımlılıq ayarlarını göstərin</translation> <translation id="1104621072296271835">Cihazlarınız birlikdə daha yaxşı işləyir</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> üçün yüksək görünmə dərəcəsini aktiv/deaktiv edin</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> İdarə edilən istifadəçi</translation> <translation id="3666266999138159418">Üzən pəncərəni gizlətmək üçün sürüşdürün</translation> +<translation id="3673898235958558034">Bluetooth-u deaktiv edəndə "<ph name="DEVICE_NAME_1" />" və "<ph name="DEVICE_NAME_2" />" Chromebook-dan ayrılacaq.</translation> <translation id="367531336287639526">Ünvan panelinin solundakı birinci ikonanı seçin</translation> <translation id="3677931086890821290">Məkan icazəsi olan tətbiq və veb-saytlara, habelə ChromeOS-a Wi-Fi və mobil şəbəkə məkanından istifadə icazəsi verilir.</translation> <translation id="3679827876008292680">Pəncərədə sonuncu taba keçin</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Daha çox tətbiq</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> endirilir</translation> <translation id="4672539464599646374">Enerjiyə Qənaət aktivdir</translation> +<translation id="4673427585974421255">Aktiv saxlayın</translation> <translation id="468293128311738995">Telefonunuzdan tətbiqlər</translation> <translation id="4690510401873698237">Rəf aşağıdadır</translation> <translation id="4696813013609194136">Cihazı valideyn kodu ilə kiliddən çıxarın</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Cəld ayarları açın</translation> <translation id="5804651031882187592">"SIM'i kilidləyin" ayarını deaktiv edin</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> şəbəkəsini aktiv etmək üçün toxunun</translation> +<translation id="5816222150329690597">Bluetooth-u deaktiv edəndə "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" və digər <ph name="DEVICE_COUNT" /> cihaz Chromebook-dan ayrılacaq.</translation> <translation id="5823239091726045201">Vebdə Google tapşırıqları</translation> <translation id="5825969630400862129">Qoşulmuş cihazların ayarları</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> pəncərəsində <ph name="ROUTE_TITLE" /> dayandırma düyməsi</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999"><ph name="FILENAME" /> endirməsi skanlanır</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> ilə paylaşılır</translation> <translation id="6546062506073634094">Kontent və şəkil önizləməsi əsasında şəkil axtarışı</translation> +<translation id="6547795021703527064">Bluetooth-u deaktiv edəndə "<ph name="DEVICE_NAME" />" Chromebook-dan ayrılacaq.</translation> <translation id="6555373427270923730">Ünvan panelində veb-ünvanı yazıb, <ph name="MODIFIER" /><ph name="KEY" /> düyməsini basın</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Yeni quraşdırma</translation>
diff --git a/ash/strings/ash_strings_be.xtb b/ash/strings/ash_strings_be.xtb index 7bc6e75..c8047e14 100644 --- a/ash/strings/ash_strings_be.xtb +++ b/ash/strings/ash_strings_be.xtb
@@ -1341,7 +1341,7 @@ <translation id="6298183524022479114">Наладзьце гэту прыладу ў праграме</translation> <translation id="6309219492973062892">Націснуць на значкі 1-8 на панэлі доступу</translation> <translation id="6315170314923504164">Галасавы ўвод</translation> -<translation id="6319058840130157106">Пераключацца назад паміж ніжнім правым вуглом, Панэллю запуску, адрасным радком, панэллю закладак, адкрытым вэб-сайтам і спампоўкамі</translation> +<translation id="6319058840130157106">Пераход у адваротным напрамку паміж ніжнім правым вуглом, Панэллю запуску, адрасным радком, панэллю закладак, адкрытым вэб-сайтам і спампоўкамі</translation> <translation id="6324916366299863871">Рэдагаваць ярлык</translation> <translation id="6330012934079202188">Паказаны вокны ўсіх працоўных сталоў. Каб пераключыцца на рэжым паказу вокнаў бягучага працоўнага стала, націсніце стрэлку ўверх</translation> <translation id="6338485349199627913"><ph name="DISPLAY_NAME" /> – сеанс, якім кіруе <ph name="MANAGER" /></translation> @@ -1927,7 +1927,7 @@ <translation id="878215960996152260"><ph name="APP_NAME" />, усталяваная праграма, заблакіравана</translation> <translation id="8785070478575117577">Падключыцца да сеткі <ph name="NETWORK_NAME" /></translation> <translation id="8788027118671217603"><ph name="STATE_TEXT" />. <ph name="ENTERPRISE_TEXT" /></translation> -<translation id="8790632710469941716">Пераключацца ўперад паміж ніжнім правым вуглом, Панэллю запуску, адрасным радком, панэллю закладак, адкрытым вэб-сайтам і спампоўкамі</translation> +<translation id="8790632710469941716">Пераход у прамым напрамку паміж ніжнім правым вуглом, Панэллю запуску, адрасным радком, панэллю закладак, адкрытым вэб-сайтам і спампоўкамі</translation> <translation id="8792626944327216835">мікрафон</translation> <translation id="8801802992492329306">5G</translation> <translation id="8806053966018712535">Папка "<ph name="FOLDER_NAME" />"</translation>
diff --git a/ash/strings/ash_strings_bs.xtb b/ash/strings/ash_strings_bs.xtb index 8472c01..be55cd7a 100644 --- a/ash/strings/ash_strings_bs.xtb +++ b/ash/strings/ash_strings_bs.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Dobar dan <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Pretraživanje kategorije <ph name="CATEGORY" />, fajlova, aplikacija i drugog. Korištenje tipki strelicama za kretanje kroz aplikacije.</translation> <translation id="1093645050124056515">Ctrl i Alt i strelica nadolje</translation> +<translation id="1094756674036064790">Isključiti Bluetooth?</translation> <translation id="109942774857561566">Dosadno mi je</translation> <translation id="1104084341931202936">Prikaži postavke pristupačnosti</translation> <translation id="1104621072296271835">Uređaji još bolje rade zajedno</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Uključite/isključite veliku vidljivost u funkciji <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733">Korisnik kojim upravlja <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Prevucite da sakrijete plutajući prozor</translation> +<translation id="3673898235958558034">Kada isključite Bluetooth, prekinut će se povezanost uređaja "<ph name="DEVICE_NAME_1" />" i "<ph name="DEVICE_NAME_2" />" s Chromebookom.</translation> <translation id="367531336287639526">Odaberite prvu ikonu s lijeve strane trake za adresu</translation> <translation id="3677931086890821290">Ovo omogućava svim aplikacijama i web lokacijama s odobrenjem za lokaciju te ChromeOS-u da koriste lokacije WiFi-ja i mobilnih mreža.</translation> <translation id="3679827876008292680">Odlazak na posljednju karticu u prozoru</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Više aplikacija</translation> <translation id="4667099493359681081">Preuzimanje fajla <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Ušteda baterije je uključena</translation> +<translation id="4673427585974421255">Ostavi uključeno</translation> <translation id="468293128311738995">Aplikacije s vašeg telefona</translation> <translation id="4690510401873698237">Polica na dnu</translation> <translation id="4696813013609194136">Otključajte uređaj pomoću koda roditelja</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Otvori Brze postavke</translation> <translation id="5804651031882187592">Isključite postavku "Zaključaj SIM"</translation> <translation id="5805809050170488595">Kliknite da aktivirate mrežu <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Kada isključite Bluetooth, prekinut će se povezanost uređaja "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" i još <ph name="DEVICE_COUNT" /> uređaja s Chromebookom.</translation> <translation id="5823239091726045201">Google Zadaci na webu</translation> <translation id="5825969630400862129">Postavke povezanih uređaja</translation> <translation id="5837036133683224804">Zaustavi <ph name="ROUTE_TITLE" /> na primaocu <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Preuzimanje fajla <ph name="FILENAME" /> koji se skenira</translation> <translation id="6542521951477560771">Emitiranje na uređaj <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Pretraživanje pomoću slika uz preglede sadržaja i slika</translation> +<translation id="6547795021703527064">Kada isključite Bluetooth, prekinut će se povezanost uređaja "<ph name="DEVICE_NAME" />" s Chromebookom.</translation> <translation id="6555373427270923730">Napišite adresu web lokacije u traku za adresu, a zatim pritisnite <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Nova instalacija</translation>
diff --git a/ash/strings/ash_strings_ca.xtb b/ash/strings/ash_strings_ca.xtb index e74e838..fb66912 100644 --- a/ash/strings/ash_strings_ca.xtb +++ b/ash/strings/ash_strings_ca.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Bona tarda, <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Cerca <ph name="CATEGORY" />, fitxers, aplicacions i més. Fes servir les tecles de fletxa per navegar per les aplicacions.</translation> <translation id="1093645050124056515">Ctrl+Alt+fletxa avall</translation> +<translation id="1094756674036064790">Vols desactivar el Bluetooth?</translation> <translation id="109942774857561566">M'avorreixo</translation> <translation id="1104084341931202936">Mostra la configuració d'accessibilitat</translation> <translation id="1104621072296271835">Els teus dispositius funcionen encara millor junts</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Commuta la visibilitat alta de <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733">Usuari gestionat (<ph name="USER_EMAIL_ADDRESS" />)</translation> <translation id="3666266999138159418">Llisca per amagar la finestra flotant</translation> +<translation id="3673898235958558034">Si desactives el Bluetooth, <ph name="DEVICE_NAME_1" /> i <ph name="DEVICE_NAME_2" /> es desconnectaran del Chromebook.</translation> <translation id="367531336287639526">Selecciona la primera icona a l'esquerra de la barra d'adreces</translation> <translation id="3677931086890821290">Això permet que totes les aplicacions i tots els llocs web que tinguin el permís d'ubicació i ChromeOS utilitzin la ubicació de la Wi-Fi i de les xarxes mòbils.</translation> <translation id="3679827876008292680">Ves a la darrera pestanya de la finestra</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Més aplicacions</translation> <translation id="4667099493359681081">S'està baixant <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Estalvi de bateria s'ha activat</translation> +<translation id="4673427585974421255">Mantén activat</translation> <translation id="468293128311738995">Aplicacions del telèfon</translation> <translation id="4690510401873698237">El prestatge és a la part inferior</translation> <translation id="4696813013609194136">Desbloqueja el dispositiu amb el codi parental</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Obre la configuració ràpida</translation> <translation id="5804651031882187592">Desactiva l'opció de configuració Bloqueja la SIM</translation> <translation id="5805809050170488595">Fes clic per activar <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Si desactives el Bluetooth, <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> i <ph name="DEVICE_COUNT" /> dispositius més es desconnectaran del Chromebook.</translation> <translation id="5823239091726045201">Google Tasks al web</translation> <translation id="5825969630400862129">Configuració dels dispositius connectats</translation> <translation id="5837036133683224804">Atura <ph name="ROUTE_TITLE" /> a <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">S'està escanejant <ph name="FILENAME" /> per baixar</translation> <translation id="6542521951477560771">S'està emetent a <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Cerca d'imatges per contingut i previsualitzacions d'imatges</translation> +<translation id="6547795021703527064">Si desactives el Bluetooth, <ph name="DEVICE_NAME" /> es desconnectarà del Chromebook.</translation> <translation id="6555373427270923730">Escriu una adreça web a la barra d'adreces i, a continuació, prem <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Instal·lació nova</translation>
diff --git a/ash/strings/ash_strings_cy.xtb b/ash/strings/ash_strings_cy.xtb index 6c79b2cc..b40ebde 100644 --- a/ash/strings/ash_strings_cy.xtb +++ b/ash/strings/ash_strings_cy.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Prynhawn Da <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Chwilio eich <ph name="CATEGORY" />, eich ffeiliau, eich apiau a rhagor. Defnyddiwch y bysellau saeth i lywio'ch apiau.</translation> <translation id="1093645050124056515">ctrl + alt + saeth i lawr</translation> +<translation id="1094756674036064790">Diffodd Bluetooth?</translation> <translation id="109942774857561566">Rydw i wedi diflasu</translation> <translation id="1104084341931202936">Dangos y gosodiadau hygyrchedd</translation> <translation id="1104621072296271835">Mae'ch dyfeisiau'n gweithio hyd yn oed yn well gyda'i gilydd</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Toglo gwelededd uchel <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Defnyddiwr a Reolir</translation> <translation id="3666266999138159418">Sweipiwch i guddio eich ffenestr arnofio</translation> +<translation id="3673898235958558034">Pan fyddwch yn diffodd Bluetooth, bydd '<ph name="DEVICE_NAME_1" />' a '<ph name="DEVICE_NAME_2" />' yn datgysylltu o'ch Chromebook.</translation> <translation id="367531336287639526">Dewis yr eicon cyntaf i'r chwith o'r bar cyfeiriad</translation> <translation id="3677931086890821290">Mae hyn yn caniatáu i bob ap a gwefan sydd â chaniatâd lleoliad a ChromeOS ddefnyddio lleoliad Wi-Fi a rhwydweithiau symudol.</translation> <translation id="3679827876008292680">Mynd i'r tab olaf yn y ffenestr</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Rhagor o apiau</translation> <translation id="4667099493359681081">Wrthi'n lawrlwytho <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Mae'r modd Arbed Batri wedi'i droi ymlaen</translation> +<translation id="4673427585974421255">Cadw ymlaen</translation> <translation id="468293128311738995">Apiau o'ch ffôn</translation> <translation id="4690510401873698237">Silff ar y gwaelod</translation> <translation id="4696813013609194136">Datgloi'r ddyfais gyda chod rhiant</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Agor Gosodiadau Cyflym</translation> <translation id="5804651031882187592">Diffodd y gosodiad "Cloi SIM"</translation> <translation id="5805809050170488595">Cliciwch i weithredu <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Pan fyddwch yn diffodd Bluetooth, bydd '<ph name="DEVICE_NAME_1" />', '<ph name="DEVICE_NAME_2" />' a '<ph name="DEVICE_COUNT" />' o ddyfeisiau eraill yn datgysylltu o'ch Chromebook.</translation> <translation id="5823239091726045201">Google Tasks ar y we</translation> <translation id="5825969630400862129">Gosodiadau dyfeisiau cysylltiedig</translation> <translation id="5837036133683224804">Stopio <ph name="ROUTE_TITLE" /> ar <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Wrthi'n sganio'r lawrlwythiad <ph name="FILENAME" /></translation> <translation id="6542521951477560771">Wrthi'n castio i <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Chwilio lluniau yn ôl cynnwys a rhagolygon lluniau</translation> +<translation id="6547795021703527064">Pan fyddwch yn diffodd Bluetooth, bydd '<ph name="DEVICE_NAME" />' yn datgysylltu o'ch Chromebook.</translation> <translation id="6555373427270923730">Teipiwch gyfeiriad gwe yn y bar cyfeiriad, yna pwyswch <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Gosodiad newydd</translation>
diff --git a/ash/strings/ash_strings_en-GB.xtb b/ash/strings/ash_strings_en-GB.xtb index 3cb23652..57652dbe 100644 --- a/ash/strings/ash_strings_en-GB.xtb +++ b/ash/strings/ash_strings_en-GB.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Good afternoon <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Search your <ph name="CATEGORY" />, files, apps and more. Use the arrow keys to navigate your apps.</translation> <translation id="1093645050124056515">ctrl + alt + down arrow</translation> +<translation id="1094756674036064790">Turn off Bluetooth?</translation> <translation id="109942774857561566">I'm bored</translation> <translation id="1104084341931202936">Show accessibility settings</translation> <translation id="1104621072296271835">Your devices work even better together</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Toggle <ph name="FEATURE_NAME" /> high visibility</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> managed user</translation> <translation id="3666266999138159418">Swipe to hide your floating window</translation> +<translation id="3673898235958558034">When you turn off Bluetooth, '<ph name="DEVICE_NAME_1" />' and '<ph name="DEVICE_NAME_2" />' will disconnect from your Chromebook.</translation> <translation id="367531336287639526">Select first icon to the left of address bar</translation> <translation id="3677931086890821290">This allows all apps and websites with the location permission and ChromeOS to use Wi-Fi and mobile networks location.</translation> <translation id="3679827876008292680">Go to last tab in window</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">More apps</translation> <translation id="4667099493359681081">Downloading <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Battery Saver turned on</translation> +<translation id="4673427585974421255">Keep on</translation> <translation id="468293128311738995">Apps from your phone</translation> <translation id="4690510401873698237">Shelf on bottom</translation> <translation id="4696813013609194136">Unlock device with parent code</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Open Quick Settings</translation> <translation id="5804651031882187592">Turn off 'Lock SIM' setting</translation> <translation id="5805809050170488595">Click to activate <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">When you turn off Bluetooth, '<ph name="DEVICE_NAME_1" />', '<ph name="DEVICE_NAME_2" />' and <ph name="DEVICE_COUNT" /> other devices will disconnect from your Chromebook.</translation> <translation id="5823239091726045201">Google tasks on web</translation> <translation id="5825969630400862129">Connected devices settings</translation> <translation id="5837036133683224804">Stop <ph name="ROUTE_TITLE" /> on <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Download scanning <ph name="FILENAME" /></translation> <translation id="6542521951477560771">Casting to <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Image search by content and image previews</translation> +<translation id="6547795021703527064">When you turn off Bluetooth, '<ph name="DEVICE_NAME" />' will disconnect from your Chromebook.</translation> <translation id="6555373427270923730">Type a web address in the address bar, then press <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> New install</translation>
diff --git a/ash/strings/ash_strings_et.xtb b/ash/strings/ash_strings_et.xtb index e2763ba..24bba16a 100644 --- a/ash/strings/ash_strings_et.xtb +++ b/ash/strings/ash_strings_et.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Tere päevast, <ph name="GIVEN_NAME" />!</translation> <translation id="1088231044944504242">Otsige <ph name="CATEGORY" />, faile, rakendusi ja muud. Kasutage rakenduste vahel navigeerimiseks nooleklahve.</translation> <translation id="1093645050124056515">ctrl + alt + allanool</translation> +<translation id="1094756674036064790">Kas lülitada Bluetooth välja?</translation> <translation id="109942774857561566">Mul on igav</translation> <translation id="1104084341931202936">Kuvab juurdepääsetavuse seaded</translation> <translation id="1104621072296271835">Teie seadmed töötavad koos veelgi paremini</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Lülitage funktsiooni <ph name="FEATURE_NAME" /> hea nähtavuse režiim sisse/välja</translation> <translation id="366222428570480733">Kontoga <ph name="USER_EMAIL_ADDRESS" /> hallatav kasutaja</translation> <translation id="3666266999138159418">Pühkige ujuva akna peitmiseks</translation> +<translation id="3673898235958558034">Kui lülitate Bluetoothi välja, katkestavad „<ph name="DEVICE_NAME_1" />” ja „<ph name="DEVICE_NAME_2" />” ühenduse teie Chromebookiga.</translation> <translation id="367531336287639526">Vali aadressiribast vasakul esimene ikoon</translation> <translation id="3677931086890821290">See võimaldab kõigil asukohale juurdepääsu loaga rakendustel ja veebisaitidel ning ChromeOS-il kasutada WiFi- ja mobiilsidevõrkude asukohta.</translation> <translation id="3679827876008292680">Aknas viimasele vahelehele liikumine</translation> @@ -916,6 +918,7 @@ <translation id="4666911709726371538">Rohkem rakendusi</translation> <translation id="4667099493359681081">Faili <ph name="FILENAME" /> allalaadimine</translation> <translation id="4672539464599646374">Akusäästja on sisse lülitatud</translation> +<translation id="4673427585974421255">Jäta sisselülitatuks</translation> <translation id="468293128311738995">Rakendused teie telefonist</translation> <translation id="4690510401873698237">Riiul asub allpool</translation> <translation id="4696813013609194136">Avage seade lapsevanema koodiga</translation> @@ -1216,6 +1219,7 @@ <translation id="5802516411616338943">Ava kiirseaded</translation> <translation id="5804651031882187592">Lülitage seade „SIM-i lukustamine“ välja</translation> <translation id="5805809050170488595">Klõpsake võrgu <ph name="NETWORK_NAME" /> aktiveerimiseks</translation> +<translation id="5816222150329690597">Kui lülitate Bluetoothi välja, katkestavad „<ph name="DEVICE_NAME_1" />”, „<ph name="DEVICE_NAME_2" />” ja veel <ph name="DEVICE_COUNT" /> seadet ühenduse teie Chromebookiga.</translation> <translation id="5823239091726045201">Google Tasks veebis</translation> <translation id="5825969630400862129">Ühendatud seadmete seaded</translation> <translation id="5837036133683224804">Katkesta <ph name="ROUTE_TITLE" /> asukohas <ph name="RECEIVER_NAME" /></translation> @@ -1396,6 +1400,7 @@ <translation id="6539852571005954999">Allalaaditava faili <ph name="FILENAME" /> skannimine</translation> <translation id="6542521951477560771">Ülekandmine seadmesse <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Pildiotsing sisu ja piltide eelvaadete järgi</translation> +<translation id="6547795021703527064">Kui lülitate Bluetoothi välja, katkestab „<ph name="DEVICE_NAME" />” ühenduse teie Chromebookiga.</translation> <translation id="6555373427270923730">Sisestage veebiaadress aadressiribale ja vajutage klahvikombinatsiooni <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Uus installimine</translation>
diff --git a/ash/strings/ash_strings_eu.xtb b/ash/strings/ash_strings_eu.xtb index 2f7313b..37b5de58 100644 --- a/ash/strings/ash_strings_eu.xtb +++ b/ash/strings/ash_strings_eu.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Arratsalde on, <ph name="GIVEN_NAME" />:</translation> <translation id="1088231044944504242">Bilatu <ph name="CATEGORY" />, fitxategiak, aplikazioak eta beste. Erabili gezi-teklak aplikazioetan nabigatzeko.</translation> <translation id="1093645050124056515">Ktrl + Alt + behera egiteko gezi-tekla</translation> +<translation id="1094756674036064790">Bluetootha desaktibatu nahi duzu?</translation> <translation id="109942774857561566">Aspertuta nago</translation> <translation id="1104084341931202936">Erakutsi erabilerraztasun-ezarpenak</translation> <translation id="1104621072296271835">Gailuek are hobeto funtzionatzen dute batera</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Aktibatu/Desaktibatu <ph name="FEATURE_NAME" /> eginbidearen ikusgaitasun handia</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" />, erabiltzaile kudeatua</translation> <translation id="3666266999138159418">Pasatu hatza leiho gainerakorra ezkutatzeko</translation> +<translation id="3673898235958558034">Bluetootha desaktibatzen duzunean, "<ph name="DEVICE_NAME_1" />" eta "<ph name="DEVICE_NAME_2" />" Chromebook-etik deskonektatuko dira.</translation> <translation id="367531336287639526">Hautatu helbide-barraren ezkerraldeko lehenengo ikonoa</translation> <translation id="3677931086890821290">Honen bidez, kokapena erabiltzeko baimena daukaten aplikazio eta webgune guztiek eta ChromeOS-ek wifiaren eta sare mugikorren araberako kokapena erabili ahal izango dute.</translation> <translation id="3679827876008292680">Joan leihoko azken fitxara</translation> @@ -916,6 +918,7 @@ <translation id="4666911709726371538">Aplikazio gehiago</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> deskargatzen</translation> <translation id="4672539464599646374">Aktibatu da Bateria-aurreztailea</translation> +<translation id="4673427585974421255">Mantendu aktibatuta</translation> <translation id="468293128311738995">Telefonoko aplikazioak</translation> <translation id="4690510401873698237">Apala behealdean dago</translation> <translation id="4696813013609194136">Desblokeatu gailua gurasoen kodearekin</translation> @@ -1216,6 +1219,7 @@ <translation id="5802516411616338943">Ireki Ezarpen bizkorrak</translation> <translation id="5804651031882187592">Desaktibatu "Blokeatu SIMa" ezarpena</translation> <translation id="5805809050170488595">Sakatu hau <ph name="NETWORK_NAME" /> aktibatzeko</translation> +<translation id="5816222150329690597">Bluetootha desaktibatzen duzunean, "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" eta beste <ph name="DEVICE_COUNT" /> gailu Chromebook-etik deskonektatuko dira.</translation> <translation id="5823239091726045201">Sareko Google Zereginak</translation> <translation id="5825969630400862129">Konektatutako gailuen ezarpenak</translation> <translation id="5837036133683224804">Utzi <ph name="ROUTE_TITLE" /> (<ph name="RECEIVER_NAME" />) hargailura igortzeari</translation> @@ -1396,6 +1400,7 @@ <translation id="6539852571005954999"><ph name="FILENAME" /> eskaneatzen deskargatu ahal izateko</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> gailura igortzen</translation> <translation id="6546062506073634094">Edukiaren araberako irudi-bilaketa eta irudien aurrebistak</translation> +<translation id="6547795021703527064">Bluetootha desaktibatzen duzunean, "<ph name="DEVICE_NAME" />" Chromebook-etik deskonektatuko da.</translation> <translation id="6555373427270923730">Idatzi web-helbide bat helbide-barran eta, gero, sakatu <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Berriki instalatu da</translation>
diff --git a/ash/strings/ash_strings_fa.xtb b/ash/strings/ash_strings_fa.xtb index 846694a3..6387cfa1 100644 --- a/ash/strings/ash_strings_fa.xtb +++ b/ash/strings/ash_strings_fa.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">بعدازظهر بهخیر <ph name="GIVEN_NAME" />،</translation> <translation id="1088231044944504242">جستجوی <ph name="CATEGORY" />، فایلها، برنامهها، و موارد بیشتر. برای پیمایش برنامهها، از کلیدهای جهتنما استفاده کنید.</translation> <translation id="1093645050124056515">مهار + دگرساز + پایینبر</translation> +<translation id="1094756674036064790">بلوتوث خاموش شود؟</translation> <translation id="109942774857561566">I’m bored (حوصلهام سر رفته)</translation> <translation id="1104084341931202936">نشان دادن تنظیمات دسترسپذیری</translation> <translation id="1104621072296271835">دستگاههایتان باهم بهمراتب بهتر کار میکنند</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">روشن/خاموش کردن سطح بالای رؤیتپذیری <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> کاربر مدیریتشده</translation> <translation id="3666266999138159418">برای پنهان کردن پنجره شناور، تند بکشید</translation> +<translation id="3673898235958558034">وقتی بلوتوث را خاموش میکنید، اتصال «<ph name="DEVICE_NAME_1" />» و «<ph name="DEVICE_NAME_2" />» از Chromebook قطع خواهد شد.</translation> <translation id="367531336287639526">انتخاب اولین نماد در سمت راست نوار نشانی</translation> <translation id="3677931086890821290">با این کار، همه برنامهها و وبسایتهای دارای اجازه مکان و ChromeOS مجاز میشوند از مکان شبکههای تلفن همراه و Wi-Fi استفاده کنند.</translation> <translation id="3679827876008292680">رفتن به آخرین برگه در پنجره</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">برنامههای بیشتر</translation> <translation id="4667099493359681081">درحال بارگیری <ph name="FILENAME" /></translation> <translation id="4672539464599646374">«بهینهسازی باتری» روشن شد</translation> +<translation id="4673427585974421255">روشن باشد</translation> <translation id="468293128311738995">برنامههای تلفن شما</translation> <translation id="4690510401873698237">قفسه در پایین است</translation> <translation id="4696813013609194136">باز کردن قفل دستگاه با کد والدین</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">باز کردن «تنظیمات فوری»</translation> <translation id="5804651031882187592">خاموش کردن تنظیم «قفل کردن سیمکارت»</translation> <translation id="5805809050170488595">برای فعالسازی <ph name="NETWORK_NAME" /> کلیک کنید</translation> +<translation id="5816222150329690597">وقتی بلوتوث را خاموش میکنید، اتصال «<ph name="DEVICE_NAME_1" />»، «<ph name="DEVICE_NAME_2" />» و <ph name="DEVICE_COUNT" /> دستگاه دیگر از Chromebook قطع خواهد شد.</translation> <translation id="5823239091726045201">Google Tasks در وب</translation> <translation id="5825969630400862129">تنظیمات دستگاههای متصل</translation> <translation id="5837036133683224804">توقف <ph name="ROUTE_TITLE" /> به <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">بارگیری <ph name="FILENAME" /> درحال اسکن</translation> <translation id="6542521951477560771">پخش محتوا به <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">تصویر را براساس پیشنمای تصویر و محتوا جستجو کنید</translation> +<translation id="6547795021703527064">وقتی بلوتوث را خاموش میکنید، اتصال «<ph name="DEVICE_NAME" />» از Chromebook قطع خواهد شد.</translation> <translation id="6555373427270923730">نشانی وبی را در نوار نشانی تایپ کنید و سپس <ph name="MODIFIER" /><ph name="KEY" /> را فشار دهید</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> نصب جدید</translation>
diff --git a/ash/strings/ash_strings_fil.xtb b/ash/strings/ash_strings_fil.xtb index 7631e29..60449394 100644 --- a/ash/strings/ash_strings_fil.xtb +++ b/ash/strings/ash_strings_fil.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Magandang hapon <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Hanapin ang iyong mga <ph name="CATEGORY" />, file, app, at higit pa. Gamitin ang mga arrow key para i-navigate ang iyong mga app.</translation> <translation id="1093645050124056515">ctrl + alt + pababang arrow</translation> +<translation id="1094756674036064790">I-off ang Bluetooth?</translation> <translation id="109942774857561566">Naiinip ako</translation> <translation id="1104084341931202936">Ipakita ang mga setting ng pagiging naa-access</translation> <translation id="1104621072296271835">Gagana nang mas maayos ang iyong mga device kung magkakasama</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">I-toggle ang mataas na visibility ng <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733">Pinapamahalaang user na <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Mag-swipe para i-hide ang iyong naka-float na window</translation> +<translation id="3673898235958558034">Kapag na-off mo ang Bluetooth, madidiskonekta ang "<ph name="DEVICE_NAME_1" />" at "<ph name="DEVICE_NAME_2" />" sa iyong Chromebook.</translation> <translation id="367531336287639526">Piliin ang unang icon sa kaliwa ng address bar</translation> <translation id="3677931086890821290">Binibigyang-daan nito ang lahat ng app at website na may pahintulot sa lokasyon at ChromeOS na gumamit ng Wi-Fi at lokasyon ng mga mobile network.</translation> <translation id="3679827876008292680">Pumunta sa huling tab sa window</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Higit pang app</translation> <translation id="4667099493359681081">Dina-download ang <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Na-on ang Pantipid ng Baterya</translation> +<translation id="4673427585974421255">I-on lang</translation> <translation id="468293128311738995">Mga app mula sa iyong telepono</translation> <translation id="4690510401873698237">Nasa ibaba ang shelf</translation> <translation id="4696813013609194136">I-unlock ang device gamit ang parent code</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Buksan ang Mga Mabilisang Setting</translation> <translation id="5804651031882187592">I-off ang setting na "I-lock ang SIM"</translation> <translation id="5805809050170488595">I-click para ma-activate ang <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Kapag na-off mo ang Bluetooth, madidiskonekta ang "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" at <ph name="DEVICE_COUNT" /> (na) iba pang device sa iyong Chromebook.</translation> <translation id="5823239091726045201">Google Tasks sa web</translation> <translation id="5825969630400862129">Mga setting ng mga nakakonektang device</translation> <translation id="5837036133683224804">Ihinto ang <ph name="ROUTE_TITLE" /> sa <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Sina-scan ang <ph name="FILENAME" /> para sa pag-download</translation> <translation id="6542521951477560771">Nagka-cast sa <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Paghahanap ng larawan ayon sa mga preview ng content at larawan</translation> +<translation id="6547795021703527064">Kapag na-off mo ang Bluetooth, madidiskonekta ang "<ph name="DEVICE_NAME" />" sa iyong Chromebook.</translation> <translation id="6555373427270923730">Mag-type ng address sa web sa address bar, at pagkatapos ay pindutin ang <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Kaka-install lang</translation>
diff --git a/ash/strings/ash_strings_gl.xtb b/ash/strings/ash_strings_gl.xtb index 32850f9..e0ac8b68 100644 --- a/ash/strings/ash_strings_gl.xtb +++ b/ash/strings/ash_strings_gl.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Boas tardes, <ph name="GIVEN_NAME" />!</translation> <translation id="1088231044944504242">Busca <ph name="CATEGORY" />, ficheiros, aplicacións e moito máis. Usa as teclas das frechas para moverte polas aplicacións.</translation> <translation id="1093645050124056515">control + alt + frecha abaixo</translation> +<translation id="1094756674036064790">Queres desactivar o Bluetooth?</translation> <translation id="109942774857561566">Abúrrome</translation> <translation id="1104084341931202936">Mostrar a configuración de accesibilidade</translation> <translation id="1104621072296271835">Os dispositivos funcionan mellor xuntos</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Activar ou desactivar o modo de alta visibilidade de <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Usuario xestionado</translation> <translation id="3666266999138159418">Pasa o dedo para ocultar a ventá flotante</translation> +<translation id="3673898235958558034">Se desactivas o Bluetooth, <ph name="DEVICE_NAME_1" /> e <ph name="DEVICE_NAME_2" /> desconectaranse do teu Chromebook.</translation> <translation id="367531336287639526">Selecciona a primeira icona á esquerda da barra de enderezos</translation> <translation id="3677931086890821290">Desta forma, todas as aplicacións e os sitios web con permiso de localización e ChromeOS poderán utilizar a localización mediante wifi e redes de telefonía móbil.</translation> <translation id="3679827876008292680">Ir á última pestana da ventá</translation> @@ -916,6 +918,7 @@ <translation id="4666911709726371538">Máis aplicacións</translation> <translation id="4667099493359681081">Descargando <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Activouse a función Aforro de batería</translation> +<translation id="4673427585974421255">Manter activado</translation> <translation id="468293128311738995">Aplicacións do teu teléfono</translation> <translation id="4690510401873698237">O estante está na parte inferior</translation> <translation id="4696813013609194136">Desbloquea o dispositivo co código parental</translation> @@ -1216,6 +1219,7 @@ <translation id="5802516411616338943">Abrir Configuración rápida</translation> <translation id="5804651031882187592">Desactivar a opción Bloquear SIM</translation> <translation id="5805809050170488595">Facer clic para activar <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Se desactivas o Bluetooth, <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> e <ph name="DEVICE_COUNT" /> dispositivos máis desconectaranse do teu Chromebook.</translation> <translation id="5823239091726045201">Tarefas de Google na Web</translation> <translation id="5825969630400862129">Configuración de dispositivos conectados</translation> <translation id="5837036133683224804">Deter <ph name="ROUTE_TITLE" /> no receptor <ph name="RECEIVER_NAME" /></translation> @@ -1396,6 +1400,7 @@ <translation id="6539852571005954999">Escaneando ficheiro <ph name="FILENAME" /> para descargalo</translation> <translation id="6542521951477560771">Emitindo en: <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Busca de imaxes por contido e vistas previas</translation> +<translation id="6547795021703527064">Se desactivas o Bluetooth, <ph name="DEVICE_NAME" /> desconectarase do teu Chromebook.</translation> <translation id="6555373427270923730">Escribe un enderezo web na barra de enderezos e despois preme <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Nova instalación</translation>
diff --git a/ash/strings/ash_strings_hr.xtb b/ash/strings/ash_strings_hr.xtb index f9fbda5..0541685 100644 --- a/ash/strings/ash_strings_hr.xtb +++ b/ash/strings/ash_strings_hr.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Dobar dan, <ph name="GIVEN_NAME" /></translation> <translation id="1088231044944504242">Pretražujte svoje <ph name="CATEGORY" />, datoteke, aplikacije i ostalo. Kroz aplikacije se krećite pomoću tipki sa strelicama.</translation> <translation id="1093645050124056515">Ctrl + Alt + strelica prema dolje</translation> +<translation id="1094756674036064790">Želiteli isključiti Bluetooth?</translation> <translation id="109942774857561566">Dosadno mi je</translation> <translation id="1104084341931202936">Prikaz postavki pristupačnosti</translation> <translation id="1104621072296271835">Vaši uređaji funkcioniraju još bolje zajedno</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Promijenite visoku vidljivost za <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> upravljani korisnik</translation> <translation id="3666266999138159418">Prijeđite prstom da biste sakrili plutajući prozor</translation> +<translation id="3673898235958558034">Kada isključite Bluetooth, prekinut će se veza između uređaja <ph name="DEVICE_NAME_1" /> i <ph name="DEVICE_NAME_2" /> s vašim Chromebookom.</translation> <translation id="367531336287639526">Odabir prve ikone lijevo od adresne trake</translation> <translation id="3677931086890821290">To svim aplikacijama i web-lokacijama s dopuštenjem za lokaciju i ChromeOS-om omogućuje upotrebu lokacije Wi-Fija i mobilnih mreža.</translation> <translation id="3679827876008292680">Posjećivanje zadnje kartice u prozoru</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Više aplikacija</translation> <translation id="4667099493359681081">Preuzima se <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Uključena je štednja baterije</translation> +<translation id="4673427585974421255">Ostavi uključeno</translation> <translation id="468293128311738995">Aplikacije s telefona</translation> <translation id="4690510401873698237">Polica pri dnu</translation> <translation id="4696813013609194136">Otključajte uređaj roditeljskim kodom</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Otvaranje Brzih postavki</translation> <translation id="5804651031882187592">Isključivanje postavke Zaključaj SIM</translation> <translation id="5805809050170488595">Kliknite da biste aktivirali mrežu <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Kada isključite Bluetooth, uređaji <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> i još ovoliko uređaja: <ph name="DEVICE_COUNT" /> prekinut će vezu s vašim Chromebookom.</translation> <translation id="5823239091726045201">Google Tasks na webu</translation> <translation id="5825969630400862129">Postavke povezanih uređaja</translation> <translation id="5837036133683224804">Zaustavite <ph name="ROUTE_TITLE" /> na uređaju <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Pregled preuzimanja datoteke <ph name="FILENAME" /></translation> <translation id="6542521951477560771">Emitiranje na uređaj <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Pretraživanje slika prema sadržaju i pregledi slika</translation> +<translation id="6547795021703527064">Kada isključite Bluetooth, veza uređaja <ph name="DEVICE_NAME" /> s Chromebookom prekinut će se.</translation> <translation id="6555373427270923730">Unesite web-adresu u adresnu traku i pritisnite <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Novo instaliranje</translation>
diff --git a/ash/strings/ash_strings_id.xtb b/ash/strings/ash_strings_id.xtb index c8194f1e..45898af 100644 --- a/ash/strings/ash_strings_id.xtb +++ b/ash/strings/ash_strings_id.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Selamat siang <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Telusuri <ph name="CATEGORY" />, file, aplikasi, dan lainnya. Gunakan tombol panah untuk membuka berbagai bagian aplikasi.</translation> <translation id="1093645050124056515">ctrl + alt + panah bawah</translation> +<translation id="1094756674036064790">Nonaktifkan Bluetooth?</translation> <translation id="109942774857561566">Saya bosan</translation> <translation id="1104084341931202936">Tampilkan setelan aksesibilitas</translation> <translation id="1104621072296271835">Perangkat berfungsi lebih baik jika digunakan bersama</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Tombol visibilitas tinggi <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733">Pengguna Terkelola <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Geser untuk menyembunyikan jendela mengambang</translation> +<translation id="3673898235958558034">Jika Anda menonaktifkan Bluetooth, koneksi "<ph name="DEVICE_NAME_1" />" dan "<ph name="DEVICE_NAME_2" />" akan diputuskan dari Chromebook.</translation> <translation id="367531336287639526">Pilih ikon pertama di sebelah kiri kolom URL</translation> <translation id="3677931086890821290">Tindakan ini akan mengizinkan semua aplikasi dan situs yang memiliki izin lokasi serta ChromeOS untuk menggunakan lokasi jaringan seluler dan Wi-Fi.</translation> <translation id="3679827876008292680">Buka tab terakhir di jendela</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Aplikasi lainnya</translation> <translation id="4667099493359681081">Mendownload <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Penghemat Baterai diaktifkan</translation> +<translation id="4673427585974421255">Tetap aktifkan</translation> <translation id="468293128311738995">Aplikasi dari ponsel Anda</translation> <translation id="4690510401873698237">Rak di bagian bawah</translation> <translation id="4696813013609194136">Buka kunci perangkat dengan kode orang tua</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Buka Setelan Cepat</translation> <translation id="5804651031882187592">Nonaktifkan setelan "Kunci SIM"</translation> <translation id="5805809050170488595">Klik untuk mengaktifkan <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Jika Anda menonaktifkan Bluetooth, koneksi "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />", dan <ph name="DEVICE_COUNT" /> perangkat lainnya akan diputuskan dari Chromebook.</translation> <translation id="5823239091726045201">Google Tasks di web</translation> <translation id="5825969630400862129">Setelan perangkat yang terhubung</translation> <translation id="5837036133683224804">Hentikan <ph name="ROUTE_TITLE" /> di <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Download <ph name="FILENAME" /> yang sedang dipindai</translation> <translation id="6542521951477560771">Transmisikan ke <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Penelusuran gambar berdasarkan pratinjau konten dan gambar</translation> +<translation id="6547795021703527064">Jika Anda menonaktifkan Bluetooth, koneksi "<ph name="DEVICE_NAME" />" akan diputuskan dari Chromebook.</translation> <translation id="6555373427270923730">Ketik alamat web di kolom URL, lalu tekan <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Baru diinstal</translation>
diff --git a/ash/strings/ash_strings_is.xtb b/ash/strings/ash_strings_is.xtb index 37ceb79..9e7988a1 100644 --- a/ash/strings/ash_strings_is.xtb +++ b/ash/strings/ash_strings_is.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Góðan dag <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Leitaðu að <ph name="CATEGORY" />, skrám, forritum og fleira. Notaðu örvalyklana til að fletta í gegnum forritin þín.</translation> <translation id="1093645050124056515">ctrl + alt + ör niður</translation> +<translation id="1094756674036064790">Slökkva á Bluetooth?</translation> <translation id="109942774857561566">Mér leiðist</translation> <translation id="1104084341931202936">Sýna aðgengisstillingar</translation> <translation id="1104621072296271835">Tækin þín virka enn betur saman</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Kveikja/slökkva á miklum sýnileika <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Stýrður notandi</translation> <translation id="3666266999138159418">Strjúktu til að fela fljótandi gluggann</translation> +<translation id="3673898235958558034">Þegar þú slekkur á Bluetooth aftengjast „<ph name="DEVICE_NAME_1" />“ og „<ph name="DEVICE_NAME_2" />“ frá Chromebook.</translation> <translation id="367531336287639526">Velja fyrsta tákn vinstra megin við veffangastiku</translation> <translation id="3677931086890821290">Þetta gerir öllum forritum og vefsvæðum með staðsetningarheimild og ChromeOS kleift að nota staðsetningu WiFi-nets og farsímakerfa.</translation> <translation id="3679827876008292680">Fara á síðasta flipann í glugganum</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Fleiri forrit</translation> <translation id="4667099493359681081">Sækir <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Kveikt á rafhlöðusparnaði</translation> +<translation id="4673427585974421255">Hafa kveikt</translation> <translation id="468293128311738995">Forrit úr símanum</translation> <translation id="4690510401873698237">Hilla neðst</translation> <translation id="4696813013609194136">Opna tæki með kóða foreldris</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Opna flýtistillingar</translation> <translation id="5804651031882187592">Slökkva á stillingunni „læsa SIM-korti“</translation> <translation id="5805809050170488595">Smelltu til að kveikja á <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Þegar þú slekkur á Bluetooth aftengjast „<ph name="DEVICE_NAME_1" />“, „<ph name="DEVICE_NAME_2" />“ og <ph name="DEVICE_COUNT" /> önnur tæki frá Chromebook.</translation> <translation id="5823239091726045201">Google-verkefni á vefnum</translation> <translation id="5825969630400862129">Stillingar tengdra tækja</translation> <translation id="5837036133683224804">Stöðva <ph name="ROUTE_TITLE" /> í <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Niðurhal skannar <ph name="FILENAME" /></translation> <translation id="6542521951477560771">Sendir út til <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Myndaleit eftir efni og forskoðun mynda</translation> +<translation id="6547795021703527064">Þegar þú slekkur á Bluetooth aftengist „<ph name="DEVICE_NAME" />“ frá Chromebook.</translation> <translation id="6555373427270923730">Sláðu veffang inn á veffangastikunni og ýttu svo á <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Ný uppsetning</translation>
diff --git a/ash/strings/ash_strings_iw.xtb b/ash/strings/ash_strings_iw.xtb index 3777bbf..f8442c4 100644 --- a/ash/strings/ash_strings_iw.xtb +++ b/ash/strings/ash_strings_iw.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">אחה"צ טובים <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">חיפוש ב<ph name="CATEGORY" />, בקבצים, באפליקציות ועוד. אפשר להשתמש במקשי החיצים כדי לנווט בין האפליקציות.</translation> <translation id="1093645050124056515">Ctrl + Alt + חץ למטה</translation> +<translation id="1094756674036064790">להשבית את Bluetooth?</translation> <translation id="109942774857561566">משעמם לי</translation> <translation id="1104084341931202936">צפייה בהגדרות הנגישות</translation> <translation id="1104621072296271835">ביחד, המכשירים שלך יוכלו לעבוד עוד יותר טוב</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">הפעלת מצב החשיפה הגבוהה של <ph name="FEATURE_NAME" /> או השבתה שלו</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> משתמש מנוהל</translation> <translation id="3666266999138159418">ניתן להחליק להסתרת החלון הצף</translation> +<translation id="3673898235958558034">אם משביתים את Bluetooth, המכשירים <ph name="DEVICE_NAME_1" /> ו-<ph name="DEVICE_NAME_2" /> יתנתקו מ-Chromebook.</translation> <translation id="367531336287639526">בחירת הסמל הראשון מימין לסרגל הכתובות</translation> <translation id="3677931086890821290">כך כל האפליקציות והאתרים עם הרשאת המיקום ו-ChromeOS יוכלו להשתמש במיקום ב-Wi-Fi וברשתות סלולריות.</translation> <translation id="3679827876008292680">מעבר לכרטיסייה האחרונה בחלון</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">עוד אפליקציות</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> בהורדה</translation> <translation id="4672539464599646374">התכונה 'חיסכון בסוללה' הופעלה</translation> +<translation id="4673427585974421255">אני רוצה להמשיך להשתמש ב-Bluetooth</translation> <translation id="468293128311738995">אפליקציות מהטלפון שלך</translation> <translation id="4690510401873698237">המדף בחלק התחתון</translation> <translation id="4696813013609194136">ביטול נעילת המכשיר באמצעות קוד הורה</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">פתיחת ההגדרות המהירות</translation> <translation id="5804651031882187592">השבתת ההגדרה 'נעילת כרטיס ה-SIM'</translation> <translation id="5805809050170488595">יש ללחוץ כדי להפעיל את <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">אם משביתים את Bluetooth, המכשירים <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> ו-<ph name="DEVICE_COUNT" /> מכשירים נוספים יתנתקו מ-Chromebook.</translation> <translation id="5823239091726045201">Google Tasks באינטרנט</translation> <translation id="5825969630400862129">הגדרות של מכשירים מחוברים</translation> <translation id="5837036133683224804">הפסקת <ph name="ROUTE_TITLE" /> במכשיר <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">מתבצעת סריקה של קובץ ההורדה <ph name="FILENAME" /></translation> <translation id="6542521951477560771">ההעברה אל <ph name="RECEIVER_NAME" /> מתבצעת</translation> <translation id="6546062506073634094">חיפוש תמונות לפי תוכן ותצוגות מקדימות של תמונות</translation> +<translation id="6547795021703527064">אם משביתים את Bluetooth, המכשיר <ph name="DEVICE_NAME" /> יתנתק מ-Chromebook.</translation> <translation id="6555373427270923730">הקלדת כתובת אינטרנט בסרגל הכתובות והקשה על <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> התקנה חדשה</translation>
diff --git a/ash/strings/ash_strings_ja.xtb b/ash/strings/ash_strings_ja.xtb index 62a2443..5d183f4 100644 --- a/ash/strings/ash_strings_ja.xtb +++ b/ash/strings/ash_strings_ja.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">こんにちは、<ph name="GIVEN_NAME" /> さん</translation> <translation id="1088231044944504242"><ph name="CATEGORY" />、ファイル、アプリなどを検索できます。アプリを切り替えるには、矢印キーを使用します。</translation> <translation id="1093645050124056515">Ctrl+Alt+下矢印</translation> +<translation id="1094756674036064790">Bluetooth をオフにしますか?</translation> <translation id="109942774857561566">退屈だな</translation> <translation id="1104084341931202936">ユーザー補助機能の設定を表示</translation> <translation id="1104621072296271835">デバイスを連携させると活用の幅が広がります</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> で付近のデバイスに表示されるモードのオンとオフを切り替える</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> の管理対象ユーザー</translation> <translation id="3666266999138159418">フローティング ウィンドウを非表示にするにはスワイプします</translation> +<translation id="3673898235958558034">Bluetooth をオフにすると、「<ph name="DEVICE_NAME_1" />」と「<ph name="DEVICE_NAME_2" />」は Chromebook との接続が解除されます。</translation> <translation id="367531336287639526">アドレスバーの左側にある最初のアイコンを選択します</translation> <translation id="3677931086890821290">位置情報へのアクセスを許可したすべてのアプリとウェブサイト、ChromeOS で、Wi-Fi とモバイル ネットワークの位置情報を使用できるようになります。</translation> <translation id="3679827876008292680">ウィンドウ内の最後のタブに移動する</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">表示するアプリを増やす</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> をダウンロードしています</translation> <translation id="4672539464599646374">バッテリー セーバーがオンになりました</translation> +<translation id="4673427585974421255">ON のまま</translation> <translation id="468293128311738995">スマートフォンのアプリ</translation> <translation id="4690510401873698237">シェルフは一番下にあります</translation> <translation id="4696813013609194136">保護者のコードでデバイスをロック解除</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">クイック設定を開く</translation> <translation id="5804651031882187592">[SIM をロックする] 設定をオフにする</translation> <translation id="5805809050170488595">クリックすると <ph name="NETWORK_NAME" /> が有効になります</translation> +<translation id="5816222150329690597">Bluetooth をオフにすると、「<ph name="DEVICE_NAME_1" />」、「<ph name="DEVICE_NAME_2" />」、その他 <ph name="DEVICE_COUNT" /> 台のデバイスは Chromebook との接続が解除されます。</translation> <translation id="5823239091726045201">ウェブの Google ToDo リスト</translation> <translation id="5825969630400862129">接続済みデバイスの設定</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> の「<ph name="ROUTE_TITLE" />」を停止します</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">ダウンロードする <ph name="FILENAME" /> をスキャンしています</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> にキャストしています</translation> <translation id="6546062506073634094">コンテンツと画像プレビューによる画像検索</translation> +<translation id="6547795021703527064">Bluetooth をオフにすると、「<ph name="DEVICE_NAME" />」は Chromebook との接続が解除されます。</translation> <translation id="6555373427270923730">アドレスバーにウェブアドレスを入力して、<ph name="MODIFIER" />+<ph name="KEY" /> キーを押す</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> 新たなインストール</translation>
diff --git a/ash/strings/ash_strings_kk.xtb b/ash/strings/ash_strings_kk.xtb index d6c6c49..9cc59c1 100644 --- a/ash/strings/ash_strings_kk.xtb +++ b/ash/strings/ash_strings_kk.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Қайырлы күн, <ph name="GIVEN_NAME" />!</translation> <translation id="1088231044944504242"><ph name="CATEGORY" />, файлдар, қолданбалар және т. б. іздеңіз. Бір қолданбадан екіншісіне өту үшін бағыт пернелерін пайдаланыңыз.</translation> <translation id="1093645050124056515">ctrl + alt + төмен бағыт пернесі</translation> +<translation id="1094756674036064790">Bluetooth-ды өшіру керек пе?</translation> <translation id="109942774857561566">Ішім пысты</translation> <translation id="1104084341931202936">Арнайы мүмкіндіктер параметрлерін көрсету</translation> <translation id="1104621072296271835">Құрылғылар бірігіп жақсы жұмыс істейді</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> үшін тез табылу режимін қосу немесе өшіру</translation> <translation id="366222428570480733">Басқарылатын пайдаланушы: <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Қалқымалы терезені жасыру үшін сырғытыңыз.</translation> +<translation id="3673898235958558034">Bluetooth-ды өшірсеңіз, "<ph name="DEVICE_NAME_1" />" және "<ph name="DEVICE_NAME_2" />" құрылғылары Chromebook-тен ажыратылады.</translation> <translation id="367531336287639526">Мекенжай жолағының сол жағындағы бірінші белгішені таңдау</translation> <translation id="3677931086890821290">Бұл геодеректі пайдалану рұқсаты мен ChromeOS жүйесі бар барлық қолданба мен веб-сайттың Wi-Fi және мобильді желілер орындарын пайдалануына мүмкіндік береді.</translation> <translation id="3679827876008292680">Терезедегі соңғы қойындыға өту</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Басқа қолданбалар</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> жүктеп алынуда</translation> <translation id="4672539464599646374">Батареяны үнемдеу режимі қосылды.</translation> +<translation id="4673427585974421255">Қосулы қалдыру</translation> <translation id="468293128311738995">Телефондағы қолданбалар</translation> <translation id="4690510401873698237">Төмен жақтағы сөре</translation> <translation id="4696813013609194136">Құрылғының құлпын ата-ана кодымен ашыңыз</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Жылдам параметрлерді ашу</translation> <translation id="5804651031882187592">"SIM картасын құлыптау" параметрін өшіру</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> іске қосу үшін басыңыз</translation> +<translation id="5816222150329690597">Bluetooth-ды өшірсеңіз, "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" және тағы <ph name="DEVICE_COUNT" /> құрылғы Chromebook-тен ажыратылады.</translation> <translation id="5823239091726045201">Ғаламтордағы Google Tasks</translation> <translation id="5825969630400862129">Байланыстырылған құрылғылар параметрлері</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> қабылдағышында <ph name="ROUTE_TITLE" /> трансляциясын тоқтату</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Жүктеп алынған <ph name="FILENAME" /> файлы сканерленіп жатыр</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> құрылғысына трансляциялануда</translation> <translation id="6546062506073634094">Суретті ішінде не нәрсе бейнеленгеніне және алғы көрінісіне байланысты іздеу</translation> +<translation id="6547795021703527064">Bluetooth-ды өшірсеңіз, "<ph name="DEVICE_NAME" />" құрылғысы Chromebook-тен ажыратылады.</translation> <translation id="6555373427270923730">Мекенжай жолағына веб-мекенжайды енгізіп, <ph name="MODIFIER" /><ph name="KEY" /> пернесін басыңыз</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Жаңадан орнатылды</translation>
diff --git a/ash/strings/ash_strings_kn.xtb b/ash/strings/ash_strings_kn.xtb index bf1ccbb..a1600b4 100644 --- a/ash/strings/ash_strings_kn.xtb +++ b/ash/strings/ash_strings_kn.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">ಶುಭ ಮಧ್ಯಾಹ್ನ <ph name="GIVEN_NAME" /> ಅವರೇ,</translation> <translation id="1088231044944504242">ನಿಮ್ಮ <ph name="CATEGORY" />, ಫೈಲ್ಗಳು, ಆ್ಯಪ್ಗಳು ಮತ್ತು ಹೆಚ್ಚಿನದನ್ನು ಹುಡುಕಿ. ನಿಮ್ಮ ಆ್ಯಪ್ಗಳನ್ನು ನ್ಯಾವಿಗೇಟ್ ಮಾಡಲು ಬಾಣದ ಗುರುತಿನ ಕೀಗಳನ್ನು ಬಳಸಿ.</translation> <translation id="1093645050124056515">ctrl + alt + ಡೌನ್ ಆ್ಯರೋ</translation> +<translation id="1094756674036064790">ಬ್ಲೂಟೂತ್ ಅನ್ನು ಆಫ್ ಮಾಡಬೇಕೆ?</translation> <translation id="109942774857561566">ನನಗೆ ಬೇಜಾರಾಗಿದೆ</translation> <translation id="1104084341931202936">ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೋರಿಸಿ</translation> <translation id="1104621072296271835">ನಿಮ್ಮ ಸಾಧನಗಳು ಜೊತೆಯಲ್ಲಿ ಇನ್ನೂ ಚೆನ್ನಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತವೆ</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">ಹೆಚ್ಚಿನ ಗೋಚರತೆಯ <ph name="FEATURE_NAME" /> ಅನ್ನು ಟಾಗಲ್ ಮಾಡಿ</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> ನಿರ್ವಹಿಸಲಾದ ಬಳಕೆದಾರರು</translation> <translation id="3666266999138159418">ನಿಮ್ಮ ಫ್ಲೋಟಿಂಗ್ ವಿಂಡೋವನ್ನು ಮರೆಮಾಡಲು ಸ್ವೈಪ್ ಮಾಡಿ</translation> +<translation id="3673898235958558034">ನೀವು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಆಫ್ ಮಾಡಿದಾಗ, "<ph name="DEVICE_NAME_1" />" ಮತ್ತು "<ph name="DEVICE_NAME_2" />" ಸಾಧನಗಳು ನಿಮ್ಮ Chromebook ನಿಂದ ಡಿಸ್ಕನೆಕ್ಟ್ ಆಗುತ್ತವೆ.</translation> <translation id="367531336287639526">ವಿಳಾಸ ಪಟ್ಟಿಯ ಎಡಭಾಗದಲ್ಲಿರುವ ಮೊದಲ ಐಕಾನ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ</translation> <translation id="3677931086890821290">ಇದು ಸ್ಥಳ ಅನುಮತಿಯನ್ನು ಹೊಂದಿರುವ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು ಮತ್ತು ವೆಬ್ಸೈಟ್ಗಳು ಹಾಗೂ ವೈ-ಫೈ ಮತ್ತು ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ಗಳ ಸ್ಥಳವನ್ನು ಬಳಸಲು ChromeOS ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ.</translation> <translation id="3679827876008292680">ವಿಂಡೋದಲ್ಲಿ ಕೊನೆಯ ಟ್ಯಾಬ್ಗೆ ಹೋಗಿ</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">ಇನ್ನಷ್ಟು ಆ್ಯಪ್ಗಳು</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ</translation> <translation id="4672539464599646374">ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ</translation> +<translation id="4673427585974421255">ಆನ್ ಆಗಿರಿಸಿ</translation> <translation id="468293128311738995">ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿನ ಆ್ಯಪ್ಗಳು</translation> <translation id="4690510401873698237">ಪರದೆಯ ಕೆಳಭಾಗದಲ್ಲಿ ಶೆಲ್ಫ್ ಇದೆ</translation> <translation id="4696813013609194136">ಪೋಷಕ ಕೋಡ್ ಬಳಸಿಕೊಂಡು ಸಾಧನವನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಿರಿ</translation> <translation id="5804651031882187592">"SIM ಅನ್ನು ಲಾಕ್ ಮಾಡಿ" ಎಂಬ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಆಫ್ ಮಾಡಿ</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> ಸಕ್ರಿಯಗೊಳಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ</translation> +<translation id="5816222150329690597">ನೀವು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಆಫ್ ಮಾಡಿದಾಗ, "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" ಮತ್ತು <ph name="DEVICE_COUNT" /> ಇತರ ಸಾಧನಗಳು ನಿಮ್ಮ Chromebook ನಿಂದ ಡಿಸ್ಕನೆಕ್ಟ್ ಆಗುತ್ತವೆ.</translation> <translation id="5823239091726045201">ವೆಬ್ನಲ್ಲಿ Google ಕಾರ್ಯಗಳು</translation> <translation id="5825969630400862129">ಕನೆಕ್ಟ್ ಮಾಡಿದ ಸಾಧನಗಳ ಸೆಟ್ಟಿಂಗ್ಗಳು</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> ನಲ್ಲಿ <ph name="ROUTE_TITLE" /> ನಿಲ್ಲಿಸಿ</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">ಸ್ಕ್ಯಾನ್ ಆಗುತ್ತಿರುವ <ph name="FILENAME" /> ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಿ</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> ಗೆ ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ</translation> <translation id="6546062506073634094">ಕಂಟೆಂಟ್ ಮತ್ತು ಚಿತ್ರದ ಪೂರ್ವವೀಕ್ಷಣೆಗಳ ಮೂಲಕ ಚಿತ್ರ ಹುಡುಕಾಟ</translation> +<translation id="6547795021703527064">ನೀವು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಆಫ್ ಮಾಡಿದಾಗ, "<ph name="DEVICE_NAME" />" ಸಾಧನವು ನಿಮ್ಮ Chromebook ನಿಂದ ಡಿಸ್ಕನೆಕ್ಟ್ ಆಗುತ್ತದೆ.</translation> <translation id="6555373427270923730">ವಿಳಾಸ ಪಟ್ಟಿಯಲ್ಲಿ ವೆಬ್ ವಿಳಾಸವನ್ನು ಟೈಪ್ ಮಾಡಿ, ನಂತರ <ph name="MODIFIER" /><ph name="KEY" /> ಅನ್ನು ಒತ್ತಿರಿ</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> ಹೊಸ ಇನ್ಸ್ಟಾಲ್</translation>
diff --git a/ash/strings/ash_strings_ko.xtb b/ash/strings/ash_strings_ko.xtb index fde996d..de49f6e 100644 --- a/ash/strings/ash_strings_ko.xtb +++ b/ash/strings/ash_strings_ko.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">즐거운 오후 보내세요, <ph name="GIVEN_NAME" />님</translation> <translation id="1088231044944504242"><ph name="CATEGORY" />, 파일, 앱 등을 검색합니다. 앱을 탐색하려면 화살표 키를 사용하세요.</translation> <translation id="1093645050124056515">Ctrl + Alt + 아래쪽 화살표</translation> +<translation id="1094756674036064790">블루투스를 사용 중지하시겠습니까?</translation> <translation id="109942774857561566">나 심심해</translation> <translation id="1104084341931202936">접근성 설정 표시</translation> <translation id="1104621072296271835">기기가 연결되면 더욱 원활하게 작동합니다</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> 높은 공개 상태 전환</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> 관리 사용자</translation> <translation id="3666266999138159418">스와이프하여 플로팅 창 숨기기</translation> +<translation id="3673898235958558034">블루투스를 사용 중지하면 "<ph name="DEVICE_NAME_1" />" 및 "<ph name="DEVICE_NAME_2" />" 기기가 Chromebook에서 연결 해제됩니다.</translation> <translation id="367531336287639526">주소 표시줄 왼쪽에 있는 첫 번째 아이콘 선택</translation> <translation id="3677931086890821290">이를 통해 위치 정보 액세스 권한이 있고 ChromeOS를 지원하는 모든 앱과 웹사이트에서 Wi-Fi 및 모바일 네트워크 위치를 사용할 수 있습니다.</translation> <translation id="3679827876008292680">창의 마지막 탭으로 이동</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">앱 더보기</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> 파일을 다운로드하는 중입니다</translation> <translation id="4672539464599646374">절전 모드 사용 설정됨</translation> +<translation id="4673427585974421255">계속 사용</translation> <translation id="468293128311738995">휴대전화 앱</translation> <translation id="4690510401873698237">앱 표시줄 하단에 표시</translation> <translation id="4696813013609194136">부모 코드로 기기 잠금 해제</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">빠른 설정 열기</translation> <translation id="5804651031882187592">'SIM 잠금' 설정 사용 중지</translation> <translation id="5805809050170488595">클릭하여 <ph name="NETWORK_NAME" /> 활성화</translation> +<translation id="5816222150329690597">블루투스를 사용 중지하면 "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" 외 <ph name="DEVICE_COUNT" />개 기기가 Chromebook에서 연결 해제됩니다.</translation> <translation id="5823239091726045201">웹의 Google 작업</translation> <translation id="5825969630400862129">연결된 기기 설정</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />에서 <ph name="ROUTE_TITLE" /> 중지</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">스캔 중인 <ph name="FILENAME" /> 파일 다운로드</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" />(으)로 전송 중</translation> <translation id="6546062506073634094">콘텐츠 및 이미지 미리보기로 이미지 검색</translation> +<translation id="6547795021703527064">블루투스를 사용 중지하면 "<ph name="DEVICE_NAME" />" 기기가 Chromebook에서 연결 해제됩니다.</translation> <translation id="6555373427270923730">주소 표시줄에 웹 주소를 입력한 후 <ph name="MODIFIER" /><ph name="KEY" /> 키 누르기</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> 새로 설치됨</translation>
diff --git a/ash/strings/ash_strings_lt.xtb b/ash/strings/ash_strings_lt.xtb index 5c06d001..8d62e460 100644 --- a/ash/strings/ash_strings_lt.xtb +++ b/ash/strings/ash_strings_lt.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Laba diena, <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Ieškokite <ph name="CATEGORY" />, failų, programų ir kt. Naršykite programas rodyklių klavišais.</translation> <translation id="1093645050124056515">„Ctrl“ + „Alt“ + rodyklė žemyn</translation> +<translation id="1094756674036064790">Išjungti „Bluetooth“?</translation> <translation id="109942774857561566">„I’m bored“ (Man nuobodu)</translation> <translation id="1104084341931202936">Rodyti pritaikymo neįgaliesiems nustatymus</translation> <translation id="1104621072296271835">Jūsų įrenginiai kartu veikia dar geriau</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Perjungti funkcijos „<ph name="FEATURE_NAME" />“ didelį matomumą</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> tvarkomas naudotojas</translation> <translation id="3666266999138159418">Perbraukite, kad paslėptumėte slankųjį langą</translation> +<translation id="3673898235958558034">Kai išjungsite „Bluetooth“, „<ph name="DEVICE_NAME_1" />“ ir „<ph name="DEVICE_NAME_2" />“ bus atjungti nuo „Chromebook“.</translation> <translation id="367531336287639526">Pasirinkti pirmą piktogramą adreso juostos kairėje</translation> <translation id="3677931086890821290">Tai leidžia visoms programoms ir svetainėms, turinčioms leidimą pasiekti vietovės duomenis ir „ChromeOS“, naudoti „Wi-Fi“ ir mobiliojo ryšio tinklų vietovę.</translation> <translation id="3679827876008292680">Eiti į paskutinį skirtuką lange</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Daugiau programų</translation> <translation id="4667099493359681081">Atsisiunčiamas failas <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Įjungta akumuliatoriaus tausojimo priemonė</translation> +<translation id="4673427585974421255">Palikti įjungtą</translation> <translation id="468293128311738995">Programos iš telefono</translation> <translation id="4690510401873698237">Lentyna apačioje</translation> <translation id="4696813013609194136">Atrakinkite įrenginį naudodami tėvų kodą</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Atidaryti sparčiuosius nustatymus</translation> <translation id="5804651031882187592">Nustatymo „Užrakinti SIM kortelę“ išjungimas</translation> <translation id="5805809050170488595">Spustelėkite, kad suaktyvintumėte „<ph name="NETWORK_NAME" />“</translation> +<translation id="5816222150329690597">Kai išjungsite „Bluetooth“, „<ph name="DEVICE_NAME_1" />“, „<ph name="DEVICE_NAME_2" />“ ir kiti įrenginiai (<ph name="DEVICE_COUNT" />) bus atjungti nuo „Chromebook“.</translation> <translation id="5823239091726045201">„Google Tasks“ žiniatinklyje</translation> <translation id="5825969630400862129">Susietų įrenginių nustatymai</translation> <translation id="5837036133683224804">Sustabdyti „<ph name="ROUTE_TITLE" />“ („<ph name="RECEIVER_NAME" />“)</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Atsisiųsti nuskaitomą „<ph name="FILENAME" />“</translation> <translation id="6542521951477560771">Perduodama į „<ph name="RECEIVER_NAME" />“</translation> <translation id="6546062506073634094">Vaizdų paieška pagal turinį ir vaizdų peržiūras</translation> +<translation id="6547795021703527064">Kai išjungsite „Bluetooth“, „<ph name="DEVICE_NAME" />“ bus atjungtas nuo „Chromebook“.</translation> <translation id="6555373427270923730">Įveskite žiniatinklio adresą adreso juostoje, tada paspauskite <ph name="MODIFIER" /> <ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Naujas įdiegimas</translation>
diff --git a/ash/strings/ash_strings_lv.xtb b/ash/strings/ash_strings_lv.xtb index 3cb2d139..a82b74f 100644 --- a/ash/strings/ash_strings_lv.xtb +++ b/ash/strings/ash_strings_lv.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Labdien, <ph name="GIVEN_NAME" />!</translation> <translation id="1088231044944504242">Meklējiet <ph name="CATEGORY" />, failus, lietotnes un citu saturu. Izmantojiet bultiņas, lai pārvietotos savās lietotnēs.</translation> <translation id="1093645050124056515">Ctrl + Alt + lejupvērstā bultiņa</translation> +<translation id="1094756674036064790">Vai izslēgt Bluetooth?</translation> <translation id="109942774857561566">Man ir garlaicīgi</translation> <translation id="1104084341931202936">Rādīt pieejamības iestatījumus</translation> <translation id="1104621072296271835">Kopā jūsu ierīces darbojas vēl labāk</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Pārslēgt augstas redzamības režīmu funkcijai “<ph name="FEATURE_NAME" />”</translation> <translation id="366222428570480733">Pārvaldīts lietotājs <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Velciet, lai paslēptu peldošo logu</translation> +<translation id="3673898235958558034">Izslēdzot Bluetooth, ierīces “<ph name="DEVICE_NAME_1" />” un “<ph name="DEVICE_NAME_2" />” tiks atvienotas no Chromebook datora.</translation> <translation id="367531336287639526">Atlasīt pirmo ikonu pa kreisi no adreses joslas</translation> <translation id="3677931086890821290">Tādējādi visas lietotnes un vietnes ar atrašanās vietas atļauju un operētājsistēmu ChromeOS varēs izmantot Wi-Fi un mobilo tīklu atrašanās vietu.</translation> <translation id="3679827876008292680">Pāriet uz loga pēdējo cilni</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Citas lietotnes</translation> <translation id="4667099493359681081">Notiek faila <ph name="FILENAME" /> lejupielāde</translation> <translation id="4672539464599646374">Ieslēgts akumulatora enerģijas taupīšanas režīms.</translation> +<translation id="4673427585974421255">Atstāt ieslēgtu</translation> <translation id="468293128311738995">Lietotnes no jūsu tālruņa</translation> <translation id="4690510401873698237">Plaukts tiek rādīts apakšā</translation> <translation id="4696813013609194136">Ierīces atbloķēšana, ievadot vecāku kodu</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Atvērt ātros iestatījumus</translation> <translation id="5804651031882187592">Iestatījuma “Bloķēt SIM karti” izslēgšana</translation> <translation id="5805809050170488595">Noklikšķiniet, lai aktivizētu tīklu <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Izslēdzot Bluetooth, ierīces “<ph name="DEVICE_NAME_1" />”, “<ph name="DEVICE_NAME_2" />” un citas ierīces (<ph name="DEVICE_COUNT" />) tiks atvienotas no Chromebook datora.</translation> <translation id="5823239091726045201">Google uzdevumi tīmeklī</translation> <translation id="5825969630400862129">Saistīto ierīču iestatījumi</translation> <translation id="5837036133683224804">Pārtraukt “<ph name="ROUTE_TITLE" />” apraidi ierīcē “<ph name="RECEIVER_NAME" />”</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Notiek lejupielādes faila “<ph name="FILENAME" />” pārbaude</translation> <translation id="6542521951477560771">Notiek apraide uz ierīci <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Attēlu meklēšana pēc satura un attēlu priekšskatījumi</translation> +<translation id="6547795021703527064">Izslēdzot Bluetooth, ierīce “<ph name="DEVICE_NAME" />” tiks atvienota no Chromebook datora.</translation> <translation id="6555373427270923730">Ierakstiet tīmekļa adresi adreses joslā un pēc tam nospiediet <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Jauna instalācija</translation>
diff --git a/ash/strings/ash_strings_mn.xtb b/ash/strings/ash_strings_mn.xtb index 2ca55f8..f695d90 100644 --- a/ash/strings/ash_strings_mn.xtb +++ b/ash/strings/ash_strings_mn.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Өдрийн мэнд <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242"><ph name="CATEGORY" />, файлууд, аппууд болон бусад зүйлээ хайгаарай. Аппуудынхаа хооронд шилжихийн тулд суман товчийг ашиглана уу.</translation> <translation id="1093645050124056515">ctrl + alt + доош сум</translation> +<translation id="1094756674036064790">Bluetooth-г унтраах уу?</translation> <translation id="109942774857561566">Би уйдаж байна</translation> <translation id="1104084341931202936">Нэвтрэлтийн тохиргоог харуулах</translation> <translation id="1104621072296271835">Таны төхөөрөмжүүд хамтдаа илүү сайн ажилладаг</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" />-н өндөр харагдцыг асаах/унтраах</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Хяналттай хэрэглэгч</translation> <translation id="3666266999138159418">Хөвөгч цонхоо нуухын тулд шударна уу</translation> +<translation id="3673898235958558034">Та Bluetooth-г унтраах үед "<ph name="DEVICE_NAME_1" />" болон "<ph name="DEVICE_NAME_2" />" таны Chromebook-с сална.</translation> <translation id="367531336287639526">Хаяг оруулах хэсгийн зүүн талын эхний дүрс тэмдгийг сонгох</translation> <translation id="3677931086890821290">Энэ нь байршлын зөвшөөрөлтэй бүх апп, вебсайт болон ChromeOS-т Wi-Fi, мобайл сүлжээнүүдийн байршлыг ашиглахыг зөвшөөрнө.</translation> <translation id="3679827876008292680">Цонхны сүүлийн таб руу очих</translation> @@ -916,6 +918,7 @@ <translation id="4666911709726371538">Бусад апп</translation> <translation id="4667099493359681081"><ph name="FILENAME" />-г татаж байна</translation> <translation id="4672539464599646374">Батарей хэмнэгчийг асаасан</translation> +<translation id="4673427585974421255">Асаалттай үлдээх</translation> <translation id="468293128311738995">Таны утасны аппууд</translation> <translation id="4690510401873698237">Доор байгаа shelf</translation> <translation id="4696813013609194136">Төхөөрөмжийн түгжээг эцэг эхийн кодоор тайлна уу</translation> @@ -1216,6 +1219,7 @@ <translation id="5802516411616338943">Шуурхай тохиргоог нээх</translation> <translation id="5804651031882187592">"SIM-г түгжих" тохиргоог унтраах</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" />-г идэвхжүүлэхийн тулд товших</translation> +<translation id="5816222150329690597">Та Bluetooth-г унтраах үед "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" болон бусад <ph name="DEVICE_COUNT" /> төхөөрөмж таны Chromebook-с сална.</translation> <translation id="5823239091726045201">Веб дээрх Google tasks</translation> <translation id="5825969630400862129">Холбогдсон төхөөрөмжүүдийн тохиргоо</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />-г <ph name="ROUTE_TITLE" />-д дамжуулахаа зогсоох</translation> @@ -1396,6 +1400,7 @@ <translation id="6539852571005954999">Татах <ph name="FILENAME" />-г скан хийж байна</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" />-д дамжуулж байна</translation> <translation id="6546062506073634094">Контент болон зургийн урьдчилан үзэлтээр зураг хайх</translation> +<translation id="6547795021703527064">Та Bluetooth-г унтраах үед "<ph name="DEVICE_NAME" />" таны Chromebook-с сална.</translation> <translation id="6555373427270923730">Хаяг оруулах хэсэгт веб хаягийг бичээд дараа нь <ph name="MODIFIER" /><ph name="KEY" />-г дарна уу</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Шинээр суулгасан</translation>
diff --git a/ash/strings/ash_strings_mr.xtb b/ash/strings/ash_strings_mr.xtb index f16eee2..25a91a4 100644 --- a/ash/strings/ash_strings_mr.xtb +++ b/ash/strings/ash_strings_mr.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">शुभ दुपार <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">तुमचे <ph name="CATEGORY" />, फाइल, अॅप्स आणि आणखी बरेच काही शोधा. तुमची अॅप्स नेव्हिगेट करण्यासाठी, अॅरो की वापरा.</translation> <translation id="1093645050124056515">ctrl + alt + down arrow</translation> +<translation id="1094756674036064790">ब्लूटूथ बंद करायचे आहे का?</translation> <translation id="109942774857561566">मला कंटाळा आला आहे</translation> <translation id="1104084341931202936">ॲक्सेसिबिलिटी सेटिंग्ज दाखवा</translation> <translation id="1104621072296271835">तुमची डिव्हाइस एकत्र आणखी चांगले काम करतात</translation> @@ -195,7 +196,7 @@ <translation id="174102739345480129">मार्कर बंद आहे.</translation> <translation id="1743570585616704562">ओळखले नाही</translation> <translation id="1743927604032653654"><ph name="NOTIFICATION_TITLE" /> ही सूचना कोलॅप्स करा</translation> -<translation id="1746730358044914197">तुमच्या ॲडमिनिस्ट्रेटरद्वारे कॉंफिगर केलेल्या इनपुट पद्धती.</translation> +<translation id="1746730358044914197">तुमच्या ॲडमिनिस्ट्रेटरद्वारे कॉन्फिगर केलेल्या इनपुट पद्धती.</translation> <translation id="1747336645387973286">शेवटची तारीख <ph name="DUE_DATE" /></translation> <translation id="1747827819627189109">ऑन-स्क्रीन कीबोर्ड सक्षम</translation> <translation id="1749109475624620922">विंडो <ph name="WINDOW_TITLE" /> सर्व डेस्कना असाइन केले</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> ची उच्च दृश्यमानता टॉगल करा</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> व्यवस्थापित वापरकर्ता</translation> <translation id="3666266999138159418">तुमची फ्लोटिंग विंडो लपवण्यासाठी स्वाइप करा</translation> +<translation id="3673898235958558034">तुम्ही ब्लूटूथ बंद करता, तेव्हा "<ph name="DEVICE_NAME_1" />" आणि "<ph name="DEVICE_NAME_2" />" तुमच्या Chromebook वरून डिस्कनेक्ट केली जातील.</translation> <translation id="367531336287639526">अॅड्रेस बारच्या डावीकडील पहिला आयकन निवडा</translation> <translation id="3677931086890821290">हे स्थान परवानगीसह सर्व अॅप्स व वेबसाइट आणि ChromeOS ला वाय-फाय व मोबाइल नेटवर्क स्थान वापरण्याची अनुमती देते.</translation> <translation id="3679827876008292680">विंडोमधील मागील टॅबवर जा</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">आणखी अॅप्स</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> डाउनलोड करत आहे</translation> <translation id="4672539464599646374">बॅटरी सेव्हर सुरू केले आहे</translation> +<translation id="4673427585974421255">सुरू ठेवा</translation> <translation id="468293128311738995">तुमच्या फोनवरील अॅप्स</translation> <translation id="4690510401873698237">शेल्फ तळाशी आहे</translation> <translation id="4696813013609194136">पालक कोडने डिव्हाइस अनलॉक करा</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">क्विक सेटिंग्ज उघडा</translation> <translation id="5804651031882187592">"सिम लॉक करा" सेटिंग बंद करा</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> अॅक्टिव्हेट करण्यासाठी क्लिक करा</translation> +<translation id="5816222150329690597">तुम्ही ब्लूटूथ बंद करता, तेव्हा "<ph name="DEVICE_NAME_1" />" "<ph name="DEVICE_NAME_2" />" आणि <ph name="DEVICE_COUNT" /> इतर डिव्हाइस Chromebook वरून डिस्कनेक्ट केली जातील.</translation> <translation id="5823239091726045201">वेबवर Google कार्ये</translation> <translation id="5825969630400862129">कनेक्ट केलेली डिव्हाइस सेटिंग्ज</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> वर <ph name="ROUTE_TITLE" /> थांबवा</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999"><ph name="FILENAME" /> डाउनलोड स्कॅन करत आहे</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> वर कास्ट करत आहे</translation> <translation id="6546062506073634094">आशय आणि इमेज पूर्वावलोकनांद्वारे इमेज शोध</translation> +<translation id="6547795021703527064">तुम्ही ब्लूटूथ बंद करता, तेव्हा "<ph name="DEVICE_NAME" />" तुमच्या Chromebook वरून डिस्कनेक्ट केली जातील.</translation> <translation id="6555373427270923730">ॲड्रेस बारमध्ये वेब अॅड्रेस टाइप करा आणि त्यानंतर <ph name="MODIFIER" /><ph name="KEY" /> प्रेस करा</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> नवीन इंस्टॉल केले आहे</translation> @@ -1660,7 +1665,7 @@ <translation id="7658239707568436148">रद्द करा</translation> <translation id="7659861092419699379">डेस्क आणि विंडो बंद केल्या आहेत</translation> <translation id="7660160718439869192"><ph name="EMAIL" /> शी लिंक केलेल्या डिव्हाइसवर तुमचे <ph name="NAME" /> दिसेल</translation> -<translation id="7662283695561029522">कॉंफिगर करण्यासाठी टॅप करा</translation> +<translation id="7662283695561029522">कॉन्फिगर करण्यासाठी टॅप करा</translation> <translation id="7670953955701272011">Google Calendar यामध्ये ही तारीख उघडा</translation> <translation id="7671610481353807627">अॅप्स रंगानुसार क्रमाने लावली जातात</translation> <translation id="7672095158465655885"><ph name="NAME" />, <ph name="SUBTEXT" /> शी कनेक्ट केलेले</translation>
diff --git a/ash/strings/ash_strings_ne.xtb b/ash/strings/ash_strings_ne.xtb index 43df0fb..ec0e9d8 100644 --- a/ash/strings/ash_strings_ne.xtb +++ b/ash/strings/ash_strings_ne.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">नमस्ते <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">आफ्ना <ph name="CATEGORY" />, फाइल, एप र अन्य कुराहरू खोज्नुहोस्। आफ्ना एपहरूमा नेभिगेट गर्न एरो कीहरू प्रयोग गर्नुहोस्।</translation> <translation id="1093645050124056515">ctrl + alt + डाउन एरो</translation> +<translation id="1094756674036064790">ब्लुटुथ अफ गर्ने हो?</translation> <translation id="109942774857561566">मलाई दिक्क लागिसक्यो</translation> <translation id="1104084341931202936">एक्सेसिबिलिटी सेटिङ देखाउनुहोस्</translation> <translation id="1104621072296271835">तपाईंका यन्त्रहरूलाई सँगै प्रयोग गरेमा तिनले अझ राम्रो काम गर्छन्</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> को उच्च भिजिबिलिटी मोड अन/अफ गर्नुहोस्</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> व्यवस्थापन गरिएका प्रयोगकर्ता</translation> <translation id="3666266999138159418">फ्लोटिङ विन्डो लुकाउन स्वाइप गर्नुहोस्</translation> +<translation id="3673898235958558034">तपाईंले ब्लुटुथ अफ गर्नुभयो भने तपाईंको Chromebook बाट "<ph name="DEVICE_NAME_1" />" र "<ph name="DEVICE_NAME_2" />" डिस्कनेक्ट हुने छन्।</translation> <translation id="367531336287639526">एड्रेस बारमा भएको बायाँतिरको पहिलो वस्तु चयन गर्नुहोस्</translation> <translation id="3677931086890821290">तपाईंले यसो गर्नुभयो भने लोकेसन प्रयोग गर्ने अनुमति दिइएका सबै एप तथा वेबसाइटहरू अनि ChromeOS ले Wi-Fi र मोबाइल नेटवर्कको लोकेसन प्रयोग गर्न पाउँछन्।</translation> <translation id="3679827876008292680">विन्डोमा रहेको अन्तिम ट्याबमा जानुहोस्</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">थप एपहरू</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> डाउनलोड गरिँदै छ</translation> <translation id="4672539464599646374">ब्याट्री सेभर अन गरिएको छ</translation> +<translation id="4673427585974421255">अन नै छाड्नुहोस्</translation> <translation id="468293128311738995">तपाईंको फोनमा भएका एपहरू</translation> <translation id="4690510401873698237">सेल्फ पुछारमा छ</translation> <translation id="4696813013609194136">अभिभावकको कोडमार्फत डिभाइस अनलक गर्नुहोस्</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">द्रुत सेटिङ खोल्नुहोस्</translation> <translation id="5804651031882187592">"SIM लक गर्नुहोस्" सेटिङ अफ गर्नुहोस्</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> अन गर्न क्लिक गर्नुहोस्</translation> +<translation id="5816222150329690597">तपाईंले ब्लुटुथ अफ गर्नुभयो भने तपाईंको Chromebook बाट "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" र अन्य <ph name="DEVICE_COUNT" /> वटा डिभाइस डिस्कनेक्ट हुने छन्।</translation> <translation id="5823239091726045201">वेबमा उपलब्ध Google Tasks</translation> <translation id="5825969630400862129">कनेक्ट गरिएका यन्त्रहरूसम्बन्धी सेटिङ</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> मा <ph name="ROUTE_TITLE" /> बन्द गर्नुहोस्</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999"><ph name="FILENAME" /> स्क्यान गरेर डाउनलोड गर्नुहोस्</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> मा Cast गर्दै</translation> <translation id="6546062506073634094">फोटोमा भएको सामग्री र फोटोको प्रिभ्यूका आधारमा फोटो खोज्ने सुविधा</translation> +<translation id="6547795021703527064">तपाईंले ब्लुटुथ अफ गर्नुभयो भने तपाईंको Chromebook बाट "<ph name="DEVICE_NAME" />" डिस्कनेक्ट हुने छ।</translation> <translation id="6555373427270923730">एड्रेस बारमा वेब ठेगाना टाइप गर्नुहोस् अनि <ph name="MODIFIER" /><ph name="KEY" /> थिच्नुहोस्</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> भर्खरै इन्स्टल गरिएको छ</translation>
diff --git a/ash/strings/ash_strings_nl.xtb b/ash/strings/ash_strings_nl.xtb index b6ce665..9327169 100644 --- a/ash/strings/ash_strings_nl.xtb +++ b/ash/strings/ash_strings_nl.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Goedemiddag <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Doorzoek onder andere je <ph name="CATEGORY" />, bestanden en apps… Gebruik de pijltoetsen om door je apps te navigeren.</translation> <translation id="1093645050124056515">ctrl + alt + pijl-omlaag</translation> +<translation id="1094756674036064790">Bluetooth uitzetten?</translation> <translation id="109942774857561566">Ik verveel me</translation> <translation id="1104084341931202936">Toegankelijkheidsinstellingen bekijken</translation> <translation id="1104621072296271835">Je apparaten werken samen nog beter</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Hoge zichtbaarheid voor <ph name="FEATURE_NAME" /> aan-/uitzetten</translation> <translation id="366222428570480733">Beheerde gebruiker <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Swipe om het zwevende venster te verbergen</translation> +<translation id="3673898235958558034">Als je bluetooth uitzet, wordt de verbinding van <ph name="DEVICE_NAME_1" /> en <ph name="DEVICE_NAME_2" /> met je Chromebook verbroken.</translation> <translation id="367531336287639526">Het eerste icoon links van de adresbalk selecteren</translation> <translation id="3677931086890821290">Hiermee kunnen alle apps en websites met locatierechten en ChromeOS de locatie van wifi en mobiele netwerken gebruiken.</translation> <translation id="3679827876008292680">Naar het laatste tabblad in het venster gaan</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Meer apps</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> downloaden</translation> <translation id="4672539464599646374">Batterijbesparing staat aan</translation> +<translation id="4673427585974421255">Aan laten</translation> <translation id="468293128311738995">Apps op je telefoon</translation> <translation id="4690510401873698237">Plank aan onderkant</translation> <translation id="4696813013609194136">Apparaat ontgrendelen met oudercode</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Snelle instellingen openen</translation> <translation id="5804651031882187592">De instelling Simkaart vergrendelen uitzetten</translation> <translation id="5805809050170488595">Klik om <ph name="NETWORK_NAME" /> te activeren</translation> +<translation id="5816222150329690597">Als je bluetooth uitzet, wordt de verbinding van <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> en <ph name="DEVICE_COUNT" /> andere apparaten met je Chromebook verbroken.</translation> <translation id="5823239091726045201">Google Tasks op het web</translation> <translation id="5825969630400862129">Instellingen voor verbonden apparaten</translation> <translation id="5837036133683224804"><ph name="ROUTE_TITLE" /> in <ph name="RECEIVER_NAME" /> stopzetten</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999"><ph name="FILENAME" /> scannen voor downloaden</translation> <translation id="6542521951477560771">Er wordt gecast naar <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Afbeeldingen zoeken op basis van content en afbeeldingsvoorbeelden</translation> +<translation id="6547795021703527064">Als je bluetooth uitzet, wordt de verbinding van <ph name="DEVICE_NAME" /> met je Chromebook verbroken.</translation> <translation id="6555373427270923730">Typ een webadres in de adresbalk en druk dan op <ph name="MODIFIER" /> en <ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Nieuwe installatie</translation>
diff --git a/ash/strings/ash_strings_no.xtb b/ash/strings/ash_strings_no.xtb index 71241231..9b2257ff 100644 --- a/ash/strings/ash_strings_no.xtb +++ b/ash/strings/ash_strings_no.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">God ettermiddag, <ph name="GIVEN_NAME" /></translation> <translation id="1088231044944504242">Søk i <ph name="CATEGORY" />, filer, apper med mer. Bruk piltastene til å navigere i appene dine.</translation> <translation id="1093645050124056515">ctrl + alt + nedoverpil</translation> +<translation id="1094756674036064790">Vil du slå av Bluetooth?</translation> <translation id="109942774857561566">Jeg kjeder meg</translation> <translation id="1104084341931202936">Vis innstillinger for tilgjengelighet</translation> <translation id="1104621072296271835">Enhetene fungerer enda bedre sammen</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Slå av/på høy synlighet for <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> – administrert bruker</translation> <translation id="3666266999138159418">Sveip for å skjule det flytende vinduet</translation> +<translation id="3673898235958558034">Når du slår av Bluetooth, blir «<ph name="DEVICE_NAME_1" />» og «<ph name="DEVICE_NAME_2" />» koblet fra Chromebooken.</translation> <translation id="367531336287639526">Velg det første ikonet til venstre for adressefeltet</translation> <translation id="3677931086890821290">Dette gir alle apper og nettsteder med posisjonstillatelse og ChromeOS tillatelse til å bruke wifi- og mobilnettverksposisjon.</translation> <translation id="3679827876008292680">Gå til den siste fanen i vinduet</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Flere apper</translation> <translation id="4667099493359681081">Laster ned <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Batterisparing er slått på</translation> +<translation id="4673427585974421255">Behold på</translation> <translation id="468293128311738995">Apper fra telefonen din</translation> <translation id="4690510401873698237">Hyllen er nederst</translation> <translation id="4696813013609194136">Lås opp enheten med foreldrekode</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Åpne Hurtiginnstillinger</translation> <translation id="5804651031882187592">Slå av innstillingen «Lås SIM-kortet»</translation> <translation id="5805809050170488595">Klikk for å aktivere <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Når du slår av Bluetooth, blir «<ph name="DEVICE_NAME_1" />», «<ph name="DEVICE_NAME_2" />» og <ph name="DEVICE_COUNT" /> enheter til koblet fra Chromebooken.</translation> <translation id="5823239091726045201">Google Oppgaver på nettet</translation> <translation id="5825969630400862129">Innstillinger for tilkoblede enheter</translation> <translation id="5837036133683224804">Stopp <ph name="ROUTE_TITLE" /> på <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Nedlastingen skannes: <ph name="FILENAME" /></translation> <translation id="6542521951477560771">Caster til <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Bildesøk basert på innhold og bildeforhåndsvisninger</translation> +<translation id="6547795021703527064">Når du slår av Bluetooth, blir «<ph name="DEVICE_NAME" />» koblet fra Chromebooken.</translation> <translation id="6555373427270923730">Skriv inn en nettadresse i adressefeltet, og trykk deretter på <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Nylig installert</translation>
diff --git a/ash/strings/ash_strings_pa.xtb b/ash/strings/ash_strings_pa.xtb index 9d6ce58..156bc0e 100644 --- a/ash/strings/ash_strings_pa.xtb +++ b/ash/strings/ash_strings_pa.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">ਆਪਣੀ <ph name="CATEGORY" />, ਫ਼ਾਈਲਾਂ, ਐਪਾਂ, ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ ਖੋਜੋ। ਆਪਣੀਆਂ ਐਪਾਂ ਵਿੱਚ ਨੈਵੀਗੇਟ ਕਰਨ ਲਈ ਤੀਰ ਕੁੰਜੀਆਂ ਵਰਤੋ।</translation> <translation id="1093645050124056515">Ctrl + alt + ਹੇਠਾਂ ਤੀਰ</translation> +<translation id="1094756674036064790">ਕੀ ਬਲੂਟੁੱਥ ਨੂੰ ਬੰਦ ਕਰਨਾ ਹੈ?</translation> <translation id="109942774857561566">ਮੈਂ ਬੋਰ ਹੋ ਚੁੱਕਾ/ਚੁੱਕੀ ਹਾਂ</translation> <translation id="1104084341931202936">ਪਹੁੰਚਯੋਗਤਾ ਸੈਟਿੰਗਾਂ ਦਿਖਾਓ</translation> <translation id="1104621072296271835">ਰਲ ਕੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਹੋਰ ਵੀ ਬਿਹਤਰ ਕੰਮ ਕਰਦੇ ਹਨ</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">ਉੱਚ ਦਿਖਣਯੋਗਤਾ <ph name="FEATURE_NAME" /> ਨੂੰ ਟੌਗਲ ਕਰੋ</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> ਪ੍ਰਬੰਧਿਤ ਵਰਤੋਂਕਾਰ</translation> <translation id="3666266999138159418">ਆਪਣੀ ਫਲੋਟਿੰਗ ਵਿੰਡੋ ਨੂੰ ਲੁਕਾਉਣ ਲਈ ਸਵਾਈਪ ਕਰੋ</translation> +<translation id="3673898235958558034">ਜਦੋਂ ਤੁਸੀਂ ਬਲੂਟੁੱਥ ਬੰਦ ਕਰਦੇ ਹੋ, ਤਾਂ "<ph name="DEVICE_NAME_1" />" ਅਤੇ "<ph name="DEVICE_NAME_2" />" ਤੁਹਾਡੀ Chromebook ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਣਗੇ।</translation> <translation id="367531336287639526">ਪਤਾ ਬਾਰ ਦੇ ਖੱਬੇ ਪਾਸੇ ਵਾਲੇ ਪਹਿਲੇ ਪ੍ਰਤੀਕ ਨੂੰ ਚੁਣੋ</translation> <translation id="3677931086890821290">ਇਸ ਨਾਲ ਉਨ੍ਹਾਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਨੂੰ ਵਾਈ-ਫਾਈ ਅਤੇ ਮੋਬਾਈਲ ਨੈੱਟਵਰਕਾਂ ਦਾ ਟਿਕਾਣਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ ਜਿਨ੍ਹਾਂ ਕੋਲ ਟਿਕਾਣਾ ਇਜਾਜ਼ਤ ਅਤੇ ChromeOS ਹੈ।</translation> <translation id="3679827876008292680">ਵਿੰਡੋ ਵਿੱਚ ਆਖਰੀ ਟੈਬ 'ਤੇ ਜਾਓ</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">ਹੋਰ ਐਪਾਂ</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> ਨੂੰ ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ</translation> <translation id="4672539464599646374">ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ</translation> +<translation id="4673427585974421255">ਚਾਲੂ ਰੱਖੋ</translation> <translation id="468293128311738995">ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਐਪਾਂ</translation> <translation id="4690510401873698237">ਹੇਠਲੇ 'ਤੇ ਸ਼ੈਲਫ਼</translation> <translation id="4696813013609194136">ਮਾਂ-ਪਿਓ ਦੇ ਕੋਡ ਨਾਲ ਡੀਵਾਈਸ ਅਣਲਾਕ ਕਰੋ</translation> @@ -1216,6 +1219,7 @@ <translation id="5802516411616338943">ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਖੋਲ੍ਹੋ</translation> <translation id="5804651031882187592">"ਸਿਮ ਲਾਕ" ਸੈਟਿੰਗ ਨੂੰ ਬੰਦ ਕਰੋ</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ</translation> +<translation id="5816222150329690597">ਜਦੋਂ ਤੁਸੀਂ ਬਲੂਟੁੱਥ ਬੰਦ ਕਰਦੇ ਹੋ, ਤਾਂ "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" ਅਤੇ <ph name="DEVICE_COUNT" /> ਹੋਰ ਡੀਵਾਈਸ ਤੁਹਾਡੀ Chromebook ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਣਗੇ।</translation> <translation id="5823239091726045201">ਵੈੱਬ 'ਤੇ Google Tasks</translation> <translation id="5825969630400862129">ਕਨੈਕਟ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਦੀਆਂ ਸੈਟਿੰਗਾਂ</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> 'ਤੇ <ph name="ROUTE_TITLE" /> ਨੂੰ ਬੰਦ ਕਰੋ</translation> @@ -1396,6 +1400,7 @@ <translation id="6539852571005954999">ਡਾਊਨਲੋਡ ਹੋ ਰਹੀ <ph name="FILENAME" /> ਫ਼ਾਈਲ ਨੂੰ ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> 'ਤੇ ਕਾਸਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ</translation> <translation id="6546062506073634094">ਸਮੱਗਰੀ ਅਤੇ ਚਿੱਤਰ ਦੀਆਂ ਪੂਰਵ-ਝਲਕਾਂ ਮੁਤਾਬਕ ਚਿੱਤਰ ਖੋਜ</translation> +<translation id="6547795021703527064">ਜਦੋਂ ਤੁਸੀਂ ਬਲੂਟੁੱਥ ਬੰਦ ਕਰਦੇ ਹੋ, ਤਾਂ "<ph name="DEVICE_NAME" />" ਤੁਹਾਡੀ Chromebook ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਵੇਗਾ।</translation> <translation id="6555373427270923730">ਪਤਾ ਬਾਰ ਵਿੱਚ ਵੈੱਬ ਪਤਾ ਟਾਈਪ ਕਰੋ, ਫਿਰ <ph name="MODIFIER" /><ph name="KEY" /> ਦਬਾਓ</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> ਨਵੀਂ ਸਥਾਪਤ ਕੀਤੀ ਗਈ</translation>
diff --git a/ash/strings/ash_strings_pt-BR.xtb b/ash/strings/ash_strings_pt-BR.xtb index f3b6fc1b..a089f211 100644 --- a/ash/strings/ash_strings_pt-BR.xtb +++ b/ash/strings/ash_strings_pt-BR.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Boa tarde, <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Pesquise <ph name="CATEGORY" />, arquivos, apps e muito mais. Use as setas para navegar pelos apps.</translation> <translation id="1093645050124056515">ctrl + alt + seta para baixo</translation> +<translation id="1094756674036064790">Desativar o Bluetooth?</translation> <translation id="109942774857561566">Que tédio</translation> <translation id="1104084341931202936">Mostrar configurações de acessibilidade</translation> <translation id="1104621072296271835">Seus dispositivos funcionam ainda melhor juntos</translation> @@ -98,7 +99,7 @@ <translation id="1306549533752902673">APPS RECOMENDADOS</translation> <translation id="1311294419381837540">Você está transmitindo uma guia. É possível pausar ou interromper a transmissão a qualquer momento.</translation> <translation id="1312604459020188865">Intensidade do sinal em <ph name="SIGNAL_STRENGTH" /></translation> -<translation id="1316069254387866896">Sempre mostrar estante</translation> +<translation id="1316069254387866896">Sempre mostrar a barra</translation> <translation id="132346741904777634">Câmera alinhada ao canto esquerdo de cima. Conflito com a superfície do sistema.</translation> <translation id="1333308631814936910"><ph name="DISPLAY_NAME" /> conectado</translation> <translation id="1340378040547539434">Diminuir zoom na página</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Ativar/desativar a alta visibilidade do recurso "<ph name="FEATURE_NAME" />"</translation> <translation id="366222428570480733">Usuário gerenciado <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Deslize para ocultar a janela flutuante</translation> +<translation id="3673898235958558034">Quando você desativar o Bluetooth, os dispositivos <ph name="DEVICE_NAME_1" /> e <ph name="DEVICE_NAME_2" /> serão desconectados do Chromebook.</translation> <translation id="367531336287639526">Selecionar o primeiro ícone à esquerda da barra de endereço</translation> <translation id="3677931086890821290">Isso permite que todos os apps e sites com permissão de localização e o ChromeOS usem a localização de redes móveis e Wi-Fi.</translation> <translation id="3679827876008292680">Ir para a última guia na janela</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Mais apps</translation> <translation id="4667099493359681081">Fazendo o download do arquivo <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Economia de bateria ativada</translation> +<translation id="4673427585974421255">Deixar ativado</translation> <translation id="468293128311738995">Apps do smartphone</translation> <translation id="4690510401873698237">Estante na parte inferior</translation> <translation id="4696813013609194136">Desbloquear dispositivo usando o código de familiar responsável</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Abrir as Configurações rápidas</translation> <translation id="5804651031882187592">Desative a configuração "Bloquear chip"</translation> <translation id="5805809050170488595">Clique para ativar <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Quando você desativar o Bluetooth, <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> e mais <ph name="DEVICE_COUNT" /> dispositivos serão desconectados do Chromebook.</translation> <translation id="5823239091726045201">Google Tarefas na Web</translation> <translation id="5825969630400862129">Configurações de dispositivos conectados</translation> <translation id="5837036133683224804">Parar <ph name="ROUTE_TITLE" /> para <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Verificando o arquivo <ph name="FILENAME" /> para download</translation> <translation id="6542521951477560771">Transmitindo para <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Pesquisa de imagens por conteúdo e visualizações de imagens</translation> +<translation id="6547795021703527064">Quando você desativar o Bluetooth, o dispositivo <ph name="DEVICE_NAME" /> será desconectado do Chromebook.</translation> <translation id="6555373427270923730">Digite um endereço da Web na barra de endereço e pressione <ph name="MODIFIER" /> + <ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Nova instalação</translation> @@ -1896,7 +1901,7 @@ <translation id="8641510901370802679">Mostrando informações sobre <ph name="ANSWER_TYPE" /></translation> <translation id="8646417893960517480">Timer de <ph name="TOTAL_TIME" /></translation> <translation id="8647931990447795414">Para adicionar uma pessoa, insira seu código de acesso do familiar responsável do Family Link</translation> -<translation id="8649597172973390955">Sempre mostrar estante</translation> +<translation id="8649597172973390955">Sempre mostrar a barra</translation> <translation id="8652175077544655965">Fechar configurações</translation> <translation id="8653151467777939995">Mostrar configurações de notificação. As notificações estão ativadas</translation> <translation id="8660331759611631213">Raiz quadrada de 71</translation>
diff --git a/ash/strings/ash_strings_ro.xtb b/ash/strings/ash_strings_ro.xtb index a3fa6e1..afd4fff 100644 --- a/ash/strings/ash_strings_ro.xtb +++ b/ash/strings/ash_strings_ro.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Bună ziua, <ph name="GIVEN_NAME" />!</translation> <translation id="1088231044944504242">Caută în <ph name="CATEGORY" />, fișiere, aplicații și altele. Folosește tastele săgeți ca să navighezi prin aplicații.</translation> <translation id="1093645050124056515">ctrl + alt + săgeată în jos</translation> +<translation id="1094756674036064790">Dezactivezi Bluetooth?</translation> <translation id="109942774857561566">M-am plictisit</translation> <translation id="1104084341931202936">Afișează setările de accesibilitate</translation> <translation id="1104621072296271835">Dispozitivele funcționează și mai bine împreună</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Activează / dezactivează vizibilitatea crescută pentru <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733">Utilizatorul gestionat <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">Glisează pentru a ascunde fereastra flotantă</translation> +<translation id="3673898235958558034">Când dezactivezi Bluetooth, <ph name="DEVICE_NAME_1" /> și <ph name="DEVICE_NAME_2" /> se vor deconecta de la Chromebook.</translation> <translation id="367531336287639526">Selectează prima pictogramă din stânga barei de adrese</translation> <translation id="3677931086890821290">Astfel, toate aplicațiile și site-urile care au permisiunea pentru locație și ChromeOS pot să folosească locația prin Wi-Fi și rețele mobile.</translation> <translation id="3679827876008292680">Accesează ultima filă din fereastră</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Mai multe aplicații</translation> <translation id="4667099493359681081">Se descarcă <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Economisirea bateriei este activată</translation> +<translation id="4673427585974421255">Menține activată</translation> <translation id="468293128311738995">Aplicații de pe telefon</translation> <translation id="4690510401873698237">Raft în partea de jos</translation> <translation id="4696813013609194136">Deblochează dispozitivul cu codul părintelui</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Deschide Setările rapide</translation> <translation id="5804651031882187592">Dezactivează setarea Blochează cardul SIM</translation> <translation id="5805809050170488595">Dă clic pentru a activa <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Când dezactivezi Bluetooth, <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> și încă <ph name="DEVICE_COUNT" /> dispozitive se vor deconecta de la Chromebook.</translation> <translation id="5823239091726045201">Google Tasks pe web</translation> <translation id="5825969630400862129">Setări pentru dispozitivele conectate</translation> <translation id="5837036133683224804">Întrerupe <ph name="ROUTE_TITLE" /> pe <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Se scanează <ph name="FILENAME" /> pentru descărcare</translation> <translation id="6542521951477560771">Se proiectează conținut la <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Căutare de imagini după conținut și previzualizări ale imaginilor</translation> +<translation id="6547795021703527064">Când dezactivezi Bluetooth, <ph name="DEVICE_NAME" /> se va deconecta de la Chromebook.</translation> <translation id="6555373427270923730">Introdu o adresă web în bara de adrese, apoi apasă pe <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Instalare nouă</translation>
diff --git a/ash/strings/ash_strings_si.xtb b/ash/strings/ash_strings_si.xtb index 75af2da..85deadb2 100644 --- a/ash/strings/ash_strings_si.xtb +++ b/ash/strings/ash_strings_si.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">සුබ අපරභාගයක් <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">ඔබගේ <ph name="CATEGORY" />, ගොනු, යෙදුම් සහ තවත් දේ සොයන්න. ඔබගේ යෙදුම්වලට සංචාලනය කිරීමට ඊතල යතුරු භාවිත කරන්න.</translation> <translation id="1093645050124056515">ctrl + alt + පහළට ඊතලය</translation> +<translation id="1094756674036064790">බ්ලූටූත් අක්රිය කරන්නද?</translation> <translation id="109942774857561566">මට කම්මැලියි</translation> <translation id="1104084341931202936">ප්රවේශ්යතා සැකසීම් පෙන්වන්න</translation> <translation id="1104621072296271835">ඔබේ උපාංග එක්ව වඩා හොඳින් වැඩ කරයි</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">ඉහළ දෘශ්යතා <ph name="FEATURE_NAME" /> ටොගල් කරන්න</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> කළමනා කරන පරිශීලකයා</translation> <translation id="3666266999138159418">ඔබේ පාවෙන කවුළුව සැඟවීමට ස්වයිප් කරන්න</translation> +<translation id="3673898235958558034">ඔබ බ්ලූටූත් අක්රිය කළ විට, "<ph name="DEVICE_NAME_1" />" සහ "<ph name="DEVICE_NAME_2" />" ඔබේ Chromebook වෙතින් විසන්ධි වෙයි.</translation> <translation id="367531336287639526">ලිපින තීරුවේ වම් පස පළමු නිරූපකය තෝරන්න</translation> <translation id="3677931086890821290">මෙය ස්ථාන අවසරය ඇති සියලු යෙදුම් සහ වෙබ් අඩවිවලට සහ ChromeOS හට Wi-Fi සහ ජංගම ජාල ස්ථානය භාවිතා කිරීමට ඉඩ දෙයි.</translation> <translation id="3679827876008292680">කවුළුවේ අවසාන පටිත්ත වෙත යන්න</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">තවත් යෙදුම්</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> බාගනිමින්</translation> <translation id="4672539464599646374">බැටරි සුරැකුම ක්රියාත්මකයි</translation> +<translation id="4673427585974421255">සක්රීයව තබන්න</translation> <translation id="468293128311738995">ඔබේ දුරකථනය වෙතින් යෙදුම්</translation> <translation id="4690510401873698237">පහළ ඇති රාක්කය</translation> <translation id="4696813013609194136">මාපිය කේතය සමඟ උපාංගය අඟුලු අරින්න</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">ක්ෂණික සැකසීම් විවෘත කරන්න</translation> <translation id="5804651031882187592">"SIM අගුළු දැමීමේ" සැකසීම ක්රියා විරහිත කරන්න</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> සක්රිය කිරීමට ක්ලික් කරන්න</translation> +<translation id="5816222150329690597">ඔබ බ්ලූටූත් අක්රිය කළ විට, "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" සහ තවත් උපාංග "<ph name="DEVICE_COUNT" />" ඔබේ Chromebook වෙතින් විසන්ධි වෙයි.</translation> <translation id="5823239091726045201">වෙබ් මත Google Tasks</translation> <translation id="5825969630400862129">සම්බන්ධිත උපාංග සැකසීම්</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> මත <ph name="ROUTE_TITLE" /> නවත්වන්න</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">ස්කෑන් කරන <ph name="FILENAME" /> බාගන්න</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> වෙත විකාශය කරමින්</translation> <translation id="6546062506073634094">අන්තර්ගතය සහ රූප පෙරදසුන් අනුව රූප සෙවීම</translation> +<translation id="6547795021703527064">ඔබ බ්ලූටූත් අක්රිය කළ විට, "<ph name="DEVICE_NAME" />" ඔබේ Chromebook වෙතින් විසන්ධි වෙයි.</translation> <translation id="6555373427270923730">ලිපින තීරුවෙහි වෙබ් ලිපිනයක් ටයිප් කර, අනතුරුව <ph name="MODIFIER" /><ph name="KEY" /> ඔබන්න</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> නව ස්ථාපනය</translation>
diff --git a/ash/strings/ash_strings_sl.xtb b/ash/strings/ash_strings_sl.xtb index b25cfbbd..4bceeaa 100644 --- a/ash/strings/ash_strings_sl.xtb +++ b/ash/strings/ash_strings_sl.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Dober dan, <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Iščite po <ph name="CATEGORY" />, datotekah, aplikacijah in drugem. S puščičnimi tipkami se pomikajte po aplikacijah.</translation> <translation id="1093645050124056515">ctrl + alt + puščica dol</translation> +<translation id="1094756674036064790">Želite izklopiti Bluetooth?</translation> <translation id="109942774857561566">Dolgočasim se</translation> <translation id="1104084341931202936">Prikaz nastavitev funkcij za ljudi s posebnimi potrebami</translation> <translation id="1104621072296271835">Naprave delujejo še bolje skupaj</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Preklop visoke vidnosti funkcije <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Upravljani uporabnik</translation> <translation id="3666266999138159418">Povlecite, če želite skriti plavajoče okno</translation> +<translation id="3673898235958558034">Ko izklopite Bluetooth, bo povezava naprav »<ph name="DEVICE_NAME_1" />« in »<ph name="DEVICE_NAME_2" />« s Chromebookom prekinjena.</translation> <translation id="367531336287639526">Izbira prve ikone levo od naslovne vrstice</translation> <translation id="3677931086890821290">To vsem aplikacijam ter spletnim mestom, ki imajo dovoljenje za lokacijo, in sistemu ChromeOS omogoča uporabo lokacije omrežij Wi-Fi in mobilnih omrežij.</translation> <translation id="3679827876008292680">Premik na zadnji zavihek v oknu</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Več aplikacij</translation> <translation id="4667099493359681081">Prenašanje datoteke <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Varčevanje z energijo baterije je vklopljeno</translation> +<translation id="4673427585974421255">Pusti vklopljeno</translation> <translation id="468293128311738995">Aplikacije iz telefona</translation> <translation id="4690510401873698237">Polica na dnu</translation> <translation id="4696813013609194136">Odklepanje naprave s kodo starša</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Odpiranje hitrih nastavitev</translation> <translation id="5804651031882187592">Izklop nastavitve zaklepanja kartice SIM</translation> <translation id="5805809050170488595">Kliknite, če želite aktivirati omrežje <ph name="NETWORK_NAME" />.</translation> +<translation id="5816222150329690597">Ko izklopite Bluetooth, bo povezava naprav »<ph name="DEVICE_NAME_1" />«, »<ph name="DEVICE_NAME_2" />« in še <ph name="DEVICE_COUNT" /> s Chromebookom prekinjena.</translation> <translation id="5823239091726045201">Google Opravila v spletu</translation> <translation id="5825969630400862129">Nastavitve povezanih naprav</translation> <translation id="5837036133683224804">Ustavi zavihek <ph name="ROUTE_TITLE" /> v sprejemniku <ph name="RECEIVER_NAME" /></translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Pregledovanje prenosa: <ph name="FILENAME" /></translation> <translation id="6542521951477560771">Predvajanje v napravi <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Iskanje slik po vsebini in predogledih slik</translation> +<translation id="6547795021703527064">Ko izklopite Bluetooth, bo povezava naprave »<ph name="DEVICE_NAME" />« s Chromebookom prekinjena.</translation> <translation id="6555373427270923730">Vnesite spletni naslov v naslovno vrstico, nato pritisnite <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Nova namestitev</translation>
diff --git a/ash/strings/ash_strings_sr-Latn.xtb b/ash/strings/ash_strings_sr-Latn.xtb index 3c07121..897f837 100644 --- a/ash/strings/ash_strings_sr-Latn.xtb +++ b/ash/strings/ash_strings_sr-Latn.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Dobar dan, <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Pretražujte kategoriju <ph name="CATEGORY" />, fajlove, aplikacije i drugo. Koristite tastere sa strelicama da biste se kretali kroz aplikacije.</translation> <translation id="1093645050124056515">ctrl + alt + strelica nadole</translation> +<translation id="1094756674036064790">Želite da isključite Bluetooth?</translation> <translation id="109942774857561566">Dosadno mi je</translation> <translation id="1104084341931202936">Pregledajte podešavanja pristupačnosti</translation> <translation id="1104621072296271835">Uređaji zajedno funkcionišu još bolje</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Uključite/isključite veliku vidljivost funkcije <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Korisnik kojim se upravlja</translation> <translation id="3666266999138159418">Prevucite da biste sakrili plutajući prozor</translation> +<translation id="3673898235958558034">Kada isključite Bluetooth, uređaji <ph name="DEVICE_NAME_1" /> i <ph name="DEVICE_NAME_2" /> će prekinuti vezu sa Chromebook-om.</translation> <translation id="367531336287639526">Izaberite prvu ikonu sa leve strane trake za adresu</translation> <translation id="3677931086890821290">Ovo omogućava svim aplikacijama i veb-sajtovima sa dozvolom za lokaciju i ChromeOS-om da koriste lokaciju WiFi-ja i mobilnih mreža.</translation> <translation id="3679827876008292680">Idi na poslednju karticu u prozoru</translation> @@ -916,6 +918,7 @@ <translation id="4666911709726371538">Još aplikacija</translation> <translation id="4667099493359681081">Preuzima se fajl <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Ušteda baterije je uključena</translation> +<translation id="4673427585974421255">Nastavi</translation> <translation id="468293128311738995">Aplikacije sa telefona</translation> <translation id="4690510401873698237">Polica u dnu</translation> <translation id="4696813013609194136">Otključajte uređaj pomoću koda roditelja</translation> @@ -1216,6 +1219,7 @@ <translation id="5802516411616338943">Otvori Brza podešavanja</translation> <translation id="5804651031882187592">Isključite podešavanje Zaključaj SIM</translation> <translation id="5805809050170488595">Kliknite da biste aktivirali <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Kada isključite Bluetooth, uređaji <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> i još njih <ph name="DEVICE_COUNT" /> će prekinuti vezu sa Chromebook-om.</translation> <translation id="5823239091726045201">Google zadaci na vebu</translation> <translation id="5825969630400862129">Podešavanja povezanih uređaja</translation> <translation id="5837036133683224804">Zaustavi <ph name="ROUTE_TITLE" /> na uređaju <ph name="RECEIVER_NAME" /></translation> @@ -1396,6 +1400,7 @@ <translation id="6539852571005954999">Skenira se fajl <ph name="FILENAME" /> koji se preuzima</translation> <translation id="6542521951477560771">Prebacuje se na <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Pretraga slika prema sadržaju i pregledima slika</translation> +<translation id="6547795021703527064">Kada isključite Bluetooth, uređaj <ph name="DEVICE_NAME" /> će prekinuti vezu sa Chromebook-om.</translation> <translation id="6555373427270923730">Unesite veb-adresu u traku za adresu, pa pritisnite <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Novo instaliranje</translation>
diff --git a/ash/strings/ash_strings_sr.xtb b/ash/strings/ash_strings_sr.xtb index c385098..e2fcd3b 100644 --- a/ash/strings/ash_strings_sr.xtb +++ b/ash/strings/ash_strings_sr.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Добар дан, <ph name="GIVEN_NAME" />,</translation> <translation id="1088231044944504242">Претражујте категорију <ph name="CATEGORY" />, фајлове, апликације и друго. Користите тастере са стрелицама да бисте се кретали кроз апликације.</translation> <translation id="1093645050124056515">ctrl + alt + стрелица надоле</translation> +<translation id="1094756674036064790">Желите да искључите Bluetooth?</translation> <translation id="109942774857561566">Досадно ми је</translation> <translation id="1104084341931202936">Прегледајте подешавања приступачности</translation> <translation id="1104621072296271835">Уређаји заједно функционишу још боље</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Укључите/искључите велику видљивост функције <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Корисник којим се управља</translation> <translation id="3666266999138159418">Превуците да бисте сакрили плутајући прозор</translation> +<translation id="3673898235958558034">Када искључите Bluetooth, уређаји <ph name="DEVICE_NAME_1" /> и <ph name="DEVICE_NAME_2" /> ће прекинути везу са Chromebook-ом.</translation> <translation id="367531336287639526">Изаберите прву икону са леве стране траке за адресу</translation> <translation id="3677931086890821290">Ово омогућава свим апликацијама и веб-сајтовима са дозволом за локацију и ChromeOS-ом да користе локацију WiFi-ја и мобилних мрежа.</translation> <translation id="3679827876008292680">Иди на последњу картицу у прозору</translation> @@ -916,6 +918,7 @@ <translation id="4666911709726371538">Још апликација</translation> <translation id="4667099493359681081">Преузима се фајл <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Уштеда батерије је укључена</translation> +<translation id="4673427585974421255">Настави</translation> <translation id="468293128311738995">Апликације са телефона</translation> <translation id="4690510401873698237">Полица у дну</translation> <translation id="4696813013609194136">Откључајте уређај помоћу кода родитеља</translation> @@ -1216,6 +1219,7 @@ <translation id="5802516411616338943">Отвори Брза подешавања</translation> <translation id="5804651031882187592">Искључите подешавање Закључај SIM</translation> <translation id="5805809050170488595">Кликните да бисте активирали <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Када искључите Bluetooth, уређаји <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> и још њих <ph name="DEVICE_COUNT" /> ће прекинути везу са Chromebook-ом.</translation> <translation id="5823239091726045201">Google задаци на вебу</translation> <translation id="5825969630400862129">Подешавања повезаних уређаја</translation> <translation id="5837036133683224804">Заустави <ph name="ROUTE_TITLE" /> на уређају <ph name="RECEIVER_NAME" /></translation> @@ -1396,6 +1400,7 @@ <translation id="6539852571005954999">Скенира се фајл <ph name="FILENAME" /> који се преузима</translation> <translation id="6542521951477560771">Пребацује се на <ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">Претрага слика према садржају и прегледима слика</translation> +<translation id="6547795021703527064">Када искључите Bluetooth, уређај <ph name="DEVICE_NAME" /> ће прекинути везу са Chromebook-ом.</translation> <translation id="6555373427270923730">Унесите веб-адресу у траку за адресу, па притисните <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Ново инсталирање</translation>
diff --git a/ash/strings/ash_strings_th.xtb b/ash/strings/ash_strings_th.xtb index 71ddb5e6..dc94a3a 100644 --- a/ash/strings/ash_strings_th.xtb +++ b/ash/strings/ash_strings_th.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">สวัสดียามบ่าย <ph name="GIVEN_NAME" /></translation> <translation id="1088231044944504242">ค้นหา<ph name="CATEGORY" /> ไฟล์ แอป และอื่นๆ ใช้แป้นลูกศรเพื่อไปยังส่วนต่างๆ ของแอป</translation> <translation id="1093645050124056515">Ctrl + Alt + ลูกศรลง</translation> +<translation id="1094756674036064790">ปิดบลูทูธไหม</translation> <translation id="109942774857561566">ฉันเบื่อจัง</translation> <translation id="1104084341931202936">แสดงการตั้งค่าการเข้าถึงพิเศษ</translation> <translation id="1104621072296271835">อุปกรณ์จะทำงานได้ดียิ่งขึ้นเมื่อใช้ร่วมกัน</translation> @@ -656,6 +657,7 @@ <translation id="3660860940251915011">เปิด/ปิดระดับการเข้าถึงสูงของ <ph name="FEATURE_NAME" /></translation> <translation id="366222428570480733">ผู้ใช้ที่ได้รับการจัดการ <ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">ปัดเพื่อซ่อนหน้าต่างแบบลอย</translation> +<translation id="3673898235958558034">เมื่อปิดบลูทูธ "<ph name="DEVICE_NAME_1" />" และ "<ph name="DEVICE_NAME_2" />" จะยกเลิกการเชื่อมต่อกับ Chromebook</translation> <translation id="367531336287639526">เลือกไอคอนแรกทางด้านซ้ายของแถบที่อยู่</translation> <translation id="3677931086890821290">การดำเนินการนี้ช่วยให้แอปและเว็บไซต์ทั้งหมดที่มีสิทธิ์เข้าถึงตำแหน่งและ ChromeOS ใช้ตำแหน่ง Wi-Fi และเครือข่ายมือถือได้</translation> <translation id="3679827876008292680">ไปยังแท็บสุดท้ายในหน้าต่าง</translation> @@ -910,6 +912,7 @@ <translation id="4666911709726371538">แสดงแอปเพิ่มเติม</translation> <translation id="4667099493359681081">กำลังดาวน์โหลด <ph name="FILENAME" /></translation> <translation id="4672539464599646374">เปิดโหมดประหยัดแบตเตอรี่แล้ว</translation> +<translation id="4673427585974421255">เปิดไว้</translation> <translation id="468293128311738995">แอปจากโทรศัพท์ของคุณ</translation> <translation id="4690510401873698237">ชั้นวางอยู่ด้านล่าง</translation> <translation id="4696813013609194136">ปลดล็อกอุปกรณ์ด้วยรหัสของผู้ปกครอง</translation> @@ -1210,6 +1213,7 @@ <translation id="5802516411616338943">เปิดการตั้งค่าด่วน</translation> <translation id="5804651031882187592">ปิดการตั้งค่า "ล็อกซิม"</translation> <translation id="5805809050170488595">คลิกเพื่อเปิดใช้ <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">เมื่อปิดบลูทูธ "<ph name="DEVICE_NAME_1" />", "<ph name="DEVICE_NAME_2" />" และอุปกรณ์อื่นอีก <ph name="DEVICE_COUNT" /> เครื่องจะยกเลิกการเชื่อมต่อกับ Chromebook</translation> <translation id="5823239091726045201">Google Tasks บนเว็บ</translation> <translation id="5825969630400862129">การตั้งค่าอุปกรณ์ที่เชื่อมต่อ</translation> <translation id="5837036133683224804">หยุด <ph name="ROUTE_TITLE" /> ใน<ph name="RECEIVER_NAME" /></translation> @@ -1390,6 +1394,7 @@ <translation id="6539852571005954999">กำลังสแกน <ph name="FILENAME" /> เพื่อดาวน์โหลด</translation> <translation id="6542521951477560771">แคสต์ไปที่<ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">ค้นหารูปภาพตามเนื้อหาและตัวอย่างรูปภาพ</translation> +<translation id="6547795021703527064">เมื่อปิดบลูทูธ "<ph name="DEVICE_NAME" />" จะยกเลิกการเชื่อมต่อกับ Chromebook</translation> <translation id="6555373427270923730">พิมพ์ที่อยู่เว็บในแถบที่อยู่แล้วกด <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> ติดตั้งใหม่</translation>
diff --git a/ash/strings/ash_strings_uk.xtb b/ash/strings/ash_strings_uk.xtb index 22a9df14..93fcd47 100644 --- a/ash/strings/ash_strings_uk.xtb +++ b/ash/strings/ash_strings_uk.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Доброго дня, <ph name="GIVEN_NAME" />!</translation> <translation id="1088231044944504242">Шукайте <ph name="CATEGORY" />, файли, додатки тощо. Натискайте клавіші зі стрілками, щоб переходити між додатками.</translation> <translation id="1093645050124056515">ctrl + alt + стрілка вниз</translation> +<translation id="1094756674036064790">Вимкнути Bluetooth?</translation> <translation id="109942774857561566">Мені нудно</translation> <translation id="1104084341931202936">Показати налаштування функцій доступності</translation> <translation id="1104621072296271835">Ваші пристрої працюватимуть разом ще краще</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">Перемикач режиму високої видимості для функції "<ph name="FEATURE_NAME" />"</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> – керований користувач</translation> <translation id="3666266999138159418">Проведіть пальцем, щоб сховати плаваюче вікно</translation> +<translation id="3673898235958558034">Якщо ви вимкнете Bluetooth, пристрої <ph name="DEVICE_NAME_1" /> і <ph name="DEVICE_NAME_2" /> від’єднаються від Chromebook.</translation> <translation id="367531336287639526">Вибрати значок ліворуч від адресного рядка</translation> <translation id="3677931086890821290">Усі додатки й веб-сайти, які мають дозвіл на доступ до геоданих, і ChromeOS зможуть використовувати Wi-Fi і мобільні мережі для геолокації.</translation> <translation id="3679827876008292680">Перейти на останню вкладку у вікні</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Більше додатків</translation> <translation id="4667099493359681081">Завантажується файл <ph name="FILENAME" /></translation> <translation id="4672539464599646374">Режим енергозбереження ввімкнено</translation> +<translation id="4673427585974421255">Не вимикати</translation> <translation id="468293128311738995">Додатки з вашого телефона</translation> <translation id="4690510401873698237">Полицю розміщено внизу</translation> <translation id="4696813013609194136">Введіть код доступу батьків</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Відкрити Швидкі налаштування</translation> <translation id="5804651031882187592">Вимкніть налаштування блокування SIM-карти</translation> <translation id="5805809050170488595">Натисніть, щоб активувати мережу <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">Якщо ви вимкнете Bluetooth, пристрої <ph name="DEVICE_NAME_1" />, <ph name="DEVICE_NAME_2" /> і ще <ph name="DEVICE_COUNT" /> від’єднаються від Chromebook.</translation> <translation id="5823239091726045201">Google Завдання у веб-переглядачі</translation> <translation id="5825969630400862129">Налаштування підключених пристроїв</translation> <translation id="5837036133683224804">Зупинити трансляцію <ph name="ROUTE_TITLE" /> на пристрій "<ph name="RECEIVER_NAME" />"</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">Сканування завантаженого файлу "<ph name="FILENAME" />"</translation> <translation id="6542521951477560771">Трансляція на пристрій "<ph name="RECEIVER_NAME" />"</translation> <translation id="6546062506073634094">Пошук зображень за вмістом і попереднім переглядом</translation> +<translation id="6547795021703527064">Якщо ви вимкнете Bluetooth, пристрій <ph name="DEVICE_NAME" /> від’єднається від Chromebook.</translation> <translation id="6555373427270923730">Введіть веб-адресу в адресному рядку й натисніть <ph name="MODIFIER" /><ph name="KEY" /></translation> <translation id="655633303491376835"><ph name="APP_NAME" /> Нове встановлення</translation>
diff --git a/ash/strings/ash_strings_ur.xtb b/ash/strings/ash_strings_ur.xtb index 7ee3ad69..3bd31ae 100644 --- a/ash/strings/ash_strings_ur.xtb +++ b/ash/strings/ash_strings_ur.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">سہ پہر بخیر <ph name="GIVEN_NAME" />،</translation> <translation id="1088231044944504242">اپنی <ph name="CATEGORY" />، فائلز، ایپس اور بہت کچھ تلاش کریں۔ اپنی ایپس کو نیویگیٹ کرنے کے لیے تیر کے نشان والی کلیدیں استعمال کریں۔</translation> <translation id="1093645050124056515">ctrl + alt + نیچے تیر کا نشان</translation> +<translation id="1094756674036064790">بلوٹوتھ آف کریں؟</translation> <translation id="109942774857561566">مجھے بوریت ہو رہی ہے</translation> <translation id="1104084341931202936">ایکسیسبیلٹی کی ترتیبات دکھائیں</translation> <translation id="1104621072296271835">آپ کے آلات مل کر اور بہتر کام کرتے ہیں</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> کی اعلی مرئیت کو ٹوگل کریں</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> نظم کردہ صارف</translation> <translation id="3666266999138159418">فلوٹنگ ونڈو کو چھپانے کے لیے سوائپ کریں</translation> +<translation id="3673898235958558034">بلوٹوتھ آف کرنے پر "<ph name="DEVICE_NAME_1" />" اور "<ph name="DEVICE_NAME_2" />" آپ کی Chromebook سے غیر منسلک ہو جائیں گے۔</translation> <translation id="367531336287639526">ایڈریس بار کے بائیں جانب موجود پہلے آئیکن کو منتخب کریں</translation> <translation id="3677931086890821290">اس سے سبھی ایپس اور ویب سائٹس کو مقام کی اجازت اور ChromeOS کے ساتھ Wi-Fi اور موبائل نیٹ ورکس کا مقام استعمال کرنے کی اجازت ملتی ہے۔</translation> <translation id="3679827876008292680">ونڈو میں آخری ٹیب پر جائیں</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">مزید ایپس</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> ڈاؤن لوڈ ہو رہی ہے</translation> <translation id="4672539464599646374">بیٹری سیور کو آن کیا گیا</translation> +<translation id="4673427585974421255">آن رکھیں</translation> <translation id="468293128311738995">آپ کے فون سے ایپس</translation> <translation id="4690510401873698237">شیلف نچلے حصے میں ہے</translation> <translation id="4696813013609194136">والدین کے کوڈ سے آلہ غیر مقفل کریں</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">فوری ترتیبات کھولیں</translation> <translation id="5804651031882187592">"SIM کو مقفل کریں" کی ترتیب آف کریں</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> کو فعال کرنے کیلئے کلک کریں</translation> +<translation id="5816222150329690597">بلوٹوتھ آف کرنے پر "<ph name="DEVICE_NAME_1" />" اور "<ph name="DEVICE_NAME_2" />" اور <ph name="DEVICE_COUNT" /> آلات آپ کی Chromebook سے غیر منسلک ہو جائیں گے۔</translation> <translation id="5823239091726045201">ویب پر Google ٹاسکس</translation> <translation id="5825969630400862129">منسلک کردہ آلات کی ترتیبات</translation> <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> پر <ph name="ROUTE_TITLE" /> کو روکیں</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999">اسکین ہونے والی <ph name="FILENAME" /> کو ڈاؤن لوڈ کریں</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> پر کاسٹ کیا جا رہا ہے</translation> <translation id="6546062506073634094">مواد اور تصویر کے پیش منظر کے لحاظ سے 'تصاویر کا استعمال کر کے تلاش'</translation> +<translation id="6547795021703527064">بلوٹوتھ آف کرنے پر "<ph name="DEVICE_NAME" />" آپ کی Chromebook سے غیر منسلک ہو جائے گا۔</translation> <translation id="6555373427270923730">ایڈریس بار میں ایک ویب پتہ ٹائپ کریں، پھر <ph name="MODIFIER" /><ph name="KEY" /> دبائیں</translation> <translation id="655633303491376835">نئی انسٹال کردہ <ph name="APP_NAME" /></translation> <translation id="6559976592393364813">منتظم سے پوچھیں</translation>
diff --git a/ash/strings/ash_strings_uz.xtb b/ash/strings/ash_strings_uz.xtb index fc822ee5..5ceb0e9 100644 --- a/ash/strings/ash_strings_uz.xtb +++ b/ash/strings/ash_strings_uz.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">Xayrli kun, <ph name="GIVEN_NAME" /></translation> <translation id="1088231044944504242"><ph name="CATEGORY" />, fayllar, ilovalar va boshqalarni qidirish. Ilovalarni strelka tugmalari yordamida varaqlang.</translation> <translation id="1093645050124056515">ctrl + alt + pastga strelka</translation> +<translation id="1094756674036064790">Bluetooth faolsizlantirilsinmi?</translation> <translation id="109942774857561566">Men zerikdim</translation> <translation id="1104084341931202936">Qulayliklar sozlamalarini ochish</translation> <translation id="1104621072296271835">Qurilmalaringiz birgalikda yaxshiroq ishlaydi</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011"><ph name="FEATURE_NAME" /> uchun keng ruxsat berish.</translation> <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> boshqariladigan hisob</translation> <translation id="3666266999138159418">Maullaq oynani yopish uchun suring</translation> +<translation id="3673898235958558034">Bluetooth sozlamasi oʻchganda "<ph name="DEVICE_NAME_1" />" va "<ph name="DEVICE_NAME_2" />" Chromebookdan uziladi.</translation> <translation id="367531336287639526">Manzil qatori chapidagi birinchi belgini tanlang</translation> <translation id="3677931086890821290">ChromeOS operatsion tizimi, shuningdek, joylashuv maʼlumotlariga kirish huquqiga ega boʻlgan barcha ilovalar va saytlarga geolokatsiya uchun Wi-Fi va mobil tarmoqdan foydalanishga ruxsat beriladi.</translation> <translation id="3679827876008292680">Oynadagi oxirgi varaqni ochish</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">Boshqa ilovalar</translation> <translation id="4667099493359681081"><ph name="FILENAME" /> yuklab olinmoqda</translation> <translation id="4672539464599646374">Quvvat tejalishi yoqildi</translation> +<translation id="4673427585974421255">Kerak emas</translation> <translation id="468293128311738995">Telefondagi ilovalar</translation> <translation id="4690510401873698237">Javon pastda</translation> <translation id="4696813013609194136">Ota-ona kodi bilan qurilmani qulfdan chiqarish</translation> @@ -1215,6 +1218,7 @@ <translation id="5802516411616338943">Tezkor sozlamalarni ochish</translation> <translation id="5804651031882187592">“SIM kartani qulflash” sozlamasini faolsizlantirish</translation> <translation id="5805809050170488595"><ph name="NETWORK_NAME" /> nomli tarmoqni faollashtirish uchun bosing</translation> +<translation id="5816222150329690597">Bluetooth sozlamasi oʻchganda "<ph name="DEVICE_NAME_1" />" va "<ph name="DEVICE_NAME_2" />" va yana <ph name="DEVICE_COUNT" /> ta qurilma Chromebookdan uziladi.</translation> <translation id="5823239091726045201">Google Tasks veb versiyasi</translation> <translation id="5825969630400862129">Ulangan qurilmalar sozlamalari</translation> <translation id="5837036133683224804"><ph name="ROUTE_TITLE" /> <ph name="RECEIVER_NAME" /> qurilmasiga translatsiya qilinishi to‘xtatilsin</translation> @@ -1395,6 +1399,7 @@ <translation id="6539852571005954999"><ph name="FILENAME" /> yuklanmasi tekshirilmoqda</translation> <translation id="6542521951477560771"><ph name="RECEIVER_NAME" /> qurilmasiga translatsiya qilinmoqda</translation> <translation id="6546062506073634094">Kontent va namunasi orqali rasm qidiruvi</translation> +<translation id="6547795021703527064">Bluetooth sozlamasi oʻchganda "<ph name="DEVICE_NAME" />" Chromebookdan uziladi.</translation> <translation id="6555373427270923730">Manzillar qatoriga veb-manzilni kiritib <ph name="MODIFIER" /><ph name="KEY" /> birikmasini bosing</translation> <translation id="655633303491376835"><ph name="APP_NAME" /> yangi oʻrnatilgan</translation>
diff --git a/ash/strings/ash_strings_zh-HK.xtb b/ash/strings/ash_strings_zh-HK.xtb index 378abe3..0bfdc514 100644 --- a/ash/strings/ash_strings_zh-HK.xtb +++ b/ash/strings/ash_strings_zh-HK.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426"><ph name="GIVEN_NAME" />,午安:</translation> <translation id="1088231044944504242">搜尋<ph name="CATEGORY" />、檔案、應用程式和其他內容,可使用方向鍵瀏覽應用程式。</translation> <translation id="1093645050124056515">Ctrl 鍵 + Alt 鍵 + 向下箭咀鍵</translation> +<translation id="1094756674036064790">要關閉藍牙嗎?</translation> <translation id="109942774857561566">我好悶</translation> <translation id="1104084341931202936">顯示無障礙功能設定</translation> <translation id="1104621072296271835">連結您的裝置,以獲得更佳的體驗</translation> @@ -607,11 +608,11 @@ <translation id="3526440770046466733">在新分頁中開啟連結並停留在目前的分頁中</translation> <translation id="353086728817903341">已連接 <ph name="NUM_DEVICES" /> 部裝置</translation> <translation id="3533126039236445965">捷徑列中的應用程式</translation> -<translation id="3537350467437346467">你查看過這個項目</translation> +<translation id="3537350467437346467">你已查看</translation> <translation id="3539957339480430241"><ph name="DEVICE_NAME" /> 熱點</translation> <translation id="3540893133818942399">取消設定查看手機最近的相片和媒體</translation> <translation id="3542066395059568317">系統會顯示建議,讓您繼續使用上次開啟的內容。只要在建議上按一下右鍵即可移除。</translation> -<translation id="3547318469722231257">你修改過這個項目</translation> +<translation id="3547318469722231257">你已修改</translation> <translation id="3552189655002856821">Wi-Fi 已關閉</translation> <translation id="3554215588514239132">顯示或隱藏 Developer Tools 面板</translation> <translation id="3554637740840164787">已經將<ph name="ITEM_TITLE" />置頂</translation> @@ -660,6 +661,7 @@ <translation id="3660860940251915011">將「<ph name="FEATURE_NAME" />」功能切換為是否向附近的所有裝置顯示</translation> <translation id="366222428570480733">受管理嘅使用者:<ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">滑動即可隱藏浮動視窗</translation> +<translation id="3673898235958558034">關閉藍牙後,「<ph name="DEVICE_NAME_1" />」和「<ph name="DEVICE_NAME_2" />」將會與 Chromebook 中斷連線。</translation> <translation id="367531336287639526">選取網址列左方的第一個圖示</translation> <translation id="3677931086890821290">此操作會允許所有獲得位置權限的應用程式和網站和 ChromeOS 使用 Wi-Fi 和流動網絡位置。</translation> <translation id="3679827876008292680">前往視窗中的最後一個分頁</translation> @@ -703,7 +705,7 @@ <translation id="385300504083504382">開頭</translation> <translation id="3859364108019690">無法以串流方式使用應用程式</translation> <translation id="3861651314799684201">㩒 Enter 掣就可以錄全螢幕畫面</translation> -<translation id="3882323608730650973">修改過</translation> +<translation id="3882323608730650973">已修改</translation> <translation id="3886872229787704059">今天開啟過</translation> <translation id="3891340733213178823">按兩下 Ctrl+Shift+Q 鍵即可登出。</translation> <translation id="3893630138897523026">ChromeVox (互動朗讀)</translation> @@ -897,7 +899,7 @@ <translation id="4582666543382004902">已關閉熱點以使用 Wi-Fi。如要使用熱點,請關閉 Wi-Fi。</translation> <translation id="4585337515783392668">停止投放到不明嘅接收器</translation> <translation id="4596144739579517758">深色主題背景已關閉</translation> -<translation id="4596442969149038771"><ph name="USER" /> 分享了這個項目</translation> +<translation id="4596442969149038771"><ph name="USER" />已分享</translation> <translation id="4611292653554630842">登入</translation> <translation id="462160925400706389">已連結 <ph name="NAME" /></translation> <translation id="4623167406982293031">驗證帳戶</translation> @@ -915,6 +917,7 @@ <translation id="4666911709726371538">更多應用程式</translation> <translation id="4667099493359681081">下載緊 <ph name="FILENAME" /></translation> <translation id="4672539464599646374">已開啟「慳電模式」</translation> +<translation id="4673427585974421255">保持開啟</translation> <translation id="468293128311738995">手機應用程式</translation> <translation id="4690510401873698237">捷徑列喺螢幕個底度</translation> <translation id="4696813013609194136">使用家長存取碼解鎖裝置</translation> @@ -1214,6 +1217,7 @@ <translation id="5802516411616338943">開啟「快速設定」</translation> <translation id="5804651031882187592">關閉「鎖定 SIM 卡」設定</translation> <translation id="5805809050170488595">按一下即可啟用 <ph name="NETWORK_NAME" /></translation> +<translation id="5816222150329690597">關閉藍牙後,「<ph name="DEVICE_NAME_1" />」、「<ph name="DEVICE_NAME_2" />」和 <ph name="DEVICE_COUNT" /> 部其他裝置將會與 Chromebook 中斷連線。</translation> <translation id="5823239091726045201">Google Tasks 網頁版</translation> <translation id="5825969630400862129">已連接裝置設定</translation> <translation id="5837036133683224804">停止喺<ph name="RECEIVER_NAME" />投放 <ph name="ROUTE_TITLE" /></translation> @@ -1394,6 +1398,7 @@ <translation id="6539852571005954999">掃瞄緊下載項目 <ph name="FILENAME" /></translation> <translation id="6542521951477560771">正在投放至<ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">按內容和圖片預覽搜尋圖片</translation> +<translation id="6547795021703527064">關閉藍牙後,「<ph name="DEVICE_NAME" />」將會與 Chromebook 中斷連線。</translation> <translation id="6555373427270923730">在網址列中輸入網址,然後按 <ph name="MODIFIER" /><ph name="KEY" /> 鍵</translation> <translation id="655633303491376835">新安裝的「<ph name="APP_NAME" />」</translation> <translation id="6559976592393364813">詢問管理員</translation> @@ -2039,7 +2044,7 @@ <translation id="953431725143473984">確定要關閉裝置嗎?</translation> <translation id="954052413789300507">可用空間不足,無法下載「<ph name="FILENAME" />」。請騰出空間。</translation> <translation id="954520015070501466">30 分鐘</translation> -<translation id="954786879461589145"><ph name="USER" />修改過這個項目</translation> +<translation id="954786879461589145"><ph name="USER" />已修改</translation> <translation id="974545358917229949">顯示緊 <ph name="RESULT_COUNT" /> 個同「<ph name="QUERY" />」有關嘅結果</translation> <translation id="981011780479609956">無截止日期</translation> <translation id="98120814841227350">前往文件結尾</translation>
diff --git a/ash/strings/ash_strings_zh-TW.xtb b/ash/strings/ash_strings_zh-TW.xtb index 961cba2..e0565be 100644 --- a/ash/strings/ash_strings_zh-TW.xtb +++ b/ash/strings/ash_strings_zh-TW.xtb
@@ -26,6 +26,7 @@ <translation id="1087110696012418426">午安,<ph name="GIVEN_NAME" />:</translation> <translation id="1088231044944504242">搜尋<ph name="CATEGORY" />、檔案、應用程式和其他內容,可使用方向鍵瀏覽應用程式。</translation> <translation id="1093645050124056515">ctrl + alt + 向下鍵</translation> +<translation id="1094756674036064790">要關閉藍牙嗎?</translation> <translation id="109942774857561566">我好無聊</translation> <translation id="1104084341931202936">顯示無障礙設定</translation> <translation id="1104621072296271835">完成連結可進一步提升裝置效能</translation> @@ -658,6 +659,7 @@ <translation id="3660860940251915011">將<ph name="FEATURE_NAME" />功能切換為向附近的所有裝置顯示</translation> <translation id="366222428570480733">受管理的使用者:<ph name="USER_EMAIL_ADDRESS" /></translation> <translation id="3666266999138159418">滑動即可隱藏浮動視窗</translation> +<translation id="3673898235958558034">關閉藍牙後,「<ph name="DEVICE_NAME_1" />」和「<ph name="DEVICE_NAME_2" />」就會與 Chromebook 中斷連線。</translation> <translation id="367531336287639526">選取網址列左側的第一個圖示</translation> <translation id="3677931086890821290">這項操作會允許具有位置存取權的所有應用程式/網站和 ChromeOS 使用 Wi-Fi 和行動網路的位置資訊。</translation> <translation id="3679827876008292680">前往視窗中的最後一個分頁</translation> @@ -912,6 +914,7 @@ <translation id="4666911709726371538">更多應用程式</translation> <translation id="4667099493359681081">正在下載 <ph name="FILENAME" /></translation> <translation id="4672539464599646374">省電模式已開啟</translation> +<translation id="4673427585974421255">保持開啟</translation> <translation id="468293128311738995">你手機上的應用程式</translation> <translation id="4690510401873698237">在底部顯示檔案櫃</translation> <translation id="4696813013609194136">使用家長存取碼將裝置解鎖</translation> @@ -1212,6 +1215,7 @@ <translation id="5802516411616338943">開啟快速設定</translation> <translation id="5804651031882187592">關閉「鎖定 SIM 卡」設定</translation> <translation id="5805809050170488595">按一下即可啟動「<ph name="NETWORK_NAME" />」</translation> +<translation id="5816222150329690597">關閉藍牙後,「<ph name="DEVICE_NAME_1" />」、「<ph name="DEVICE_NAME_2" />」和另外 <ph name="DEVICE_COUNT" /> 部裝置就會與 Chromebook 中斷連線。</translation> <translation id="5823239091726045201">Google Tasks 網頁版</translation> <translation id="5825969630400862129">設定已連結的裝置</translation> <translation id="5837036133683224804">停止透過<ph name="RECEIVER_NAME" />投放「<ph name="ROUTE_TITLE" />」</translation> @@ -1392,6 +1396,7 @@ <translation id="6539852571005954999">正在掃描下載項目「<ph name="FILENAME" />」</translation> <translation id="6542521951477560771">正在投放至<ph name="RECEIVER_NAME" /></translation> <translation id="6546062506073634094">依內容和圖片預覽搜尋圖片</translation> +<translation id="6547795021703527064">關閉藍牙後,「<ph name="DEVICE_NAME" />」就會與 Chromebook 中斷連線。</translation> <translation id="6555373427270923730">在網址列輸入網址,然後按下 <ph name="MODIFIER" /><ph name="KEY" /> 鍵</translation> <translation id="655633303491376835">新安裝的「<ph name="APP_NAME" />」</translation> <translation id="6559976592393364813">詢問系統管理員</translation>
diff --git a/ash/style/color_palette_controller.cc b/ash/style/color_palette_controller.cc index eaa18c6..6256cfb 100644 --- a/ash/style/color_palette_controller.cc +++ b/ash/style/color_palette_controller.cc
@@ -336,7 +336,7 @@ use_k_means ? GetCurrentKMeanColor() : *celebi_seed_color; // Schemes need to be copied as the underlying memory for the span could go // out of scope. - std::vector<const style::mojom::ColorScheme> schemes_copy( + const std::vector<style::mojom::ColorScheme> schemes_copy( color_scheme_buttons.begin(), color_scheme_buttons.end()); const auto barrier_callback = base::BarrierCallback<SampleColorScheme>( color_scheme_buttons.size(),
diff --git a/ash/wm/desks/desk_mini_view.cc b/ash/wm/desks/desk_mini_view.cc index 71a1f11..cd7b5b1 100644 --- a/ash/wm/desks/desk_mini_view.cc +++ b/ash/wm/desks/desk_mini_view.cc
@@ -22,7 +22,7 @@ #include "ash/wm/desks/desk_bar_view_base.h" #include "ash/wm/desks/desk_name_view.h" #include "ash/wm/desks/desk_preview_view.h" -#include "ash/wm/desks/desk_profiles_view.h" +#include "ash/wm/desks/desk_profiles_button.h" #include "ash/wm/desks/desk_textfield.h" #include "ash/wm/desks/desks_constants.h" #include "ash/wm/desks/desks_controller.h"
diff --git a/ash/wm/desks/desk_profiles_view.cc b/ash/wm/desks/desk_profiles_button.cc similarity index 98% rename from ash/wm/desks/desk_profiles_view.cc rename to ash/wm/desks/desk_profiles_button.cc index faee806..725ca87 100644 --- a/ash/wm/desks/desk_profiles_view.cc +++ b/ash/wm/desks/desk_profiles_button.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/wm/desks/desk_profiles_view.h" +#include "ash/wm/desks/desk_profiles_button.h" #include <cstdint> #include <memory>
diff --git a/ash/wm/desks/desk_profiles_view.h b/ash/wm/desks/desk_profiles_button.h similarity index 95% rename from ash/wm/desks/desk_profiles_view.h rename to ash/wm/desks/desk_profiles_button.h index 5bb8c33c..9edc603b 100644 --- a/ash/wm/desks/desk_profiles_view.h +++ b/ash/wm/desks/desk_profiles_button.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_WM_DESKS_DESK_PROFILES_VIEW_H_ -#define ASH_WM_DESKS_DESK_PROFILES_VIEW_H_ +#ifndef ASH_WM_DESKS_DESK_PROFILES_BUTTON_H_ +#define ASH_WM_DESKS_DESK_PROFILES_BUTTON_H_ #include "ash/ash_export.h" #include "ash/wm/desks/desk.h" @@ -82,4 +82,4 @@ } // namespace ash -#endif // ASH_WM_DESKS_DESK_PROFILES_VIEW_H_ +#endif // ASH_WM_DESKS_DESK_PROFILES_BUTTON_H_
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc index 70b16b6..ef52b5f 100644 --- a/ash/wm/desks/desks_unittests.cc +++ b/ash/wm/desks/desks_unittests.cc
@@ -62,7 +62,7 @@ #include "ash/wm/desks/desk_mini_view.h" #include "ash/wm/desks/desk_name_view.h" #include "ash/wm/desks/desk_preview_view.h" -#include "ash/wm/desks/desk_profiles_view.h" +#include "ash/wm/desks/desk_profiles_button.h" #include "ash/wm/desks/desk_textfield.h" #include "ash/wm/desks/desks_controller.h" #include "ash/wm/desks/desks_histogram_enums.h"
diff --git a/ash/wm/overview/overview_focus_cycler.cc b/ash/wm/overview/overview_focus_cycler.cc index c3b5ebf..03213c1e 100644 --- a/ash/wm/overview/overview_focus_cycler.cc +++ b/ash/wm/overview/overview_focus_cycler.cc
@@ -12,7 +12,7 @@ #include "ash/wm/desks/desk_mini_view.h" #include "ash/wm/desks/desk_name_view.h" #include "ash/wm/desks/desk_preview_view.h" -#include "ash/wm/desks/desk_profiles_view.h" +#include "ash/wm/desks/desk_profiles_button.h" #include "ash/wm/desks/desks_controller.h" #include "ash/wm/desks/legacy_desk_bar_view.h" #include "ash/wm/desks/templates/saved_desk_grid_view.h"
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 5cf8f19..a1c3492 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -7819,7 +7819,18 @@ // Verify that when in overview mode, the selector items unsnappable indicator // shows up when expected. -TEST_F(SplitViewOverviewSessionTest, OverviewUnsnappableIndicatorVisibility) { +// TODO(crbug.com/324024580): Re-enable this test. Causes build failures on +// MSAN/ASAN on CrOS. +#if BUILDFLAG(IS_CHROMEOS) && \ + (defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER)) +#define MAYBE_OverviewUnsnappableIndicatorVisibility \ + DISABLED_OverviewUnsnappableIndicatorVisibility +#else +#define MAYBE_OverviewUnsnappableIndicatorVisibility \ + OverviewUnsnappableIndicatorVisibility +#endif +TEST_F(SplitViewOverviewSessionTest, + MAYBE_OverviewUnsnappableIndicatorVisibility) { // Create three windows; two normal and one unsnappable, so that when after // snapping |window1| to enter split view we can test the state of each normal // and unsnappable windows. @@ -8268,8 +8279,18 @@ // Verify that if the split view divider is dragged all the way to the edge, the // window being dragged gets returned to the overview list, if overview mode is // still active. +// TODO(crbug.com/324024580): Re-enable this test. Causes build failures on +// MSAN/ASAN on CrOS. +#if BUILDFLAG(IS_CHROMEOS) && \ + (defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER)) +#define MAYBE_DividerDraggedToEdgeReturnsWindowToOverviewList \ + DISABLED_DividerDraggedToEdgeReturnsWindowToOverviewList +#else +#define MAYBE_DividerDraggedToEdgeReturnsWindowToOverviewList \ + DividerDraggedToEdgeReturnsWindowToOverviewList +#endif TEST_F(SplitViewOverviewSessionTest, - DividerDraggedToEdgeReturnsWindowToOverviewList) { + MAYBE_DividerDraggedToEdgeReturnsWindowToOverviewList) { const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -8314,9 +8335,19 @@ // all the way to the opposite edge, then the split view window is reinserted // into the overview grid at the correct position according to MRU order, and // the stacking order is also correct. +// TODO(crbug.com/324024580): Re-enable this test. Causes build failures on +// MSAN/ASAN on CrOS. +#if BUILDFLAG(IS_CHROMEOS) && \ + (defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER)) +#define MAYBE_SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded \ + DISABLED_SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded +#else +#define MAYBE_SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded \ + SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded +#endif TEST_F( SplitViewOverviewSessionTest, - SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded) { + MAYBE_SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded) { const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc index 0027c01..a9647ac1 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc +++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc
@@ -1318,22 +1318,6 @@ // This test checks how the std library handles collections like // std::vector<raw_ptr<T>>. -// -// When this test is written, reallocating std::vector's storage (e.g. -// when growing the vector) requires calling raw_ptr's destructor on the -// old storage (after std::move-ing the data to the new storage). In -// the future we hope that TRIVIAL_ABI (or [trivially_relocatable]] -// proposed by P1144 [1]) will allow memcpy-ing the elements into the -// new storage (without invoking destructors and move constructors -// and/or move assignment operators). At that point, the assert in the -// test should be modified to capture the new, better behavior. -// -// In the meantime, this test serves as a basic correctness test that -// ensures that raw_ptr<T> stored in a std::vector passes basic smoke -// tests. -// -// [1] -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1144r5.html#wording-attribute TEST_F(RawPtrTest, TrivialRelocability) { std::vector<CountingRawPtr<int>> vector; int x = 123; @@ -1350,28 +1334,7 @@ } number_of_capacity_changes++; } while (number_of_capacity_changes < 10); -#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \ - BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR) || \ - BUILDFLAG(RAW_PTR_ZERO_ON_DESTRUCT) - // TODO(lukasza): In the future (once C++ language and std library - // support custom trivially relocatable objects) this #if branch can - // be removed (keeping only the right long-term expectation from the - // #else branch). - EXPECT_NE(0, RawPtrCountingImpl::release_wrapped_ptr_cnt); -#else - // This is the right long-term expectation. - // - // (This EXPECT_EQ assertion is slightly misleading when NoOpImpl is used, - // because, unless zeroing is requested, it forces raw_ptr<> to use a default - // destructor that doesn't go through RawPtrCountingImpl::ReleaseWrappedPtr, - // so we can't really depend on `g_release_wrapped_ptr_cnt`. Nevertheless, the - // spirit of the EXPECT_EQ is correct + the assertion should be true in the - // long-term.) EXPECT_EQ(0, RawPtrCountingImpl::release_wrapped_ptr_cnt); -#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || - // BUILDFLAG(USE_ASAN_UNOWNED_PTR) || - // BUILDFLAG(RAW_PTR_ZERO_ON_DESTRUCT) - // Basic smoke test that raw_ptr elements in a vector work okay. for (const auto& elem : vector) { EXPECT_EQ(elem.get(), &x);
diff --git a/base/fuchsia/time_zone_data_unittest.cc b/base/fuchsia/time_zone_data_unittest.cc index c87b09f..2919a4bda 100644 --- a/base/fuchsia/time_zone_data_unittest.cc +++ b/base/fuchsia/time_zone_data_unittest.cc
@@ -18,15 +18,11 @@ namespace { -// Directory path to the tzdata configuration files. -const char kTzDataDirPath[] = "/pkg/base/test/data/tzdata/icu/44/le"; +// Directory path to the tzdata configuration files, used in tests only. +const char kTestTzDataDirPath[] = "/pkg/base/test/data/tzdata/icu/44/le"; // File path to the text file containing the expected ICU library revision, for -// example "2019c". -// TODO(crbug.com/1360077): Remove once tzdata is fully migrated away from -// config-data. I.e. all released Chromium versions in Fuchsia support it. -const char kRevisionFilePath[] = "/config/data/tzdata/revision.txt"; -// Same as above, except the modern version. +// example "2019c". This file is available in production. const char kTZDataRevisionFilePath[] = "/config/tzdata/icu/revision.txt"; } // namespace @@ -67,18 +63,7 @@ // that this test is not skipped. In Chromium build bot setup, this file may // not be present, in which case we skip running this test. TEST_F(TimeZoneDataTest, CompareSystemRevisionWithExpected) { - std::string revision_file_path; - if (base::PathExists(base::FilePath(kTZDataRevisionFilePath))) { - revision_file_path = kTZDataRevisionFilePath; - } else if (base::PathExists(base::FilePath(kRevisionFilePath))) { - // Legacy path. - revision_file_path = kRevisionFilePath; - } - - if (revision_file_path.empty()) { - FAIL() << "No revision file found"; - } - + ASSERT_TRUE(base::PathExists(base::FilePath(kTZDataRevisionFilePath))); // ResetIcu() ensures that time zone data is loaded from the default location. // This is done after the GTEST_SKIP() call above, since that may output a // timestamp that requires ICU to be set up. @@ -86,8 +71,9 @@ ASSERT_TRUE(InitializeICU()); std::string expected; - EXPECT_TRUE( - base::ReadFileToString(base::FilePath(revision_file_path), &expected)); + ASSERT_TRUE(base::ReadFileToString(base::FilePath(kTZDataRevisionFilePath), + &expected)) + << "Could not read from path: " << kTZDataRevisionFilePath; std::string actual; GetActualRevision(&actual); EXPECT_EQ(expected, actual); @@ -100,9 +86,9 @@ // this could be a sign that all platforms Chromium runs on need to upgrade the // ICU library versions. TEST_F(TimeZoneDataTest, TestLoadingTimeZoneDataFromKnownConfigs) { - ASSERT_TRUE(base::DirectoryExists(base::FilePath(kTzDataDirPath))); + ASSERT_TRUE(base::DirectoryExists(base::FilePath(kTestTzDataDirPath))); ResetIcu(); - SetIcuTimeZoneDataDirForTesting(kTzDataDirPath); + SetIcuTimeZoneDataDirForTesting(kTestTzDataDirPath); ASSERT_TRUE(InitializeICU()); std::string actual; @@ -111,16 +97,14 @@ "version, tzdata version needs to be upgraded"; } -TEST_F(TimeZoneDataTest, DoesNotCrashWithInvalidPath) { +using TimeZoneDataDeathTest = TimeZoneDataTest; + +TEST_F(TimeZoneDataDeathTest, CrashesWithNonexistentPath) { ResetIcu(); SetIcuTimeZoneDataDirForTesting("/some/nonexistent/path"); - ASSERT_TRUE(InitializeICU()); - std::string actual; - GetActualRevision(&actual); - EXPECT_TRUE( - base::StartsWith(actual, "20", base::CompareCase::INSENSITIVE_ASCII)) - << "Got version: " << actual; + EXPECT_DEATH(InitializeICU(), + "Could not open directory: '/some/nonexistent/path'"); } } // namespace i18n
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc index b62e461..931942b 100644 --- a/base/i18n/icu_util.cc +++ b/base/i18n/icu_util.cc
@@ -97,21 +97,18 @@ // See for details: http://userguide.icu-project.org/datetime/timezone const char kIcuTimeZoneEnvVariable[] = "ICU_TIMEZONE_FILES_DIR"; -// Up-to-date time zone data is expected to be provided by the system as a +// Up-to-date time zone data MUST be provided by the system as a // directory offered to Chromium components at /config/tzdata. Chromium -// components should "use" the `tzdata` directory capability, specifying the -// "/config/tzdata" path. The capability's "availability" should be set to -// "required" or "optional" as appropriate - if no data is provided then ICU -// initialization will (in future silently) fall-back to the (potentially stale) -// timezone data included in the package. +// components "use" the `tzdata` directory capability, specifying the +// "/config/tzdata" path. Chromium components will crash if this capability +// is not available. // // TimeZoneDataTest.* tests verify that external timezone data is correctly // loaded from the system, to alert developers if the platform and Chromium // versions are no longer compatible versions. +// LINT.IfChange(icu_time_zone_data_path) const char kIcuTimeZoneDataDir[] = "/config/tzdata/icu/44/le"; - -// Path used to receive tzdata via the legacy config-data mechanism. -const char kLegacyIcuTimeZoneDataDir[] = "/config/data/tzdata/icu/44/le"; +// LINT.ThenChange(//sandbox/policy.fuchsia/sandbox_policy_fuchsia.cc:icu_time_zone_data_path) #endif // BUILDFLAG(IS_FUCHSIA) #if BUILDFLAG(IS_ANDROID) @@ -207,26 +204,11 @@ // Set the environment variable to override the location used by ICU. // Loading can still fail if the directory is empty or its data is invalid. std::unique_ptr<base::Environment> env = base::Environment::Create(); - - // If the ICU tzdata path exists then do not fall-back to config-data. - // TODO(crbug.com/1360077): Remove fall-back once all components are migrated. - if (base::PathExists(base::FilePath(g_icu_time_zone_data_dir))) { - // If the tzdata directory does not exist then silently fallback to - // using the inbuilt (possibly stale) timezone data. - if (base::DirectoryExists(base::FilePath(g_icu_time_zone_data_dir))) { - env->SetVar(kIcuTimeZoneEnvVariable, g_icu_time_zone_data_dir); - } - - } else if (g_icu_time_zone_data_dir == kIcuTimeZoneDataDir && - base::DirectoryExists( - base::FilePath((kLegacyIcuTimeZoneDataDir)))) { - // Only fall-back to attempting to load from the legacy config-data path - // if `g_icu_time_zone_data_dir` has not been changed by a test. - env->SetVar(kIcuTimeZoneEnvVariable, kLegacyIcuTimeZoneDataDir); - } else { - PLOG(WARNING) << "Could not locate tzdata in config-data. " - << "Using built-in timezone database"; + if (!base::DirectoryExists(base::FilePath(g_icu_time_zone_data_dir))) { + PLOG(FATAL) << "Could not open directory: '" << g_icu_time_zone_data_dir + << "'"; } + env->SetVar(kIcuTimeZoneEnvVariable, g_icu_time_zone_data_dir); #endif // BUILDFLAG(IS_FUCHSIA) }
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 75935ea..b1bf874b 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2137,6 +2137,8 @@ # Use resource IDs provided by another APK target when compiling resources # (via. "aapt2 link --stable-ids") # + # override_target_sdk: (optional) + # Update the manifest to target this SDK # # Output variables: # arsc_output: Path to output .ap_ file (optional). @@ -2164,6 +2166,11 @@ _script = "//build/android/gyp/compile_resources.py" + _target_sdk_version = invoker.target_sdk_version + if(defined(invoker.override_target_sdk)) { + _target_sdk_version = invoker.override_target_sdk + } + _inputs = [ invoker.build_config, android_sdk_tools_bundle_aapt2, @@ -2208,7 +2215,7 @@ "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)", "--extra-res-packages=@FileArg($_rebased_build_config:deps_info:extra_package_names)", "--min-sdk-version=${invoker.min_sdk_version}", - "--target-sdk-version=${invoker.target_sdk_version}", + "--target-sdk-version=${_target_sdk_version}", "--webp-cache-dir=obj/android-webp-cache", ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index b69c2795..2ab84d6c 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1187,6 +1187,7 @@ arsc_output = _resource_arsc_output min_sdk_version = default_min_sdk_version target_sdk_version = android_sdk_version + forward_variables_from(invoker, ["override_target_sdk"]) } # apkbuilder step needed only to add android assets to the .ap_ file. @@ -2376,6 +2377,7 @@ "shared_resources", "shared_resources_allowlist_locales", "uses_split", + "override_target_sdk" ]) android_manifest = _android_manifest android_manifest_dep = ":$_merge_manifest_target" @@ -3406,6 +3408,7 @@ "max_sdk_version", "min_sdk_version", "mergeable_android_manifests", + "override_target_sdk", "module_name", "native_lib_placeholders", "package_id",
diff --git a/build/config/android/system_image.gni b/build/config/android/system_image.gni index 3ada8425..d48b562 100644 --- a/build/config/android/system_image.gni +++ b/build/config/android/system_image.gni
@@ -54,6 +54,11 @@ } } + _target_sdk_version = default_android_sdk_version + if (defined(invoker.override_target_sdk)) { + _target_sdk_version = invoker.override_target_sdk + } + action_with_pydeps(_resource_apk_target_name) { script = "//build/android/gyp/compile_resources.py" inputs = [ @@ -65,7 +70,7 @@ "--aapt2-path", rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), "--min-sdk-version=$default_min_sdk_version", - "--target-sdk-version=$default_android_sdk_version", + "--target-sdk-version=$_target_sdk_version", "--android-manifest", rebase_path(_manifest_path, root_build_dir), "--arsc-path", @@ -150,6 +155,7 @@ [ "static_library_name", "static_library_version", + "override_target_sdk" ]) package_info_from_target = invoker.apk_or_bundle_target stub_output = invoker.stub_output
diff --git a/build/config/fuchsia/test/README.md b/build/config/fuchsia/test/README.md index 5f4b4b42..4825fff 100644 --- a/build/config/fuchsia/test/README.md +++ b/build/config/fuchsia/test/README.md
@@ -48,10 +48,6 @@ (default) `chromium` test realm. It is the default base fragment for most `test()` Components. -The system-wide `config-data` directory capability is routed to tests running in -the realm so that individual tests may route subdirectories as needed. -TODO(crbug.com/1360077): Remove this after migrating to the new mechanism. - #### logger.shard.test-cml For tests that test logging functionality by providing `fuchsia.logger.Log`.
diff --git a/build/config/fuchsia/test/minimum.shard.test-cml b/build/config/fuchsia/test/minimum.shard.test-cml index 78e4d467..6f0fed9 100644 --- a/build/config/fuchsia/test/minimum.shard.test-cml +++ b/build/config/fuchsia/test/minimum.shard.test-cml
@@ -24,11 +24,6 @@ } ], use: [ - { - directory: "config-data", - rights: [ "r*" ], - path: "/config/data", - }, // Holds ICU time zone data files. // See: // https://fuchsia.dev/fuchsia-src/concepts/process/namespaces?typical_directory_structure
diff --git a/build/config/fuchsia/test/system_test_minimum.shard.test-cml b/build/config/fuchsia/test/system_test_minimum.shard.test-cml index 6d9e515..46aeada 100644 --- a/build/config/fuchsia/test/system_test_minimum.shard.test-cml +++ b/build/config/fuchsia/test/system_test_minimum.shard.test-cml
@@ -7,11 +7,6 @@ ], use: [ { - directory: "config-data", - rights: [ "r*" ], - path: "/config/data", - }, - { directory: "tzdata-icu", rights: [ "r*" ], path: "/config/tzdata/icu",
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 1a853e0..cc1aba16 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision vars in //DEPS. - libcxx_revision = "3c2f3884e62e17b137ede3e2f3e7214ef294e2c9" + libcxx_revision = "6024b26887625fef52ea0f227d888c4b815488be" }
diff --git a/cc/input/scroll_snap_data.cc b/cc/input/scroll_snap_data.cc index d69045e..9f5ffe86 100644 --- a/cc/input/scroll_snap_data.cc +++ b/cc/input/scroll_snap_data.cc
@@ -544,8 +544,7 @@ if (distance > smallest_distance) { return; } - if (distance < smallest_distance || - candidate.element_id() == active_element_id) { + if (distance < smallest_distance || candidate.has_focus_within()) { smallest_distance = distance; closest = candidate; } @@ -572,6 +571,7 @@ : IsSnapportCoveredOnAxis(axis, intended_position, area.rect))) { if (std::optional<SnapSearchResult> covering = FindCoveringCandidate(area, axis, candidate, intended_position)) { + covering->set_has_focus_within(area.has_focus_within); if (covering->snap_offset() == intended_position) { SetOrUpdateResult(*covering, &covering_intended, active_element_id); } else { @@ -642,6 +642,7 @@ } result.Clip(max_position_.y(), max_position_.x()); } + result.set_has_focus_within(area.has_focus_within); result.set_element_id(area.element_id); return result; }
diff --git a/cc/input/scroll_snap_data.h b/cc/input/scroll_snap_data.h index 990a51c1..4d76c3fc 100644 --- a/cc/input/scroll_snap_data.h +++ b/cc/input/scroll_snap_data.h
@@ -117,6 +117,11 @@ std::optional<gfx::RangeF> covered_range() const { return covered_range_; } void set_covered_range(const gfx::RangeF& range) { covered_range_ = range; } + bool has_focus_within() const { return has_focus_within_; } + void set_has_focus_within(bool has_focus_within) { + has_focus_within_ = has_focus_within; + } + private: // Scroll offset corresponding to this snap position. If covered_range_ is set // then this will be a position inside the range. In the covered case, the @@ -134,6 +139,10 @@ // The ElementId of the snap area that corresponds to this SnapSearchResult. ElementId element_id_; + // Whether the snap area generating this result has focus or has a descendant + // element which has focus. + bool has_focus_within_; + // This is set if the validity of this result derives from the fact that the // snap area covers the viewport, as described in the spec section on // "Snapping Boxes that Overflow the Scrollport": @@ -159,13 +168,19 @@ SnapAreaData(const ScrollSnapAlign& align, const gfx::RectF& rec, bool msnap, + bool has_focus_within, ElementId id) - : scroll_snap_align(align), rect(rec), must_snap(msnap), element_id(id) {} + : scroll_snap_align(align), + rect(rec), + must_snap(msnap), + has_focus_within(has_focus_within), + element_id(id) {} bool operator==(const SnapAreaData& other) const { return (other.element_id == element_id) && (other.scroll_snap_align == scroll_snap_align) && - (other.rect == rect) && (other.must_snap == must_snap); + (other.rect == rect) && (other.must_snap == must_snap) && + (other.has_focus_within == has_focus_within); } bool operator!=(const SnapAreaData& other) const { return !(*this == other); } @@ -182,6 +197,9 @@ // See https://www.w3.org/TR/css-scroll-snap-1/#scroll-snap-stop bool must_snap; + // Whether this area has focus or has a descendant element which has focus. + bool has_focus_within = false; + // ElementId of the corresponding snap area. ElementId element_id; };
diff --git a/cc/input/scroll_snap_data_unittest.cc b/cc/input/scroll_snap_data_unittest.cc index 66ed1692..d64c902 100644 --- a/cc/input/scroll_snap_data_unittest.cc +++ b/cc/input/scroll_snap_data_unittest.cc
@@ -72,7 +72,8 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(10, 10, 200, 300), gfx::PointF(600, 800)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 150, 100, 100), false, ElementId(10)); + gfx::RectF(100, 150, 100, 100), false, false, + ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> strategy = @@ -92,7 +93,8 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(10, 10, 200, 300), gfx::PointF(600, 800)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kCenter), - gfx::RectF(100, 150, 100, 100), false, ElementId(10)); + gfx::RectF(100, 150, 100, 100), false, false, + ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> strategy = @@ -112,7 +114,8 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(10, 10, 200, 200), gfx::PointF(600, 800)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kEnd), - gfx::RectF(150, 200, 100, 100), false, ElementId(10)); + gfx::RectF(150, 200, 100, 100), false, false, + ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> strategy = @@ -131,7 +134,7 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(100, 100)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kEnd, SnapAlignment::kStart), - gfx::RectF(200, 0, 100, 100), false, ElementId(10)); + gfx::RectF(200, 0, 100, 100), false, false, ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> strategy = @@ -154,12 +157,12 @@ gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), - gfx::RectF(80, 0, 150, 150), false, ElementId(10)); + gfx::RectF(80, 0, 150, 150), false, false, ElementId(10)); SnapAreaData snap_y_only( ScrollSnapAlign(SnapAlignment::kStart, SnapAlignment::kNone), - gfx::RectF(0, 70, 150, 150), false, ElementId(20)); + gfx::RectF(0, 70, 150, 150), false, false, ElementId(20)); SnapAreaData snap_on_both(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(50, 150, 150, 150), false, + gfx::RectF(50, 150, 150, 150), false, false, ElementId(30)); container.AddSnapAreaData(snap_x_only); container.AddSnapAreaData(snap_y_only); @@ -182,12 +185,12 @@ gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), - gfx::RectF(80, 0, 150, 150), false, ElementId(10)); + gfx::RectF(80, 0, 150, 150), false, false, ElementId(10)); SnapAreaData snap_y_only( ScrollSnapAlign(SnapAlignment::kStart, SnapAlignment::kNone), - gfx::RectF(0, 70, 150, 150), false, ElementId(20)); + gfx::RectF(0, 70, 150, 150), false, false, ElementId(20)); SnapAreaData snap_on_both(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(50, 150, 150, 150), false, + gfx::RectF(50, 150, 150, 150), false, false, ElementId(30)); container.AddSnapAreaData(snap_x_only); @@ -210,10 +213,10 @@ gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), - gfx::RectF(80, 0, 150, 150), false, ElementId(10)); + gfx::RectF(80, 0, 150, 150), false, false, ElementId(10)); SnapAreaData snap_y_only( ScrollSnapAlign(SnapAlignment::kStart, SnapAlignment::kNone), - gfx::RectF(0, 70, 150, 150), false, ElementId(20)); + gfx::RectF(0, 70, 150, 150), false, false, ElementId(20)); container.AddSnapAreaData(snap_x_only); container.AddSnapAreaData(snap_y_only); @@ -234,10 +237,10 @@ gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), - gfx::RectF(300, 400, 100, 100), false, ElementId(10)); + gfx::RectF(300, 400, 100, 100), false, false, ElementId(10)); SnapAreaData snap_y_only( ScrollSnapAlign(SnapAlignment::kStart, SnapAlignment::kNone), - gfx::RectF(400, 300, 100, 100), false, ElementId(20)); + gfx::RectF(400, 300, 100, 100), false, false, ElementId(20)); container.AddSnapAreaData(snap_x_only); container.AddSnapAreaData(snap_y_only); @@ -261,13 +264,13 @@ // conflict with the snap point on x. SnapAreaData snap_x( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), - gfx::RectF(150, 0, 100, 100), false, ElementId(10)); + gfx::RectF(150, 0, 100, 100), false, false, ElementId(10)); SnapAreaData snap_y1( ScrollSnapAlign(SnapAlignment::kStart, SnapAlignment::kNone), - gfx::RectF(0, 180, 100, 100), false, ElementId(20)); + gfx::RectF(0, 180, 100, 100), false, false, ElementId(20)); SnapAreaData snap_y2( ScrollSnapAlign(SnapAlignment::kStart, SnapAlignment::kNone), - gfx::RectF(250, 80, 100, 100), false, ElementId(30)); + gfx::RectF(250, 80, 100, 100), false, false, ElementId(30)); container.AddSnapAreaData(snap_x); container.AddSnapAreaData(snap_y1); container.AddSnapAreaData(snap_y2); @@ -290,7 +293,7 @@ container.set_proximity_range(gfx::PointF(50, 50)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(80, 160, 100, 100), false, ElementId(10)); + gfx::RectF(80, 160, 100, 100), false, false, ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> strategy = @@ -313,7 +316,7 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(2000, 2000)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(600, 0, 100, 100), false, ElementId(10)); + gfx::RectF(600, 0, 100, 100), false, false, ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> direction_strategy = @@ -360,7 +363,7 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(2000, 2000)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(600, 0, 100, 100), false, ElementId(10)); + gfx::RectF(600, 0, 100, 100), false, false, ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> direction_strategy = @@ -407,11 +410,13 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(2000, 2000)); SnapAreaData must_snap_1(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(200, 0, 100, 100), true, ElementId(10)); + gfx::RectF(200, 0, 100, 100), true, false, + ElementId(10)); SnapAreaData must_snap_2(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(400, 0, 100, 100), true, ElementId(20)); + gfx::RectF(400, 0, 100, 100), true, false, + ElementId(20)); SnapAreaData closer_to_target(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(600, 0, 100, 100), false, + gfx::RectF(600, 0, 100, 100), false, false, ElementId(30)); container.AddSnapAreaData(must_snap_1); container.AddSnapAreaData(must_snap_2); @@ -439,9 +444,10 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData stop_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 0, 100, 100), true, ElementId(10)); + gfx::RectF(100, 0, 100, 100), true, false, + ElementId(10)); SnapAreaData covering_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(250, 0, 600, 600), false, + gfx::RectF(250, 0, 600, 600), false, false, ElementId(20)); container.AddSnapAreaData(stop_area); container.AddSnapAreaData(covering_area); @@ -468,7 +474,8 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData stop_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 0, 100, 100), true, ElementId(10)); + gfx::RectF(100, 0, 100, 100), true, false, + ElementId(10)); container.AddSnapAreaData(stop_area); std::unique_ptr<SnapSelectionStrategy> strategy = @@ -492,9 +499,10 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData closer_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 0, 1, 1), false, ElementId(10)); + gfx::RectF(100, 0, 1, 1), false, false, + ElementId(10)); SnapAreaData stop_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(120, 0, 1, 1), true, ElementId(20)); + gfx::RectF(120, 0, 1, 1), true, false, ElementId(20)); container.AddSnapAreaData(closer_area); container.AddSnapAreaData(stop_area); @@ -518,11 +526,14 @@ gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData closer_area_x(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 0, 1, 1), false, ElementId(10)); + gfx::RectF(100, 0, 1, 1), false, false, + ElementId(10)); SnapAreaData target_area_x(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(200, 100, 1, 1), false, ElementId(20)); + gfx::RectF(200, 100, 1, 1), false, false, + ElementId(20)); SnapAreaData closer_area_y(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(300, 50, 1, 1), false, ElementId(30)); + gfx::RectF(300, 50, 1, 1), false, false, + ElementId(30)); container.AddSnapAreaData(closer_area_x); container.AddSnapAreaData(target_area_x); @@ -551,11 +562,14 @@ gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData closer_area_y(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 100, 1, 1), false, ElementId(10)); + gfx::RectF(0, 100, 1, 1), false, false, + ElementId(10)); SnapAreaData target_area_y(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 200, 1, 1), false, ElementId(20)); + gfx::RectF(100, 200, 1, 1), false, false, + ElementId(20)); SnapAreaData closer_area_x(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(50, 300, 1, 1), false, ElementId(30)); + gfx::RectF(50, 300, 1, 1), false, false, + ElementId(30)); container.AddSnapAreaData(closer_area_y); container.AddSnapAreaData(target_area_y); @@ -584,11 +598,14 @@ gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); SnapAreaData target_area_x(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 200, 1, 1), false, ElementId(10)); + gfx::RectF(100, 200, 1, 1), false, false, + ElementId(10)); SnapAreaData target_area_y(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(200, 100, 1, 1), false, ElementId(20)); + gfx::RectF(200, 100, 1, 1), false, false, + ElementId(20)); SnapAreaData closer_area_both(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 0, 1, 1), false, ElementId(30)); + gfx::RectF(0, 0, 1, 1), false, false, + ElementId(30)); container.AddSnapAreaData(target_area_x); container.AddSnapAreaData(target_area_y); @@ -616,12 +633,14 @@ gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); SnapAreaData target_area_x(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 500, 1, 1), false, ElementId(10)); + gfx::RectF(100, 500, 1, 1), false, false, + ElementId(10)); SnapAreaData target_area_y(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(500, 100, 1, 1), false, ElementId(20)); + gfx::RectF(500, 100, 1, 1), false, false, + ElementId(20)); SnapAreaData area_mutually_visible_to_targets( ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(350, 350, 1, 1), false, - ElementId(30)); + false, ElementId(30)); container.AddSnapAreaData(target_area_x); container.AddSnapAreaData(target_area_y); @@ -648,11 +667,13 @@ SnapContainerData container( ScrollSnapType(false, SnapAxis::kX, SnapStrictness::kMandatory), gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); - SnapAreaData snapped_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 0, 100, 100), false, ElementId(10)); + SnapAreaData unfocused_area(ScrollSnapAlign(SnapAlignment::kStart), + gfx::RectF(0, 0, 100, 100), false, false, + ElementId(10)); SnapAreaData focused_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 100, 100, 100), false, ElementId(20)); - container.AddSnapAreaData(snapped_area); + gfx::RectF(0, 100, 100, 100), false, true, + ElementId(20)); + container.AddSnapAreaData(unfocused_area); container.AddSnapAreaData(focused_area); // Initially both snap areas are horizontally aligned with the snap position. @@ -680,11 +701,13 @@ SnapContainerData container( ScrollSnapType(false, SnapAxis::kY, SnapStrictness::kMandatory), gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); - SnapAreaData snapped_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 0, 100, 100), false, ElementId(10)); + SnapAreaData unfocused_area(ScrollSnapAlign(SnapAlignment::kStart), + gfx::RectF(0, 0, 100, 100), false, false, + ElementId(10)); SnapAreaData focused_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 0, 100, 100), false, ElementId(20)); - container.AddSnapAreaData(snapped_area); + gfx::RectF(100, 0, 100, 100), false, true, + ElementId(20)); + container.AddSnapAreaData(unfocused_area); container.AddSnapAreaData(focused_area); // Initially both snap areas are vertically aligned with the snap position. @@ -712,11 +735,13 @@ SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); - SnapAreaData snapped_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 0, 100, 100), false, ElementId(10)); + SnapAreaData unfocused_area(ScrollSnapAlign(SnapAlignment::kStart), + gfx::RectF(0, 0, 100, 100), false, false, + ElementId(10)); SnapAreaData focused_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 0, 100, 100), false, ElementId(20)); - container.AddSnapAreaData(snapped_area); + gfx::RectF(0, 0, 100, 100), false, true, + ElementId(20)); + container.AddSnapAreaData(unfocused_area); container.AddSnapAreaData(focused_area); // Initially both snap areas are coincident with the snap position. @@ -747,7 +772,7 @@ ScrollSnapType(false, SnapAxis::kY, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(0, 2000)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 50, 200, 1000), false, ElementId(10)); + gfx::RectF(0, 50, 200, 1000), false, false, ElementId(10)); container.AddSnapAreaData(area); std::unique_ptr<SnapSelectionStrategy> end_direction_strategy = @@ -779,11 +804,14 @@ ScrollSnapType(false, SnapAxis::kY, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(0, 4800)); SnapAreaData big_area(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 50, 200, 4900), false, ElementId(10)); + gfx::RectF(0, 50, 200, 4900), false, false, + ElementId(10)); SnapAreaData small_1(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 2000, 200, 300), false, ElementId(20)); + gfx::RectF(0, 2000, 200, 300), false, false, + ElementId(20)); SnapAreaData small_2(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(0, 2300, 200, 300), false, ElementId(30)); + gfx::RectF(0, 2300, 200, 300), false, false, + ElementId(30)); container.AddSnapAreaData(big_area); container.AddSnapAreaData(small_1); @@ -812,11 +840,14 @@ ScrollSnapType(false, SnapAxis::kX, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(4800, 0)); SnapAreaData big_area(ScrollSnapAlign(SnapAlignment::kEnd), - gfx::RectF(0, 0, 5000, 200), false, ElementId(10)); + gfx::RectF(0, 0, 5000, 200), false, false, + ElementId(10)); SnapAreaData small_1(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(100, 0, 300, 200), false, ElementId(20)); + gfx::RectF(100, 0, 300, 200), false, false, + ElementId(20)); SnapAreaData small_2(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(500, 0, 300, 200), false, ElementId(30)); + gfx::RectF(500, 0, 300, 200), false, false, + ElementId(30)); container.AddSnapAreaData(big_area); container.AddSnapAreaData(small_1);
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 54b0190..0abc0cd 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -220,6 +220,14 @@ return true; } +void HeadsUpDisplayLayerImpl::DidDraw( + viz::ClientResourceProvider* resource_provider) { + LayerImpl::DidDraw(resource_provider); + // We always clear `placeholder_quad_` as drawing may get skipped and + // `UpdateHudTexture` might not get called. + placeholder_quad_ = nullptr; +} + void HeadsUpDisplayLayerImpl::AppendQuads( viz::CompositorRenderPass* render_pass, AppendQuadsData* append_quads_data) {
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h index 115ae194..565d31a9 100644 --- a/cc/layers/heads_up_display_layer_impl.h +++ b/cc/layers/heads_up_display_layer_impl.h
@@ -54,6 +54,7 @@ bool WillDraw(DrawMode draw_mode, viz::ClientResourceProvider* resource_provider) override; + void DidDraw(viz::ClientResourceProvider* resource_provider) override; void AppendQuads(viz::CompositorRenderPass* render_pass, AppendQuadsData* append_quads_data) override; void UpdateHudTexture(DrawMode draw_mode,
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 0c4aa51..61e0da5 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -765,7 +765,8 @@ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), gfx::RectF(0, 0, 200, 200), gfx::PointF(300, 300)); SnapAreaData area_data(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(50, 50, 100, 100), false, ElementId(10)); + gfx::RectF(50, 50, 100, 100), false, false, + ElementId(10)); container_data.AddSnapAreaData(area_data); GetScrollNode(overflow)->snap_container_data.emplace(container_data); DrawFrame(); @@ -3110,9 +3111,9 @@ gfx::RectF(0, 0, 100, 100), gfx::PointF(0, 900)); ScrollSnapAlign start = ScrollSnapAlign(SnapAlignment::kStart); container.AddSnapAreaData( - SnapAreaData(start, snap_area_1, false, ElementId(10))); + SnapAreaData(start, snap_area_1, false, false, ElementId(10))); container.AddSnapAreaData( - SnapAreaData(start, snap_area_2, false, ElementId(20))); + SnapAreaData(start, snap_area_2, false, false, ElementId(20))); GetScrollNode(overflow)->snap_container_data.emplace(container); DrawFrame(); @@ -7261,7 +7262,7 @@ gfx::RectF(0, 0, 100, 100), gfx::PointF(0, 900)); ScrollSnapAlign start = ScrollSnapAlign(SnapAlignment::kStart); container.AddSnapAreaData( - SnapAreaData(start, snap_area_1, false, ElementId(10))); + SnapAreaData(start, snap_area_1, false, false, ElementId(10))); host_impl_->OuterViewportScrollNode()->snap_container_data.emplace(container); DrawFrame(); @@ -19045,9 +19046,9 @@ gfx::RectF(0, 0, 100, 100), gfx::PointF(0, 4900)); ScrollSnapAlign start = ScrollSnapAlign(SnapAlignment::kStart); container.AddSnapAreaData( - SnapAreaData(start, snap_area_1, false, ElementId(10))); + SnapAreaData(start, snap_area_1, false, false, ElementId(10))); container.AddSnapAreaData( - SnapAreaData(start, snap_area_2, false, ElementId(20))); + SnapAreaData(start, snap_area_2, false, false, ElementId(20))); GetScrollNode(snapping_layer)->snap_container_data.emplace(container); DrawFrame();
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index ed0f2323..d7d1fd0 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -1280,7 +1280,7 @@ CopyProperties(scroller_.get(), snap_area_.get()); scroller_->AddChild(snap_area_); SnapAreaData snap_area_data(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(500, 500, 100, 100), false, + gfx::RectF(500, 500, 100, 100), false, false, snap_area_id_); // Set up snap container data. @@ -1415,7 +1415,7 @@ CopyProperties(scroller_a_.get(), snap_area_a_.get()); scroller_a_->AddChild(snap_area_a_); SnapAreaData snap_area_data_a(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(500, 500, 100, 100), false, + gfx::RectF(500, 500, 100, 100), false, false, snap_area_a_id_); snap_area_b_ = Layer::Create(); @@ -1424,7 +1424,7 @@ CopyProperties(scroller_b_.get(), snap_area_b_.get()); scroller_b_->AddChild(snap_area_b_); SnapAreaData snap_area_data_b(ScrollSnapAlign(SnapAlignment::kStart), - gfx::RectF(500, 500, 100, 100), false, + gfx::RectF(500, 500, 100, 100), false, false, snap_area_b_id_); // Set up snap container data.
diff --git a/chrome/VERSION b/chrome/VERSION index d201303e..feb4a37f 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=123 MINOR=0 -BUILD=6285 +BUILD=6286 PATCH=0
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java index 18dfbe8d..953c659 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java
@@ -159,9 +159,7 @@ case PopupItemId.PASSWORD_ENTRY: case PopupItemId.DATALIST_ENTRY: case PopupItemId.SCAN_CREDIT_CARD: - case PopupItemId.USERNAME_ENTRY: case PopupItemId.ACCOUNT_STORAGE_PASSWORD_ENTRY: - case PopupItemId.ACCOUNT_STORAGE_USERNAME_ENTRY: return true; } return true; // If it's not a special id, show the regular suggestion! @@ -337,8 +335,7 @@ } private static boolean containsPasswordInfo(AutofillSuggestion suggestion) { - return suggestion.getPopupItemId() == PopupItemId.USERNAME_ENTRY - || suggestion.getPopupItemId() == PopupItemId.PASSWORD_ENTRY; + return suggestion.getPopupItemId() == PopupItemId.PASSWORD_ENTRY; } private static boolean containsCreditCardInfo(AutofillSuggestion suggestion) {
diff --git a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java index 85ca741..88a395f5 100644 --- a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java +++ b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java
@@ -439,7 +439,7 @@ .setLabel("John") .setSubLabel("****") .setItemTag("") - .setPopupItemId(PopupItemId.USERNAME_ENTRY) + .setPopupItemId(PopupItemId.PASSWORD_ENTRY) .setFeatureForIPH("") .build(); AutofillSuggestion passwordSuggestion2 =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java index d4d4c3e..a6ed1fa6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java
@@ -7,9 +7,14 @@ import android.os.Bundle; import androidx.annotation.CallSuper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.chromium.chrome.browser.app.bookmarks.BookmarkActivity; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.profiles.ProfileManager; +import org.chromium.chrome.browser.profiles.ProfileProvider; /** * Ensures that the native library is loaded by synchronously initializing it on creation. @@ -19,12 +24,49 @@ * background with the Activity visible. One example is {@link BookmarkActivity} and its kin. */ public abstract class SynchronousInitializationActivity extends ChromeBaseAppCompatActivity { + private ProfileProvider mProfileProvider; + @CallSuper @Override protected void onCreate(Bundle savedInstanceState) { // Make sure the native is initialized before calling super.onCreate(), as calling // super.onCreate() will recreate fragments that might depend on the native code. ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); + mProfileProvider = createProfileProvider(); super.onCreate(savedInstanceState); } + + private ProfileProvider createProfileProvider() { + assert ProfileManager.isInitialized(); + // TODO(crbug/1410601): Pass the Profile information via the launching Intent and remove + // getLastUsedRegularProfile below. + Profile profile = Profile.getLastUsedRegularProfile(); + return new ProfileProvider() { + @NonNull + @Override + public Profile getOriginalProfile() { + return profile; + } + + @Nullable + @Override + public Profile getOffTheRecordProfile(boolean createIfNeeded) { + // TODO(crbug/1410601): Instead of using getPrimaryOTRProfile, this should account + // for instances where the incognito profile is using a + // non-primary key. Because the Bookmark model redirects to the + // original profile regardless, this is not a critical issue. + return profile.getPrimaryOTRProfile(createIfNeeded); + } + + @Override + public boolean hasOffTheRecordProfile() { + return profile.hasPrimaryOTRProfile(); + } + }; + } + + /** Return the {@link ProfileProvider} for this Activity. */ + public ProfileProvider getProfileProvider() { + return mProfileProvider; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java index 1e737ac..f20de9ec 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java
@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.bookmarks.BookmarkUiPrefs; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.profiles.ProfileProvider; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.embedder_support.util.UrlConstants; @@ -38,12 +39,7 @@ boolean isIncognito = IntentUtils.safeGetBooleanExtra( getIntent(), IntentHandler.EXTRA_INCOGNITO_MODE, false); - Profile profile = Profile.getLastUsedRegularProfile(); - // TODO(crbug/1410601): Instead of using getPrimaryOTRProfile, this should account for - // instances where the incognito profile is using a non-primary key. - // Because the Bookmark model redirects to the original profile - // regardless, this is not a critical issue. - if (isIncognito) profile = profile.getPrimaryOTRProfile(true); + Profile profile = ProfileProvider.getOrCreateProfile(getProfileProvider(), isIncognito); mBookmarkManagerCoordinator = new BookmarkManagerCoordinator( this,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkAddEditFolderActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkAddEditFolderActivity.java index 9d7cb119..7279807 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkAddEditFolderActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkAddEditFolderActivity.java
@@ -24,7 +24,6 @@ import org.chromium.chrome.browser.bookmarks.BookmarkModelObserver; import org.chromium.chrome.browser.bookmarks.BookmarkTextInputLayout; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; -import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.TintedDrawable; @@ -132,7 +131,7 @@ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mModel = BookmarkModel.getForProfile(Profile.getLastUsedRegularProfile()); + mModel = BookmarkModel.getForProfile(getProfileProvider().getOriginalProfile()); mModel.addObserver(mBookmarkModelObserver); mIsAddMode = getIntent().getBooleanExtra(INTENT_IS_ADD_MODE, false); if (mIsAddMode) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditActivity.java index 4030451..b8483aa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditActivity.java
@@ -104,7 +104,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mModel = BookmarkModel.getForProfile(Profile.getLastUsedRegularProfile()); + mModel = BookmarkModel.getForProfile(getProfileProvider().getOriginalProfile()); mBookmarkId = BookmarkId.getBookmarkIdFromString(getIntent().getStringExtra(INTENT_BOOKMARK_ID)); mModel.addObserver(mBookmarkModelObserver); @@ -161,7 +161,7 @@ mBookmarkUiPrefs.addObserver(mBookmarkUiPrefsObserver); Resources res = getResources(); - Profile profile = Profile.getLastUsedRegularProfile(); + Profile profile = getProfileProvider().getOriginalProfile(); mFolderSelectRowCoordinator = new ImprovedBookmarkRowCoordinator( this,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivity.java index 42c86e7..47a8da0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivity.java
@@ -56,7 +56,8 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mBookmarkModel = BookmarkModel.getForProfile(Profile.getLastUsedRegularProfile()); + Profile profile = getProfileProvider().getOriginalProfile(); + mBookmarkModel = BookmarkModel.getForProfile(profile); List<String> bookmarkIdsAsStrings = IntentUtils.safeGetStringArrayListExtra(getIntent(), INTENT_BOOKMARK_IDS); @@ -67,7 +68,6 @@ } Resources res = getResources(); - Profile profile = Profile.getLastUsedRegularProfile(); mBookmarkImageFetcher = new BookmarkImageFetcher( this,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java index 4aa67c49..0658e05f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java
@@ -32,7 +32,6 @@ import org.chromium.chrome.browser.bookmarks.BookmarkModelObserver; import org.chromium.chrome.browser.bookmarks.BookmarkUiPrefs.BookmarkRowDisplayPref; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; -import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.util.TraceEventVectorDrawableCompat; @@ -138,7 +137,7 @@ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mModel = BookmarkModel.getForProfile(Profile.getLastUsedRegularProfile()); + mModel = BookmarkModel.getForProfile(getProfileProvider().getOriginalProfile()); List<String> stringList = IntentUtils.safeGetStringArrayListExtra(getIntent(), INTENT_BOOKMARKS_TO_MOVE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java index ea1daab4..cde93ad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java
@@ -93,11 +93,12 @@ mLifecycleDispatcher = new ActivityLifecycleDispatcherImpl(this); mShareDelegateSupplier = new ShareDelegateSupplier(); mTabShareDelegateSupplier = new ShareDelegateSupplier(); - mProfileSupplier = new ObservableSupplierImpl<>(); - mProfile = Profile.getLastUsedRegularProfile(); - mProfileSupplier.set(mProfile); super.onCreate(savedInstanceState); + mProfileSupplier = new ObservableSupplierImpl<>(); + mProfile = getProfileProvider().getOriginalProfile(); + mProfileSupplier.set(mProfile); + IntentRequestTracker intentRequestTracker = IntentRequestTracker.createFromActivity(this); mWindowAndroid = new ActivityWindowAndroid(this, false, intentRequestTracker);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java index b4b65d54..0451af324 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
@@ -82,6 +82,7 @@ import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController; import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController; import org.chromium.components.feature_engagement.Tracker; +import org.chromium.content_public.browser.NavigationEntry; import org.chromium.content_public.browser.NavigationHandle; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.DeviceFormFactor; @@ -398,10 +399,15 @@ .getPageInsightsIntentParams(mIntentDataProvider.get()); } - private PageInsightsConfig getPageInsightsConfig(NavigationHandle navigationHandle) { + private PageInsightsConfig getPageInsightsConfig( + @Nullable NavigationHandle navigationHandle, + @Nullable NavigationEntry navigationEntry) { return CustomTabsConnection.getInstance() .getPageInsightsConfig( - mIntentDataProvider.get(), navigationHandle, mProfileSupplier); + mIntentDataProvider.get(), + navigationHandle, + navigationEntry, + mProfileSupplier); } public @Nullable PageInsightsCoordinator getPageInsightsCoordinator() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java index 9d9ddfaf..b7d9725 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -1967,16 +1967,8 @@ return PageInsightsIntentParams.getDefaultInstance(); } - /** - * Returns how the Page Insights feature should be configured for the given params. Only applies - * if {@link #shouldEnablePageInsightsForIntent(BrowserServicesIntentDataProvider)} returns - * true. - * - * @param intentData {@link BrowserServicesIntentDataProvider} built from the Intent that - * launched this CCT. - * @param navigationHandle the {@link NavigationHandle} for the current page. - * @param profileSupplier supplier of the current {@link Profile}. - */ + /** DEPRECATED - do not use. */ + @Deprecated public PageInsightsConfig getPageInsightsConfig( BrowserServicesIntentDataProvider intentData, @Nullable NavigationHandle navigationHandle, @@ -1986,7 +1978,6 @@ .setShouldAutoTrigger(false) .setShouldXsurfaceLog(false) .setIsInitialPage(false) - .setShouldAttachGaiaToRequest(false) .setServerShouldNotLogOrPersonalize(true) .build(); } @@ -2012,7 +2003,6 @@ .setShouldAutoTrigger(false) .setShouldXsurfaceLog(false) .setIsInitialPage(false) - .setShouldAttachGaiaToRequest(false) .setServerShouldNotLogOrPersonalize(true) .build(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java index bc0c2e181..cc5a1e7d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.browser.back_press.SecondaryActivityBackPressUma.SecondaryActivity; import org.chromium.chrome.browser.history_clusters.HistoryClustersConstants; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.profiles.ProfileProvider; /** Activity for displaying the browsing history manager. */ public class HistoryActivity extends SnackbarActivity { @@ -36,13 +37,13 @@ getIntent(), HistoryClustersConstants.EXTRA_HISTORY_CLUSTERS_QUERY); String clientPackageName = IntentUtils.safeGetStringExtra(getIntent(), Intent.EXTRA_PACKAGE_NAME); - Profile profile = Profile.getLastUsedRegularProfile(); + Profile profile = getProfileProvider().getOriginalProfile(); mHistoryManager = new HistoryManager( this, true, getSnackbarManager(), - isIncognito ? profile.getPrimaryOTRProfile(true) : profile, + ProfileProvider.getOrCreateProfile(getProfileProvider(), isIncognito), /* Supplier<Tab>= */ null, showHistoryClustersImmediately, historyClustersQuery,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/FullscreenVideoPictureInPictureController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/FullscreenVideoPictureInPictureController.java index ee9e507..4d127de 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/FullscreenVideoPictureInPictureController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/FullscreenVideoPictureInPictureController.java
@@ -233,12 +233,7 @@ try { if (!mActivity.enterPictureInPictureMode(builder.build())) return; } catch (IllegalStateException | IllegalArgumentException e) { - Log.e( - TAG, - "Error entering PiP with bounds (%d, %d): %s", - bounds.width(), - bounds.height(), - e); + Log.e(TAG, "Error entering PiP with bounds %s", bounds, e); return; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java index bfbdd893..88feb2c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java
@@ -40,10 +40,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.signin_activity); - - // TODO(crbug/1410601): Pass the Profile information via the launching Intent and remove - // getLastUsedRegularProfile below. - mProfile = Profile.getLastUsedRegularProfile(); + mProfile = getProfileProvider().getOriginalProfile(); FragmentManager fragmentManager = getSupportFragmentManager(); Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java index a7feccde..5b9090b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
@@ -33,7 +33,7 @@ private static TabModelSelectorObserver sObserverForTesting; - private List<TabModel> mTabModels = new ArrayList<>(); + private final List<TabModel> mTabModels = new ArrayList<>(); private IncognitoTabModel mIncognitoTabModel; /** @@ -270,7 +270,9 @@ + " Is destroyed " + tab.isDestroyed() + " Is detached " - + tab.isDetached(); + + tab.isDetached() + + " Model-size: " + + getModels().size(); return false; }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java index 36dda71..73d5f43b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java
@@ -339,6 +339,8 @@ R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id, @@ -369,6 +371,8 @@ R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id, @@ -389,6 +393,8 @@ R.string.menu_new_incognito_tab, 0, R.string.menu_history, + R.string.menu_quick_delete, + 0, R.string.menu_downloads, R.string.menu_bookmarks, R.string.menu_recent_tabs, @@ -440,6 +446,8 @@ R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id, @@ -460,6 +468,8 @@ R.string.menu_new_incognito_tab, 0, R.string.menu_history, + R.string.menu_quick_delete, + 0, R.string.menu_downloads, R.string.menu_bookmarks, R.string.menu_recent_tabs, @@ -507,6 +517,8 @@ R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id, @@ -561,6 +573,7 @@ R.id.new_tab_menu_id, R.id.new_incognito_tab_menu_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id, @@ -589,6 +602,7 @@ R.id.new_incognito_tab_menu_id, R.id.close_all_tabs_menu_id, tabSelectionEditorMenuItemId, + R.id.quick_delete_menu_id, R.id.preferences_id }; assertMenuItemsAreEqual(menu, expectedItems); @@ -654,6 +668,8 @@ R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id, @@ -1072,6 +1088,8 @@ R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id,
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java index 20348b2..cbfcf57 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java
@@ -248,6 +248,8 @@ R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id,
diff --git a/chrome/android/modules/chrome_bundle_tmpl.gni b/chrome/android/modules/chrome_bundle_tmpl.gni index 57371525..92c7cfa 100644 --- a/chrome/android/modules/chrome_bundle_tmpl.gni +++ b/chrome/android/modules/chrome_bundle_tmpl.gni
@@ -131,6 +131,7 @@ "is_64_bit_browser", "manifest_package", "target_sdk_version", + "override_target_sdk" ]) is_monochrome = _is_monochrome is_trichrome = _is_trichrome
diff --git a/chrome/android/modules/chrome_feature_module_tmpl.gni b/chrome/android/modules/chrome_feature_module_tmpl.gni index 1d53699..d14a8f4 100644 --- a/chrome/android/modules/chrome_feature_module_tmpl.gni +++ b/chrome/android/modules/chrome_feature_module_tmpl.gni
@@ -110,6 +110,7 @@ "target_sdk_version", "version_code", "version_name", + "override_target_sdk", ]) forward_variables_from(_module_desc, [
diff --git a/chrome/app/resources/chromium_strings_pa.xtb b/chrome/app/resources/chromium_strings_pa.xtb index 048db7e..734035c 100644 --- a/chrome/app/resources/chromium_strings_pa.xtb +++ b/chrome/app/resources/chromium_strings_pa.xtb
@@ -163,7 +163,7 @@ <translation id="388648406173476553">Chromium ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰਕੇ ਕੰਟਰੋਲ ਕਰੋ। ਕਿਸੇ ਚੀਜ਼ ਨੂੰ ਤੁਹਾਡੇ ਧਿਆਨ ਦੇਣ ਦੀ ਲੋੜ ਹੈ - ਵੇਰਵਿਆਂ ਲਈ ਕਲਿੱਕ ਕਰੋ।</translation> <translation id="3889543394854987837">Chromium ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਆਪਣੇ ਨਾਮ 'ਤੇ ਕਲਿੱਕ ਕਰੋ ਅਤੇ ਬ੍ਰਾਊਜ਼ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰੋ।</translation> <translation id="390528597099634151"><ph name="EXISTING_USER" /> ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਇਸ Chromium ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਹੈ। ਤੁਹਾਡੀ ਬ੍ਰਾਊਜ਼ਿੰਗ ਨੂੰ ਵੱਖਰਾ ਰੱਖਣ ਲਈ, Chromium ਤੁਹਾਡੇ ਲਈ ਤੁਹਾਡਾ ਖੁਦ ਦਾ ਪ੍ਰੋਫਾਈਲ ਬਣਾ ਸਕਦਾ ਹੈ।</translation> -<translation id="3909353120217047026">ਇਹ ਐਕਸਟੈਂਸ਼ਨ 'Chrome Web Store' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ ਅਤੇ ਇਹ ਅਸੁਰੱਖਿਅਤ ਹੋ ਸਕਦੀ ਹੈ। ਇਸਨੂੰ Chromium ਤੋਂ ਹਟਾਓ, ਤਾਂ ਜੋ ਇਹ ਹੁਣ ਤੁਹਾਡੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਸਮੇਤ ਤੁਹਾਡੇ ਵੱਲੋਂ ਦੇਖੀਆਂ ਗਈਆਂ ਸਾਈਟਾਂ 'ਤੇ ਮੌਜੂਦ ਤੁਹਾਡੇ ਡਾਟੇ ਨੂੰ ਦੇਖ ਅਤੇ ਬਦਲ ਨਾ ਸਕੇ।</translation> +<translation id="3909353120217047026">ਇਹ ਐਕਸਟੈਂਸ਼ਨ 'Chrome ਵੈੱਬ ਸਟੋਰ' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ ਅਤੇ ਇਹ ਅਸੁਰੱਖਿਅਤ ਹੋ ਸਕਦੀ ਹੈ। ਇਸਨੂੰ Chromium ਤੋਂ ਹਟਾਓ, ਤਾਂ ਜੋ ਇਹ ਹੁਣ ਤੁਹਾਡੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਸਮੇਤ ਤੁਹਾਡੇ ਵੱਲੋਂ ਦੇਖੀਆਂ ਗਈਆਂ ਸਾਈਟਾਂ 'ਤੇ ਮੌਜੂਦ ਤੁਹਾਡੇ ਡਾਟੇ ਨੂੰ ਦੇਖ ਅਤੇ ਬਦਲ ਨਾ ਸਕੇ।</translation> <translation id="391789666908693569">ਤੁਹਾਡਾ ਖਾਤਾ <ph name="MANAGER_NAME" /> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਇਸ Chromium ਬ੍ਰਾਊਜ਼ਰ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸਦੇ ਡਾਟੇ ਨੂੰ ਦੇਖ ਸਕਦਾ ਹੈ ਅਤੇ ਇਸਦਾ ਸੰਪਾਦਨ ਕਰ ਸਕਦਾ ਹੈ, ਜਿਵੇਂ ਕਿ ਬੁੱਕਮਾਰਕ, ਇਤਿਹਾਸ ਅਤੇ ਪਾਸਵਰਡ।</translation> <translation id="3922825997980843979">ਟਾਈਪ ਕਰਨ ਵੇਲੇ, Chromium ਪਤਾ ਬਾਰ ਜਾਂ ਖੋਜ ਬਾਕਸ ਦੀ ਸਮੱਗਰੀ ਨੂੰ ਤੁਹਾਡੇ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਖੋਜ ਇੰਜਣ ਨੂੰ ਭੇਜਦਾ ਹੈ</translation> <translation id="3941890832296813527">ਸਥਾਪਤ ਕਰਨ ਵਿੱਚ ਗੜਬੜ: ਸਥਾਪਨਾਕਾਰ ਫ਼ਾਈਲ ਨਾਮ ਅਵੈਧ ਜਾਂ ਅਸਮਰਥਿਤ ਹੈ।</translation>
diff --git a/chrome/app/resources/chromium_strings_vi.xtb b/chrome/app/resources/chromium_strings_vi.xtb index bf7c27d..70fa4bd 100644 --- a/chrome/app/resources/chromium_strings_vi.xtb +++ b/chrome/app/resources/chromium_strings_vi.xtb
@@ -161,7 +161,7 @@ <translation id="388648406173476553">Tùy chỉnh và kiểm soát Chromium. Bạn cần lưu ý - nhấp để xem thông tin chi tiết.</translation> <translation id="3889543394854987837">Nhấp vào tên của bạn để mở Chromium và bắt đầu duyệt web.</translation> <translation id="390528597099634151"><ph name="EXISTING_USER" /> đã đăng nhập vào hồ sơ này trên Chromium. Để tách biệt hoạt động duyệt web của bạn, Chromium có thể tạo hồ sơ riêng cho bạn.</translation> -<translation id="3909353120217047026">Tiện ích này vi phạm chính sách của Chrome Web Store và có thể không an toàn. Hãy xoá khỏi Chromium để tiện ích này không thể xem và thay đổi dữ liệu của bạn (bao gồm cả thông tin cá nhân) trên các trang web bạn truy cập nữa.</translation> +<translation id="3909353120217047026">Tiện ích này vi phạm chính sách của Cửa hàng Chrome trực tuyến và có thể không an toàn. Hãy xoá khỏi Chromium để tiện ích này không thể xem và thay đổi dữ liệu của bạn (bao gồm cả thông tin cá nhân) trên các trang web bạn truy cập nữa.</translation> <translation id="391789666908693569">Tài khoản của bạn do <ph name="MANAGER_NAME" /> quản lý. Quản trị viên của bạn có thể xem và chỉnh sửa hồ sơ trình duyệt Chromium này cũng như dữ liệu trong đó, chẳng hạn như dấu trang, lịch sử và mật khẩu.</translation> <translation id="3922825997980843979">Khi bạn nhập, Chromium sẽ gửi nội dung trong thanh địa chỉ hoặc hộp tìm kiếm đến công cụ tìm kiếm mặc định</translation> <translation id="3941890832296813527">Lỗi cài đặt: Tên tệp của trình cài đặt không hợp lệ hoặc không được hỗ trợ.</translation>
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb index bcae366..23b6631 100644 --- a/chrome/app/resources/generated_resources_am.xtb +++ b/chrome/app/resources/generated_resources_am.xtb
@@ -1726,6 +1726,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{ሁሉንም በ&አዲስ የትር ቡድን ይክፈቱ}=1{በ&አዲስ የትር ቡድን ይክፈቱ}one{ሁሉንም ({COUNT}) በ&አዲስ የትር ቡድን ይክፈቱ}other{ሁሉንም ({COUNT}) በ&አዲስ የትር ቡድን ይክፈቱ}}</translation> <translation id="2285942871162473373">የእርስዎ የጣት አሻራዎች ተለይተው ሊታወቁ አልተቻለም። እንደገና ይሞክሩ።</translation> <translation id="2287617382468007324">የአይፒፒ አድራሻን በማተም ላይ</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{ውሂብዎን ለመጠበቅ፣ ፈቃዶች በቅርቡ ካልተጎበኘ ጣቢያ ተወግደዋል}one{ውሂብዎን ለመጠበቅ፣ ፈቃዶች በቅርቡ ካልተጎበኘ ጣቢያ ተወግደዋል}other{ውሂብዎን ለመጠበቅ፣ ፈቃዶች በቅርቡ ካልተጎበኙ ጣቢያዎች ተወግደዋል}}</translation> <translation id="2287944065963043964">መግቢያ ገፅ</translation> <translation id="2290615375132886363">የጡባዊ ዳሰሳ አዝራሮች</translation> <translation id="2291452790265535215">የጎን ፓነሉን ለእልባቶች፣ ለጉዞዎች እና ለሌሎችም ለመጠቀም ይሞክሩ</translation> @@ -4309,6 +4310,7 @@ <translation id="4275788652681621337">የጎን ፓነልን ዝጋ</translation> <translation id="4275830172053184480">መሣሪያዎን ዳግም ያስጀምሩ</translation> <translation id="4277434192562187284">የXML ውቅረት ምንጭ</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{ፈቃዶች ከ1 ጣቢያ ተወግደዋል}one{ከ{NUM_SITES} ጣቢያ ፈቃዶች ተወግደዋል}other{ከ{NUM_SITES} ጣቢያዎች ፈቃዶች ተወግደዋል}}</translation> <translation id="4278390842282768270">ተፈቅዷል</translation> <translation id="4278498748067682896">መሣሪያው በኪዮስክ ወይም በምልክት ሁነታ ላይ ብቻ እንዲሰራ የሚያስችል የኪዮስክ እና የምልክት ማሻሻያ ይጠቀማሉ። ተጠቃሚዎች ወደ መሣሪያው እንዲገቡ ከፈለጉ እባክዎ ይመለሱ እና የChrome የንግድ ድርጅት ማሻሸያን በመጠቀም ይመዝገቡ።</translation> <translation id="4278779213160967034">ይህ ሂደት ጥቂት ደቂቃዎችን ሊወስድ ይችላል። ፋይሎችን በማውረድ ላይ።</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb index aff334c..54708d4 100644 --- a/chrome/app/resources/generated_resources_ar.xtb +++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -3298,6 +3298,7 @@ <translation id="3497560059572256875">مشاركة رسومات الشعار المبتكرة</translation> <translation id="3497915391670770295">الإرسال إلى أجهزتك</translation> <translation id="3500417806337761827">حدث خطأ أثناء تثبيت المشاركة. سبَق وأن تمّ تثبيت العديد من مشاركات بروتوكول Server Message Block (SMB).</translation> +<translation id="3500764001796099683">تشغيل تطبيقات الويب المعزولة</translation> <translation id="350397915809787283">إذا لم يكن لديك حساب، يُرجى تحديد الخيار الأول لإنشاء حساب.</translation> <translation id="3503995387997205657">يمكنك استعادة التطبيقات السابقة.</translation> <translation id="3505100368357440862">اقتراحات التسوّق</translation> @@ -7171,6 +7172,7 @@ <translation id="6551508934388063976">الأمر غير متوفر. اضغط على control-N لفتح نافذة جديدة.</translation> <translation id="6551606359270386381">أداة رسم الأشكال البيضاوية</translation> <translation id="6551612971599078809">يستخدم الموقع الإلكتروني جهاز USB.</translation> +<translation id="6551620030439692385">الوصول إلى الموقع الجغرافي محظور. تم ضبط المنطقة الزمنية حاليًا على <ph name="TIMEZONE" /> ويمكن تعديلها يدويًا فقط.</translation> <translation id="6551739526055143276">هذا الحساب مُدار من خلال Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> من المستخدمين</translation> <translation id="6555432686520421228">إزالة جميع حسابات المستخدمين وإعادة تعيين جهاز <ph name="IDS_SHORT_PRODUCT_NAME" /> كما لو كان جديدًا.</translation> @@ -7247,6 +7249,7 @@ <translation id="6608773371844092260">لضبط إعدادات بصمة الإصبع، اطلب من طفلك لمس أداة استشعار بصمة الإصبع في الجانب الأيمن من جهاز <ph name="DEVICE_TYPE" /> هذا. يتم تخزين بيانات بصمة إصبع طفلك بشكل آمن وتظلّ محفوظة على جهاز <ph name="DEVICE_TYPE" /> هذا فقط.</translation> <translation id="6609478180749378879">سيتم حفظ بيانات تسجيل الدخول على هذا الجهاز بعد الخروج من "وضع التصفُّح المتخفي". وستتمكّن من تسجيل الدخول إلى هذا الموقع الإلكتروني باستخدام جهازك مرة أخرى لاحقًا.</translation> <translation id="6610002944194042868">خيارات الترجمة</translation> +<translation id="6610064275805055636">إدارة تطبيقات الويب المعزولة</translation> <translation id="6611972847767394631">ستجد علامات التبويب هنا</translation> <translation id="661266467055912436">تحسين الأمان من أجلك ومن أجل جميع المستخدمين على الإنترنت</translation> <translation id="6613267708691765962">جارٍ البحث عن برامج ضارة…</translation> @@ -8611,6 +8614,7 @@ <translation id="7671472752213333268">تطلب الإضافة "<ph name="EXTENSION_NAME" />" إجراء مسح ضوئي من قِبل "<ph name="SCANNER_NAME" />".</translation> <translation id="7672504401554182757">اختَر الجهاز الذي يحتوي على مفتاح المرور لتسجيل الدخول إلى "<ph name="APP_NAME" />".</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />، في <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">الوصول إلى الموقع الجغرافي محظور. تم ضبط الجدول الزمني حاليًا على <ph name="SUNRISE_TIME" /> إلى <ph name="SUNSET_TIME" /> ويمكن تعديله يدويًا فقط.</translation> <translation id="7673313156293624327">سجلات مدير الاتصال Shill لنظام ChromeOS</translation> <translation id="7674416868315480713">إيقاف جميع المنافذ التي يتم إعادة توجيهها في نظام التشغيل Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> تطبيق</translation> @@ -9545,6 +9549,7 @@ <translation id="8376384591331888629">بما في ذلك ملفات تعريف الارتباط التابعة لجهات خارجية على هذا الموقع الإلكتروني</translation> <translation id="8376451933628734023">إذا كان تطبيق الويب هذا يحاول خداعك عن طريق انتحال هوية تطبيق آخر، عليك إلغاء تثبيته.</translation> <translation id="8376532149031784008">جارٍ إعادة تحميل <ph name="DOMAIN" />…</translation> +<translation id="8376610503048439696">سيظل بإمكان الإضافات التي ثبَّتها المشرف قراءة هذا الموقع الإلكتروني وتغييره.</translation> <translation id="8376752431516546391">اللوحة الجانبية لمحرك بحث Google</translation> <translation id="8377625247046155446">سيتم حفظ مفتاح المرور هذا على هذا الجهاز فقط. وسيبقى محفوظًا على هذا الجهاز بعد إغلاق جميع نوافذ التصفّح المتخفي.</translation> <translation id="8378714024927312812">بإدارة مؤسستك</translation>
diff --git a/chrome/app/resources/generated_resources_as.xtb b/chrome/app/resources/generated_resources_as.xtb index 962bc56..fe56fab0 100644 --- a/chrome/app/resources/generated_resources_as.xtb +++ b/chrome/app/resources/generated_resources_as.xtb
@@ -1730,6 +1730,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{&নতুন টেবৰ গোটত আটাইবোৰ খোলক}=1{&নতুন টেবৰ গোটত খোলক}one{&নতুন টেবৰ গোটত আটাইবোৰ ({COUNT} টা) খোলক}other{&নতুন টেবৰ গোটত আটাইবোৰ ({COUNT} টা) খোলক}}</translation> <translation id="2285942871162473373">আপোনাৰ ফিংগাৰপ্ৰিণ্ট চিনাক্ত কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰক।</translation> <translation id="2287617382468007324">প্ৰিণ্ট কৰাৰ IPP ঠিকনা</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{আপোনাৰ ডাটা সুৰক্ষিত কৰিবলৈ, আপুনি শেহতীয়াকৈ এক্সেছ নকৰা এটা ছাইটৰ পৰা অনুমতিসমূহ আঁতৰোৱা হৈছে}one{আপোনাৰ ডাটা সুৰক্ষিত কৰিবলৈ, আপুনি শেহতীয়াকৈ এক্সেছ নকৰা ছাইটসমূহৰ পৰা অনুমতিসমূহ আঁতৰোৱা হৈছে}other{আপোনাৰ ডাটা সুৰক্ষিত কৰিবলৈ, আপুনি শেহতীয়াকৈ এক্সেছ নকৰা ছাইটসমূহৰ পৰা অনুমতিসমূহ আঁতৰোৱা হৈছে}}</translation> <translation id="2287944065963043964">লগ ইন স্ক্রীন</translation> <translation id="2290615375132886363">টেবলেটৰ নেভিগেশ্বনৰ বুটামসমূহ</translation> <translation id="2291452790265535215">বুকমাৰ্ক, যাত্ৰা আৰু অধিকৰ বাবে ছাইডৰ পেনেল ব্যৱহাৰ কৰি চাওক</translation> @@ -3306,6 +3307,7 @@ <translation id="3497560059572256875">ডুডল শ্বেয়াৰ কৰক</translation> <translation id="3497915391670770295">আপোনাৰ &ডিভাইচলৈ পঠিয়াওক</translation> <translation id="3500417806337761827">শ্বেয়াৰ মাউণ্ট কৰোঁতে আসোঁৱাহ হৈছে। অতি বেছিসংখ্যক SMB শ্বেয়াৰ ইতিমধ্যে মাউণ্ট কৰা হৈছে।</translation> +<translation id="3500764001796099683">পোনপটীয়াকৈ বিতৰণ কৰা ৱেব এপ্ সক্ষম কৰক</translation> <translation id="350397915809787283">যদি আপোনাৰ কোনো একাউণ্ট নাই, তেন্তে এটা সৃষ্টি কৰিবলৈ প্ৰথম বিকল্পটো বাছনি কৰক।</translation> <translation id="3503995387997205657">আপুনি আপোনাৰ পূৰ্বৱৰ্তী এপ্সমূহ পুনঃস্থাপন কৰিব পাৰে</translation> <translation id="3505100368357440862">শ্বপিঙৰ বিষয়ে পৰামৰ্শ</translation> @@ -4313,6 +4315,7 @@ <translation id="4275788652681621337">ছাইডৰ পেনেল বন্ধ কৰক</translation> <translation id="4275830172053184480">আপোনাৰ ডিভাইচটো ৰিষ্টাৰ্ট কৰক</translation> <translation id="4277434192562187284">XML কনফিগাৰেশ্বনৰ উৎস</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{১ টা ছাইটৰ পৰা অনুমতি আঁতৰোৱা হৈছে}one{{NUM_SITES} টা ছাইটৰ পৰা অনুমতি আঁতৰোৱা হৈছে}other{{NUM_SITES} টা ছাইটৰ পৰা অনুমতি আঁতৰোৱা হৈছে}}</translation> <translation id="4278390842282768270">অনুমতি দিয়া হৈছে</translation> <translation id="4278498748067682896">আপুনি এটা কিঅ’স্ক আৰু ছাইনেজ আপগ্ৰে’ড ব্যৱহাৰ কৰিব যিয়ে ডিভাইচটোক কেৱল কিঅ’স্ক অথবা ছাইনেজ ম’ডত চলিবলৈ দিয়ে। আপুনি যদি ব্যৱহাৰকাৰীয়ে ডিভাইচটোত ছাইন ইন কৰাটো বিচাৰে, অনুগ্ৰহ কৰি উভতি যাওক আৰু Chrome Enterpriseৰ আপগ্ৰে’ড ব্যৱহাৰ কৰি পঞ্জীয়ন কৰক।</translation> <translation id="4278779213160967034">এই প্ৰক্ৰিয়াৰ বাবে কেইমিনিটমান সময় লাগিব পাৰে। ফাইল ডাউনল’ড কৰি থকা হৈছে।</translation> @@ -5176,6 +5179,7 @@ <translation id="4953808748584563296">ডিফ’ল্ট কমলা অৱতাৰ</translation> <translation id="4955707703665801001"><ph name="FEATURE_NAME" /> দৃশ্যমানতা</translation> <translation id="4955710816792587366">আপোনাৰ পিন বাছনি কৰক</translation> +<translation id="4956847150856741762">1</translation> <translation id="4959262764292427323">আপুনি সকলো ডিভাইচতে ব্যৱহাৰ কৰিব পৰাকৈ নিজৰ Google একাউণ্টত পাছৱর্ডসমূহ ছেভ কৰা হয়</translation> <translation id="4960020053211143927">কিছুমান এপে সমৰ্থন নকৰে</translation> <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> - <ph name="PROFILE_NAME" /></translation> @@ -7180,6 +7184,7 @@ <translation id="6551508934388063976">কামাণ্ড উপলব্ধ নহয়। নতুন টেব খুলিবলৈ control-N টিপক।</translation> <translation id="6551606359270386381">উপবৃত্তৰ সঁজুলি</translation> <translation id="6551612971599078809">ছাইটোৱে ইউএছবি ব্যৱহাৰ কৰি আছে</translation> +<translation id="6551620030439692385">অৱৰোধ কৰা আছে। সময় মণ্ডল বৰ্তমান <ph name="TIMEZONE" /> হিচাপে ছেট কৰা আছে আৰু সেয়া কেৱল মেনুৱেলভাৱেহে আপডে’ট কৰিব পাৰি।</translation> <translation id="6551739526055143276">Family Linkএ পৰিচালনা কৰা</translation> <translation id="655384502888039633"><ph name="USER_COUNT" />জন ব্যৱহাৰকাৰী</translation> <translation id="6555432686520421228">সকলো ব্যৱহাৰকাৰী একাউণ্ট আঁতৰাওক আৰু আপোনাৰ <ph name="IDS_SHORT_PRODUCT_NAME" /> ডিভাইচটো নতুন ডিভাইচৰ দৰে হোৱাকৈ ৰিছেট কৰক।</translation> @@ -7250,6 +7255,7 @@ <translation id="6608773371844092260">ফিংগাৰপ্ৰিণ্ট ছেট আপ কৰিবলৈ আপোনাৰ শিশুক এই <ph name="DEVICE_TYPE" />ৰ সোঁফালে থকা ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰিবলৈ দিয়ক। আপোনাৰ শিশুৰ ফিংগাৰপ্ৰিণ্টৰ ডেটা সুৰক্ষিতভাৱে ষ্ট’ৰ কৰা হয় আৰু সেইখিনি সদায় এই <ph name="DEVICE_TYPE" />ত থাকে।</translation> <translation id="6609478180749378879">আপুনি ইনক’গনিট’ ম’ডৰ পৰা বাহিৰ ওলোৱাৰ পাছত এই ডিভাইচটোত ছাইন-ইনৰ ডেটা ষ্ট’ৰ কৰা হ’ব। আপুনি নিজৰ ডিভাইচটোৰ জৰিয়তে এই ৱেবছাইটটোত পাছত পুনৰ ছাইন ইন কৰিব পাৰিব।</translation> <translation id="6610002944194042868">অনুবাদৰ বিকল্প</translation> +<translation id="6610064275805055636">পোনপটীয়াকৈ বিতৰণ কৰা ৱেব এপ্ পৰিচালনা কৰক</translation> <translation id="6611972847767394631">ইয়াত আপোনাৰ টেবসমূহ বিচাৰক</translation> <translation id="661266467055912436">আপোনাৰ লগতে ৱেবত থকা প্ৰত্যেকজনৰ বাবে সুৰক্ষা উন্নত কৰে।</translation> <translation id="6613267708691765962">মালৱেৰৰ বাবে স্কেন কৰি থকা হৈছে...</translation> @@ -8613,6 +8619,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />"এ "<ph name="SCANNER_NAME" />"ৰ পৰা স্কেন কৰিব বিচাৰে।</translation> <translation id="7672504401554182757"><ph name="APP_NAME" />ৰ বাবে কোনটো ডিভাইচত পাছকী আছে বাছনি কৰক</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" />ত।</translation> +<translation id="7672726198839739113">অৱৰোধ কৰা আছে। সময়সূচী বৰ্তমান <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> হিচাপে ছেট কৰা আছে আৰু সেয়া কেৱল মেনুৱেলভাৱেহে আপডে’ট কৰিব পাৰি।</translation> <translation id="7673313156293624327">ChromeOS শ্বিল (সংযোগ পৰিচালক) লগ</translation> <translation id="7674416868315480713">Linuxত ফৰৱাৰ্ড হৈ থকা সকলো প’ৰ্ট নিষ্ক্ৰিয় কৰক</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> টা এপ্</translation> @@ -9545,6 +9552,7 @@ <translation id="8376384591331888629">এই ছাইটটোত থকা তৃতীয় পক্ষৰ কুকিসমূহো অন্তৰ্ভুক্ত কৰক</translation> <translation id="8376451933628734023">যদি এই ৱেব এপ্টোৱে আপোনাক অন্য এটা এপ্ বুলি জালত পেলাবলৈ চেষ্টা কৰি আছে, এইটোক আনইনষ্টল কৰক।</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> পুনৰ ল’ড কৰি থকা হৈছে...</translation> +<translation id="8376610503048439696">আপোনাৰ প্ৰশাসকে ইনষ্টল কৰা এক্সটেনশ্বনসমূহে এই ছাইটটো তথাপি পঢ়িব আৰু সলনি কৰিব পাৰে</translation> <translation id="8376752431516546391">Google Searchৰ ছাইডৰ পেনেল</translation> <translation id="8377625247046155446">এই পাছকীটো কেৱল এই ডিভাইচটোত ছেভ কৰা হ’ব। আপুনি আটাইবোৰ ইনক’গনিট’ ৱিণ্ড’ বন্ধ কৰাৰ পাছত সেইটো এই ডিভাইচটোতে থাকিব।</translation> <translation id="8378714024927312812">আপোনাৰ প্ৰতিষ্ঠানৰ দ্বাৰা পৰিচালিত</translation>
diff --git a/chrome/app/resources/generated_resources_az.xtb b/chrome/app/resources/generated_resources_az.xtb index 5f16df6..e564899c 100644 --- a/chrome/app/resources/generated_resources_az.xtb +++ b/chrome/app/resources/generated_resources_az.xtb
@@ -3292,6 +3292,7 @@ <translation id="3497560059572256875">Doodle Paylaşın</translation> <translation id="3497915391670770295">Cihazlarınıza göndərin</translation> <translation id="3500417806337761827">Paylaşım əlavə edərkən xəta baş verdi. Hazırda həddindən çox SMB paylaşımı əlavə edilib.</translation> +<translation id="3500764001796099683">Təcrid edilmiş veb-tətbiqləri aktivləşdirin</translation> <translation id="350397915809787283">Hesab yoxdursa, birincini seçərək yaradın.</translation> <translation id="3503995387997205657">Əvvəlki tətbiqlərinizi bərpa edə bilərsiniz</translation> <translation id="3505100368357440862">Şopinq təklifləri</translation> @@ -7163,6 +7164,7 @@ <translation id="6551508934388063976">Əmr əlçatmazdır. Yeni pəncərə açmaq üçün control-N basın.</translation> <translation id="6551606359270386381">Ellips Aləti</translation> <translation id="6551612971599078809">Sayt USB istifadə edir</translation> +<translation id="6551620030439692385">Bloklanıb. Saat qurşağı <ph name="TIMEZONE" /> olaraq ayarlanıb və yalnız manual qaydada güncəllənə bilər.</translation> <translation id="6551739526055143276">Family Link tərəfindən idarə edilir</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> istifadəçi</translation> <translation id="6555432686520421228">Tamamilə yeni olmaq üçün bütün istifadəçi hesablarınızı silin və <ph name="IDS_SHORT_PRODUCT_NAME" /> cihazınızı sıfırlayın.</translation> @@ -7231,6 +7233,7 @@ <translation id="6608773371844092260">Barmaq izini ayarlamaq üçün uşağınızdan bu <ph name="DEVICE_TYPE" /> cihazının sağ tərəfində olan barmaq izi sensoruna toxunmasını istəyin. Övladınızın barmaq izi datası təhlükəsiz şəkildə saxlanılır və heç vaxt <ph name="DEVICE_TYPE" /> cihazından kənara ötürülmür.</translation> <translation id="6609478180749378879">Anonim rejimdən çıxdıqdan sonra giriş datası bu cihazda saxlanılacaq. Bu veb sayta daha sonra cihazınızla yenidən daxil ola biləcəksiniz.</translation> <translation id="6610002944194042868">Tərcümə Seçimləri</translation> +<translation id="6610064275805055636">Təcrid edilmiş veb-tətbiqləri idarə edin</translation> <translation id="6611972847767394631">Tablarınızı burada tapın</translation> <translation id="661266467055912436">Siz və vebdəki hər kəs üçün təhlükəsizliyi artırır.</translation> <translation id="6613267708691765962">Zərərli proqram skanlanır...</translation> @@ -8594,6 +8597,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" "<ph name="SCANNER_NAME" />" skanerindən skanlamaq istəyir.</translation> <translation id="7672504401554182757"><ph name="APP_NAME" /> üçün giriş açarı olan cihazı seçin</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> ünvanında.</translation> +<translation id="7672726198839739113">Bloklanıb. Cədvəl <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> olaraq ayarlanıb və yalnız manual qaydada güncəllənə bilər.</translation> <translation id="7673313156293624327">ChromeOS Shill (bağlantı meneceri) jurnalları</translation> <translation id="7674416868315480713">Linux'da yönləndirilən bütün portları deaktiv edin</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> tətbiq</translation> @@ -9526,6 +9530,7 @@ <translation id="8376384591331888629">Bu saytdakı üçüncü tərəf kukilər daxil olmaqla</translation> <translation id="8376451933628734023">Bu veb tətbiq fərqli bir tətbiq olduğunu düşünmənizə çalışırsa, onu ləğv edin.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> yenidən yüklənir...</translation> +<translation id="8376610503048439696">Administratorun quraşdırdığı artırmalar yenə də bu saytı oxuya və dəyişə bilər</translation> <translation id="8376752431516546391">Google Axtarış yan paneli</translation> <translation id="8377625247046155446">Bu giriş açarı yalnız bu cihazda yadda saxlanılacaq. Bütün Anonim pəncərələri bağladıqdan sonra o, bu cihazda qalacaq.</translation> <translation id="8378714024927312812">Təşkilatınız tərəfindən idarə olunur</translation>
diff --git a/chrome/app/resources/generated_resources_be.xtb b/chrome/app/resources/generated_resources_be.xtb index fc10264..465799e 100644 --- a/chrome/app/resources/generated_resources_be.xtb +++ b/chrome/app/resources/generated_resources_be.xtb
@@ -1009,7 +1009,7 @@ <translation id="1757301747492736405">Чакаецца выдаленне</translation> <translation id="175772926354468439">Уключыць тэму</translation> <translation id="1757786065507923842">Не ўдалося запытаць бацькоўскі дазвол.</translation> -<translation id="17584710573359123">Прагледзець у Chrome Web Store</translation> +<translation id="17584710573359123">Прагледзець у Вэб-краме Chrome</translation> <translation id="1761402971842586829">Кнопка "<ph name="BUTTON_NAME" />" перапрызначана для дзеяння "<ph name="REMAPPING_OPTION" />".</translation> <translation id="1761845175367251960">Уліковыя запісы карыстальніка <ph name="NAME" /></translation> <translation id="176272781006230109">прапановы тавараў</translation> @@ -2253,7 +2253,7 @@ <translation id="2673873887296220733">Скапіраваць 1 файл у сэрвіс "<ph name="CLOUD_PROVIDER" />" перад адкрыццём?</translation> <translation id="267442004702508783">абнавіць</translation> <translation id="2674764818721168631">Выключана</translation> -<translation id="2676084251379299915">Гэта пашырэнне было адключана згодна з карпаратыўнай палітыкай, бо яно больш не даступнае ў Chrome Web Store.</translation> +<translation id="2676084251379299915">Гэта пашырэнне было адключана згодна з карпаратыўнай палітыкай, бо яно больш не даступнае ў Вэб-краме Chrome.</translation> <translation id="2678063897982469759">Паўторна ўключыць</translation> <translation id="2678100101831051676">Не ўдалося запусціць трансляцыю.</translation> <translation id="268053382412112343">Гі&сторыя</translation> @@ -3656,7 +3656,7 @@ <translation id="3775432569830822555">Сертыфікат сервера SSL</translation> <translation id="3775705724665058594">Адпраўка на вашы прылады</translation> <translation id="3776508619697147021">Сайты могуць запытваць дазвол на аўтаматычнае спампоўванне некалькіх файлаў</translation> -<translation id="3776796446459804932">Гэта пашырэнне парушае палітыку Chrome Web Store.</translation> +<translation id="3776796446459804932">Гэта пашырэнне парушае палітыку Вэб-крамы Chrome.</translation> <translation id="3777483481409781352">Не ўдалося актываваць сотавую прыладу</translation> <translation id="3777796259512476958">Будзе выкананы выхад з уліковых запісаў на большасці сайтаў</translation> <translation id="3778208826288864398">Ключ бяспекі заблакіраваны, бо занадта шмат разоў быў уведзены няправільны PIN-код. Вам трэба будзе скінуць ключ бяспекі.</translation> @@ -5049,7 +5049,7 @@ <translation id="4870724079713069532">З дапамогай гэтай праграмы можна адкрываць і змяняць сумяшчальныя файлы ў Правадніку і іншых праграмах. Каб указаць, якія файлы павінны адкрывацца ў гэтай праграме стандартна, <ph name="BEGIN_LINK" />перайдзіце ў налады Windows<ph name="END_LINK" />.</translation> <translation id="4870758487381879312">Каб атрымаць звесткі пра канфігурацыю, увядзіце атрыманы ад адміністратара пароль</translation> <translation id="4870995365819149457">Некаторыя спасылкі, якія падтрымліваюцца, па-ранейшаму будуць адкрывацца ў праграмах "<ph name="APP_NAME" />", "<ph name="APP_NAME_2" />", "<ph name="APP_NAME_3" />" і яшчэ адной праграме.</translation> -<translation id="4871308555310586478">Не з Chrome Web Store.</translation> +<translation id="4871308555310586478">Не з Вэб-крамы Chrome.</translation> <translation id="4871322859485617074">PIN-код змяшчае недапушчальныя сімвалы</translation> <translation id="4871370605780490696">Дадаць закладку</translation> <translation id="4871568871368204250">Выключыць сінхранізацыю</translation> @@ -6020,7 +6020,7 @@ <translation id="5636996382092289526">Каб выкарыстоўваць сетку "<ph name="NETWORK_ID" />", спачатку можа спатрэбіцца <ph name="LINK_START" />наведаць старонку ўваходу ў сетку<ph name="LINK_END" />, якая адкрыецца аўтаматычна праз некалькі секунд. Калі гэтага не адбылося, сетку выкарыстоўваць нельга.</translation> <translation id="5637476008227280525">Уключэнне мабільнай перадачы даных</translation> <translation id="563821631542362636">Дазволіць сайту захоўваць даныя</translation> -<translation id="5638309510554459422">Шукайце пашырэнні і тэмы ў <ph name="BEGIN_LINK" />Chrome Web Store<ph name="END_LINK" /></translation> +<translation id="5638309510554459422">Шукайце пашырэнні і тэмы ў <ph name="BEGIN_LINK" />Вэб-краме Chrome<ph name="END_LINK" /></translation> <translation id="5639549361331209298">Перазагрузіць гэту старонку (утрымлівайце, каб убачыць больш варыянтаў)</translation> <translation id="5640133431808313291">Кіраванне ключамі бяспекі</translation> <translation id="5640159004008030285">Гэты пароль захаваны толькі на дадзенай прыладзе. Каб мець магчымасць выкарыстоўваць яго на іншых прыладах, <ph name="BEGIN_LINK" />захавайце гэты пароль ва Уліковым запісе Google<ph name="END_LINK" />.</translation> @@ -8200,7 +8200,7 @@ <translation id="737728204345822099">На ключы бяспекі можа быць пакінуты запіс пра наведванне вамі гэтага вэб-сайта.</translation> <translation id="7377451353532943397">Працягваць блакіраваць доступ да датчыкаў</translation> <translation id="7377481913241237033">Падключыцца з дапамогай кода</translation> -<translation id="73786666777299047">Адкрыць Chrome Web Store</translation> +<translation id="73786666777299047">Адкрыць Вэб-краму Chrome</translation> <translation id="7380272457268061606">Адключыць аднаўленне лакальных даных?</translation> <translation id="7380459290951585794">Упэўніцеся, што тэлефон разблакіраваны, знаходзіцца паблізу і на ім уключаны Bluetooth і Wi-Fi</translation> <translation id="7380622428988553498">Назва прылады змяшчае недапушчальныя сімвалы</translation>
diff --git a/chrome/app/resources/generated_resources_bs.xtb b/chrome/app/resources/generated_resources_bs.xtb index cd5efd5..6ff4e9f 100644 --- a/chrome/app/resources/generated_resources_bs.xtb +++ b/chrome/app/resources/generated_resources_bs.xtb
@@ -1731,6 +1731,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Otvori sve u &novoj grupi kartica}=1{Otvori u &novoj grupi kartica}one{Otvori sve ({COUNT}) u &novoj grupi kartica}few{Otvori sve ({COUNT}) u &novoj grupi kartica}other{Otvori sve ({COUNT}) u &novoj grupi kartica}}</translation> <translation id="2285942871162473373">Prepoznavanje vašeg otiska prsta nije uspjelo. Pokušajte ponovo.</translation> <translation id="2287617382468007324">IPP adresa štampanja</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokaciju koju niste posjećivali u posljednje vrijeme}one{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokacije koje niste posjećivali u posljednje vrijeme}few{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokacije koje niste posjećivali u posljednje vrijeme}other{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokacije koje niste posjećivali u posljednje vrijeme}}</translation> <translation id="2287944065963043964">Ekran za prijavu</translation> <translation id="2290615375132886363">Dugmad za navigaciju po tabletu</translation> <translation id="2291452790265535215">Isprobajte bočnu ploču za oznake, putovanja i još mnogo toga</translation> @@ -3307,6 +3308,7 @@ <translation id="3497560059572256875">Dijeli crtež</translation> <translation id="3497915391670770295">Pošaljite na svoje &uređaje</translation> <translation id="3500417806337761827">Greška prilikom aktiviranja dijeljenja. Previše MSP dijeljenja je već aktivirano.</translation> +<translation id="3500764001796099683">Omogućite izolirane web aplikacije</translation> <translation id="350397915809787283">Ako nemate račun, odaberite prvu opciju da ga kreirate.</translation> <translation id="3503995387997205657">Možete vratiti prethodne aplikacije</translation> <translation id="3505100368357440862">Prijedlozi za kupovinu</translation> @@ -4315,6 +4317,7 @@ <translation id="4275788652681621337">Zatvori bočnu ploču</translation> <translation id="4275830172053184480">Ponovo pokrenite uređaj</translation> <translation id="4277434192562187284">Izvor konfiguracije za XML</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{Dopuštenja su uklonjena za jednu web-lokaciju}one{Dopuštenja su uklonjena za {NUM_SITES} web-lokaciju}few{Dopuštenja su uklonjena za {NUM_SITES} web-lokacije}other{Dopuštenja su uklonjena za {NUM_SITES} web-lokacija}}</translation> <translation id="4278390842282768270">Dozvoljeno</translation> <translation id="4278498748067682896">Koristit ćete Kiosk i Nadogradnju potpisivanja što dozvoljava uređaju da radi samo u načinu rada kioska ili potpisivanja. Ako želite da se korisnici prijave na uređaj, vratite se i prijavite pomoću nadogradnje Chrome Enterprisea.</translation> <translation id="4278779213160967034">Ovo može potrajati nekoliko minuta. Preuzimanje fajlova.</translation> @@ -7183,6 +7186,7 @@ <translation id="6551508934388063976">Komanda nije dostupna. Pritiniste control-N da otvorite novi prozor.</translation> <translation id="6551606359270386381">Alat za crtanje elipsi</translation> <translation id="6551612971599078809">Web lokacija koristi USB</translation> +<translation id="6551620030439692385">Blokirano. Vremenska zona je trenutno postavljena na <ph name="TIMEZONE" /> i može se ažurirati samo ručno.</translation> <translation id="6551739526055143276">Računom upravlja Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> korisnika</translation> <translation id="6555432686520421228">Uklonite sve korisničke račune i ponovo pokrenite <ph name="IDS_SHORT_PRODUCT_NAME" /> uređaj koji će biti kao nov.</translation> @@ -7255,6 +7259,7 @@ <translation id="6608773371844092260">Da postavite otisak prsta, dijete treba dodirnuti senzor za otisak prsta na desnoj strani uređaja <ph name="DEVICE_TYPE" />. Podaci otiska prsta vašeg djeteta se sigurno pohranjuju i nikada ne napuštaju uređaj <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Podaci za prijavu će se pohraniti na ovom uređaju nakon što izađete iz anonimnog načina rada. Moći ćete se ponovo prijaviti na ovu web lokaciju svojim uređajem kasnije.</translation> <translation id="6610002944194042868">Opcije za prevođenje</translation> +<translation id="6610064275805055636">Upravljajte izoliranim web aplikacijama</translation> <translation id="6611972847767394631">Ovdje pronađite svoje kartice</translation> <translation id="661266467055912436">Poboljšava vašu i svačiju sigurnost na webu.</translation> <translation id="6613267708691765962">Skeniranje radi provjere prisustva zlonamjernog softvera…</translation> @@ -8619,6 +8624,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" želi skenirati putem skenera "<ph name="SCANNER_NAME" />".</translation> <translation id="7672504401554182757">Odaberite uređaj koji ima pristupni ključ za aplikaciju <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, na stranici <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blokirano. Raspored je trenutno postavljen na <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" /> i može se ažurirati samo ručno.</translation> <translation id="7673313156293624327">Zapisnici ChromeOS Shill-a (Upravitelj veza)</translation> <translation id="7674416868315480713">Deaktiviranje svih priključaka koji se prosljeđuju u Linuxu</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> aplikacije(a)</translation> @@ -9552,6 +9558,7 @@ <translation id="8376384591331888629">Uključujući kolačiće treće strane na ovoj web lokaciji</translation> <translation id="8376451933628734023">Ako vas ova web aplikacija pokušava prevariti da mislite da je neka druga, deinstalirajte je.</translation> <translation id="8376532149031784008">Ponovno učitavanje stranice <ph name="DOMAIN" />…</translation> +<translation id="8376610503048439696">Ekstenzije koje je instalirao administrator i dalje mogu čitati i mijenjati ovu web lokaciju</translation> <translation id="8376752431516546391">Bočna ploča Google Pretraživanja</translation> <translation id="8377625247046155446">Ovaj pristupni ključ će se sačuvati samo na ovom uređaju. Ostat će na ovom uređaju nakon što zatvorite sve anonimne prozore.</translation> <translation id="8378714024927312812">Ovim upravlja vaša organizacija</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb index 6d3a499..5128919 100644 --- a/chrome/app/resources/generated_resources_ca.xtb +++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -2272,7 +2272,7 @@ <translation id="2692901429679246677">Aiguamarina</translation> <translation id="2693134906590795721">Sons de càrrega</translation> <translation id="2693176596243495071">S'ha produït un error desconegut. Torna-ho a provar més tard o contacta amb l'administrador si el problema no es resol.</translation> -<translation id="2698147581454716013">Aquest és un dispositiu agrupat i no es pot inscriure amb la Llicència de Kiosk i Signage.</translation> +<translation id="2698147581454716013">Aquest és un dispositiu amb llicència integrada i no es pot inscriure amb la Llicència de Kiosk i Signage.</translation> <translation id="2699911226086014512">Ha fallat l'operació del PIN; codi: <ph name="RETRIES" />.</translation> <translation id="2701330563083355633">S'ha compartit des del dispositiu <ph name="DEVICE_NAME" /></translation> <translation id="2701737434167469065">Inicia la sessió, <ph name="EMAIL" /></translation> @@ -3293,6 +3293,7 @@ <translation id="3497560059572256875">Comparteix el doodle</translation> <translation id="3497915391670770295">Envia als teus &dispositius</translation> <translation id="3500417806337761827">S'ha produït un error en activar l'ús compartit. Ja hi ha activats massa comparticions d'SMB.</translation> +<translation id="3500764001796099683">Activa les aplicacions web aïllades</translation> <translation id="350397915809787283">Si no tens cap compte, selecciona la primera opció per crear-ne un.</translation> <translation id="3503995387997205657">Pots restaurar les aplicacions anteriors</translation> <translation id="3505100368357440862">Suggeriments de compra</translation> @@ -7166,6 +7167,7 @@ <translation id="6551508934388063976">L'ordre no està disponible. Premeu Ctrl + N per obrir una finestra nova.</translation> <translation id="6551606359270386381">Eina d'el·lipse</translation> <translation id="6551612971599078809">El lloc web fa servir USB</translation> +<translation id="6551620030439692385">S'ha bloquejat. Actualment, la zona horària està establerta en <ph name="TIMEZONE" /> i només es pot actualitzar manualment.</translation> <translation id="6551739526055143276">Gestionats per Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> usuaris</translation> <translation id="6555432686520421228">Suprimeix tots els comptes d'usuari i restableix el dispositiu <ph name="IDS_SHORT_PRODUCT_NAME" />, com si fos nou.</translation> @@ -7234,6 +7236,7 @@ <translation id="6608773371844092260">Per configurar una impremta digital, fes que el teu fill o filla toqui el sensor d'empremtes digitals que hi ha a la part dreta d'aquest <ph name="DEVICE_TYPE" />. Les dades de la seva empremta digital s'emmagatzemen de manera segura i no surten mai del <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Les dades d'inici de sessió s'emmagatzemaran en aquest dispositiu quan surtis del mode d'incògnit. Podràs tornar a iniciar la sessió en aquest lloc web amb el teu dispositiu més endavant.</translation> <translation id="6610002944194042868">Opcions del Traductor</translation> +<translation id="6610064275805055636">Gestiona les aplicacions web aïllades</translation> <translation id="6611972847767394631">Aquí trobaràs les teves pestanyes</translation> <translation id="661266467055912436">Millora la seguretat per a tu i per a tots els usuaris del web.</translation> <translation id="6613267708691765962">S'està cercant programari maliciós...</translation> @@ -8598,6 +8601,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" vol escanejar des de "<ph name="SCANNER_NAME" />".</translation> <translation id="7672504401554182757">Tria quin dispositiu té la clau d'accés per a <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, a <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">S'ha bloquejat. Actualment, la programació està establerta en <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> i només es pot actualitzar manualment.</translation> <translation id="7673313156293624327">Registres de Shill (gestor de connexions) de ChromeOS</translation> <translation id="7674416868315480713">Desactiva tots els ports que es redirigeixen a Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> aplicacions</translation> @@ -9532,6 +9536,7 @@ <translation id="8376384591331888629">Incloses les galetes de tercers en aquest lloc web</translation> <translation id="8376451933628734023">Si aquesta aplicació web està provant d'enganyar-te perquè pensis que és una altra aplicació, desinstal·la-la.</translation> <translation id="8376532149031784008">S'està tornant a carregar <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Les extensions instal·lades per l'administrador poden continuar llegint i canviant aquest lloc web</translation> <translation id="8376752431516546391">Tauler lateral de la Cerca de Google</translation> <translation id="8377625247046155446">Aquesta clau d'accés només es desarà en aquest dispositiu. S'hi conservarà després que tanquis totes les finestres d'incògnit.</translation> <translation id="8378714024927312812">Gestionat per la teva organització</translation>
diff --git a/chrome/app/resources/generated_resources_cy.xtb b/chrome/app/resources/generated_resources_cy.xtb index 5b9bd24..bb37076d 100644 --- a/chrome/app/resources/generated_resources_cy.xtb +++ b/chrome/app/resources/generated_resources_cy.xtb
@@ -3311,6 +3311,7 @@ <translation id="3497560059572256875">Rhannu Doodle</translation> <translation id="3497915391670770295">Anfon at Eich &Dyfeisiau</translation> <translation id="3500417806337761827">Bu gwall wrth osod cyfran. Mae gormod o gyfrannau SMB eisoes wedi'u gosod.</translation> +<translation id="3500764001796099683">Galluogi apiau gwe wedi'u hynysu</translation> <translation id="350397915809787283">Os nad oes gennych gyfrif, dewiswch yr opsiwn cyntaf i greu un.</translation> <translation id="3503995387997205657">Gallwch adfer eich apiau blaenorol</translation> <translation id="3505100368357440862">Awgrymiadau siopa</translation> @@ -5182,6 +5183,7 @@ <translation id="4953808748584563296">Rhithffurf oren diofyn</translation> <translation id="4955707703665801001">Gwelededd <ph name="FEATURE_NAME" /></translation> <translation id="4955710816792587366">Dewiswch eich PIN</translation> +<translation id="4956847150856741762">1</translation> <translation id="4959262764292427323">Mae cyfrineiriau'n cael eu cadw i'ch Cyfrif Google fel y gallwch eu defnyddio ar unrhyw ddyfais</translation> <translation id="4960020053211143927">Ni chefnogir hyn gan rai apiau</translation> <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> - <ph name="PROFILE_NAME" /></translation> @@ -7186,6 +7188,7 @@ <translation id="6551508934388063976">Nid yw'r gorchymyn ar gael. Pwyswch control-N i agor ffenestr newydd.</translation> <translation id="6551606359270386381">Offeryn Ellipsis</translation> <translation id="6551612971599078809">Mae'r wefan yn defnyddio USB</translation> +<translation id="6551620030439692385">Rhwystrwyd. Mae cylchfa amser wedi'i osod i <ph name="TIMEZONE" /> ar hyn o bryd a dim ond â llaw y gellir ei ddiweddaru.</translation> <translation id="6551739526055143276">Rheolir gan Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> o ddefnyddwyr</translation> <translation id="6555432686520421228">Tynnwch yr holl gyfrifon defnyddwyr ac ailosodwch eich dyfais <ph name="IDS_SHORT_PRODUCT_NAME" /> i fod yn union fel newydd.</translation> @@ -7262,6 +7265,7 @@ <translation id="6608773371844092260">I osod olion bysedd, gofynnwch i'ch plentyn gyffwrdd â'r synhwyrydd olion bysedd ar ochr dde'r <ph name="DEVICE_TYPE" /> hwn. Mae data olion bysedd eich plentyn yn cael eu storio'n ddiogel a byth yn gadael y <ph name="DEVICE_TYPE" /> hwn.</translation> <translation id="6609478180749378879">Bydd data mewngofnodi'n cael eu storio ar y ddyfais hon ar ôl i chi adael y Modd Anhysbys. Byddwch yn gallu mewngofnodi i'r wefan hon gyda'ch dyfais eto yn nes ymlaen.</translation> <translation id="6610002944194042868">Opsiynau cyfieithu</translation> +<translation id="6610064275805055636">Rheoli apiau gwe wedi'u hynysu</translation> <translation id="6611972847767394631">Gallwch ddod o hyd i'ch tabiau yma</translation> <translation id="661266467055912436">Yn gwella diogelwch i chi a phawb ar y we.</translation> <translation id="6613267708691765962">Sganio am ddrwgwedd...</translation> @@ -8625,6 +8629,7 @@ <translation id="7671472752213333268">Mae "<ph name="EXTENSION_NAME" />" eisiau sganio o "<ph name="SCANNER_NAME" />".</translation> <translation id="7672504401554182757">Dewiswch pa ddyfais sydd â'r cod pas ar gyfer <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, yn <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Rhwystrwyd. Mae'r amserlen wedi'i gosod i <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> ar hyn o bryd a dim ond â llaw y gellir ei diweddaru.</translation> <translation id="7673313156293624327">Logiau ChromeOS Shill (Rheolwr Cysylltiad)</translation> <translation id="7674416868315480713">Dadweithredu pob porth sy'n cael ei anfon ymlaen yn Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> ap</translation> @@ -9557,6 +9562,7 @@ <translation id="8376384591331888629">Gan gynnwys cwcis trydydd parti ar y wefan hon</translation> <translation id="8376451933628734023">Os mae'r ap gwe yn ceisio eich twyllo i feddwl ei fod yn ap gwahanol, dadosodwch ef.</translation> <translation id="8376532149031784008">Wrthi'n ail-lwytho <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Gall estyniadau a osodwyd gan eich gweinyddwr ddarllen a newid y wefan hon o hyd</translation> <translation id="8376752431516546391">Panel ochr Google Search</translation> <translation id="8377625247046155446">Bydd y cod pas hwn yn cael ei gadw ar y ddyfais hon yn unig. Bydd yn aros ar y ddyfais hon ar ôl i chi gau pob ffenestr Anhysbys.</translation> <translation id="8378714024927312812">Rheolir gan eich sefydliad</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb index 5efe0c73..8e375ef 100644 --- a/chrome/app/resources/generated_resources_de.xtb +++ b/chrome/app/resources/generated_resources_de.xtb
@@ -542,7 +542,7 @@ <translation id="1415708812149920388">Lesezugriff auf Zwischenablage verweigert</translation> <translation id="1415990189994829608"><ph name="EXTENSION_NAME" /> (Erweiterungs-ID "<ph name="EXTENSION_ID" />") ist bei diesem Sitzungstyp nicht zulässig.</translation> <translation id="1417428793154876133">{NUM_APPS,plural, =1{App entfernen}other{Apps entfernen}}</translation> -<translation id="1417497355604638350">Damit werden Diagnose- und Nutzungsdaten gesendet.</translation> +<translation id="1417497355604638350">Diagnose- und Nutzungsdaten senden.</translation> <translation id="1418552618736477642">Benachrichtigungen und Apps</translation> <translation id="1418559532423038045">Entfernt <ph name="VM_NAME" /> von deinem Gerät (<ph name="DEVICE_TYPE" />). Dadurch werden alle Apps und Daten der virtuellen Maschine gelöscht.</translation> <translation id="1418882096915998312">Enterprise-Registrierung wird durchgeführt</translation> @@ -4337,7 +4337,7 @@ <translation id="4305817255990598646">Wechseln</translation> <translation id="4306119971288449206">Für Apps muss der Inhaltstyp "<ph name="CONTENT_TYPE" />" bereitgestellt werden</translation> <translation id="4307992518367153382">Grundeinstellungen</translation> -<translation id="4309165024397827958">Android-Apps und -Dienste mit Berechtigung zur Standortermittlung dürfen den Standort deines Geräts nutzen. Google kann in regelmäßigen Abständen anonymisierte Standortdaten erfassen und diese zur Verbesserung der Standortgenauigkeit und standortbasierter Dienste verwenden.</translation> +<translation id="4309165024397827958">Android-Apps und ‑Dienste mit Berechtigung zur Standortermittlung dürfen den Standort deines Geräts nutzen. Google kann in regelmäßigen Abständen anonymisierte Standortdaten erfassen und diese zur Verbesserung der Standortgenauigkeit und standortbasierter Dienste verwenden.</translation> <translation id="4309183709806093061">Auch Audio des Systems teilen. Dieses Gerät wird stummgeschaltet, um eine Rückkopplung zu verhindern.</translation> <translation id="4309420042698375243"><ph name="NUM_KILOBYTES" /> KB (<ph name="NUM_KILOBYTES_LIVE" /> KB live)</translation> <translation id="4310132194679586591">Wähle eine App auf deinem Gerät aus, um diesen Link zu öffnen</translation> @@ -5715,7 +5715,7 @@ <translation id="5411856344659127989">Wenn du ein Konto für jemand anderen hinzufügen möchtest, kannst du <ph name="LINK_BEGIN" />deinem <ph name="DEVICE_TYPE" /> eine neue Person hinzufügen<ph name="LINK_END" />. Berechtigungen, die du Websites und Apps bereits gewährt hast, gelten möglicherweise für dieses Konto. Du kannst deine Google-Konten in den <ph name="SETTINGS_LINK_BEGIN" />Einstellungen<ph name="SETTINGS_LINK_END" /> verwalten.</translation> -<translation id="5413640305322530561">Weitere Informationen über Diagnose und Nutzungsdaten</translation> +<translation id="5413640305322530561">Weitere Informationen über Diagnose- und Nutzungsdaten</translation> <translation id="5414198321558177633">Profilliste wird aktualisiert. Das kann einige Minuten dauern.</translation> <translation id="5414566801737831689">Die Symbole der von dir besuchten Websites lesen</translation> <translation id="5414836363063783498">Überprüfung...</translation> @@ -6299,7 +6299,7 @@ <translation id="5864754048328252126">Aktion bei Inaktivität beim Aufladen</translation> <translation id="5865508026715185451"><ph name="APP_NAME" /> wird bald pausiert</translation> <translation id="586567932979200359">Du führst <ph name="PRODUCT_NAME" /> vom Datenträgerabbild aus. Wenn du den Browser auf deinem Computer installierst, wird er ohne Datenträgerabbild ausgeführt und immer automatisch aktualisiert.</translation> -<translation id="5865733239029070421">Nutzungsstatistiken und Absturzberichte automatisch an Google senden</translation> +<translation id="5865733239029070421">Nutzungsstatistiken und Absturzberichte werden automatisch an Google gesendet</translation> <translation id="5868434909835797817">Das Mikrofon ist auf deinem Gerät deaktiviert</translation> <translation id="5868479397518301468">Zeitüberschreitung bei der Anmeldung</translation> <translation id="5868822853313956582">Gerätefarben übernehmen</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb index cdacca6..00f5f461 100644 --- a/chrome/app/resources/generated_resources_en-GB.xtb +++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -3308,6 +3308,7 @@ <translation id="3497560059572256875">Share Doodle</translation> <translation id="3497915391670770295">Send to Your &Devices</translation> <translation id="3500417806337761827">Error mounting share. Too many SMB shares are already mounted.</translation> +<translation id="3500764001796099683">Enable isolated web apps</translation> <translation id="350397915809787283">If you don't have an account, select the first option to create one.</translation> <translation id="3503995387997205657">You can restore your previous apps</translation> <translation id="3505100368357440862">Shopping suggestions</translation> @@ -7184,6 +7185,7 @@ <translation id="6551508934388063976">Command unavailable. Press control-N to open a new window.</translation> <translation id="6551606359270386381">Ellipse tool</translation> <translation id="6551612971599078809">Site is using USB</translation> +<translation id="6551620030439692385">Blocked. Time zone is currently set to <ph name="TIMEZONE" /> and can only be updated manually.</translation> <translation id="6551739526055143276">Managed by Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> users</translation> <translation id="6555432686520421228">Remove all user accounts and reset your <ph name="IDS_SHORT_PRODUCT_NAME" /> device to be just like new.</translation> @@ -7252,6 +7254,7 @@ <translation id="6608773371844092260">To set up fingerprint, have your child touch the fingerprint sensor at the right hand side of this <ph name="DEVICE_TYPE" />. Your child's fingerprint data is stored securely and never leaves this <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Sign-in data will be stored on this device after you exit Incognito mode. You'll be able to sign in to this website with your device again later.</translation> <translation id="6610002944194042868">Translate Options</translation> +<translation id="6610064275805055636">Manage isolated web apps</translation> <translation id="6611972847767394631">Find your tabs here</translation> <translation id="661266467055912436">Improves security for you and everyone on the web.</translation> <translation id="6613267708691765962">Scanning for malware...</translation> @@ -8616,6 +8619,7 @@ <translation id="7671472752213333268">'<ph name="EXTENSION_NAME" />' wants to scan from '<ph name="SCANNER_NAME" />'.</translation> <translation id="7672504401554182757">Choose which device has the passkey for <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, in <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blocked. Schedule is currently set to <ph name="SUNRISE_TIME" /> – <ph name="SUNSET_TIME" /> and can only be updated manually.</translation> <translation id="7673313156293624327">ChromeOS Shill (Connection Manager) Logs</translation> <translation id="7674416868315480713">Deactivate all ports being forwarded in Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> apps</translation> @@ -9549,6 +9553,7 @@ <translation id="8376384591331888629">Including third-party cookies on this site</translation> <translation id="8376451933628734023">If this web app is trying to trick you into thinking it's a different app, uninstall it.</translation> <translation id="8376532149031784008">Reloading <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Extensions installed by your administrator can still read and change this site</translation> <translation id="8376752431516546391">Google Search side panel</translation> <translation id="8377625247046155446">This passkey will only be saved on this device. It will remain on this device after you close all incognito windows.</translation> <translation id="8378714024927312812">Managed by your organisation</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb index 5d96216..1a1536ce 100644 --- a/chrome/app/resources/generated_resources_es-419.xtb +++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -542,7 +542,7 @@ <translation id="1415708812149920388">Se denegó el acceso de lectura al portapapeles</translation> <translation id="1415990189994829608">No se permite <ph name="EXTENSION_NAME" /> (ID de extensión "<ph name="EXTENSION_ID" />") en este tipo de sesión.</translation> <translation id="1417428793154876133">{NUM_APPS,plural, =1{Quitar app}other{Quitar apps}}</translation> -<translation id="1417497355604638350">Envía datos de uso y diagnóstico</translation> +<translation id="1417497355604638350">Envía datos de uso y diagnóstico.</translation> <translation id="1418552618736477642">Notificaciones y apps</translation> <translation id="1418559532423038045">Quita <ph name="VM_NAME" /> de tu <ph name="DEVICE_TYPE" />. Esta acción borrará todas las apps y los datos de la máquina virtual.</translation> <translation id="1418882096915998312">Inscripción en Enterprise en progreso</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb index f80e680..b6df6ce 100644 --- a/chrome/app/resources/generated_resources_et.xtb +++ b/chrome/app/resources/generated_resources_et.xtb
@@ -3299,6 +3299,7 @@ <translation id="3497560059572256875">Jaga Doodle'i vigurlogo</translation> <translation id="3497915391670770295">Saatmine teie &seadmetesse</translation> <translation id="3500417806337761827">Viga ühiskasutusse andmisel. SMB on ühiskasutusse antud juba liiga paljudele kasutajatele.</translation> +<translation id="3500764001796099683">Isoleeritud veebirakenduste lubamine</translation> <translation id="350397915809787283">Kui teil pole kontot, valige selle loomiseks esimene valik.</translation> <translation id="3503995387997205657">Saate oma varasemad rakendused taastada</translation> <translation id="3505100368357440862">Ostusoovitused</translation> @@ -7174,6 +7175,7 @@ <translation id="6551508934388063976">Käsk pole saadaval. Uue akna avamiseks vajutage klahve Ctrl + N.</translation> <translation id="6551606359270386381">Ovaaljoonetööriist</translation> <translation id="6551612971599078809">Sait kasutab USB-seadet</translation> +<translation id="6551620030439692385">Blokeeritud. Praegune ajavöönd on <ph name="TIMEZONE" /> ja seda saab muuta ainult käsitsi.</translation> <translation id="6551739526055143276">Hallatakse Family Linkiga</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> kasutajat</translation> <translation id="6555432686520421228">Eemaldage kõik kasutajakontod ja lähtestage seade <ph name="IDS_SHORT_PRODUCT_NAME" />, et taas nullist alustada.</translation> @@ -7242,6 +7244,7 @@ <translation id="6608773371844092260">Sõrmejälje seadistamiseks paluge lapsel puudutada seadme <ph name="DEVICE_TYPE" /> paremas servas olevat sõrmejäljeandurit. Teie lapse sõrmejäljeandmed talletatakse turvaliselt ja neid ei edastata kunagi seadmest <ph name="DEVICE_TYPE" /> väljapoole.</translation> <translation id="6609478180749378879">Sisselogimisandmed salvestatakse sellesse seadmesse pärast inkognito režiimist väljumist. Hiljem saate oma seadmega sellele veebisaidile uuesti sisse logida.</translation> <translation id="6610002944194042868">Tõlkimise valikud</translation> +<translation id="6610064275805055636">Isoleeritud veebirakenduste haldamine</translation> <translation id="6611972847767394631">Oma vahekaardid leiate siit</translation> <translation id="661266467055912436">Täiendab turvalisust teie ja kõigi teiste veebikasutajate jaoks.</translation> <translation id="6613267708691765962">Pahavara otsimine …</translation> @@ -8606,6 +8609,7 @@ <translation id="7671472752213333268">„<ph name="EXTENSION_NAME" />” soovib skannida skannerist „<ph name="SCANNER_NAME" />”</translation> <translation id="7672504401554182757">Valige, millises seadmes on rakenduse <ph name="APP_NAME" /> pääsuvõti</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> lehel <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blokeeritud. Praegune ajakava on <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" /> ja seda saab muuta ainult käsitsi.</translation> <translation id="7673313156293624327">ChromeOS-i Shilli (ühenduse haldur) logid</translation> <translation id="7674416868315480713">Inaktiveeri kõik pordid, mis Linuxis on edasi suunatud</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> rakendust</translation> @@ -9539,6 +9543,7 @@ <translation id="8376384591331888629">Sh sellel saidil olevad kolmanda osapoole küpsisefailid</translation> <translation id="8376451933628734023">Kui see veebirakendus üritab jätta muljet, et tegemist on teise rakendusega, desinstallige see.</translation> <translation id="8376532149031784008">Domeeni <ph name="DOMAIN" /> uuesti laadimine …</translation> +<translation id="8376610503048439696">Teie administraatori installitud laiendused pääsevad endiselt sellele saidile juurde ja saavad seda muuta.</translation> <translation id="8376752431516546391">Google’i otsingu külgpaneel</translation> <translation id="8377625247046155446">See pääsuvõti salvestatakse ainult sellesse seadmesse. Pärast kõigi inkognito akende sulgemist jääb see sellesse seadmesse.</translation> <translation id="8378714024927312812">Haldab teie organisatsioon</translation>
diff --git a/chrome/app/resources/generated_resources_eu.xtb b/chrome/app/resources/generated_resources_eu.xtb index f6b38d9f..086668d 100644 --- a/chrome/app/resources/generated_resources_eu.xtb +++ b/chrome/app/resources/generated_resources_eu.xtb
@@ -3293,6 +3293,7 @@ <translation id="3497560059572256875">Partekatu doodle-a</translation> <translation id="3497915391670770295">Bidali zure gailuetara</translation> <translation id="3500417806337761827">Errore bat gertatu da fitxategiak partekatzeko biltegia muntatzean. SMBko fitxategiak partekatzeko biltegi gehiegi daude jada muntatuta.</translation> +<translation id="3500764001796099683">Gaitu sareko aplikazio isolatuak</translation> <translation id="350397915809787283">Konturik ez baduzu, hautatu lehenengo aukera eta sortu bat.</translation> <translation id="3503995387997205657">Aurretik zenituen aplikazioak lehenera ditzakezu</translation> <translation id="3505100368357440862">erosketei buruzko iradokizunak</translation> @@ -7165,6 +7166,7 @@ <translation id="6551508934388063976">Agindua ez dago erabilgarri. Beste leiho bat irekitzeko, sakatu Kontrol+N.</translation> <translation id="6551606359270386381">Hiru puntuen tresna</translation> <translation id="6551612971599078809">USB gailu bat erabiltzen ari da webgunea</translation> +<translation id="6551620030439692385">Blokeatuta. <ph name="TIMEZONE" /> ordu-zona ezarrita dago, eta eskuz soilik alda daiteke.</translation> <translation id="6551739526055143276">Family Link-ek kudeatzen du</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> erabiltzaile</translation> <translation id="6555432686520421228">Kendu erabiltzaile-kontu guztiak eta berrezarri <ph name="IDS_SHORT_PRODUCT_NAME" /> gailua, berria izango balitz bezala gera dadin.</translation> @@ -7233,6 +7235,7 @@ <translation id="6608773371844092260">Hatz-marka konfiguratzeko, eskatu haurrari <ph name="DEVICE_TYPE" /> honen eskuinaldean dagoen hatz-marken sentsorea sakatzeko. Haurraren hatz-markaren datuak modu seguruan gordeko dira eta ez dira inoiz aterako <ph name="DEVICE_TYPE" /> gailutik.</translation> <translation id="6609478180749378879">Ezkutuko modutik irteten zarenean, saioa hasteko datuak gailu honetan gordeko dira. Horrela, gailu honekin webgune honetan saioa hasi ahalko duzu berriro.</translation> <translation id="6610002944194042868">Itzultzeko aukerak</translation> +<translation id="6610064275805055636">Kudeatu sareko aplikazio isolatuak</translation> <translation id="6611972847767394631">Bilatu fitxak hemen</translation> <translation id="661266467055912436">Segurtasuna hobetzen du, bai zuretzat, bai sareko gainontzeko erabiltzaileentzat.</translation> <translation id="6613267708691765962">Malwarea dagoen egiaztatzen…</translation> @@ -8274,7 +8277,7 @@ <translation id="7429415133937917139">Etengabe freskatzen den braille-pantaila baten idazketa simulatzen du pantailaren goialdeko ChromeVox-en panelean</translation> <translation id="7431719494109538750">Ez da aurkitu HID gailurik</translation> <translation id="7431991332293347422">Kontrolatu arakatze-historia nola erabiltzen den Bilaketa eta beste zerbitzu batzuk pertsonalizatzeko</translation> -<translation id="7432200167665670017">Administratzaileak "<ph name="EXTENSION_NAME" />" blokeatu du. Aplikazioaren IDa: <ph name="EXTENSION_ID" />.</translation> +<translation id="7432200167665670017">Administratzaileak "<ph name="EXTENSION_NAME" />" blokeatu du. Aplikazio-identifikatzailea: <ph name="EXTENSION_ID" />.</translation> <translation id="7433708794692032816">Sartu txartel adimenduna <ph name="DEVICE_TYPE" /> erabiltzen jarraitzeko</translation> <translation id="7433957986129316853">Mantendu</translation> <translation id="7434100547946193426">Beste aplikazio batzuk</translation> @@ -8595,6 +8598,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" luzapenak "<ph name="SCANNER_NAME" />" bidez zerbait eskaneatu nahi du.</translation> <translation id="7672504401554182757">Aukeratu <ph name="APP_NAME" /> webgunerako sarbide-gakoak dauzkan gailua</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> orrian.</translation> +<translation id="7672726198839739113">Blokeatuta. <ph name="SUNRISE_TIME" />-<ph name="SUNSET_TIME" /> programazioa ezarrita dago, eta eskuz soilik alda daiteke.</translation> <translation id="7673313156293624327">ChromeOS Shill-en (konexio-kudeatzailea) erregistroak</translation> <translation id="7674416868315480713">Desaktibatu Linux-en desbideratzen ari diren ataka guztiak</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> aplikazio</translation> @@ -9527,6 +9531,7 @@ <translation id="8376384591331888629">Webgune honetako hirugarrenen cookieak barne</translation> <translation id="8376451933628734023">Sareko aplikazio hau beste aplikazio baten plantak egiten ari bada, desinstala ezazu.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> berriro kargatzen…</translation> +<translation id="8376610503048439696">Hala ere, administratzaileak instalatutako luzapenek webgune hau irakurri eta alda dezakete</translation> <translation id="8376752431516546391">Google Bilaketa zerbitzuaren alboko panela</translation> <translation id="8377625247046155446">Sarbide-gakoa gailu honetan soilik gordeko da. Gailuan jarraituko du ezkutuko moduko leiho guztiak itxi ondoren.</translation> <translation id="8378714024927312812">Erakundeak kudeatzen du</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb index 3f8e6949..6096d6b 100644 --- a/chrome/app/resources/generated_resources_fa.xtb +++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -3305,6 +3305,7 @@ <translation id="3497560059572256875">همرسانی Doodle</translation> <translation id="3497915391670770295">ارسال به دستگاههای شما</translation> <translation id="3500417806337761827">هنگام نشاندن همرسانی خطایی روی داد. همرسانیهای SMB زیادی نشانده شده است.</translation> +<translation id="3500764001796099683">فعال کردن برنامههای وب مجزا</translation> <translation id="350397915809787283">اگر حساب ندارید، اولین گزینه را برای ایجاد حساب انتخاب کنید.</translation> <translation id="3503995387997205657">میتوانید برنامههای قبلیتان را بازیابی کنید</translation> <translation id="3505100368357440862">پیشنهادهای خرید</translation> @@ -7181,6 +7182,7 @@ <translation id="6551508934388063976">فرمان در دسترس نیست. برای باز کردن پنجرهای جدید، Control-N را فشار دهید.</translation> <translation id="6551606359270386381">ابزار بیضی</translation> <translation id="6551612971599078809">سایت درحال استفاده از USB است</translation> +<translation id="6551620030439692385">مسدودشده. درحالحاضر منطقه زمانی روی <ph name="TIMEZONE" /> تنظیم شده است و آن را فقط بهصورت دستی میتوان بهروز کرد.</translation> <translation id="6551739526055143276">تحت مدیریت Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> کاربر</translation> <translation id="6555432686520421228">همه حسابهای کاربر حذف شود و دستگاه <ph name="IDS_SHORT_PRODUCT_NAME" /> شما بازنشانی شود تا جدید شود.</translation> @@ -7251,6 +7253,7 @@ <translation id="6608773371844092260">برای تنظیم اثر انگشت، از فرزندتان بخواهید حسگر اثر انگشت را در سمت راست این <ph name="DEVICE_TYPE" /> لمس کند. دادههای اثر انگشت فرزندتان بهصورت ایمن ذخیره میشود و هرگز از این <ph name="DEVICE_TYPE" /> خارج نمیشود.</translation> <translation id="6609478180749378879">پساز خروج از «حالت ناشناس»، دادههای ورود به سیستم در این دستگاه ذخیره خواهد شد. بعداً میتوانید با دستگاهتان دوباره به سیستم این وبسایت وارد شوید.</translation> <translation id="6610002944194042868">گزینههای ترجمه</translation> +<translation id="6610064275805055636">مدیریت برنامههای وب مجزا</translation> <translation id="6611972847767394631">برگههایتان را در اینجا پیدا کنید</translation> <translation id="661266467055912436">امنیت را برای شما و همه کاربران دیگر وب بهبود میبخشد.</translation> <translation id="6613267708691765962">درحال اسکن کردن برای یافتن بدافزار…</translation> @@ -8615,6 +8618,7 @@ <translation id="7671472752213333268">«<ph name="EXTENSION_NAME" />» میخواهد ازطریق «<ph name="SCANNER_NAME" />» اسکن کند.</translation> <translation id="7672504401554182757">انتخاب کنید کدام دستگاه حاوی گذرکلید <ph name="APP_NAME" /> است</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />، در <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">مسدودشده. درحالحاضر زمانبندی روی <ph name="SUNRISE_TIME" /> تا <ph name="SUNSET_TIME" /> تنظیم شده است و آن را فقط بهصورت دستی میتوان بهروز کرد.</translation> <translation id="7673313156293624327">گزارشهای Shill (مدیر اتصال) ChromeOS</translation> <translation id="7674416868315480713">غیرفعال کردن همه درگاههای بازارسالشده در Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> برنامه</translation> @@ -9547,6 +9551,7 @@ <translation id="8376384591331888629">شامل کوکیهای شخص ثالث در این سایت میشود</translation> <translation id="8376451933628734023">اگر این برنامه وب میخواهد شما را فریب دهد که فکر کنید برنامه دیگری است، آن را حذف نصب کنید.</translation> <translation id="8376532149031784008">درحال بار کردن مجدد <ph name="DOMAIN" />…</translation> +<translation id="8376610503048439696">افزونههایی که سرپرست شما نصب کرده است همچنان میتوانند این سایت را بخوانند و تغییر دهند</translation> <translation id="8376752431516546391">پانل کناری «جستجوی Google»</translation> <translation id="8377625247046155446">این گذرکلید فقط در این دستگاه ذخیره خواهد شد. پساز بستن همه «پنجرههای ناشناس»، این گذرکلید در این دستگاه باقی خواهد ماند.</translation> <translation id="8378714024927312812">توسط سازمانتان مدیریت میشود</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb index ba9236e..d89a608b 100644 --- a/chrome/app/resources/generated_resources_fil.xtb +++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -1733,6 +1733,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Buksan lahat sa &bagong grupo ng tab}=1{Buksan sa &bagong grupo ng tab}one{Buksan lahat ({COUNT}) sa &bagong grupo ng tab}other{Buksan lahat ({COUNT}) sa &bagong grupo ng tab}}</translation> <translation id="2285942871162473373">Hindi nakilala ang iyong fingerprint. Subukan ulit.</translation> <translation id="2287617382468007324">IPP Address sa Pag-print</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{Para maprotektahan ang iyong data, inalis ang mga pahintulot sa isang site na hindi mo binisita kamakailan}one{Para maprotektahan ang iyong data, inalis ang mga pahintulot sa mga site na hindi mo binisita kamakailan}other{Para maprotektahan ang iyong data, inalis ang mga pahintulot sa mga site na hindi mo binisita kamakailan}}</translation> <translation id="2287944065963043964">Screen sa pag-log in</translation> <translation id="2290615375132886363">Mga button sa pag-navigate sa tablet</translation> <translation id="2291452790265535215">Subukang gamitin ang panel sa gilid para sa mga bookmark, journey, at higit pa</translation> @@ -3309,6 +3310,7 @@ <translation id="3497560059572256875">Ibahagi ang Doodle</translation> <translation id="3497915391670770295">Ipadala sa Iyong Mga &Device</translation> <translation id="3500417806337761827">Nagka-error sa pag-mount ng pagbabahagi. Masyado nang marami ang na-mount na pagbabahagi ng SMB.</translation> +<translation id="3500764001796099683">I-enable ang mga naka-isolate na web app</translation> <translation id="350397915809787283">Kung wala kang account, piliin ang unang opsyon para gumawa nito.</translation> <translation id="3503995387997205657">Puwede mong i-restore ang iyong mga dating app</translation> <translation id="3505100368357440862">Mga suhestyon sa pamimili</translation> @@ -4317,6 +4319,7 @@ <translation id="4275788652681621337">Isara ang panel sa gilid</translation> <translation id="4275830172053184480">I-restart ang iyong device</translation> <translation id="4277434192562187284">Source ng XML configuration</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{Inalis ang mga pahintulot sa 1 site}one{Inalis ang mga pahintulot sa {NUM_SITES} site}other{Inalis ang mga pahintulot sa {NUM_SITES} na site}}</translation> <translation id="4278390842282768270">Pinapayagan</translation> <translation id="4278498748067682896">Gagamit ka ng Pag-upgrade sa Kiosk at Signage na nagbibigay-daan lang sa device na tumakbo sa kiosk o signage mode. Kung gusto mong mag-sign in sa device ang mga user, bumalik at mag-enroll gamit ang Chrome Enterprise Upgrade.</translation> <translation id="4278779213160967034">Puwedeng magtagal ang prosesong ito nang ilang minuto. Nagda-download ng mga file.</translation> @@ -7185,6 +7188,7 @@ <translation id="6551508934388063976">Hindi available ang command. Pindutin ang control-N upang magbukas ng bagong window.</translation> <translation id="6551606359270386381">Ellipse Tool</translation> <translation id="6551612971599078809">Gumagamit ng USB ang site</translation> +<translation id="6551620030439692385">Naka-block. Kasalukuyang nakatakda ang time zone sa <ph name="TIMEZONE" /> at maa-update lang ito sa manual na paraan.</translation> <translation id="6551739526055143276">Pinapamahalaan ng Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> )(na) user</translation> <translation id="6555432686520421228">Alisin ang lahat ng account ng user at i-reset ang iyong <ph name="IDS_SHORT_PRODUCT_NAME" /> na device upang maging parang bago.</translation> @@ -7255,6 +7259,7 @@ <translation id="6608773371844092260">Para i-set up ang fingerprint, ipapindot sa iyong anak ang sensor para sa fingerprint sa kanang bahagi ng <ph name="DEVICE_TYPE" /> na ito. Secure na sino-store ang data ng fingerprint ng iyong anak at hindi ito kailanman lalabas sa <ph name="DEVICE_TYPE" /> na ito.</translation> <translation id="6609478180749378879">Iso-store ang data ng pag-sign in sa device na ito pagkatapos mong lumabas sa Incognito mode. Makakapag-sign in ka ulit sa website na ito gamit ang iyong device sa ibang pagkakataon.</translation> <translation id="6610002944194042868">Mga Opsyon sa Pagsasalin</translation> +<translation id="6610064275805055636">Pamahalaan ang mga naka-isolate na web app</translation> <translation id="6611972847767394631">Hanapin ang iyong mga tab dito</translation> <translation id="661266467055912436">Pinapahusay ang seguridad para sa iyo at sa lahat ng tao sa web.</translation> <translation id="6613267708691765962">Sina-scan para sa malware...</translation> @@ -8619,6 +8624,7 @@ <translation id="7671472752213333268">Gusto ng "<ph name="EXTENSION_NAME" />" na mag-scan mula sa "<ph name="SCANNER_NAME" />."</translation> <translation id="7672504401554182757">Piliin kung aling device ang may passkey para sa <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, sa <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Naka-block. Kasalukuyang nakatakda ang iskedyul sa <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> at maa-update lang ito sa manual na paraan.</translation> <translation id="7673313156293624327">Mga Log ng ChromeOS Shill (Manager ng Koneksyon)</translation> <translation id="7674416868315480713">I-deactivate ang lahat ng port na fino-forward sa Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> (na) app</translation> @@ -9552,6 +9558,7 @@ <translation id="8376384591331888629">Kasama ang third-party na cookies sa site na ito</translation> <translation id="8376451933628734023">Kung sinusubukan kang linlangin ng web app na ito para maisip mong ibang app ito, i-uninstall ito.</translation> <translation id="8376532149031784008">Nire-reload ang <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Magagawa pa rin ng mga extension na na-install ng iyong administrator na basahin at baguhin ang site na ito</translation> <translation id="8376752431516546391">Panel sa gilid ng Google Search</translation> <translation id="8377625247046155446">Mase-save lang ang passkey na ito sa device na ito. Mananatili ito sa device na ito pagkatapos mong isara ang lahat ng Incognito window.</translation> <translation id="8378714024927312812">Pinapamahalaan ng iyong organisasyon</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb index d098d42..78fe670b 100644 --- a/chrome/app/resources/generated_resources_fr.xtb +++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -3742,7 +3742,7 @@ <translation id="3826440694796503677">Votre administrateur a désactivé la fonctionnalité d'ajout d'autres comptes Google</translation> <translation id="3827774300009121996">&Plein écran</translation> <translation id="3828029223314399057">Rechercher dans les favoris</translation> -<translation id="3828953470056652895">J'ai lu et j'accepte les <ph name="BEGIN_LINK1" />Conditions d'utilisation de Google<ph name="END_LINK1" />, les<ph name="BEGIN_LINK2" />Conditions d'utilisation supplémentaires de Chrome et Chrome OS<ph name="END_LINK2" />, ainsi que les <ph name="BEGIN_LINK3" />Conditions d'utilisation de Play<ph name="END_LINK3" />.</translation> +<translation id="3828953470056652895">J'ai lu et j'accepte les <ph name="BEGIN_LINK1" />Conditions d'utilisation de Google<ph name="END_LINK1" />, les <ph name="BEGIN_LINK2" />Conditions d'utilisation supplémentaires de Chrome et Chrome OS<ph name="END_LINK2" />, ainsi que les <ph name="BEGIN_LINK3" />Conditions d'utilisation de Play<ph name="END_LINK3" />.</translation> <translation id="3829530269338026191"><ph name="WINDOW_TITLE" /> - Utilisation élevée de la mémoire - <ph name="MEMORY_VALUE" /></translation> <translation id="3829765597456725595">Partage de fichiers SMB</translation> <translation id="3830470485672984938">Utiliser une autre clé d'accès</translation> @@ -5742,7 +5742,7 @@ <translation id="5425863515030416387">Se connecter facilement sur tous les appareils</translation> <translation id="5427278936122846523">Toujours traduire</translation> <translation id="5427459444770871191">Rotation &horaire</translation> -<translation id="542750953150239272">En continuant, vous acceptez que cet appareil puisse aussi télécharger et installer automatiquement des mises à jour et des applis de Google, de votre opérateur et du fabricant de votre appareil, probablement via le réseau mobile. Certaines de ces applis permettent d'y effectuer des achats.</translation> +<translation id="542750953150239272">En continuant, vous acceptez que cet appareil puisse aussi télécharger et installer automatiquement des mises à jour et des applis de Google, de votre opérateur et du fabricant de votre appareil, éventuellement via des données mobiles. Certaines de ces applis permettent d'y effectuer des achats.</translation> <translation id="5428850089342283580"><ph name="ACCNAME_APP" /> (mise à jour disponible)</translation> <translation id="542948651837270806">Vous devez mettre à jour le micrologiciel TPM (Trusted Platform Module). Consultez la page <ph name="TPM_FIRMWARE_UPDATE_LINK" /></translation> <translation id="5429818411180678468">Pleine largeur</translation> @@ -7526,7 +7526,7 @@ <translation id="6826872289184051766">Valider via USB</translation> <translation id="6827121912381363404">Autoriser toutes les extensions à lire et modifier <ph name="PERMITTED_SITE" /></translation> <translation id="6827422464708099620">Sélectionner pour afficher plus d'options</translation> -<translation id="6827517233063803343">Vos applis et paramètres seront synchronisés sur tous les appareils Chrome OS où vous êtes connecté à votre compte Google. Pour voir les options de synchronisation du navigateur, accédez aux <ph name="LINK_BEGIN" />paramètres de Chrome<ph name="LINK_END" />.</translation> +<translation id="6827517233063803343">Vos applis et paramètres seront synchronisés sur tous les appareils ChromeOS où vous êtes connecté à votre compte Google. Pour voir les options de synchronisation du navigateur, accédez aux <ph name="LINK_BEGIN" />paramètres de Chrome<ph name="LINK_END" />.</translation> <translation id="6827767090350758381">Les anciennes versions des applis Chrome ne s'ouvriront plus sur les appareils Windows après décembre 2022. Contactez votre administrateur pour passer à une nouvelle version ou supprimer cette appli.</translation> <translation id="6828153365543658583">Autoriser uniquement les utilisateurs suivants à se connecter :</translation> <translation id="6828182567531805778">Saisissez votre phrase secrète pour synchroniser vos données.</translation>
diff --git a/chrome/app/resources/generated_resources_gl.xtb b/chrome/app/resources/generated_resources_gl.xtb index 1212c5d..b219330 100644 --- a/chrome/app/resources/generated_resources_gl.xtb +++ b/chrome/app/resources/generated_resources_gl.xtb
@@ -3292,6 +3292,7 @@ <translation id="3497560059572256875">Compartir doodle</translation> <translation id="3497915391670770295">Enviar aos teus &dispositivos</translation> <translation id="3500417806337761827">Produciuse un erro ao montar o recurso compartido. Xa hai montados demasiados recursos compartidos SMB.</translation> +<translation id="3500764001796099683">Activar aplicacións web illadas</translation> <translation id="350397915809787283">Se non tes ningunha conta, selecciona a primeira opción para crear unha.</translation> <translation id="3503995387997205657">Xa podes restaurar as aplicacións antigas</translation> <translation id="3505100368357440862">Suxestións de compras</translation> @@ -7167,6 +7168,7 @@ <translation id="6551508934388063976">Comando non dispoñible. Preme control-N para abrir unha ventá nova.</translation> <translation id="6551606359270386381">Ferramenta de elipses</translation> <translation id="6551612971599078809">O sitio está utilizando un USB</translation> +<translation id="6551620030439692385">Bloqueado. Actualmente o fuso horario está definido como <ph name="TIMEZONE" /> e só se pode modificar manualmente.</translation> <translation id="6551739526055143276">Contas xestionadas por Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> usuarios</translation> <translation id="6555432686520421228">Elimina todas as contas de usuario e restablece o dispositivo <ph name="IDS_SHORT_PRODUCT_NAME" /> como se fose novo.</translation> @@ -7235,6 +7237,7 @@ <translation id="6608773371844092260">Para configurar a impresión dixital, pídelle ao teu fillo ou filla que toque o sensor correspondente situado na parte dereita deste dispositivo (<ph name="DEVICE_TYPE" />). Os datos da súa impresión dixital almacenaranse de maneira segura neste dispositivo (<ph name="DEVICE_TYPE" />) e nunca sairán del.</translation> <translation id="6609478180749378879">Os datos de inicio de sesión almacenaranse neste dispositivo cando saias do modo de incógnito. Poderás iniciar sesión de novo neste sitio web desde o teu dispositivo máis tarde.</translation> <translation id="6610002944194042868">Opcións de tradución</translation> +<translation id="6610064275805055636">Xestionar aplicacións web illadas</translation> <translation id="6611972847767394631">Atopa aquí as túas pestanas</translation> <translation id="661266467055912436">Mellora a túa seguranza e a do resto dos usuarios da Web.</translation> <translation id="6613267708691765962">Analizando en busca de software malicioso...</translation> @@ -8598,6 +8601,7 @@ <translation id="7671472752213333268"><ph name="EXTENSION_NAME" /> quere escanear documentos desde <ph name="SCANNER_NAME" />.</translation> <translation id="7672504401554182757">Escolle o dispositivo que ten a clave de acceso para <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, en <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Bloqueado. Actualmente o horario está definido de <ph name="SUNRISE_TIME" /> a <ph name="SUNSET_TIME" /> e só se pode modificar manualmente.</translation> <translation id="7673313156293624327">Rexistros de ChromeOS Shill (xestor de conexións)</translation> <translation id="7674416868315480713">Desactivar todos os portos que se estean encamiñando en Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> aplicacións</translation> @@ -9530,6 +9534,7 @@ <translation id="8376384591331888629">Incluír as cookies de terceiros deste sitio</translation> <translation id="8376451933628734023">Se esta aplicación web está tentando enganarte para que penses que se trata dunha distinta, desinstálaa.</translation> <translation id="8376532149031784008">Volvendo cargar <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">As extensións instaladas pola persoa administradora poderán seguir lendo e modificando este sitio</translation> <translation id="8376752431516546391">Panel lateral da Busca de Google</translation> <translation id="8377625247046155446">Esta clave de acceso só se gardará neste dispositivo. Permanecerá neste dispositivo despois de que peches todas as ventás do modo de incógnito.</translation> <translation id="8378714024927312812">Xestionado pola túa organización</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb index 165164c..d9f5c56 100644 --- a/chrome/app/resources/generated_resources_hr.xtb +++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -1720,6 +1720,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Otvori sve u &novoj grupi kartica}=1{Otvori u &novoj grupi kartica}one{Otvori sve ({COUNT}) u &novoj grupi kartica}few{Otvori sve ({COUNT}) u &novoj grupi kartica}other{Otvori sve ({COUNT}) u &novoj grupi kartica}}</translation> <translation id="2285942871162473373">Prepoznavanje vašeg otiska prsta nije uspjelo. Pokušajte ponovo.</translation> <translation id="2287617382468007324">Ispis IPP adrese</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokaciju koju niste posjećivali u posljednje vrijeme}one{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokacije koje niste posjećivali u posljednje vrijeme}few{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokacije koje niste posjećivali u posljednje vrijeme}other{Radi zaštite vaših podataka dopuštenja su uklonjena za web-lokacije koje niste posjećivali u posljednje vrijeme}}</translation> <translation id="2287944065963043964">Zaslon za prijavu</translation> <translation id="2290615375132886363">Gumbi za kretanje na tabletu</translation> <translation id="2291452790265535215">Isprobajte bočnu ploču za oznake, putovanja i ostalo</translation> @@ -3296,6 +3297,7 @@ <translation id="3497560059572256875">Dijeljenje doodle logotipa</translation> <translation id="3497915391670770295">Pošalji na svoje uređaje</translation> <translation id="3500417806337761827">Pogreška prilikom učitavanja dijeljenja. Već je učitano previše SMB dijeljenja.</translation> +<translation id="3500764001796099683">Omogući izolirane web-aplikacije</translation> <translation id="350397915809787283">Ako nemate račun, odaberite prvu opciju da biste ga izradili.</translation> <translation id="3503995387997205657">Možete vratiti svoje prethodne aplikacije</translation> <translation id="3505100368357440862">Prijedlozi za kupnju</translation> @@ -4304,6 +4306,7 @@ <translation id="4275788652681621337">Zatvori bočnu ploču</translation> <translation id="4275830172053184480">Ponovo pokrenite svoj uređaj</translation> <translation id="4277434192562187284">Izvor XML konfiguracije</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{Dopuštenja su uklonjena za jednu web-lokaciju}one{Dopuštenja su uklonjena za {NUM_SITES} web-lokaciju}few{Dopuštenja su uklonjena za {NUM_SITES} web-lokacije}other{Dopuštenja su uklonjena za {NUM_SITES} web-lokacija}}</translation> <translation id="4278390842282768270">Dopušteno</translation> <translation id="4278498748067682896">Upotrebljavat ćete nadogradnju kioska i znakovlja koja uređaju omogućuje pokretanje samo načina rada kioska ili znakovlja. Ako želite da se korisnici prijave na uređaj, vratite se i registrirajte pomoću Nadogradnje za Chrome za poduzeća.</translation> <translation id="4278779213160967034">Taj postupak može potrajati nekoliko minuta. Preuzimaju se datoteke.</translation> @@ -7168,6 +7171,7 @@ <translation id="6551508934388063976">Naredba nije dostupna. Pritisnite tipke Ctrl – N za otvaranje novog prozora.</translation> <translation id="6551606359270386381">Alat za elipse</translation> <translation id="6551612971599078809">Web-lokacija upotrebljava USB</translation> +<translation id="6551620030439692385">Blokirano. Vremenska zona trenutačno je postavljena na <ph name="TIMEZONE" /> i može se ažurirati samo ručno.</translation> <translation id="6551739526055143276">Upravlja Family Link</translation> <translation id="655384502888039633">Broj korisnika: <ph name="USER_COUNT" /></translation> <translation id="6555432686520421228">Uklonite sve korisničke račune i ponovo postavite svoj uređaj <ph name="IDS_SHORT_PRODUCT_NAME" /> kao da je novi.</translation> @@ -7240,6 +7244,7 @@ <translation id="6608773371844092260">Da biste postavili otisak prsta, neka vaše dijete dodirne senzor otiska prsta s desne strane uređaja <ph name="DEVICE_TYPE" />. Podaci o otisku prsta vašeg djeteta sigurno se pohranjuju i nikamo se ne šalju s uređaja <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Podaci za prijavu pohranit će se na ovom uređaju nakon što izađete iz anonimnog načina. Kasnije ćete se pomoću svojeg uređaja ponovno moći prijaviti na ovu web-lokaciju.</translation> <translation id="6610002944194042868">Opcije Prevoditelja</translation> +<translation id="6610064275805055636">Upravljajte izoliranim web-aplikacijama</translation> <translation id="6611972847767394631">Ovdje možete pronaći svoje kartice</translation> <translation id="661266467055912436">Poboljšava sigurnost za vas i sve ostale na webu.</translation> <translation id="6613267708691765962">Traženje zlonamjernog softvera...</translation> @@ -8604,6 +8609,7 @@ <translation id="7671472752213333268"><ph name="EXTENSION_NAME" /> želi skenirati s uređaja <ph name="SCANNER_NAME" />.</translation> <translation id="7672504401554182757">Odaberite koji uređaj ima pristupni ključ za aplikaciju <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, na stranici <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blokirano. Raspored je trenutačno postavljen na <ph name="SUNRISE_TIME" /> – <ph name="SUNSET_TIME" /> i može se ažurirati samo ručno.</translation> <translation id="7673313156293624327">Zapisnici zapisnika Shill OS-a Chrome (Upravitelj povezivanja)</translation> <translation id="7674416868315480713">Deaktiviraj sve priključke koji se prosljeđuju u Linuxu</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> aplikacije</translation> @@ -9537,6 +9543,7 @@ <translation id="8376384591331888629">Uključujući kolačiće treće strane na ovoj web-lokaciji</translation> <translation id="8376451933628734023">Ako vas ova web-aplikacija pokušava prevariti kako biste pomislili da je neka druga aplikacija, deinstalirajte je.</translation> <translation id="8376532149031784008">Ponovno učitavanje <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Proširenja koja je instalirao vaš administrator i dalje mogu čitati i mijenjati ovu web-lokaciju</translation> <translation id="8376752431516546391">Bočna ploča Google pretraživanja</translation> <translation id="8377625247046155446">Ovaj će se pristupni ključ spremiti samo na ovom uređaju. Ostat će na ovom uređaju nakon što zatvorite sve anonimne prozore.</translation> <translation id="8378714024927312812">Pod upravljanjem vaše organizacije</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb index 6b887e6e..9ec23dbb 100644 --- a/chrome/app/resources/generated_resources_id.xtb +++ b/chrome/app/resources/generated_resources_id.xtb
@@ -3308,6 +3308,7 @@ <translation id="3497560059572256875">Bagikan Doodle</translation> <translation id="3497915391670770295">Kirim ke &Perangkat Anda</translation> <translation id="3500417806337761827">Error saat memasang fitur berbagi SMB. Terlalu banyak fitur berbagi SMB yang telah terpasang.</translation> +<translation id="3500764001796099683">Aktifkan aplikasi web terisolasi</translation> <translation id="350397915809787283">Jika Anda belum memiliki akun, pilih opsi pertama untuk membuat akun.</translation> <translation id="3503995387997205657">Anda dapat memulihkan aplikasi sebelumnya</translation> <translation id="3505100368357440862">Saran belanja</translation> @@ -7184,6 +7185,7 @@ <translation id="6551508934388063976">Perintah tidak tersedia. Tekan Control-N untuk membuka jendela baru.</translation> <translation id="6551606359270386381">Alat Elips</translation> <translation id="6551612971599078809">Situs menggunakan USB</translation> +<translation id="6551620030439692385">Diblokir. Zona waktu saat ini disetel ke <ph name="TIMEZONE" /> dan hanya dapat diperbarui secara manual.</translation> <translation id="6551739526055143276">Dikelola oleh Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> pengguna</translation> <translation id="6555432686520421228">Hapus semua akun pengguna dan reset perangkat <ph name="IDS_SHORT_PRODUCT_NAME" /> Anda agar menjadi seperti baru.</translation> @@ -7252,6 +7254,7 @@ <translation id="6608773371844092260">Untuk menyiapkan sidik jari, minta anak Anda menyentuh sensor sidik jari di sisi kanan <ph name="DEVICE_TYPE" /> ini. Data sidik jari anak Anda disimpan dengan aman dan tidak pernah dikirim ke luar <ph name="DEVICE_TYPE" /> ini.</translation> <translation id="6609478180749378879">Data login akan disimpan di perangkat ini setelah Anda keluar dari mode Samaran. Anda dapat login ke situs ini dengan perangkat Anda lagi nanti.</translation> <translation id="6610002944194042868">Opsi Terjemahan</translation> +<translation id="6610064275805055636">Kelola aplikasi web terisolasi</translation> <translation id="6611972847767394631">Temukan tab Anda di sini</translation> <translation id="661266467055912436">Meningkatkan keamanan untuk Anda dan semua orang di web.</translation> <translation id="6613267708691765962">Memindai malware...</translation> @@ -8615,6 +8618,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" ingin memindai dari "<ph name="SCANNER_NAME" />".</translation> <translation id="7672504401554182757">Pilih perangkat yang memiliki kunci sandi untuk <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, di <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Diblokir. Jadwal saat ini disetel ke <ph name="SUNRISE_TIME" /> — <ph name="SUNSET_TIME" /> dan hanya dapat diperbarui secara manual.</translation> <translation id="7673313156293624327">Log Shill (Pengelola Koneksi) ChromeOS</translation> <translation id="7674416868315480713">Nonaktifkan semua port yang diteruskan di Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> aplikasi</translation> @@ -9548,6 +9552,7 @@ <translation id="8376384591331888629">Menyertakan cookie pihak ketiga di situs ini</translation> <translation id="8376451933628734023">Uninstal aplikasi web ini jika mencoba mengelabui Anda agar berpikir bahwa ini adalah aplikasi yang berbeda.</translation> <translation id="8376532149031784008">Memuat ulang <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Ekstensi yang diinstal oleh administrator masih dapat membaca dan mengubah situs ini</translation> <translation id="8376752431516546391">Panel samping Google Penelusuran</translation> <translation id="8377625247046155446">Kunci sandi ini hanya akan disimpan di perangkat ini. Kunci akan tetap ada di perangkat ini setelah Anda menutup semua jendela Samaran.</translation> <translation id="8378714024927312812">Dikelola oleh organisasi</translation>
diff --git a/chrome/app/resources/generated_resources_is.xtb b/chrome/app/resources/generated_resources_is.xtb index 440050f..e3f1cdd9 100644 --- a/chrome/app/resources/generated_resources_is.xtb +++ b/chrome/app/resources/generated_resources_is.xtb
@@ -3309,6 +3309,7 @@ <translation id="3497560059572256875">Deila dúllu</translation> <translation id="3497915391670770295">Senda í tækin þín</translation> <translation id="3500417806337761827">Villa við tengingu skráageymslu. Of margar SMB-geymslur eru þegar tengdar.</translation> +<translation id="3500764001796099683">Kveikja á einangruðum vefforritum</translation> <translation id="350397915809787283">Ef þú ert ekki með reikning skaltu velja fyrsta valkostinn til að búa hann til.</translation> <translation id="3503995387997205657">Þú getur endurheimt fyrri forrit</translation> <translation id="3505100368357440862">Innkaupatillögur</translation> @@ -7185,6 +7186,7 @@ <translation id="6551508934388063976">Skipun óaðgengileg. Ýttu á Ctrl+N til að opna nýjan glugga.</translation> <translation id="6551606359270386381">Sporbaugsverkfæri</translation> <translation id="6551612971599078809">Vefsvæðið notar USB</translation> +<translation id="6551620030439692385">Á bannlista. Tímabelti er nú stillt á <ph name="TIMEZONE" /> og aðeins er hægt að uppfæra það handvirkt.</translation> <translation id="6551739526055143276">Í umsjón Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> notendur</translation> <translation id="6555432686520421228">Fjarlæga alla notendareikninga og núllstilla <ph name="IDS_SHORT_PRODUCT_NAME" /> tækið þannig að það verði eins og þegar það var nýtt.</translation> @@ -7255,6 +7257,7 @@ <translation id="6608773371844092260">Til að skrá fingrafar skaltu láta barnið snerta fingrafaralesarann hægra megin í <ph name="DEVICE_TYPE" />. Fingrafaragögn barnsins eru í öruggri geymslu og fara aldrei út fyrir þetta <ph name="DEVICE_TYPE" />-tæki.</translation> <translation id="6609478180749378879">Innskráningargögn verða geymd í þessu tæki eftir að þú lokar huliðsstillingu. Þú getur skráð þig aftur inn á þetta vefsvæði með tækinu þínu síðar.</translation> <translation id="6610002944194042868">Valkostir þýðinga</translation> +<translation id="6610064275805055636">Stjórna einangruðum vefforritum</translation> <translation id="6611972847767394631">Finndu flipana þína hér</translation> <translation id="661266467055912436">Eykur öryggi þitt og allra á vefnum.</translation> <translation id="6613267708691765962">Leitar að spilliforritum...</translation> @@ -8618,6 +8621,7 @@ <translation id="7671472752213333268">„<ph name="EXTENSION_NAME" />“ vill skanna með „<ph name="SCANNER_NAME" />“.</translation> <translation id="7672504401554182757">Veldu hvaða tæki er með aðgangslykil fyrir <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, á <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Á bannlista. Áætlun er nú stillt á <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> og aðeins er hægt að uppfæra hana handvirkt.</translation> <translation id="7673313156293624327">Annálar ChromeOS Shill (tengingarstjórnun)</translation> <translation id="7674416868315480713">Gera framsendingu allra gátta óvirka í Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> forrit</translation> @@ -9550,6 +9554,7 @@ <translation id="8376384591331888629">Hafa fótspor þriðju aðila á þessu vefsvæði með</translation> <translation id="8376451933628734023">Þú ættir að fjarlægja þetta vefforrit ef það reynir að plata þig með því að þykjast vera eitthvert annað forrit.</translation> <translation id="8376532149031784008">Endurhleður <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Viðbætur sem stjórnandi hefur sett upp geta áfram lesið þetta vefsvæði og breytt því</translation> <translation id="8376752431516546391">Hliðargluggi í Google-leit</translation> <translation id="8377625247046155446">Þessi aðgangslykill verður aðeins vistaður í þessu tæki. Hann verður áfram í þessu tæki eftir að þú lokar öllum huliðsgluggum.</translation> <translation id="8378714024927312812">Stjórnað af fyrirtækinu þínu</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb index 27b1505..7482040 100644 --- a/chrome/app/resources/generated_resources_it.xtb +++ b/chrome/app/resources/generated_resources_it.xtb
@@ -5708,7 +5708,7 @@ <translation id="5404740137318486384">Premi un sensore o un tasto della tastiera per assegnarlo a "<ph name="ACTION" />". Puoi assegnare più sensori a questa azione.</translation> <translation id="540495485885201800">Scambia con elemento precedente</translation> -<translation id="5405146885510277940">Reimposta</translation> +<translation id="5405146885510277940">Ripristina impostazioni</translation> <translation id="5406844893187365798">Digitazione flessibile</translation> <translation id="5407167491482639988">Incomprensibile</translation> <translation id="5408750356094797285">Zoom: <ph name="PERCENT" /></translation> @@ -7015,7 +7015,7 @@ <translation id="6435339218366409950">Scegli la lingua in cui tradurre i sottotitoli codificati</translation> <translation id="6436164536244065364">Visualizza nel Web Store</translation> <translation id="6436778875248895551">L'estensione "<ph name="EXTENSION_NAME" />" è stata bloccata dall'amministratore</translation> -<translation id="6438234780621650381">Ripristino delle impostazioni</translation> +<translation id="6438234780621650381">Ripristina impostazioni</translation> <translation id="6438475350605608554">Stai già importando le password in un'altra scheda</translation> <translation id="6438992844451964465"><ph name="WINDOW_TITLE" /> - Riproduzione audio in corso</translation> <translation id="6440291723980579689">Le pagine si caricano solo una volta aperte</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb index 5564a77..8aaecdb 100644 --- a/chrome/app/resources/generated_resources_iw.xtb +++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -3308,6 +3308,7 @@ <translation id="3497560059572256875">שיתוף הדודל</translation> <translation id="3497915391670770295">שליחה אל &המכשירים שלך</translation> <translation id="3500417806337761827">אירעה שגיאה בטעינת השיתוף. כבר נטענו יותר מדי שיתופי SMB.</translation> +<translation id="3500764001796099683">הפעלה של אפליקציות אינטרנט מבודדות (IWA)</translation> <translation id="350397915809787283">אם אין לך חשבון, עליך לבחור באפשרות הראשונה כדי ליצור חשבון.</translation> <translation id="3503995387997205657">יש לך אפשרות לשחזר את האפליקציות הקודמות שבהן השתמשת</translation> <translation id="3505100368357440862">הצעות לקניות</translation> @@ -7185,6 +7186,7 @@ <translation id="6551508934388063976">הפקודה לא זמינה. יש להקיש על Control-N לפתיחת חלון חדש.</translation> <translation id="6551606359270386381">כלי האליפסה</translation> <translation id="6551612971599078809">נעשה שימוש בחיבור USB באתר</translation> +<translation id="6551620030439692385">הגישה חסומה. אזור הזמן שמוגדר כרגע הוא <ph name="TIMEZONE" />, ואפשר לעדכן אותו רק באופן ידני.</translation> <translation id="6551739526055143276">הניהול מתבצע באמצעות Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> משתמשים</translation> <translation id="6555432686520421228">הסרת כל חשבונות המשתמשים ואיפוס המכשיר <ph name="IDS_SHORT_PRODUCT_NAME" /> כך שיהיה כמו חדש.</translation> @@ -7257,6 +7259,7 @@ <translation id="6608773371844092260">כדי להגדיר טביעת אצבע, על הילד או הילדה לגעת בחיישן טביעות האצבע שבצד ימין של מכשיר <ph name="DEVICE_TYPE" /> הזה. נתוני טביעות האצבע של הילד או הילדה נשמרים באופן מאובטח ואף פעם לא נשלחים ממכשיר <ph name="DEVICE_TYPE" /> הזה.</translation> <translation id="6609478180749378879">פרטי הכניסה יאוחסנו במכשיר הזה אחרי היציאה ממצב אנונימי. מאוחר יותר תהיה לך אפשרות להיכנס שוב לחשבון באתר הזה באמצעות המכשיר.</translation> <translation id="6610002944194042868">אפשרויות תרגום</translation> +<translation id="6610064275805055636">ניהול של אפליקציות אינטרנט מבודדות (IWA)</translation> <translation id="6611972847767394631">הכרטיסיות שלך נמצאות כאן</translation> <translation id="661266467055912436">רמת אבטחה משופרת עבורך ועבור כל מי שמתחבר לאינטרנט.</translation> <translation id="6613267708691765962">מתבצעת סריקה לאיתור תוכנה זדונית…</translation> @@ -8621,6 +8624,7 @@ <translation id="7671472752213333268">'<ph name="EXTENSION_NAME" />' רוצה לסרוק מ-'<ph name="SCANNER_NAME" />'.</translation> <translation id="7672504401554182757">יש לבחור את המכשיר שמכיל את מפתח הגישה עבור <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, ב-<ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">הגישה חסומה. לוח הזמנים שמוגדר כרגע הוא <ph name="SUNRISE_TIME" /> עד <ph name="SUNSET_TIME" />, ואפשר לעדכן אותו רק באופן ידני.</translation> <translation id="7673313156293624327">יומנים של ChromeOS Shill (Connection Manager)</translation> <translation id="7674416868315480713">השבתה של כל היציאות שמוגדרת לגביהן העברה ב-Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> אפליקציות</translation> @@ -9555,6 +9559,7 @@ <translation id="8376384591331888629">כולל קובצי cookie של צד שלישי באתר זה</translation> <translation id="8376451933628734023">אם אפליקציית האינטרנט הזו מנסה להטעות אותך ולחשוב שמדובר באפליקציה אחרת, צריך להסיר אותה.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> בטעינה מחדש…</translation> +<translation id="8376610503048439696">לתוספים שהותקנו על ידי האדמין עדיין יש הרשאה לקרוא ולשנות את האתר הזה</translation> <translation id="8376752431516546391">החלונית הצדדית של חיפוש Google</translation> <translation id="8377625247046155446">מפתח הגישה הזה יישמר רק במכשיר הזה. הוא יישאר במכשיר הזה אחרי שסגרת את כל החלונות הפרטיים.</translation> <translation id="8378714024927312812">מנוהל על-ידי הארגון</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb index 0a4f718..a4fd2774 100644 --- a/chrome/app/resources/generated_resources_ja.xtb +++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -3287,6 +3287,7 @@ <translation id="3497560059572256875">Doodle を共有</translation> <translation id="3497915391670770295">お使いのデバイスに送信(&D)</translation> <translation id="3500417806337761827">共有フォルダのマウントエラー。マウントされた SMB 共有の数が上限を超えています。</translation> +<translation id="3500764001796099683">独立したウェブアプリを有効にする</translation> <translation id="350397915809787283">アカウントがない場合は、最初のオプションを選択して作成してください。</translation> <translation id="3503995387997205657">前回のアプリを復元できます</translation> <translation id="3505100368357440862">おすすめのショッピング情報</translation> @@ -3537,7 +3538,7 @@ <translation id="3702797829026927713"><ph name="BEGIN_PARAGRAPH1" />このデモデバイスを設定する販売店の名前と番号を入力してください*。<ph name="END_PARAGRAPH1" /> <ph name="BEGIN_PARAGRAPH2" />販売店の番号が不明な場合は、「0000」と入力するとデモモードのインストールを続行できます。<ph name="END_PARAGRAPH2" /> <ph name="BEGIN_PARAGRAPH3" />*注: Google は、デバイスが受信するデモモードのバージョンを特定し、デモモードの使用状況を測定する目的でこの情報を使用します。<ph name="END_PARAGRAPH3" /></translation> -<translation id="3703166520839776970">この問題がまだ解消しない場合は、下の [詳細] を選択して <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> の詳細をご覧ください。</translation> +<translation id="3703166520839776970">問題が解消しない場合は、下の [詳細] を選択して <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> の詳細をご覧ください。</translation> <translation id="3703699162703116302">チケットが更新されました</translation> <translation id="370415077757856453">JavaScript がブロックされました</translation> <translation id="3704331259350077894">処理が停止した</translation> @@ -7157,6 +7158,7 @@ <translation id="6551508934388063976">コマンドを使用できません。Ctrl+N を押して新しいウィンドウを開いてください。</translation> <translation id="6551606359270386381">楕円ツール</translation> <translation id="6551612971599078809">サイトで USB が使用されています</translation> +<translation id="6551620030439692385">ブロックされています。現在、タイムゾーンは <ph name="TIMEZONE" /> に設定されており、手動でのみ更新できます。</translation> <translation id="6551739526055143276">ファミリー リンクの管理対象</translation> <translation id="655384502888039633">ユーザー数: <ph name="USER_COUNT" /> 人</translation> <translation id="6555432686520421228">すべてのユーザー アカウントを削除し、<ph name="IDS_SHORT_PRODUCT_NAME" /> デバイスを出荷時と同じ状態にリセットします。</translation> @@ -7225,6 +7227,7 @@ <translation id="6608773371844092260">指紋を設定するには、この <ph name="DEVICE_TYPE" /> の右側にある指紋認証センサーをお子様にタップしてもらってください。お子様の指紋データはこの <ph name="DEVICE_TYPE" /> にのみ安全に保存されます。</translation> <translation id="6609478180749378879">ログインデータはシークレット モードの終了後にこのデバイスに保存されます。今後、このデバイスからこのウェブサイトにログインできるようになります。</translation> <translation id="6610002944194042868">翻訳オプション</translation> +<translation id="6610064275805055636">独立したウェブアプリを管理する</translation> <translation id="6611972847767394631">ここからタブを確認できます</translation> <translation id="661266467055912436">すべてのウェブユーザーの安全性を高めます。</translation> <translation id="6613267708691765962">マルウェアをスキャンしています...</translation> @@ -8587,6 +8590,7 @@ <translation id="7671472752213333268">「<ph name="EXTENSION_NAME" />」が「<ph name="SCANNER_NAME" />」のスキャンをリクエストしています。</translation> <translation id="7672504401554182757"><ph name="APP_NAME" /> のパスキーがあるデバイスを選択してください</translation> <translation id="7672520070349703697"><ph name="PAGE_TITLE" /> 内の <ph name="HUNG_IFRAME_URL" /> が停止しています。</translation> +<translation id="7672726198839739113">ブロックされています。現在、スケジュールは <ph name="SUNRISE_TIME" />~<ph name="SUNSET_TIME" /> に設定されており、手動でのみ更新できます。</translation> <translation id="7673313156293624327">ChromeOS Shill(接続マネージャー)のログ</translation> <translation id="7674416868315480713">Linux で転送中のポートをすべて無効にする</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> 個のアプリ</translation> @@ -9519,6 +9523,7 @@ <translation id="8376384591331888629">サイト上のサードパーティ Cookie も対象</translation> <translation id="8376451933628734023">このウェブアプリが別のアプリになりすまそうとしている場合は、アンインストールしてください。</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> を再読み込みしています...</translation> +<translation id="8376610503048439696">管理者がインストールした拡張機能では、このサイトの読み取りや変更が可能です</translation> <translation id="8376752431516546391">Google 検索サイドパネル</translation> <translation id="8377625247046155446">このパスキーはこのデバイスにのみ保存されます。すべてのシークレット ウィンドウを閉じた後も、パスキーはこのデバイスには残ります。</translation> <translation id="8378714024927312812">組織によって管理されています</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb index 74cd770..d23ae678 100644 --- a/chrome/app/resources/generated_resources_kk.xtb +++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -3290,6 +3290,7 @@ <translation id="3497560059572256875">Дудлды бөлісу</translation> <translation id="3497915391670770295">&Құрылғыларыңызға жіберу</translation> <translation id="3500417806337761827">Бөлісу кезінде қате шықты. Тым көп SMB бөлісілген.</translation> +<translation id="3500764001796099683">Оқшау веб-қолданбаларды қосу</translation> <translation id="350397915809787283">Аккаунтыңыз болмаса, жасау үшін бірінші опцияны таңдаңыз.</translation> <translation id="3503995387997205657">Алдыңғы қолданбаларды қалпына келтіре аласыз.</translation> <translation id="3505100368357440862">Сатып алу ұсыныстары</translation> @@ -7162,6 +7163,7 @@ <translation id="6551508934388063976">Пәрмен қолжетімсіз. Жаңа терезе ашу үшін Ctrl+N тіркесімін басыңыз.</translation> <translation id="6551606359270386381">Эллипс құралы</translation> <translation id="6551612971599078809">Сайт USB құрылғысын пайдалануда</translation> +<translation id="6551620030439692385">Блокталған. Уақыт белдеуі <ph name="TIMEZONE" /> деп орнатылды. Оны тек қолмен өзгертуге болады.</translation> <translation id="6551739526055143276">Family Link арқылы басқарылады.</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> пайдаланушы</translation> <translation id="6555432686520421228">Барлық пайдаланушы аккаунттарын жойып, <ph name="IDS_SHORT_PRODUCT_NAME" /> құрылғыңызды жаңадай қылып бастапқы күйіне орнатады.</translation> @@ -7230,6 +7232,7 @@ <translation id="6608773371844092260">Саусақ ізін реттеу үшін балаңыз осы <ph name="DEVICE_TYPE" /> оң жағындағы саусақ ізін оқу сканерін түртуі керек. Бала саусағының ізі туралы деректер қауіпсіз сақталған және <ph name="DEVICE_TYPE" /> құрылғысынан басқа ешқайда жіберілмейді.</translation> <translation id="6609478180749378879">Сіз инкогнито режимінен шыққаннан кейін де, аккаунтқа кіру деректері осы құрылғыда сақталады. Кейінірек құрылғыңызбен бұл веб-сайтқа қайта кіре аласыз.</translation> <translation id="6610002944194042868">Аудару опциялары</translation> +<translation id="6610064275805055636">Оқшау веб-қолданбаларды басқару</translation> <translation id="6611972847767394631">Қойындыларыңыз осы жерде</translation> <translation id="661266467055912436">Интернеттегі сіздің және басқалардың қауіпсіздігін күшейтеді.</translation> <translation id="6613267708691765962">Зиянды бағдарламаның бар-жоғы тексеріліп жатыр...</translation> @@ -8592,6 +8595,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" "<ph name="SCANNER_NAME" />" құрылғысынан сканерлеуге рұқсат сұрайды.</translation> <translation id="7672504401554182757">Қандай құрылғыда <ph name="APP_NAME" /> қолданбасына кіру кілті бар екенін таңдаңыз.</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> қызметінде.</translation> +<translation id="7672726198839739113">Блокталған. Кесте <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> деп орнатылды. Оны тек қолмен өзгертуге болады.</translation> <translation id="7673313156293624327">ChromeOS Shill (байланыс менеджері) журналдары</translation> <translation id="7674416868315480713">Linux-ке бағытталған барлық портты өшіру</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> қолданба</translation> @@ -9524,6 +9528,7 @@ <translation id="8376384591331888629">Осы сайттағы үшінші тараптың cookie файлдарын қоса</translation> <translation id="8376451933628734023">Егер бұл веб-қолданба өзінің басқа қолданба екеніне сізді сендіргісі келсе, оны жойып тастаңыз.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> қайта жүктелуде…</translation> +<translation id="8376610503048439696">Әкімшіңіз орнатқан кеңейтімдер әлі де бұл сайтты оқи және өзгерте алады.</translation> <translation id="8376752431516546391">Google Search бүйірлік панелі</translation> <translation id="8377625247046155446">Бұл кіру кілті тек осы құрылғыда сақталады. Барлық инкогнито терезесін жапқаннан кейін, ол осы құрылғыда қалады.</translation> <translation id="8378714024927312812">Ұйым басқарады</translation>
diff --git a/chrome/app/resources/generated_resources_km.xtb b/chrome/app/resources/generated_resources_km.xtb index 9556323..1db90bc0 100644 --- a/chrome/app/resources/generated_resources_km.xtb +++ b/chrome/app/resources/generated_resources_km.xtb
@@ -1732,6 +1732,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{បើកទាំងអស់នៅក្នុង&ក្រុមផ្ទាំងថ្មី}=1{បើកនៅក្នុង&ក្រុមផ្ទាំងថ្មី}other{បើកទាំងអស់ ({COUNT}) នៅក្នុង&ក្រុមផ្ទាំងថ្មី}}</translation> <translation id="2285942871162473373">មិនស្គាល់ស្នាមម្រាមដៃរបស់អ្នកទេ។ សូមព្យាយាមម្ដងទៀត។</translation> <translation id="2287617382468007324">អាសយដ្ឋាន IPP សម្រាប់បោះពុម្ព</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{ដើម្បីការពារទិន្នន័យរបស់អ្នក ការអនុញ្ញាតត្រូវបានដកចេញពីគេហទំព័រដែលអ្នកមិនបានចូលមើលនាពេលថ្មីៗនេះ}other{ដើម្បីការពារទិន្នន័យរបស់អ្នក ការអនុញ្ញាតត្រូវបានដកចេញពីគេហទំព័រដែលអ្នកមិនបានចូលមើលនាពេលថ្មីៗនេះ}}</translation> <translation id="2287944065963043964">អេក្រង់ចូល</translation> <translation id="2290615375132886363">ប៊ូតុងរុករកក្នុងមុខងារថេប្លេត</translation> <translation id="2291452790265535215">សាកល្បងប្រើផ្ទាំងចំហៀងសម្រាប់ចំណាំ ការធ្វើដំណើរ និងអ្វីៗជាច្រើនទៀត</translation> @@ -4317,6 +4318,7 @@ <translation id="4275788652681621337">បិទផ្ទាំងចំហៀង</translation> <translation id="4275830172053184480">ចាប់ផ្តើមឧបករណ៍របស់អ្នកឡើងវិញ</translation> <translation id="4277434192562187284">ប្រភពនៃការកំណត់រចនាសម្ព័ន្ធ XML</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{បានដកការអនុញ្ញាតចេញពីគេហទំព័រចំនួន 1}other{បានដកការអនុញ្ញាតចេញពីគេហទំព័រចំនួន {NUM_SITES}}}</translation> <translation id="4278390842282768270">បានអនុញ្ញាត</translation> <translation id="4278498748067682896">អ្នកនឹងប្រើ Kiosk & Signage Upgrade ដែលអនុញ្ញាតឱ្យឧបករណ៍ដំណើរការក្នុងមុខងារបញ្ជរ ឬផ្ទាំងអេក្រង់ឌីជីថលតែប៉ុណ្ណោះ។ ប្រសិនបើអ្នកចង់ឱ្យអ្នកប្រើប្រាស់ចូលឧបករណ៍ សូមត្រឡប់ក្រោយ ហើយចុះឈ្មោះដោយប្រើ Chrome Enterpirse Upgrade។</translation> <translation id="4278779213160967034">ដំណើរការនេះអាចចំណាយពេលពីរបីនាទី។ កំពុងទាញយកឯកសារ។</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb index 89062f1..3896da2 100644 --- a/chrome/app/resources/generated_resources_kn.xtb +++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -3301,6 +3301,7 @@ <translation id="3497560059572256875">ಡೂಡಲ್ ಹಂಚಿಕೊಳ್ಳಿ</translation> <translation id="3497915391670770295">ನಿಮ್ಮ &ಸಾಧನಗಳಿಗೆ ಕಳುಹಿಸಿ</translation> <translation id="3500417806337761827">ಹಂಚಿಕೆಯನ್ನು ಅಳವಡಿಸುವಾಗ ದೋಷ ಉಂಟಾಗಿದೆ. ಹಲವಾರು SMB ಹಂಚಿಕೆಗಳನ್ನು ಈಗಾಗಲೇ ಅಳವಡಿಸಲಾಗಿದೆ.</translation> +<translation id="3500764001796099683">ಪ್ರತ್ಯೇಕಗೊಳಿಸಲಾದ ವೆಬ್ ಆ್ಯಪ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ</translation> <translation id="350397915809787283">ನೀವು ಖಾತೆಯನ್ನು ಹೊಂದಿಲ್ಲದಿದ್ದರೆ, ಒಂದನ್ನು ರಚಿಸಲು ಮೊದಲ ಆಯ್ಕೆಯನ್ನು ಆರಿಸಿ.</translation> <translation id="3503995387997205657">ನಿಮ್ಮ ಹಿಂದಿನ ಆ್ಯಪ್ಗಳನ್ನು ನೀವು ಮರುಸ್ಥಾಪಿಸಬಹುದು</translation> <translation id="3505100368357440862">ಶಾಪಿಂಗ್ ಸಲಹೆಗಳು</translation> @@ -7179,6 +7180,7 @@ <translation id="6551508934388063976">ಕಮಾಂಡ್ ಲಭ್ಯವಿಲ್ಲ. ಹೊಸ ವಿಂಡೋ ತೆರೆಯಲು control-N ಒತ್ತಿರಿ.</translation> <translation id="6551606359270386381">ಎಲಿಪ್ಸ್ ಟೂಲ್</translation> <translation id="6551612971599078809">ಸೈಟ್, USB ಅನ್ನು ಬಳಸುತ್ತಿದೆ</translation> +<translation id="6551620030439692385">ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ. ಸಮಯವಲಯವನ್ನು ಪ್ರಸ್ತುತ <ph name="TIMEZONE" /> ಗೆ ಸೆಟ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು ಹಸ್ತಚಾಲಿತವಾಗಿ ಮಾತ್ರ ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದಾಗಿದೆ.</translation> <translation id="6551739526055143276">Family Link ಮೂಲಕ ನಿರ್ವಹಿಸಿರುವುದು</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> ಬಳಕೆದಾರರು</translation> <translation id="6555432686520421228">ಎಲ್ಲಾ ಬಳಕೆದಾರರ ಖಾತೆಗಳನ್ನು ತೆಗೆದುಹಾಕಿ ಹಾಗೂ ನಿಮ್ಮ <ph name="IDS_SHORT_PRODUCT_NAME" /> ಸಾಧನವನ್ನು ಹೊಸ ರೀತಿಯಲ್ಲಿ ಮರುಹೊಂದಿಸಿ.</translation> @@ -7249,6 +7251,7 @@ <translation id="6608773371844092260">ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆಟ್ ಮಾಡಲು, ಈ <ph name="DEVICE_TYPE" /> ರ ಬಲಭಾಗದಲ್ಲಿರುವ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ನಿಮ್ಮ ಮಗು ಸ್ಪರ್ಶಿಸುವಂತೆ ಮಾಡಿ. ನಿಮ್ಮ ಮಗುವಿನ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಡೇಟಾವನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಸಂಗ್ರಹಣೆ ಮಾಡಲಾಗಿದೆ ಮತ್ತು ಇದು ಎಂದೂ ಈ <ph name="DEVICE_TYPE" /> ನಿಂದ ಹೊರಗೆ ಹೋಗುವುದಿಲ್ಲ.</translation> <translation id="6609478180749378879">ನೀವು ಅಜ್ಞಾತ ಮೋಡ್ನಿಂದ ನಿರ್ಗಮಿಸಿದ ಬಳಿಕ, ಸೈನ್ ಇನ್ ಡೇಟಾವನ್ನು ಈ ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ. ನಂತರ ಮತ್ತೆ ನಿಮ್ಮ ಸಾಧನದ ಮೂಲಕ ಈ ವೆಬ್ಸೈಟ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ.</translation> <translation id="6610002944194042868">ಅನುವಾದ ಆಯ್ಕೆಗಳು</translation> +<translation id="6610064275805055636">ಪ್ರತ್ಯೇಕಗೊಳಿಸಲಾದ ವೆಬ್ ಆ್ಯಪ್ಗಳನ್ನು ನಿರ್ವಹಿಸಿ</translation> <translation id="6611972847767394631">ನಿಮ್ಮ ಟ್ಯಾಬ್ಗಳನ್ನು ಇಲ್ಲಿ ಕಂಡುಕೊಳ್ಳಿ</translation> <translation id="661266467055912436">ನಿಮಗಾಗಿ ಹಾಗೂ ವೆಬ್ನಲ್ಲಿರುವ ಎಲ್ಲರಿಗಾಗಿ ಸುರಕ್ಷತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ.</translation> <translation id="6613267708691765962">ಮಾಲ್ವೇರ್ಗಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ...</translation> @@ -8613,6 +8616,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />", "<ph name="SCANNER_NAME" />" ನಿಂದ ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಬಯಸುತ್ತದೆ.</translation> <translation id="7672504401554182757"><ph name="APP_NAME" /> ಆ್ಯಪ್ಗಾಗಿ ಯಾವ ಸಾಧನವು ಪಾಸ್ಕೀ ಅನ್ನು ಹೊಂದಿದೆ ಎಂಬುದನ್ನು ಆರಿಸಿ</translation> <translation id="7672520070349703697"><ph name="PAGE_TITLE" /> ನಲ್ಲಿ <ph name="HUNG_IFRAME_URL" /></translation> +<translation id="7672726198839739113">ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ. ವೇಳಾಪಟ್ಟಿಯನ್ನು ಪ್ರಸ್ತುತ <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> ಗೆ ಸೆಟ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು ಹಸ್ತಚಾಲಿತವಾಗಿ ಮಾತ್ರ ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದಾಗಿದೆ.</translation> <translation id="7673313156293624327">ChromeOS ಶಿಲ್ (ಕನೆಕ್ಷನ್ ಮ್ಯಾನೇಜರ್) ಲಾಗ್ಗಳು</translation> <translation id="7674416868315480713">Linux ನಲ್ಲಿ ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗುತ್ತಿರುವ ಎಲ್ಲಾ ಪೋರ್ಟ್ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> ಆ್ಯಪ್ಗಳು</translation> @@ -9542,6 +9546,7 @@ <translation id="8376384591331888629">ಈ ಸೈಟ್ನಲ್ಲಿನ ಥರ್ಡ್ ಪಾರ್ಟಿ ಕುಕೀಗಳನ್ನು ಒಳಗೊಂಡಿದೆ</translation> <translation id="8376451933628734023">ಈ ವೆಬ್ ಆ್ಯಪ್, ಇದು ವಿಭಿನ್ನ ಆ್ಯಪ್ ಆಗಿದೆಯೇ ಎಂದು ನೀವು ಯೋಚನೆ ಮಾಡುವಂತೆ ಮಾಡಿದರೆ, ನಿಮ್ಮನ್ನು ಮೋಸಗೊಳಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದರೆ, ಅದನ್ನು ಅನ್ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> ಅನ್ನು ಪುನಃ ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ...</translation> +<translation id="8376610503048439696">ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಎಕ್ಸ್ಟೆನ್ಶನ್ಗಳು ಈಗಲೂ ಈ ಸೈಟ್ ಅನ್ನು ಓದಬಹುದು ಮತ್ತು ಬದಲಾಯಿಸಬಹುದು</translation> <translation id="8376752431516546391">Google Search ಪಾರ್ಶ್ವ ಫಲಕ</translation> <translation id="8377625247046155446">ಈ ಪಾಸ್ಕೀಯನ್ನು ಈ ಸಾಧನದಲ್ಲಿ ಮಾತ್ರ ಉಳಿಸಲಾಗುತ್ತದೆ. ನೀವು ಎಲ್ಲಾ ಅಜ್ಞಾತ ವಿಂಡೋಗಳನ್ನು ಮುಚ್ಚಿದ ನಂತರ ಅದು ಈ ಸಾಧನದಲ್ಲಿ ಉಳಿಯುತ್ತದೆ.</translation> <translation id="8378714024927312812">ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗಿದೆ</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb index 3def259..fcb5f08 100644 --- a/chrome/app/resources/generated_resources_ko.xtb +++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -3310,6 +3310,7 @@ <translation id="3497560059572256875">기념일 로고 공유</translation> <translation id="3497915391670770295">내 기기로 보내기(&D)</translation> <translation id="3500417806337761827">공유를 마운트하는 중에 오류가 발생했습니다. 너무 많은 SMB 공유가 이미 마운트되었습니다.</translation> +<translation id="3500764001796099683">분리형 웹 앱 사용 설정</translation> <translation id="350397915809787283">계정이 없는 경우 첫 번째 옵션을 선택하여 계정을 만드세요.</translation> <translation id="3503995387997205657">이전 앱을 복원할 수 있습니다.</translation> <translation id="3505100368357440862">쇼핑 추천</translation> @@ -7184,6 +7185,7 @@ <translation id="6551508934388063976">명령어가 없습니다. 컨트롤 키와 N을 눌러 새 창을 여세요.</translation> <translation id="6551606359270386381">말줄임표 도구</translation> <translation id="6551612971599078809">사이트에서 USB를 사용하고 있습니다.</translation> +<translation id="6551620030439692385">차단되어 있습니다. 현재 시간대가 <ph name="TIMEZONE" />(으)로 설정되어 있으며, 수동으로만 업데이트할 수 있습니다.</translation> <translation id="6551739526055143276">Family Link로 관리됨</translation> <translation id="655384502888039633">사용자 <ph name="USER_COUNT" />명</translation> <translation id="6555432686520421228">모든 사용자 계정을 삭제하고 사용 중인 <ph name="IDS_SHORT_PRODUCT_NAME" /> 기기를 재설정하여 새것처럼 만듭니다.</translation> @@ -7252,6 +7254,7 @@ <translation id="6608773371844092260">지문을 설정하려면 자녀가 <ph name="DEVICE_TYPE" /> 오른쪽에 있는 지문 센서를 터치하게 하세요. 자녀의 지문 데이터는 안전하게 저장되며 절대 <ph name="DEVICE_TYPE" /> 외부로 유출되지 않습니다.</translation> <translation id="6609478180749378879">시크릿 모드를 종료한 후 로그인 데이터가 기기에 저장됩니다. 나중에 다시 기기에서 이 웹사이트에 로그인할 수 있습니다.</translation> <translation id="6610002944194042868">번역 옵션</translation> +<translation id="6610064275805055636">분리형 웹 앱 관리</translation> <translation id="6611972847767394631">여기에서 탭 찾아보기</translation> <translation id="661266467055912436">모든 웹 사용자를 위해 보안을 향상합니다.</translation> <translation id="6613267708691765962">멀웨어 검사 중...</translation> @@ -8615,6 +8618,7 @@ <translation id="7671472752213333268">'<ph name="EXTENSION_NAME" />'에서 '<ph name="SCANNER_NAME" />'부터 스캔하려고 합니다</translation> <translation id="7672504401554182757"><ph name="APP_NAME" />의 패스키가 있는 기기를 선택하세요.</translation> <translation id="7672520070349703697"><ph name="PAGE_TITLE" />에 포함된 <ph name="HUNG_IFRAME_URL" /></translation> +<translation id="7672726198839739113">차단되어 있습니다. 현재 일정이 <ph name="SUNRISE_TIME" />~<ph name="SUNSET_TIME" />로 설정되어 있으며, 수동으로만 업데이트할 수 있습니다.</translation> <translation id="7673313156293624327">ChromeOS Shill(연결 관리자) 로그</translation> <translation id="7674416868315480713">Linux에서 전달되는 모든 포트 비활성화</translation> <translation id="7674537509496907005">앱 <ph name="APP_COUNT" />개</translation> @@ -9549,6 +9553,7 @@ <translation id="8376384591331888629">이 사이트의 서드 파티 쿠키 포함</translation> <translation id="8376451933628734023">웹 앱이 다른 앱인 것처럼 사용자를 속이려 한다면 앱을 제거하시기 바랍니다.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> 도메인 새로고침 중...</translation> +<translation id="8376610503048439696">관리자가 설치한 확장 프로그램에서 계속 이 사이트를 읽고 변경할 수 있습니다.</translation> <translation id="8376752431516546391">Google 검색 측면 패널</translation> <translation id="8377625247046155446">이 패스키는 이 기기에만 저장되며 시크릿 창을 모두 닫은 후에도 이 기기에 남아 있습니다.</translation> <translation id="8378714024927312812">조직에서 관리</translation>
diff --git a/chrome/app/resources/generated_resources_ky.xtb b/chrome/app/resources/generated_resources_ky.xtb index 997fa5dd..40773d0 100644 --- a/chrome/app/resources/generated_resources_ky.xtb +++ b/chrome/app/resources/generated_resources_ky.xtb
@@ -1017,7 +1017,7 @@ <translation id="1757301747492736405">Чыгарып салуу күтүлүүдө</translation> <translation id="175772926354468439">Теманы иштетүү</translation> <translation id="1757786065507923842">Ата-эненин уруксат сурамы ишке ашкан жок.</translation> -<translation id="17584710573359123">Chrome Интернет дүкөнүндө көрүү</translation> +<translation id="17584710573359123">Chrome Web Store'до көрүү</translation> <translation id="1761402971842586829"><ph name="BUTTON_NAME" /> <ph name="REMAPPING_OPTION" /> болуп дайындалды.</translation> <translation id="1761845175367251960"><ph name="NAME" /> аккаунту</translation> <translation id="176272781006230109">Соода кылуу сунуштары</translation> @@ -1229,7 +1229,7 @@ <translation id="1904603806662441960">Chrome'до сайтка берилген камера уруксаттарын тескөө</translation> <translation id="1905375423839394163">Chromebook түзмөгүнүн аталышы</translation> <translation id="1906181697255754968">Сайттар адатта ишиңизди автоматтык түрдө сактоо сыяктуу функциялар үчүн түзмөгүңүздөгү файлдарды жана папкаларды колдонот</translation> -<translation id="1906488504371069394">Дагы башка кеңейтүүлөрдү жана темаларды <ph name="BEGIN_LINK" />Chrome Интернет дүкөнүнөн<ph name="END_LINK" /> табасыз</translation> +<translation id="1906488504371069394">Дагы башка кеңейтүүлөрдү жана темаларды <ph name="BEGIN_LINK" />Chrome Web Store'дон<ph name="END_LINK" /> табасыз</translation> <translation id="1907044622262489040">Айтып териңиз. Search + D баскычтарын басып, сүйлөп баштаңыз.</translation> <translation id="1907659324308286326">Ойдогудай иштеши үчүн Thunderbolt же USB4 аксессуарларына эстутумду колдонууга уруксат берүү керек.</translation> <translation id="1908591798274282246">Жабылган топту кайра ачуу</translation> @@ -2267,7 +2267,7 @@ <translation id="2673873887296220733">1 файлды ачуу үчүн ал <ph name="CLOUD_PROVIDER" /> кызматына көчүрүлсүнбү?</translation> <translation id="267442004702508783">жаңылоо</translation> <translation id="2674764818721168631">Өчүк</translation> -<translation id="2676084251379299915">Бул кеңейтүү Chrome Интернет дүкөнүндө мындан ары жеткиликсиз болгондуктан, Enterprise саясаты тарабынан өчүрүлдү.</translation> +<translation id="2676084251379299915">Бул кеңейтүү Chrome Web Store'до мындан ары жеткиликсиз болгондуктан, Enterprise саясаты тарабынан өчүрүлдү.</translation> <translation id="2678063897982469759">Кайра иштетүү</translation> <translation id="2678100101831051676">Тышкы экранга чыгарылбай жатат.</translation> <translation id="268053382412112343">Та&ржымал</translation> @@ -5818,7 +5818,7 @@ <translation id="5470735824776589490">Түзмөктү "жууп салып" баштапкы абалга келтирээрден мурун, аны өчүрүп күйгүзүү керек. <ph name="LINK_BEGIN" />Кеңири маалымат<ph name="LINK_END" /></translation> <translation id="5471768120198416576">Салам! Мен сизге текстти окуп беремин.</translation> <translation id="5472627187093107397">Бул сайттагы сырсөздөрдү сактоо</translation> -<translation id="5473062644742711742">Chrome Интернет дүкөнүндө көбүрөөк атайын мүмкүнчүлүктөр куралдарын таап алыңыз</translation> +<translation id="5473062644742711742">Chrome Web Store'до көбүрөөк атайын мүмкүнчүлүктөр куралдарын таап алыңыз</translation> <translation id="5473075389972733037">IBM</translation> <translation id="5473099001878321374">Улантуу менен бул түзмөккө Google'дан, байланыш операторуңуздан жана түзмөгүңүздүн өндүрүүчүсүнөн жаңыртууларды жана колдонмолорду автоматтык түрдө жүктөп алып, орнотууга мүмкүнчүлүк береcиз (мобилдик Интернет аркылуу дагы). Бул колдонмолордун айрымдары колдонмо аркылуу сатып алууну сунушташы мүмкүн.</translation> <translation id="5473156705047072749">{NUM_CHARACTERS,plural, =1{PIN код кеминде бир символдон турушу керек}other{PIN код кеминде # символдон турушу керек}}</translation> @@ -6038,7 +6038,7 @@ <translation id="5636996382092289526"><ph name="NETWORK_ID" /> колдонуу үчүн адегенде <ph name="LINK_START" />тармактын кирүү бетине өтүңүз<ph name="LINK_END" />, ал бир нече секунддун ичинде автоматтык түрдө ачылат. Эгер ачылбаса, тармакты колдоно албайсыз.</translation> <translation id="5637476008227280525">Мобилдик Интернетти иштетүү</translation> <translation id="563821631542362636">Сайтка маалымат сактоого уруксат берүү</translation> -<translation id="5638309510554459422"><ph name="BEGIN_LINK" />Chrome Интернет дүкөнүнөн<ph name="END_LINK" /> кеңейтүүлөрдү жана темаларды таап алыңыз</translation> +<translation id="5638309510554459422"><ph name="BEGIN_LINK" />Chrome Web Store'дон<ph name="END_LINK" /> кеңейтүүлөрдү жана темаларды таап алыңыз</translation> <translation id="5639549361331209298">Бул баракты кайра жүктөп, көбүрөөк параметр көрүү үчүн коё бербей кармап туруңуз</translation> <translation id="5640133431808313291">Коопсуздук ачкычтарын башкаруу</translation> <translation id="5640159004008030285">Бул сырсөз ушул түзмөктө гана сакталат. Аны башка түзмөктөрдө колдонуу үчүн <ph name="BEGIN_LINK" />Google аккаунтуңузда сактаңыз<ph name="END_LINK" />.</translation> @@ -7088,7 +7088,7 @@ <translation id="6476482583633999078">Кептин ылдамдыгы</translation> <translation id="6477822444490674459">Жумуш профилиндеги телефондордо билдирмелер шайкештирилбейт. <ph name="LINK_BEGIN" />Кеңири маалымат<ph name="LINK_END" /></translation> <translation id="6478248366783946499">Бул коркунучтуу файл сакталсынбы?</translation> -<translation id="6479881432656947268">Chrome Интернет дүкөнүнө баш багуу</translation> +<translation id="6479881432656947268">Chrome Web Store'го баш багуу</translation> <translation id="6480327114083866287"><ph name="MANAGER" /> башкарат</translation> <translation id="6481749622989211463">Жакын жердеги түзмөктөр менен файлдарды жана башка нерселерди бөлүшүңүз. <ph name="LINK_BEGIN" />Кеңири маалымат<ph name="LINK_END" /></translation> <translation id="6482559668224714696">Толук экран режиминдеги лупа</translation> @@ -8301,7 +8301,7 @@ <translation id="7434509671034404296">Иштеп чыгуучу</translation> <translation id="7434757724413878233">Чычканды ылдамдаткыч</translation> <translation id="7434969625063495310">Басып чыгаруу сервери кошулган жок. Сервердин конфигурациясын текшерип, кайталап көрүңүз.</translation> -<translation id="7436452443388501706">{NUM_EXTENSIONS,plural, =1{Chrome Интернет дүкөнүнөн өчүрүлгөн 1 кеңейтүүнү карап чыгыңыз}other{Chrome Интернет дүкөнүнөн өчүрүлгөн {NUM_EXTENSIONS} кеңейтүүнү карап чыгыңыз}}</translation> +<translation id="7436452443388501706">{NUM_EXTENSIONS,plural, =1{Chrome Web Store'дон өчүрүлгөн 1 кеңейтүүнү карап чыгыңыз}other{Chrome Web Store'дон өчүрүлгөн {NUM_EXTENSIONS} кеңейтүүнү карап чыгыңыз}}</translation> <translation id="7436921188514130341">Ка-ап! Аталышы өзгөртүлүп жатканда ката кетти.</translation> <translation id="7439519621174723623">Улантуу үчүн түзмөктүн аталышын кошуңуз</translation> <translation id="7441736532026945583">Топту өтмөктөр тактасынан алып салуу үчүн "Топту жашыруу" параметрин тандаңыз</translation> @@ -9975,7 +9975,7 @@ <translation id="8708000541097332489">Чыгууда тазалансын</translation> <translation id="870805141700401153">Microsoft Жеке кодунун колтамгасы</translation> <translation id="8708671767545720562">&Көбүрөөк маалымат</translation> -<translation id="8709368517685334931">Эски түстөрдү Chrome Интернет дүкөнүнөн табасыз</translation> +<translation id="8709368517685334931">Эски түстөрдү Chrome Web Store'дон табасыз</translation> <translation id="8710550057342691420">Окшош өтмөктөрдү иретке келтирүү</translation> <translation id="8711402221661888347">Туздалган бадыраң</translation> <translation id="8711538096655725662">Сиз баш баккан бардык сайттарда автоматтык түрдө иштейт</translation>
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb index 248fbd8..b1d045c 100644 --- a/chrome/app/resources/generated_resources_lo.xtb +++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -1730,6 +1730,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{ເປີດທັງໝົດໃນກຸ່ມແຖບ&ໃໝ່}=1{ເປີດໃນກຸ່ມແຖບ&ໃໝ່}other{ເປີດທັງໝົດ ({COUNT}) ໃນກຸ່ມແຖບ&ໃໝ່}}</translation> <translation id="2285942871162473373">ບໍ່ສາມາດຮັບຮູ້ລາຍນິ້ວມືຂອງທ່ານໄດ້. ລອງໃໝ່.</translation> <translation id="2287617382468007324">ກຳລັງພິມທີ່ຢູ່ IPP</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{ເພື່ອປົກປ້ອງຂໍ້ມູນຂອງທ່ານ, ລະບົບໄດ້ລຶບສິດການອະນຸຍາດອອກຈາກເວັບໄຊທີ່ທ່ານບໍ່ໄດ້ເຂົ້າເບິ່ງເມື່ອໄວໆນີ້ແລ້ວ}other{ເພື່ອປົກປ້ອງຂໍ້ມູນຂອງທ່ານ, ລະບົບໄດ້ລຶບສິດການອະນຸຍາດອອກຈາກເວັບໄຊທີ່ທ່ານບໍ່ໄດ້ເຂົ້າເບິ່ງເມື່ອໄວໆນີ້ແລ້ວ}}</translation> <translation id="2287944065963043964">ໜ້າຈໍການເຂົ້າສູ່ລະບົບ</translation> <translation id="2290615375132886363">ປຸ່ມນຳທາງໃນແທັບເລັດ</translation> <translation id="2291452790265535215">ລອງໃຊ້ແຜງຄວບຄຸມດ້ານຂ້າງສຳລັບບຸກມາກ, ເສັ້ນທາງການທ່ອງເວັບ ແລະ ອື່ນໆ</translation> @@ -4316,6 +4317,7 @@ <translation id="4275788652681621337">ປິດແຜງຄວບຄຸມດ້ານຂ້າງ</translation> <translation id="4275830172053184480">ເລີ່ມຕົ້ນອຸປະກອນຂອງທ່ານໃໝ່</translation> <translation id="4277434192562187284">ແຫຼ່ງທີ່ມາການຕັ້ງຄ່າ XML</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{ລຶບສິດການອະນຸຍາດອອກຈາກເວັບໄຊແລ້ວ 1 ລາຍການ}other{ລຶບສິດການອະນຸຍາດອອກຈາກເວັບໄຊແລ້ວ {NUM_SITES} ລາຍການ}}</translation> <translation id="4278390842282768270">ອະນຸຍາດແລ້ວ</translation> <translation id="4278498748067682896">ທ່ານຈະໃຊ້ອັບເກຣດຄີອອສ ແລະ ປ້າຍເຊິ່ງອະນຸຍາດໃຫ້ອຸປະກອນເອີ້ນໃຊ້ໃນໂໝດຄີອອສ ຫຼື ປ້າຍເທົ່ານັ້ນ. ຫາກທ່ານຢາກໃຫ້ຜູ້ໃຊ້ເຂົ້າສູ່ລະບົບຫາອຸປະກອນ, ກະລຸນາກັບຄືນໄປແລ້ວລົງທະບຽນໂດຍໃຊ້ Chrome Enterprise Upgrade.</translation> <translation id="4278779213160967034">ຂັ້ນຕອນນີ້ອາດໃຊ້ເວລາສອງສາມນາທີ. ກຳລັງດາວໂຫຼດໄຟລ໌.</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb index e800cafb..d1897c7d 100644 --- a/chrome/app/resources/generated_resources_lt.xtb +++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -3311,6 +3311,7 @@ <translation id="3497560059572256875">Bendrinti papuoštą logotipą</translation> <translation id="3497915391670770295">Siųsti į įrenginius</translation> <translation id="3500417806337761827">Montuojant bendrinimą įvyko klaida. Jau sumontuota per daug mažų ir vidutinių įmonių bendrinimų.</translation> +<translation id="3500764001796099683">Įgalinti izoliuotas žiniatinklio programas</translation> <translation id="350397915809787283">Jei neturite paskyros, pasirinkite pirmąją parinktį, kad ją sukurtumėte.</translation> <translation id="3503995387997205657">Galite atkurti ankstesnes programas</translation> <translation id="3505100368357440862">Apsipirkimo pasiūlymai</translation> @@ -7188,6 +7189,7 @@ <translation id="6551508934388063976">Komanda negalima. Paspauskite „Control“ – N, kad atidarytumėte naują langą.</translation> <translation id="6551606359270386381">Elipsės įrankis</translation> <translation id="6551612971599078809">Svetainėje naudojamas USB</translation> +<translation id="6551620030439692385">Užblokuota. Šiuo metu laiko juosta nustatyta į <ph name="TIMEZONE" /> ir ją galima atnaujinti tik neautomatiškai.</translation> <translation id="6551739526055143276">Tvarkoma naudojant „Family Link“</translation> <translation id="655384502888039633">Naudotojų: <ph name="USER_COUNT" /></translation> <translation id="6555432686520421228">Pašalinamos visos naudotojų paskyros ir „<ph name="IDS_SHORT_PRODUCT_NAME" />“ įrenginys nustatomas iš naujo, kad būtų kaip naujas.</translation> @@ -7262,6 +7264,7 @@ <translation id="6608773371844092260">Jei norite nustatyti piršto atspaudą, paprašykite, kad vaikas paliestų piršto atspaudo jutiklį dešinėje šio „<ph name="DEVICE_TYPE" />“ pusėje. Vaiko piršto atspaudo duomenys patikimai saugomi ir niekada nepatenka už „<ph name="DEVICE_TYPE" />“ ribų.</translation> <translation id="6609478180749378879">Prisijungimo duomenys bus saugomi šiame įrenginyje, kai išjungsite inkognito režimą. Vėl galėsite prisijungti prie šios svetainės naudodami savo įrenginį vėliau.</translation> <translation id="6610002944194042868">Vertimo parinktys</translation> +<translation id="6610064275805055636">Tvarkyti izoliuotas žiniatinklio programas</translation> <translation id="6611972847767394631">Čia rasite savo skirtukus</translation> <translation id="661266467055912436">Sustiprina jūsų ir visų žiniatinklio naudotojų saugą.</translation> <translation id="6613267708691765962">Nuskaitoma, ar nėra kenkėjiškų programų...</translation> @@ -8626,6 +8629,7 @@ <translation id="7671472752213333268">Plėtinys „<ph name="EXTENSION_NAME" />“ nori nuskaityti iš „<ph name="SCANNER_NAME" />“.</translation> <translation id="7672504401554182757">Pasirinkite, kuriame įrenginyje bus „passkey“, skirtas „<ph name="APP_NAME" />“</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, puslapyje „<ph name="PAGE_TITLE" />“.</translation> +<translation id="7672726198839739113">Užblokuota. Šiuo metu tvarkaraštis nustatytas į <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" /> ir jį galima atnaujinti tik neautomatiškai.</translation> <translation id="7673313156293624327">„ChromeOS“ „Shill“ (ryšio valdytojo) žurnalai</translation> <translation id="7674416868315480713">Išaktyvinti visus sistemoje „Linux“ persiunčiamus prievadus</translation> <translation id="7674537509496907005">Programų: <ph name="APP_COUNT" /></translation> @@ -9559,6 +9563,7 @@ <translation id="8376384591331888629">Įskaitant trečiosios šalies slapukus jūsų svetainėje</translation> <translation id="8376451933628734023">Jei ši žiniatinklio programa bando apsimesti kita programa, ją pašalinkite.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> įkeliama iš naujo...</translation> +<translation id="8376610503048439696">Administratoriaus įdiegti plėtiniai vis tiek galės skaityti ir keisti šią svetainę</translation> <translation id="8376752431516546391">„Google“ paieškos šoninis skydelis</translation> <translation id="8377625247046155446">Šis „passkey“ bus išsaugotas tik šiame įrenginyje. Jis liks šiame įrenginyje, kai uždarysite visus inkognito langus.</translation> <translation id="8378714024927312812">Tvarko jūsų organizacija</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb index 06dad9f..0cff7f5f 100644 --- a/chrome/app/resources/generated_resources_lv.xtb +++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -3295,6 +3295,7 @@ <translation id="3497560059572256875">Kopīgot svētku logotipu</translation> <translation id="3497915391670770295">Sūtīt uz manām &ierīcēm</translation> <translation id="3500417806337761827">Iekļaujot kopīgošanu, radās kļūda. Iekļauti pārāk daudzi SMB faili.</translation> +<translation id="3500764001796099683">Iespējot izolētas tīmekļa lietotnes</translation> <translation id="350397915809787283">Ja jums nav konta, atlasiet pirmo opciju, lai izveidotu kontu.</translation> <translation id="3503995387997205657">Varat atjaunot iepriekšējās lietotnes</translation> <translation id="3505100368357440862">Pirkumu ieteikumi</translation> @@ -7167,6 +7168,7 @@ <translation id="6551508934388063976">Komanda nav pieejama. Nospiediet taustiņu kombināciju Control-N, lai atvērtu jaunu logu.</translation> <translation id="6551606359270386381">Elipses rīks</translation> <translation id="6551612971599078809">Vietnē tiek izmantota USB ierīce</translation> +<translation id="6551620030439692385">Bloķēta. Pašlaik ir iestatīta šāda laika josla: <ph name="TIMEZONE" />. To var atjaunināt tikai manuāli.</translation> <translation id="6551739526055143276">Pārvaldīti lietotnē Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> lietotāji</translation> <translation id="6555432686520421228">Noņemiet visus lietotāju kontus un atiestatiet savu <ph name="IDS_SHORT_PRODUCT_NAME" /> ierīci, lai izmantotu sākotnējos rūpnīcas iestatījumus.</translation> @@ -7239,6 +7241,7 @@ <translation id="6608773371844092260">Lai iestatītu pirksta nospiedumu, bērnam ir jāpieskaras pirksta nospieduma sensoram ierīces <ph name="DEVICE_TYPE" /> labajā pusē. Bērna pirksta nospieduma dati tiek glabāti drošībā un vienmēr atrodas tikai šajā ierīcē (<ph name="DEVICE_TYPE" />).</translation> <translation id="6609478180749378879">Pēc tam, kad iziesiet no inkognito režīma, pierakstīšanās dati tiks glabāti šajā ierīcē. Ierīcē varēsiet vēlāk atkal pierakstīties šajā tīmekļa vietnē.</translation> <translation id="6610002944194042868">Tulkošanas opcijas</translation> +<translation id="6610064275805055636">Pārvaldīt izolētas tīmekļa lietotnes</translation> <translation id="6611972847767394631">Jūsu cilnes ir pieejamas šeit</translation> <translation id="661266467055912436">Šis režīms efektīvāk aizsargā gan jūs, gan visus citus tīmekļa lietotājus.</translation> <translation id="6613267708691765962">Notiek ļaunprātīgas programmatūras meklēšana…</translation> @@ -8603,6 +8606,7 @@ <translation id="7671472752213333268">Paplašinājums “<ph name="EXTENSION_NAME" />” vēlas veikt meklēšanu no “<ph name="SCANNER_NAME" />”.</translation> <translation id="7672504401554182757">Izvēlieties, kurā ierīcē ir vietnes <ph name="APP_NAME" /> piekļuves atslēga.</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, lapā <ph name="PAGE_TITLE" /></translation> +<translation id="7672726198839739113">Bloķēta. Pašlaik ir iestatīts šāds grafiks: <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" />. To var atjaunināt tikai manuāli.</translation> <translation id="7673313156293624327">ChromeOS Shill (savienojumu pārvaldnieka) žurnāli</translation> <translation id="7674416868315480713">Deaktivizēt visus portus, kas tiek pārsūtīti sistēmā Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> lietotnes</translation> @@ -9535,6 +9539,7 @@ <translation id="8376384591331888629">Arī šajā vietnē esošos trešo pušu sīkfailus</translation> <translation id="8376451933628734023">Ja šī tīmekļa lietotne ir maldinošs citas lietotnes atdarinājums, atinstalējiet to.</translation> <translation id="8376532149031784008">Notiek domēna <ph name="DOMAIN" /> ielāde…</translation> +<translation id="8376610503048439696">Jūsu administratora instalētie paplašinājumi joprojām var lasīt un mainīt šo vietni.</translation> <translation id="8376752431516546391">Google meklēšanas sānu panelis</translation> <translation id="8377625247046155446">Šī piekļuves atslēga tiks saglabāta tikai šajā ierīcē. Tā paliks šajā ierīcē pēc visu inkognito režīma logu aizvēršanas.</translation> <translation id="8378714024927312812">Pārvalda jūsu organizācija</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb index b13e3ae5..b9fd186 100644 --- a/chrome/app/resources/generated_resources_mn.xtb +++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -3304,6 +3304,7 @@ <translation id="3497560059572256875">Doodle-г хуваалцах</translation> <translation id="3497915391670770295">&Төхөөрөмжүүд рүүгээ илгээх</translation> <translation id="3500417806337761827">Хуваалцахыг залгаж чадсангүй. Хэт олон SMB хуваалцлыг хэдийн залгасан байна.</translation> +<translation id="3500764001796099683">Тусгаарласан веб аппуудыг идэвхжүүлэх</translation> <translation id="350397915809787283">Хэрэв танд бүртгэл байхгүй бол нэгийг үүсгэхийн тулд эхний сонголтыг сонгоно уу.</translation> <translation id="3503995387997205657">Та өмнөх аппуудаа сэргээх боломжтой</translation> <translation id="3505100368357440862">Дэлгүүр хэсэх зөвлөмж</translation> @@ -7179,6 +7180,7 @@ <translation id="6551508934388063976">Комманд боломжгүй байна. Шинэ цонх нээхийн тулд control-N-ийг дар</translation> <translation id="6551606359270386381">Зууван дүрсний хэрэгсэл</translation> <translation id="6551612971599078809">Сайт USB ашиглаж байна</translation> +<translation id="6551620030439692385">Блоклосон. Цагийн бүсийг одоогоор <ph name="TIMEZONE" /> болгож тохируулсан бөгөөд зөвхөн гар аргаар шинэчлэх боломжтой.</translation> <translation id="6551739526055143276">Family Link-р удирддаг</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> хэрэглэгчид</translation> <translation id="6555432686520421228">Бүх хэрэглэгчийн бүртгэлүүдийг устгаад <ph name="IDS_SHORT_PRODUCT_NAME" /> төхөөрөмжийнхөө тохиргоог дахин хийж шинэ юм шиг болгоорой.</translation> @@ -7247,6 +7249,7 @@ <translation id="6608773371844092260">Хурууны хээ тохируулахын тулд хүүхдээрээ энэ <ph name="DEVICE_TYPE" />-н баруун гар талд байх хурууны хээ мэдрэгчид хурууг нь хүргүүлнэ үү. Таны хүүхдийн хурууны хээний өгөгдлийг аюулгүй хадгалдаг бөгөөд энэ өгөгдөл энэ <ph name="DEVICE_TYPE" />-с гадагш хэзээ ч гарахгүй.</translation> <translation id="6609478180749378879">Таныг Нууцлалын горимоос гарсны дараа нэвтрэх өгөгдлийг энэ төхөөрөмж дээр хадгална. Та энэ вебсайтад дараа нь төхөөрөмжөөрөө нэвтрэх боломжтой болно.</translation> <translation id="6610002944194042868">Орчуулах сонголт</translation> +<translation id="6610064275805055636">Тусгаарласан веб аппуудыг удирдах</translation> <translation id="6611972847767394631">Эндээс табуудаа олоорой</translation> <translation id="661266467055912436">Таны болон веб дэх хүн бүрийн аюулгүй байдлыг нэмэгдүүлдэг.</translation> <translation id="6613267708691765962">Хортой программыг скан хийж байна...</translation> @@ -8610,6 +8613,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" "<ph name="SCANNER_NAME" />"-с скан хийх хүсэлтэй байна.</translation> <translation id="7672504401554182757"><ph name="APP_NAME" />-н passkey аль төхөөрөмжид байгааг сонгоно уу</translation> <translation id="7672520070349703697"><ph name="PAGE_TITLE" />-н <ph name="HUNG_IFRAME_URL" />.</translation> +<translation id="7672726198839739113">Блоклосон. Хуваарийг одоогоор <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> болгож тохируулсан бөгөөд зөвхөн гар аргаар шинэчлэх боломжтой.</translation> <translation id="7673313156293624327">ChromeOS Shill-н (Холболтын менежер) логууд</translation> <translation id="7674416868315480713">Linux-д шилжүүлж буй бүх портыг идэвхгүй болгох</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> апп</translation> @@ -9540,6 +9544,7 @@ <translation id="8376384591331888629">Энэ сайт дээрх гуравдагч талын күүкитэй цуг</translation> <translation id="8376451933628734023">Хэрэв энэ веб апп өөрийгөө өөр апп гэж танд итгүүлж, хуурахаар оролдож байвал үүнийг устгана уу.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" />-г дахин ачаалж байна...</translation> +<translation id="8376610503048439696">Танай администраторын суулгасан өргөтгөлүүд энэ сайтыг унших болон өөрчлөх боломжтой хэвээр байна</translation> <translation id="8376752431516546391">Google Хайлтын хажуугийн самбар</translation> <translation id="8377625247046155446">Энэ passkey-г зөвхөн уг төхөөрөмж дээр хадгална. Энэ нь таныг нууцлалтай бүх цонхыг хаасны дараа уг төхөөрөмж дээр үлдэнэ.</translation> <translation id="8378714024927312812">Танай байгууллагаас удирддаг</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb index 42b40ed..115f817b 100644 --- a/chrome/app/resources/generated_resources_mr.xtb +++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -475,7 +475,7 @@ <translation id="1361655923249334273">न वापरलेले</translation> <translation id="1362829980946830670">तुमचे वर्तमान सेशन अॅक्टिव्ह असताना तुम्ही तुमचे मागील सेशन पुन्हा सुरू करू शकता.</translation> <translation id="1362865166188278099">यांत्रिकी समस्या. प्रिंटर तपासा</translation> -<translation id="1363585519747660921">USB प्रिंटर कॉंफिगर करणे आवश्यक आहे</translation> +<translation id="1363585519747660921">USB प्रिंटर कॉन्फिगर करणे आवश्यक आहे</translation> <translation id="136378536198524553">एनर्जी सेव्हर सुरू आहे</translation> <translation id="136522805455656552">तुमचे डिव्हाइस सुरक्षित ठेवण्यासाठी, तुम्ही फक्त विश्वासार्ह स्रोत आणि डेव्हलपर यांच्याकडील सॉफ्टवेअर रन व इंस्टॉल केले पाहिजे. <ph name="LEARN_MORE" /></translation> <translation id="1367817137674340530">जनरेट केलेल्या <ph name="COUNT" /> इमेज</translation> @@ -1278,7 +1278,7 @@ <translation id="1940546824932169984">कनेक्ट केलेली डिव्हाइस</translation> <translation id="1941410638996203291">सुरू होण्याची वेळ <ph name="TIME" /></translation> <translation id="1941553344801134989">आवृत्ती: <ph name="APP_VERSION" /></translation> -<translation id="1941685451584875710">तुमच्या अॅडमिनिस्ट्रेटरने तुमचे खाते Microsoft OneDrive शी आपोआप कनेक्ट होण्यासाठी कॉंफिगर केले, पण काहीतरी चुकले.</translation> +<translation id="1941685451584875710">तुमच्या अॅडमिनिस्ट्रेटरने तुमचे खाते Microsoft OneDrive शी आपोआप कनेक्ट होण्यासाठी कॉन्फिगर केले, पण काहीतरी चुकले.</translation> <translation id="194174710521904357">तुम्ही या साइटला तृतीय पक्ष कुकी वापरण्याची तात्पुरती अनुमती दिली आहे, याचा अर्थ असा आहे, की ब्राउझ करताना कमी संरक्षण पण साइटची वैशिष्ट्ये अपेक्षेनुसार काम करण्याची अधिक शक्यता आहे.</translation> <translation id="1941995177877935582">की मॅपिंग दाखवा</translation> <translation id="1942128823046546853">सर्व वेबसाइटवरील तुमचा सर्व डेटा वाचू आणि बदलू शकते</translation> @@ -1324,7 +1324,7 @@ <translation id="1977965994116744507">तुमचे <ph name="DEVICE_TYPE" /> अनलॉक करण्यासाठी तुमचा फोन जवळ आणा.</translation> <translation id="1978249384651349182"><ph name="BEGIN_DESCRIPTION" />तुमच्या संस्थेमध्ये तुमच्या डिव्हाइसची नोंदणी केल्याने ती केंद्रित डिव्हाइस व्यवस्थापनासाठी सेट केली जातात. तुमच्या संस्थेला एकाहून अधिक कारणांसाठी नोंदणी आवश्यक असू शकते:<ph name="END_DESCRIPTION" /> <ph name="BEGIN_SUBTITLE1" /><ph name="BEGIN_BOLD" />सुरक्षा वाढवणे<ph name="END_BOLD" /><ph name="END_SUBTITLE1" /> - <ph name="BEGIN_DESCRIPTION1" />अतिरिक्त सुरक्षा सेटिंग्ज कॉंफिगर करून, संस्था ही वापरकर्ता आणि डिव्हाइस डेटा सुरक्षित ठेवू शकते. हे रिमोट रीसेट किंवा हरवलेले डिव्हाइस बंद करणे यांसारख्या कृतीदेखील करू शकते.<ph name="END_DESCRIPTION1" /> + <ph name="BEGIN_DESCRIPTION1" />अतिरिक्त सुरक्षा सेटिंग्ज कॉन्फिगर करून, संस्था ही वापरकर्ता आणि डिव्हाइस डेटा सुरक्षित ठेवू शकते. हे रिमोट रीसेट किंवा हरवलेले डिव्हाइस बंद करणे यांसारख्या कृतीदेखील करू शकते.<ph name="END_DESCRIPTION1" /> <ph name="BEGIN_SUBTITLE2" /><ph name="BEGIN_BOLD" />अनुभव कस्टमाइझ करणे<ph name="END_BOLD" /><ph name="END_SUBTITLE2" /> <ph name="BEGIN_DESCRIPTION2" />बूटअप झाल्यावर, लॉगिन स्क्रीनवर आणि लॉगिन केल्यानंतर डिव्हाइसचे वर्तन संस्थेच्या आवश्यकतेनुसार कस्टमाइझ केले जाऊ शकते.<ph name="END_DESCRIPTION2" /> <ph name="BEGIN_SUBTITLE3" /><ph name="BEGIN_BOLD" />सपोर्ट पुरवणे<ph name="END_BOLD" /><ph name="END_SUBTITLE3" /> @@ -1393,7 +1393,7 @@ <translation id="202500043506723828">EID</translation> <translation id="2025632980034333559"><ph name="APP_NAME" /> क्रॅश झाला. एक्स्टेंशन रीलोड करण्यासाठी या फुग्यावर क्लिक करा.</translation> <translation id="2028449514182362831">मोशन सेन्सरची आवश्यकता असलेली वैशिष्ट्ये काम करणार नाहीत</translation> -<translation id="202918510990975568">सुरक्षितता कॉंफिगर करण्यासाठी आणि साइन इन करण्यासाठी तुमचा पासवर्ड एंटर करा</translation> +<translation id="202918510990975568">सुरक्षितता कॉन्फिगर करण्यासाठी आणि साइन इन करण्यासाठी तुमचा पासवर्ड एंटर करा</translation> <translation id="2030455719695904263">ट्रॅकपॅड</translation> <translation id="2030803782168502207">डिव्हाइसवरून सदस्यत्व काढून टाका</translation> <translation id="2031914984822377766"><ph name="LINK_BEGIN" />वेबसाइटवर तुमच्या प्राधान्य असलेल्या भाषा निवडा<ph name="LINK_END" />. सूचीमधील टॉप भाषा भाषांतर करण्यासाठी वापरली जाईल.</translation> @@ -1773,7 +1773,7 @@ <ph name="BEGIN_BOLD" />टीप:<ph name="END_BOLD" /> प्रक्रियेदरम्यान सिस्टीम रीबूट होईल.</translation> <translation id="23030561267973084">"<ph name="EXTENSION_NAME" />" नी अतिरिक्त परवानग्यांची विनंती केली आहे.</translation> <translation id="2306794767168143227">या डिव्हाइसवर <ph name="BRAND" /> मध्ये सेव्ह करा</translation> -<translation id="2307462900900812319">नेटवर्क कॉंफिगर करा</translation> +<translation id="2307462900900812319">नेटवर्क कॉन्फिगर करा</translation> <translation id="2307553512430195144">तुम्ही सहमती दर्शवल्यास, Google Assistant हे “Ok Google” डिटेक्ट करण्यासाठी स्टँडबाय मोडमध्ये प्रतीक्षा करेल आणि <ph name="SUPERVISED_USER_NAME" /> बोलत असल्याचे Voice Match वापरून ओळखू शकेल. <ph name="BR" /> Voice Match हे Google Assistant ला तुमच्या <ph name="DEVICE_TYPE" /> वर <ph name="SUPERVISED_USER_NAME" /> चा आवाज ओळखण्यात आणि त्यांच्यात व इतरांमध्ये फरक ओळखण्यात मदत करते. @@ -2645,7 +2645,7 @@ <translation id="2959127025785722291">काहीतरी चूक झाली. स्कॅनिंग पूर्ण करता आले नाही. कृपया पुन्हा प्रयत्न करा.</translation> <translation id="2959474507964749987">या एन्क्रिप्ट केलेल्या फाइलमध्ये व्हायरस किंवा मालवेअर असू शकते.<ph name="LINE_BREAK" />ती असुरक्षित आहे की नाही हे तपासण्यासाठी, तुम्ही Google सुरक्षित ब्राउझिंग ला फाइल आणि पासवर्ड पाठवू शकता. स्कॅनला काही सेकंद लागू शकतात.<ph name="LINE_BREAK" /> स्कॅन करण्यासाठी, फाइलचा पासवर्ड जोडा.</translation> <translation id="2959842337402130152">स्टोरेज जागा कमी असल्यामुळे रिस्टोअर करू शकत नाही. डिव्हाइसमधील <ph name="SPACE_REQUIRED" /> जागा मोकळी करा आणि पुन्हा प्रयत्न करा.</translation> -<translation id="2960208947600937804">Linux कॉंफिगर करताना एरर आली. तुमच्या अॅडमिनिस्ट्रेटरशी संपर्क साधा.</translation> +<translation id="2960208947600937804">Linux कॉन्फिगर करताना एरर आली. तुमच्या अॅडमिनिस्ट्रेटरशी संपर्क साधा.</translation> <translation id="2960942820860729477">रिफ्रेश रेट</translation> <translation id="2961090598421146107"><ph name="CERTIFICATE_NAME" /> (एक्स्टेंशन प्रदान केले)</translation> <translation id="2961695502793809356">पुढे जाण्यासाठी क्लिक करा, इतिहास पहाण्यासाठी होल्ड करा</translation> @@ -3075,7 +3075,7 @@ <translation id="3308852433423051161">Google Assistant लोड करत आहे...</translation> <translation id="3309330461362844500">सर्टिफिकेट प्रोफाइल आयडी</translation> <translation id="3311445899360743395">या अॅपशी संबंधित डेटा डिव्हाइसवरून काढला जाऊ शकतो.</translation> -<translation id="3312470654018965389">Linux कंटेनर कॉंफिगर करत आहे</translation> +<translation id="3312470654018965389">Linux कंटेनर कॉन्फिगर करत आहे</translation> <translation id="3312883087018430408">विशिष्ट साइट किंवा Chrome चा भाग शोधण्यासाठी, त्याचा शॉर्टकट आणि त्यानंतर तुमचा प्राधान्य दिलेला कीबोर्ड शॉर्टकट अॅड्रेस बारमध्ये टाइप करा. उदाहरणार्थ, फक्त Bookmarks शोधण्यासाठी, "@bookmarks" टाइप करा आणि त्यानंतर टॅब किंवा स्पेस प्रेस करा.</translation> <translation id="3313622045786997898">सर्टिफिकेट स्वाक्षरी मूल्य</translation> <translation id="3313950410573257029">कनेक्शन तपासा</translation> @@ -3307,6 +3307,7 @@ <translation id="3497560059572256875">डूडल शेअर करा</translation> <translation id="3497915391670770295">तुमच्या डिव्हाइसवर पाठवा</translation> <translation id="3500417806337761827">शेअर माउंट करताना एरर आली. खूप जास्त SMB शेअर आधीच माउंट केले गेले आहेत.</translation> +<translation id="3500764001796099683">आयसोलेटेड वेब ॲप्स सुरू करा</translation> <translation id="350397915809787283">तुमच्याकडे खाते नसल्यास, ते तयार करण्यासाठी पहिला पर्याय निवडा.</translation> <translation id="3503995387997205657">तुम्ही तुमची आधीची अॅप्स रिस्टोअर करू शकता</translation> <translation id="3505100368357440862">खरेदीशी संबंधित शिफारशी</translation> @@ -3381,7 +3382,7 @@ <translation id="3562655211539199254">तुमच्या फोनमधील अलीकडील Chrome टॅब पहा</translation> <translation id="3563392617245068355">मूड</translation> <translation id="3563432852173030730">कियोस्क ॲप्लिकेशन डाउनलोड केले जाऊ शकले नाही.</translation> -<translation id="3563558822383875692">DLC कॉंफिगर करत आहे.</translation> +<translation id="3563558822383875692">DLC कॉन्फिगर करत आहे.</translation> <translation id="3564334271939054422">तुम्ही वापरत असलेल्या (<ph name="NETWORK_ID" />) वाय-फाय नेटवर्कला तुम्ही त्याच्या लॉग इन पेजला भेट देणे आवश्यक असू शकते.</translation> <translation id="3564848315152754834">USB सिक्युरिटी की</translation> <translation id="3566325075220776093">या डिव्हाइसवरून</translation> @@ -3397,7 +3398,7 @@ <translation id="3577473026931028326">काहीतरी चूक झाली. पुन्हा प्रयत्न करा.</translation> <translation id="3577487026101678864">फाइल सिंक सुरू आहे</translation> <translation id="3577745545227000795"><ph name="DEVICE_OS" /> हार्डवेअर डेटा संग्रह</translation> -<translation id="3581605050355435601">आयपी अॅड्रेस ऑटो कॉंफिगर करा</translation> +<translation id="3581605050355435601">आयपी अॅड्रेस ऑटो कॉन्फिगर करा</translation> <translation id="3582057310199111521">फसव्या साइटवर एंटर केला आणि डेटा भंग करत असल्याचे आढळले</translation> <translation id="3582299299336701326">फिकट रंगाच्या स्क्रीन गडद आणि गडद रंगाच्या स्क्रीन फिकट करा. कलर इन्व्हर्जन सुरू आणि बंद करण्यासाठी Search + Ctrl + H प्रेस करा.</translation> <translation id="3584169441612580296">तुमच्या कॉंप्युटरवरील फोटो, संगीत आणि अन्य मीडिया वाचा आणि बदला</translation> @@ -3555,7 +3556,7 @@ <translation id="3700888195348409686">सादर करत आहे (<ph name="PAGE_ORIGIN" />)</translation> <translation id="3700993174159313525">साइटना तुमच्या कॅमेराच्या स्थानाचा माग ठेवण्याची अनुमती देऊ नका</translation> <translation id="3701515417135397388">डेटा भंगामध्ये पासवर्ड धोक्यात आला असल्यास, तुम्हाला चेतावणी दिली जावी</translation> -<translation id="3702797829026927713"><ph name="BEGIN_PARAGRAPH1" />ज्या रिटेल विक्रेत्यासाठी हे डेमो डिव्हाइस कॉंफिगर केले जात आहे त्याचे नाव आणि स्टोअर नंबर एंटर करा*. <ph name="END_PARAGRAPH1" /> +<translation id="3702797829026927713"><ph name="BEGIN_PARAGRAPH1" />ज्या रिटेल विक्रेत्यासाठी हे डेमो डिव्हाइस कॉन्फिगर केले जात आहे त्याचे नाव आणि स्टोअर नंबर एंटर करा*. <ph name="END_PARAGRAPH1" /> <ph name="BEGIN_PARAGRAPH2" />तुम्हाला स्टोअर नंबर माहित नसल्यास, डेमो मोड इंस्टॉलेशन सुरू ठेवण्यासाठी तुम्ही "००००" एंटर करू शकता. <ph name="END_PARAGRAPH2" /> <ph name="BEGIN_PARAGRAPH3" />*टीप: डिव्हाइसला डेमो मोड ची कोणती आवृत्ती मिळावी हे ओळखण्यासाठी आणि डेमो मोड च्या वापराचे मापन करण्यासाठी Google ही माहिती वापरते.<ph name="END_PARAGRAPH3" /></translation> <translation id="3703166520839776970">ही समस्या येत राहिल्यास, <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> कडून अधिक माहिती मिळवण्यासाठी खाली "आणखी तपशील" निवडा.</translation> @@ -3600,7 +3601,7 @@ <translation id="3727473233247516571">बॅक/फॉरवर्ड कॅशे केलेली सबफ्रेम: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation> <translation id="3727850735097852673">macOS Keychain सह Google Password Manager वापरण्यासाठी, Chrome पुन्हा लाँच करा आणि Keychain च्या अॅक्सेसची अनुमती द्या. पुन्हा लाँच केल्यानंतर तुमचे टॅब पुन्हा उघडतील.</translation> <translation id="3728188878314831180">तुमच्या फोनवरून सूचना मिरर करू शकते</translation> -<translation id="3728681439294129328">नेटवर्क अॅड्रेस कॉंफिगर करा</translation> +<translation id="3728681439294129328">नेटवर्क अॅड्रेस कॉन्फिगर करा</translation> <translation id="3729506734996624908">अनुमती असलेल्या साइट</translation> <translation id="3729957991398443677">तुमचा पासवर्ड पाहण्यासाठी किंवा त्याविषयी टीप जोडण्यासाठी, शोध आणि अॅड्रेस बारमध्ये तुमचे पासवर्ड व्यवस्थापित करा निवडा</translation> <translation id="3730076362938942381">स्टायलस लेखन अॅप</translation> @@ -4253,7 +4254,7 @@ <translation id="4231095370974836764">Google Play वरून तुमच्या <ph name="DEVICE_TYPE" /> वर ॲप्स आणि गेम इंस्टॉल करा. <ph name="LINK_BEGIN" />अधिक जाणून घ्या<ph name="LINK_END" /></translation> <translation id="4231141543165771749">गेम नियंत्रणे बंद करा</translation> <translation id="4231231258999726714">Chromebook साठी Steam सेट करत आहेत</translation> -<translation id="4232375817808480934">Kerberos कॉंफिगर करा</translation> +<translation id="4232375817808480934">Kerberos कॉन्फिगर करा</translation> <translation id="4233739489690259993">तुमच्या Chromebook ला आता सुरक्षा आणि सॉफ्टवेअर अपडेट मिळत नाहीत. नवीनतम सुरक्षेसाठी आणि नवीन वैशिष्ट्यांसाठी तुमचे डिव्हाइस अपग्रेड करा. ऑफर अटी लागू.</translation> <translation id="4235965441080806197">साइन इन रद्द करा</translation> <translation id="4235976607074422892">स्क्रोलिंगचा वेग</translation> @@ -4395,7 +4396,7 @@ <translation id="4342417854108207000">तुमच्या डिव्हाइसवरील फाइल किंवा फोल्डर संपादित करण्याची अनुमती आहे</translation> <translation id="4343250402091037179">विशिष्ट साइट किंवा Chrome चा भाग शोधण्यासाठी, त्याचा शॉर्टकट आणि त्यानंतर तुमचा प्राधान्य दिलेला कीबोर्ड शॉर्टकट अॅड्रेस बारमध्ये टाइप करा.</translation> <translation id="4345457680916430965"><ph name="APP" /> मध्ये उघडा</translation> -<translation id="4345587454538109430">कॉंफिगर करा...</translation> +<translation id="4345587454538109430">कॉन्फिगर करा...</translation> <translation id="4345732373643853732">सर्व्हरला वापर कर्ता नाव माहीत नाही</translation> <translation id="4346159263667201092">पर्यायी तपशील जोडा</translation> <translation id="4348426576195894795">हे खाते हटवल्यामुळे, या खात्यासह साइन इन केलेली कोणतीही Chrome प्रोफाइलदेखील हटवली जातील</translation> @@ -4574,7 +4575,7 @@ <translation id="4478664379124702289">या फॉरमॅटमध्ये लिंक सेव्ह करा...</translation> <translation id="4479424953165245642">कियोस्क ॲप्लिकेशन व्यवस्थापित करा</translation> <translation id="4479639480957787382">इथरनेट</translation> -<translation id="4479877282574735775">व्हर्च्युअल मशीन कॉंफिगर करत आहे. यासाठी काही मिनिटे लागू शकतात.</translation> +<translation id="4479877282574735775">व्हर्च्युअल मशीन कॉन्फिगर करत आहे. यासाठी काही मिनिटे लागू शकतात.</translation> <translation id="4481448477173043917">तुमचे <ph name="DEVICE_TYPE" /> अनपेक्षितपणे रीस्टार्ट झाले</translation> <translation id="4481467543947557978">सेवा कर्मचारी</translation> <translation id="4482990632723642375">अलीकडे बंद केलेला टॅब</translation> @@ -4793,7 +4794,7 @@ <translation id="4651921906638302153">हे खाते वापरून साइन इन करू शकत नाही</translation> <translation id="4652935475563630866">कॅमेऱ्याच्या सेटिंगमधील बदलासाठी Parallels Desktop पुन्हा लाँच करणे आवश्यक आहे. Parallels Desktop वर पुढे सुरू ठेवण्यासाठी पुन्हा लाँच करा.</translation> <translation id="4653116291358041820">लहान शॅडो</translation> -<translation id="4653405415038586100">Linux कॉंफिगर करताना एरर आली</translation> +<translation id="4653405415038586100">Linux कॉन्फिगर करताना एरर आली</translation> <translation id="465406513924180949">तुम्हाला संपूर्ण वेबवर शॉपिंग कार्टमध्ये साठवलेल्या आयटमवर सहजपणे परत जाण्यासाठी मदत करणारी कार्ट दिसत आहेत. <ph name="BREAK" /> <ph name="BREAK" /> @@ -4940,7 +4941,7 @@ <translation id="4777458362738635055">या डिव्हाइसचे इतर वापरकर्ते हे नेटवर्क वापरू शकतात</translation> <translation id="4777813841994368231">सुरू केले • हे एक्स्टेंशन त्याच्या डेव्हलपरने अप्रकाशित केले होते</translation> <translation id="4777825441726637019">Play स्टोअर</translation> -<translation id="4777943778632837590">नेटवर्क नाव सर्व्हर कॉंफिगर करा</translation> +<translation id="4777943778632837590">नेटवर्क नाव सर्व्हर कॉन्फिगर करा</translation> <translation id="4778653490315793244">अद्याप दाखवण्यासाठी काहीही नाही</translation> <translation id="4779083564647765204">झूम</translation> <translation id="4779136857077979611">ओनिगिरी</translation> @@ -5820,7 +5821,7 @@ <translation id="5473099001878321374">पुढे सुरू ठेवून, तुम्ही सहमती दर्शवता, की हे डिव्हाइस कदाचित मोबाइल डेटा वापरून Google, तुमच्या लहान मुलाचा वाहक आणि या डिव्हाइसचा उत्पादक यांच्याकडून अपडेट व अॅप्स आपोआप डाउनलोड आणि इंस्टॉलदेखील करू शकेल. यांपैकी काही अॅप्स अॅपमधील खरेदी करण्याचा पर्याय देऊ शकतात.</translation> <translation id="5473156705047072749">{NUM_CHARACTERS,plural, =1{पिन हा किमान एका वर्णाचा असणे आवश्यक आहे}other{पिन हा किमान # वर्णांचा असणे आवश्यक आहे}}</translation> <translation id="5474859849784484111"><ph name="MANAGER" /> नुसार तुम्ही आता वाय-फायशी कनेक्ट करून अपडेट डाउनलोड करणे आवश्यक आहे. किंवा मर्यादित कनेक्शनमधून डाउनलोड करा (शुल्क लागू शकते).</translation> -<translation id="5477089831058413614"><ph name="DEVICE_TYPE" /> हॉटस्पॉट कॉंफिगर करा</translation> +<translation id="5477089831058413614"><ph name="DEVICE_TYPE" /> हॉटस्पॉट कॉन्फिगर करा</translation> <translation id="5481273127572794904">एकाहून अधिक फाइल आपोआप डाउनलोड करण्याची अनुमती नाही</translation> <translation id="5481941284378890518">जवळपासचे प्रिंटर जोडा</translation> <translation id="5482417738572414119">Chrome ला टॅब गट सुचवू देण्यासाठी आणि तुमचे टॅब संगतवार ठेवू देण्यासाठी साइन इन करा</translation> @@ -6276,7 +6277,7 @@ <translation id="5836999627049108525">ज्यामधून भाषांतर करायचे आहे ती भाषा</translation> <translation id="583756221537636748">केस</translation> <translation id="5840680448799937675">फाइल नेहमी ऑफलाइन शेअर केल्या जातील</translation> -<translation id="5841270259333717135">इथरनेट कॉंफिगर करा</translation> +<translation id="5841270259333717135">इथरनेट कॉन्फिगर करा</translation> <translation id="5842497610951477805">ब्लूटूथ सक्षम आहे</translation> <translation id="5844284118433003733">तुम्ही साइन इन केले असते, तेव्हा संपूर्ण Google सेवांवर तुमचे संरक्षण करण्यासाठी हा डेटा तुमच्या Google खाते शी लिंक केला जातो, उदाहरणार्थ सुरक्षेशी संबंधित घटनेनंतर Gmail मध्ये संरक्षण वाढवणे.</translation> <translation id="5844574845205796324">एक्सप्लोर करण्यासाठी नवीन आशय सुचवा</translation> @@ -6820,7 +6821,7 @@ <translation id="6254503684448816922">की तडजोड</translation> <translation id="6254892857036829079">उत्तम आहे</translation> <translation id="6257602895346497974">सिंक सुरू करा…</translation> -<translation id="625827534921607067">पूर्वी कनेक्ट केलेले किंवा कॉंफिगर केलेले एकापेक्षा जास्त नेटवर्क उपलब्ध असल्यास, या नेटवर्कला प्राधान्य दिले जाईल</translation> +<translation id="625827534921607067">पूर्वी कनेक्ट केलेले किंवा कॉन्फिगर केलेले एकापेक्षा जास्त नेटवर्क उपलब्ध असल्यास, या नेटवर्कला प्राधान्य दिले जाईल</translation> <translation id="62586649943626337">टॅब गटांसह तुमचे टॅब संगतवार लावा</translation> <translation id="6262371516389954471">तुमचे बॅकअप Google वर अपलोड केले जातात आणि तुमचा Google खाते पासवर्ड वापरून एंक्रिप्ट केले जातात.</translation> <translation id="6263082573641595914">Microsoft CA आवृत्ती</translation> @@ -6926,7 +6927,7 @@ <translation id="6344608411615208519">तुमचा <ph name="BEGIN_LINK" />ब्राउझर व्यवस्थापित केला जातो<ph name="END_LINK" /> तुमच्या पालकांद्वारे</translation> <translation id="6344622098450209924">ट्रॅकिंग संरक्षण</translation> <translation id="6345203628032613660"><ph name="VISUAL_SEARCH_PROVIDER" /> वापरून व्हिडिओ फ्रेम शोधा</translation> -<translation id="6345418402353744910">प्रॉक्सी <ph name="PROXY" /> साठी तुमचे वापरकर्ता नाव आणि पासवर्ड आवश्यक आहे जेणेकरून, ॲडमिन तुमचे नेटवर्क कॉंफिगर करू शकेल</translation> +<translation id="6345418402353744910">प्रॉक्सी <ph name="PROXY" /> साठी तुमचे वापरकर्ता नाव आणि पासवर्ड आवश्यक आहे जेणेकरून, ॲडमिन तुमचे नेटवर्क कॉन्फिगर करू शकेल</translation> <translation id="6345566021391290381"><ph name="WEBSITE_NAME" /> साठी तुमच्यासोबत पासवर्ड शेअर केले आहेत. तुम्ही ते साइन-इन फॉर्ममध्ये वापरू शकता.</translation> <translation id="6345878117466430440">वाचलेले अशी खूण करा</translation> <translation id="6346952829206698721">क्लिपबोर्डवरून पेस्ट करा</translation> @@ -7182,6 +7183,7 @@ <translation id="6551508934388063976">कमांड अनुपलब्ध. एक नवीन विंडो उघडण्यासाठी control-N प्रेस करा.</translation> <translation id="6551606359270386381">एलिप्स टूल</translation> <translation id="6551612971599078809">साइट USB वापरत आहे</translation> +<translation id="6551620030439692385">ब्लॉक केलेले. टाइम झोन सध्या <ph name="TIMEZONE" /> सेट केला आहे आणि फक्त मॅन्युअली अपडेट केला जाऊ शकतो.</translation> <translation id="6551739526055143276">Family Link द्वारे व्यवस्थापित</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> वापरकर्ते</translation> <translation id="6555432686520421228">सर्व वापरकर्ता खाती काढा आणि तुमचा <ph name="IDS_SHORT_PRODUCT_NAME" /> डिव्हाइस अगदी नव्यासारखे सेट करा.</translation> @@ -7250,6 +7252,7 @@ <translation id="6608773371844092260">फिंगरप्रिंट सेट करण्यासाठी, तुमच्या लहान मुलाला या <ph name="DEVICE_TYPE" /> च्या उजव्या बाजूला असलेल्या फिंगरप्रिंट सेन्सरला स्पर्श करण्यास सांगा. तुमच्या लहान मुलाचा फिंगरप्रिंट डेटा सुरक्षितपणे स्टोअर केला जातो आणि तो या <ph name="DEVICE_TYPE" /> मध्येच राहतो.</translation> <translation id="6609478180749378879">तुम्ही गुप्त मोड यामधून बाहेर पडल्यानंतर साइन इन डेटा या डिव्हाइसवर सेव्ह केला जाईल. तुम्हाला नंतर पुन्हा तुमचे डिव्हाइस वापरून या वेबसाइटवर साइन करता येईल.</translation> <translation id="6610002944194042868">भाषांतराचे पर्याय</translation> +<translation id="6610064275805055636">आयसोलेटेड वेब ॲप्स व्यवस्थापित करा</translation> <translation id="6611972847767394631">येथे तुमचे टॅब शोधा</translation> <translation id="661266467055912436">तुमच्यासाठी आणि वेबवरील प्रत्येकजणासाठी सुरक्षिततेत सुधारणा करते.</translation> <translation id="6613267708691765962">मालवेअरसाठी स्कॅन करत आहे…</translation> @@ -7713,7 +7716,7 @@ <translation id="6966370001499648704">तुम्ही कोणते फोन सिक्युरिटी की म्हणून वापरता ते नियंत्रित करा</translation> <translation id="6967112302799758487">Chromebook (बीटा) साठी Steam वापरून इंस्टॉल केलेली कोणतीही अॅप्स आणि गेम या डिव्हाइसवरून काढून टाकले जातील. या अॅप्स आणि गेमशी संबंधित डेटादेखील काढून टाकला जाईल. अनइंस्टॉल करण्यापूर्वी सेव्ह केलेल्या अॅप्स आणि गेमचा बॅकअप घेतल्याची खात्री करा.</translation> <translation id="6967430741871315905">या डिव्हाइसला अनुमती आहे की नाही हे तपासता आले नाही</translation> -<translation id="6968288415730398122">स्क्रीन लॉक कॉंफिगर करण्यासाठी तुमचा पासवर्ड एंटर करा</translation> +<translation id="6968288415730398122">स्क्रीन लॉक कॉन्फिगर करण्यासाठी तुमचा पासवर्ड एंटर करा</translation> <translation id="6969047215179982698">Nearby सह शेअरिंग बंद करा</translation> <translation id="6969216690072714773">या डिव्हाइसशी संलग्न करण्यासाठी नवीन माहिती एंटर करा किंवा सद्य माहिती अपडेट करा.</translation> <translation id="696942486482903620">तुम्ही तुमच्या Google खाते मध्ये पासवर्ड सेव्ह करता, तेव्हा तुम्ही ते या डिव्हाइसवर आणि तुम्ही साइन इन केलेल्या इतर कोणत्याही ठिकाणी वापरू शकता</translation> @@ -7759,7 +7762,7 @@ <translation id="6997707937646349884">तुमच्या डिव्हाइसवर:</translation> <translation id="6998793565256476099">डीव्हाइसची व्हिडिओ काँफरंससाठी नोंदणी करा</translation> <translation id="6999956497249459195">नवीन गट</translation> -<translation id="7000206553895739324"><ph name="PRINTER_NAME" /> कनेक्ट केलेला आहे पण कॉंफिगर करणे आवश्यक आहे</translation> +<translation id="7000206553895739324"><ph name="PRINTER_NAME" /> कनेक्ट केलेला आहे पण कॉन्फिगर करणे आवश्यक आहे</translation> <translation id="7000347579424117903">Ctrl, Alt किंवा शोधचा समावेश करा</translation> <translation id="7001036685275644873">Linux अॅप्स आणि फायलींचा बॅकअप घेत आहे</translation> <translation id="7001066449188684145"><ph name="PRINTER_NAME" /> वर प्रिंट करण्यासाठी ओळखीची पडताळणी करणे आवश्यक आहे. कृपया तुमच्या अॅडमिनिस्ट्रेटरशी संपर्क साधा.</translation> @@ -7841,7 +7844,7 @@ <translation id="7063311912041006059">क्वेरीच्या जागेवर <ph name="SPECIAL_SYMBOL" /> सह URL</translation> <translation id="706342288220489463">मदत करण्यासाठी, Assistant ला तुमच्या स्क्रीनवरील माहिती वापरण्याची अनुमती द्या</translation> <translation id="70641621694466590">पासवर्ड पेजवर जा</translation> -<translation id="7064734931812204395">Linux कंटेनर कॉंफिगर करत आहे. याला सुमारे ३० मिनिटे लागू शकतात.</translation> +<translation id="7064734931812204395">Linux कंटेनर कॉन्फिगर करत आहे. याला सुमारे ३० मिनिटे लागू शकतात.</translation> <translation id="7065223852455347715">हे डिव्हाइस संस्था नोंदणीस प्रतिबंध करणार्या मोडमध्ये लॉक केले आहे. तुम्ही हिव्हाइसची नोंदणी करू इच्छित असल्यास आपल्याला प्रथम डिव्हाइस पुनर्संचयामधून जाणे आवश्यक आहे.</translation> <translation id="7065343991414968778">{NUM_PASSWORDS,plural, =1{एक पासवर्ड <ph name="USER_EMAIL" /> साठी <ph name="BRAND" /> वर इंपोर्ट केला आहे}other{{NUM_PASSWORDS} पासवर्ड <ph name="USER_EMAIL" /> साठी <ph name="BRAND" /> वर इंपोर्ट केले आहेत}}</translation> <translation id="7065534935986314333">सिस्टम बद्दल</translation> @@ -7862,7 +7865,7 @@ <translation id="708060913198414444">ऑडिओ पत्ता कॉपी करा</translation> <translation id="7082568314107259011"><ph name="NETWORK_NAME" /> हे तुमच्या अॅडमिनिस्ट्रेटरद्वारे व्यवस्थापित केले जाते</translation> <translation id="7083774521940805477">तुमच्या Chromebook वर Chromebook (बीटा) साठी Steam उपलब्ध नाही.</translation> -<translation id="708550780726587276">(कॉंफिगर केलेले नाही)</translation> +<translation id="708550780726587276">(कॉन्फिगर केलेले नाही)</translation> <translation id="7086672505018440886">संग्रहणामध्ये Chrome लॉग फाइलचा समावेश करा.</translation> <translation id="7088434364990739311">अपडेट तपासणी सुरू होण्यात अयशस्वी (एरर कोड <ph name="ERROR" />).</translation> <translation id="7088674813905715446">हे डिव्हाइस ॲडमिनिस्ट्रेटरद्वारे तरतूद नसलेल्या स्थितीमध्ये ठेवले गेले आहे. ते नोंदणीकरिता सक्षम करण्यासाठी, कृपया तुमच्या ॲडमिनिस्ट्रेटरने डिव्हाइस एका प्रलंबित स्थितीमध्ये ठेवावे.</translation> @@ -7960,7 +7963,7 @@ <translation id="7172470549472604877">{NUM_TABS,plural, =1{नवीन गटामध्ये टॅब जोडा}other{नवीन गटामध्ये टॅब जोडा}}</translation> <translation id="7173114856073700355">सेटिंग्ज उघडा</translation> <translation id="7174199383876220879">नवीन! तुमचे संगीत, व्हिडिओ आणि आणखी बरेच काही नियंत्रित करा.</translation> -<translation id="7175037578838465313"><ph name="NAME" /> कॉंफिगर करा</translation> +<translation id="7175037578838465313"><ph name="NAME" /> कॉन्फिगर करा</translation> <translation id="7175353351958621980">येथून लोड केले:</translation> <translation id="7177079607604198383">मर्यादित दृश्य आणि संपादनाशी संबंधित पर्याय वापरण्यासाठी, तुमचे इंटरनेट कनेक्शन तपासा आणि "पुन्हा प्रयत्न करा" किंवा "ऑफलाइन संपादकामध्ये उघडा" निवडा.</translation> <translation id="7180611975245234373">रिफ्रेश करा</translation> @@ -8590,7 +8593,7 @@ <translation id="7661259717474717992">कुकी डेटा सेव्ह करण्यास आणि वाचण्यास साइटना अनुमती द्या</translation> <translation id="7661451191293163002">नोंदणी सर्टिफिकेट प्राप्त करणे शक्य झाले नाही.</translation> <translation id="7662164944369232556">मजकूर फाइल डाउनलोड करता आल्या नाहीत. नंतर पुन्हा प्रयत्न करा.</translation> -<translation id="7662283695561029522">कॉंफिगर करण्यासाठी टॅप करा</translation> +<translation id="7662283695561029522">कॉन्फिगर करण्यासाठी टॅप करा</translation> <translation id="7663719505383602579">प्राप्तकर्ता: <ph name="ARC_PROCESS_NAME" /></translation> <translation id="7663774460282684730">कीबोर्ड शॉर्टकट उपलब्ध आहे</translation> <translation id="7663859337051362114">eSIM प्रोफाइल जोडा</translation> @@ -8614,6 +8617,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" ला "<ph name="SCANNER_NAME" />" मधून स्कॅन करायचे आहे.</translation> <translation id="7672504401554182757"><ph name="APP_NAME" /> साठी कोणत्या डिव्हाइसकडे पासकी असावी ते निवडा</translation> <translation id="7672520070349703697"><ph name="PAGE_TITLE" /> मध्ये <ph name="HUNG_IFRAME_URL" />.</translation> +<translation id="7672726198839739113">ब्लॉक केलेले. शेड्यूल सध्या <ph name="SUNRISE_TIME" /> <ph name="SUNSET_TIME" /> - वर सेट केले आहे आणि फक्त मॅन्युअली अपडेट केले जाऊ शकते.</translation> <translation id="7673313156293624327">ChromeOS शिल (कनेक्शन व्यवस्थापक) लॉग</translation> <translation id="7674416868315480713">Linux मध्ये पाठवले जाणारे सर्व पोर्ट बंद करा</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> अॅप्स</translation> @@ -9169,7 +9173,7 @@ <translation id="8084429490152575036">मोबाइल APN सेटिंग्ज</translation> <translation id="8084510406207562688">सर्व टॅब रिस्टोअर करा</translation> <translation id="8084628902026812045">ही साइट सुरक्षित कनेक्शन वापरत नाही आणि फाइलमध्ये छेडछाड केली गेली असू शकते</translation> -<translation id="8086015605808120405"><ph name="PRINTER_NAME" /> कॉंफिगर करत आहे...</translation> +<translation id="8086015605808120405"><ph name="PRINTER_NAME" /> कॉन्फिगर करत आहे...</translation> <translation id="8086121155774250556">हा टॅब तुमची स्क्रीन शेअर करत आहे</translation> <translation id="8086610718778464681">Linux अॅप्स आणि फाइलचा बॅकअप घेऊ शकत नाही</translation> <translation id="80866457114322936">{NUM_FILES,plural, =1{ही फाइल एंक्रिप्ट केलेली आहे. तिच्या मालकाला ती डिक्रिप्ट करण्यास सांगा.}other{यांपैकी काही फाइल एंक्रिप्ट केलेल्या आहेत. त्यांच्या मालकाला त्या डिक्रिप्ट करण्यास सांगा.}}</translation> @@ -9257,7 +9261,7 @@ <translation id="8149870652370242480">तुमचे सेव्ह केलेले पासवर्ड तुमच्या फोनवर वापरण्यासाठी, iOS साठी Chrome डाउनलोड करा आणि तुमच्या Google खाते मध्ये साइन इन करा.</translation> <translation id="8151057139207656239">बिल्डचे तपशील कॉपी केले आहेत</translation> <translation id="815114315010033526">त्याऐवजी QR कोड वापरा</translation> -<translation id="8151638057146502721">कॉंफिगर करा</translation> +<translation id="8151638057146502721">कॉन्फिगर करा</translation> <translation id="8154790740888707867">फाईल नाही</translation> <translation id="815491593104042026">अरेरे! ऑथेंटिकेशन अ-सुरक्षित (<ph name="BLOCKED_URL" />) URL वापरण्यासाठी कॉंफिगर केल्यामुळे ते अयशस्वी झाले. कृपया तुमच्या ॲडमिनिस्ट्रेटरशी संपर्क साधा.</translation> <translation id="8155676038687609779">{COUNT,plural, =0{धोक्यात असलेले पासवर्ड सापडले नाहीत}=1{{COUNT} धोक्यात असलेला पासवर्ड}other{{COUNT} धोक्यात असलेले पासवर्ड}}</translation> @@ -9545,6 +9549,7 @@ <translation id="8376384591331888629">या साइटवरील तृतीय-पक्ष कुकीच्या समावेशासह</translation> <translation id="8376451933628734023">हे वेब ॲप तुम्हाला ते वेगळे ॲप असल्याचे भासवून फसवण्याचा प्रयत्न करत असल्यास, ते अनइंस्टॉल करा.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> रीलोड करत आहे...</translation> +<translation id="8376610503048439696">तुमच्या अॅडमिनिस्ट्रेटरने इंस्टॉल केलेली एक्स्टेंशन तरीही ही साइट रीड करू आणि बदलू शकतात</translation> <translation id="8376752431516546391">Google Search साइड पॅनल</translation> <translation id="8377625247046155446">ही पासकी फक्त या डिव्हाइसवर सेव्ह केली जाईल. तुम्ही सर्व गुप्त विंडो बंद केल्यानंतर, ती या डिव्हाइसवर राहील.</translation> <translation id="8378714024927312812">तुमच्या संस्थेकडून व्यवस्थापित केलेले</translation> @@ -10050,7 +10055,7 @@ <translation id="8756969031206844760">पासवर्ड अपडेट करायचा आहे का?</translation> <translation id="8757368836647541092"><ph name="USER_NAME_OR_EMAIL" /> ला काढून टाकले</translation> <translation id="8759753423332885148">अधिक जाणून घ्या.</translation> -<translation id="876161309768861172">तुम्हाला साइन इन केले जाऊ शकत नाही, कृपया पुन्हा प्रयत्न करा</translation> +<translation id="876161309768861172">तुम्हाला साइन इन करता आले नाही, कृपया पुन्हा प्रयत्न करा</translation> <translation id="8761945298804995673">हा वापरकर्ता आधीपासून अस्तित्वात आहे</translation> <translation id="8762886931014513155">तुमच्या <ph name="DEVICE_TYPE" /> ला अपडेट करण्याची आवश्यकता आहे</translation> <translation id="8763927697961133303">USB डिव्हाइस</translation> @@ -10489,7 +10494,7 @@ <translation id="9087183943157874068">तुम्ही तुमच्या टॅब गटासंबंधित सूचना कधीही तपासू शकता</translation> <translation id="9087949559523851360">प्रतिबंधित वापरकर्ता जोडा</translation> <translation id="9088234649737575428">संस्थेच्या धोरणाद्वारे <ph name="PLUGIN_NAME" /> ब्लॉक केले आहे</translation> -<translation id="9088446193279799727">Linux कॉंफिगर करता आले नाही. इंटरनेटशी कनेक्ट करा आणि पुन्हा प्रयत्न करा.</translation> +<translation id="9088446193279799727">Linux कॉन्फिगर करता आले नाही. इंटरनेटशी कनेक्ट करा आणि पुन्हा प्रयत्न करा.</translation> <translation id="90885733430013283">वायफाय SSID</translation> <translation id="9089416786594320554">इनपुट पद्धती</translation> <translation id="9089959054554410481">टचपॅड स्क्रोलिंगची दिशा बदला</translation> @@ -10563,7 +10568,7 @@ <translation id="9137157311132182254">प्राधान्य असलेले शोध इंजीन</translation> <translation id="9137916601698928395"><ph name="USER" /> म्हणून लिंक उघडा</translation> <translation id="9138978632494473300">खालील ठिकाणी शॉर्टकट जोडा:</translation> -<translation id="9139988741193276691">Linux कॉंफिगर करत आहे</translation> +<translation id="9139988741193276691">Linux कॉन्फिगर करत आहे</translation> <translation id="9140067245205650184">तुम्ही एक सपोर्ट नसलेला वैशिष्ट्य फ्लॅग वापरत आहात: <ph name="BAD_FLAG" />. स्थिरता आणि सुरक्षा प्रभावित होईल.</translation> <translation id="914031120300235526">प्रोफाइल अनलॉक करू शकत नाही</translation> <translation id="9142637293078737510">इमेजचे उपनाव</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb index 613455d..04ae19d3 100644 --- a/chrome/app/resources/generated_resources_ms.xtb +++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -1732,6 +1732,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Buka semua dalam kumpulan tab &baharu}=1{Buka dalam kumpulan tab &baharu}other{Buka semua ({COUNT}) dalam kumpulan tab &baharu}}</translation> <translation id="2285942871162473373">Cap jari anda tidak dapat dicam. Cuba lagi.</translation> <translation id="2287617382468007324">Mencetak Alamat IPP</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{Untuk melindungi data anda, kebenaran telah dialih keluar daripada laman yang tidak anda lawati baru-baru ini}other{Untuk melindungi data anda, kebenaran telah dialih keluar daripada laman yang tidak anda lawati baru-baru ini}}</translation> <translation id="2287944065963043964">Skrin log masuk</translation> <translation id="2290615375132886363">Butang navigasi tablet</translation> <translation id="2291452790265535215">Cuba gunakan panel sisi untuk penanda halaman, perjalanan dan pelbagai lagi</translation> @@ -4317,6 +4318,7 @@ <translation id="4275788652681621337">Tutup panel sisi</translation> <translation id="4275830172053184480">Mulakan semula peranti anda</translation> <translation id="4277434192562187284">Sumber konfigurasi XML</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{Kebenaran dialih keluar daripada 1 laman}other{Kebenaran dialih keluar daripada {NUM_SITES} laman}}</translation> <translation id="4278390842282768270">Dibenarkan</translation> <translation id="4278498748067682896">Anda akan menggunakan Peningkatan Kios & Papan Tanda yang hanya membenarkan peranti berjalan dalam mod kios atau papan tanda. Jika anda ingin pengguna log masuk ke peranti, sila kembali dan daftar menggunakan Peningkatan Chrome Enterprise.</translation> <translation id="4278779213160967034">Proses ini mungkin mengambil masa beberapa minit. Memuat turun fail.</translation>
diff --git a/chrome/app/resources/generated_resources_ne.xtb b/chrome/app/resources/generated_resources_ne.xtb index 4e4a2779..1d80ad6d 100644 --- a/chrome/app/resources/generated_resources_ne.xtb +++ b/chrome/app/resources/generated_resources_ne.xtb
@@ -3291,6 +3291,7 @@ <translation id="3497560059572256875">Doodle सेयर गर्नुहोस्</translation> <translation id="3497915391670770295">आफ्ना डिभाइसहरूमा पठाउनुहोस्</translation> <translation id="3500417806337761827">सेयर माउन्ट गर्ने क्रममा त्रुटि भयो। अहिले थुप्रै SMB सेयरहरू माउन्ट गरिएका छन्।</translation> +<translation id="3500764001796099683">आइसोलेटेड वेब एपहरू अन गर्नुहोस्</translation> <translation id="350397915809787283">तपाईंसँग खाता छैन भने एउटा खाता बनाउन पहिलो विकल्प रोज्नुहोस्।</translation> <translation id="3503995387997205657">तपाईं आफूले यसअघि चलाइरहेका एपहरू रिस्टोर गर्न सक्नुहुन्छ</translation> <translation id="3505100368357440862">किनमेलसम्बन्धी सुझावहरू</translation> @@ -7164,6 +7165,7 @@ <translation id="6551508934388063976">आदेश अनुपलब्ध छ। नया विन्डो खोल्नको लागि control-N थिच्नुहोस्।</translation> <translation id="6551606359270386381">दीर्घवृत्त बनाउने टुल</translation> <translation id="6551612971599078809">साइटले USB प्रयोग गर्दै छ</translation> +<translation id="6551620030439692385">ब्लक गरिएको छ। हाल सेट गरिएको प्रामाणिक समय <ph name="TIMEZONE" /> हो र यो म्यानुअल रूपमा मात्र परिवर्तन गर्न मिल्छ।</translation> <translation id="6551739526055143276">Family Link मार्फत व्यवस्थापन गरिएका</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> प्रयोगकर्ताहरू</translation> <translation id="6555432686520421228">तपाइँका सबै प्रयोगकर्ता खाताहरू हटाउनुहोस् र नयाँ जस्तै बनााउनको लागि तपाइँको <ph name="IDS_SHORT_PRODUCT_NAME" /> यन्त्र रिसेट गर्नुहोस्।</translation> @@ -7232,6 +7234,7 @@ <translation id="6608773371844092260">तपाईं आफ्ना बच्चाको फिंगरप्रिन्ट सेटअप गर्न चाहनुहुन्छ भने उनलाई यो <ph name="DEVICE_TYPE" /> को दायाँतिर रहेको फिंगरप्रिन्ट सेन्सरमा छुन लगाउनुहोस्। तपाईंका बच्चाको फिंगरप्रिन्ट डेटा सुरक्षित रूपमा भण्डारण गरिन्छ र यो डेटा कहिल्यै पनि यस <ph name="DEVICE_TYPE" /> बाट अन्यत्र पठाइँदैन।</translation> <translation id="6609478180749378879">तपाईं इन्कोग्निटो मोडबाट बाहिरिएपछि साइन इन गर्न चाहिने डेटा यो डिभाइसमा भण्डारण गरिने छ। तपाईं पछि आफ्नो यन्त्रमार्फत यो वेबसाइटमा फेरि साइन इन गर्न सक्नु हुने छ।</translation> <translation id="6610002944194042868">अनुवादसम्बन्धी विकल्पहरू</translation> +<translation id="6610064275805055636">आइसोलेटेड वेब एपहरू व्यवस्थापन गर्नुहोस्</translation> <translation id="6611972847767394631">आफ्ना ट्याबहरू यहाँ फेला पार्नुहोस्</translation> <translation id="661266467055912436">तपाईं र वेब प्रयोग गर्ने सम्पूर्ण प्रयोगकर्ताहरूलाई झन् सुरक्षित पार्छ।</translation> <translation id="6613267708691765962">मालवेयरका लागि स्क्यान गरिँदै छ...</translation> @@ -8595,6 +8598,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" "<ph name="SCANNER_NAME" />" मार्फत स्क्यान गर्न चाहन्छ।</translation> <translation id="7672504401554182757"><ph name="APP_NAME" /> को पासकी भएको डिभाइस छनौट गर्नुहोस्</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> मा।</translation> +<translation id="7672726198839739113">ब्लक गरिएको छ। हाल तोकिएको समयतालिका <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> हो र यो म्यानुअल रूपमा मात्र परिवर्तन गर्न मिल्छ।</translation> <translation id="7673313156293624327">ChromeOS Shill (कनेक्सन म्यानेजर) का लगहरू</translation> <translation id="7674416868315480713">Linux मा फरवार्ड भइराखेका सबै पोर्टहरू निष्क्रिय पार्नुहोस्</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> वटा एप</translation> @@ -9527,6 +9531,7 @@ <translation id="8376384591331888629">यस साइटका तेस्रो पक्षीय कुकीसमेत</translation> <translation id="8376451933628734023">यो वेब एपले अर्कै एप जस्तो बनेर तपाईंलाई झुक्याउन खोज्दै छ भने यसलाई अनइन्स्टल गरिहाल्नुहोस्।</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> रिलोड गरिँदै छ…</translation> +<translation id="8376610503048439696">तपाईंका एड्मिनले इन्स्टल गरेका एक्स्टेन्सनहरूले अझै पनि यो साइट रिड गर्न र बदल्न सक्छन्</translation> <translation id="8376752431516546391">Google Search को साइड प्यानल</translation> <translation id="8377625247046155446">यो पासकी यस डिभाइसमा मात्र सेभ गरिने छ। तपाईंले सबै इन्कोग्निटो विन्डो बन्द गरेपछि पनि यो पासकी यस डिभाइसमा रहने छ।</translation> <translation id="8378714024927312812">तपाईंको सङ्गठनले व्यवस्थापन गरेको</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb index b6107801..aae7dcf 100644 --- a/chrome/app/resources/generated_resources_nl.xtb +++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -323,7 +323,7 @@ <translation id="1236009322878349843">Telefoon bewerken</translation> <translation id="1239594683407221485">De content van het apparaat verkennen in de app Bestanden.</translation> <translation id="1239841552505950173">App starten</translation> -<translation id="1240903469550363138"><ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> deelt je naam, e-mailadres, adres en profielfoto met deze site om door te gaan. Bekijk het <ph name="BEGIN_LINK1" />privacybeleid<ph name="END_LINK1" /> en de <ph name="BEGIN_LINK2" />servicevoorwaarden<ph name="END_LINK2" /> van deze site.</translation> +<translation id="1240903469550363138"><ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> deelt je naam, e-mailadres en profielfoto met deze site om door te gaan. Bekijk het <ph name="BEGIN_LINK1" />privacybeleid<ph name="END_LINK1" /> en de <ph name="BEGIN_LINK2" />servicevoorwaarden<ph name="END_LINK2" /> van deze site.</translation> <translation id="1241066500170667906">Experimentstatus selecteren voor <ph name="EXPERIMENT_NAME" /></translation> <translation id="124116460088058876">Meer talen</translation> <translation id="1241381048229838873">Alle bookmarks tonen</translation> @@ -1717,6 +1717,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Alles openen in &nieuwe tabbladgroep}=1{Openen in &nieuwe tabbladgroep}other{Alles ({COUNT}) openen in &nieuwe tabbladgroep}}</translation> <translation id="2285942871162473373">Je vingerafdruk kan niet worden herkend. Probeer het opnieuw.</translation> <translation id="2287617382468007324">IPP-adres afdrukken</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{Ter bescherming van je gegevens zijn de rechten verwijderd voor een site die je niet recent hebt bezocht}other{Ter bescherming van je gegevens zijn de rechten verwijderd voor sites die je niet recent hebt bezocht}}</translation> <translation id="2287944065963043964">Inlogscherm</translation> <translation id="2290615375132886363">Navigatieknoppen tablet</translation> <translation id="2291452790265535215">Gebruik het zijvenster onder meer voor bookmarks en trajecten</translation> @@ -3293,6 +3294,7 @@ <translation id="3497560059572256875">Doodle delen</translation> <translation id="3497915391670770295">Versturen naar je &apparaten</translation> <translation id="3500417806337761827">Fout bij activeren van fileshare. Er zijn al te veel SMB-fileshares geactiveerd.</translation> +<translation id="3500764001796099683">Geïsoleerde web-apps aanzetten</translation> <translation id="350397915809787283">Als je geen account hebt, selecteer je de eerste optie om een account te maken.</translation> <translation id="3503995387997205657">Je kunt je vorige apps herstellen</translation> <translation id="3505100368357440862">Winkelsuggesties</translation> @@ -4300,6 +4302,7 @@ <translation id="4275788652681621337">Zijvenster sluiten</translation> <translation id="4275830172053184480">Je apparaat opnieuw opstarten</translation> <translation id="4277434192562187284">XML-configuratiebron</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{Rechten verwijderd voor 1 site}other{Rechten verwijderd voor {NUM_SITES} sites}}</translation> <translation id="4278390842282768270">Toegestaan</translation> <translation id="4278498748067682896">Je gebruikt een upgrade voor kiosken en digitale borden waardoor het apparaat alleen de kioskmodus of modus voor digitale borden kan gebruiken. Als je wilt dat gebruikers kunnen inloggen op het apparaat, ga je terug en schrijf je het in via Chrome Enterprise Upgrade.</translation> <translation id="4278779213160967034">Dit kan een paar minuten duren. Bestanden downloaden.</translation> @@ -7162,6 +7165,7 @@ <translation id="6551508934388063976">Opdracht niet beschikbaar. Druk op Ctrl-N om een nieuw venster te openen.</translation> <translation id="6551606359270386381">Tool Ovaal</translation> <translation id="6551612971599078809">De site gebruikt een USB-apparaat</translation> +<translation id="6551620030439692385">Geblokkeerd. De tijdzone is op dit moment ingesteld op <ph name="TIMEZONE" /> en kan alleen handmatig worden geüpdatet.</translation> <translation id="6551739526055143276">Beheerd door Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> gebruikers</translation> <translation id="6555432686520421228">Alle gebruikersaccounts verwijderen en je <ph name="IDS_SHORT_PRODUCT_NAME" />-apparaat opnieuw instellen.</translation> @@ -7230,6 +7234,7 @@ <translation id="6608773371844092260">Als je een vingerafdruk wilt instellen, laat je je kind de vingerafdruksensor aan de rechterkant van deze <ph name="DEVICE_TYPE" /> aanraken. De vingerafdrukgegevens van je kind worden beveiligd opgeslagen en blijven uitsluitend op deze <ph name="DEVICE_TYPE" /> staan.</translation> <translation id="6609478180749378879">Nadat je de incognitomodus hebt afgesloten, worden de inloggegevens opgeslagen op dit apparaat. Je kunt later weer inloggen bij deze website met je apparaat.</translation> <translation id="6610002944194042868">Opties voor vertalen</translation> +<translation id="6610064275805055636">Geïsoleerde web-apps beheren</translation> <translation id="6611972847767394631">Hier vind je je tabbladen</translation> <translation id="661266467055912436">Verbetert de beveiliging voor jou en alle andere internetgebruikers.</translation> <translation id="6613267708691765962">Scannen op malware...</translation> @@ -8592,6 +8597,7 @@ <translation id="7671472752213333268"><ph name="EXTENSION_NAME" /> wil scannen vanuit <ph name="SCANNER_NAME" /></translation> <translation id="7672504401554182757">Kies welk apparaat de toegangssleutel voor <ph name="APP_NAME" /> heeft</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, in <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Geblokkeerd. De planning is op dit moment ingesteld op <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> en kan alleen handmatig worden geüpdatet.</translation> <translation id="7673313156293624327">ChromeOS Shill-logboeken (verbindingsbeheer)</translation> <translation id="7674416868315480713">Alle doorgeschakelde poorten deactiveren in Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> apps</translation> @@ -9523,6 +9529,7 @@ <translation id="8376384591331888629">Inclusief cookies van derden op deze site</translation> <translation id="8376451933628734023">Als deze web-app zich voordoet als een andere app, verwijder je deze.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> opnieuw laden...</translation> +<translation id="8376610503048439696">Extensies die door je beheerder zijn geïnstalleerd, kunnen deze site nog steeds lezen en wijzigen</translation> <translation id="8376752431516546391">Zijvenster van Google Zoeken</translation> <translation id="8377625247046155446">Deze toegangssleutel wordt alleen opgeslagen op dit apparaat. De sleutel blijft op dit apparaat staan nadat je alle incognitovensters hebt gesloten.</translation> <translation id="8378714024927312812">Beheerd door je organisatie</translation> @@ -10442,7 +10449,7 @@ <translation id="9068598199622656904">Druk op 1 toets tegelijk voor sneltoetsen in plaats van dat je toetsen tegelijk ingedrukt moet houden.</translation> <translation id="9068878141610261315">Niet-ondersteund bestandstype</translation> <translation id="9069417381769492963">Er zijn geen bookmarks die overeenkomen met je zoekopdracht</translation> -<translation id="9069665781180028115">Geselecteerde items zijn beschikbaar op deze Chromebook. Als je nieuw bent bij Chromebook, synchroniseer je alle items zodat om een back-up van je voorkeuren te maken. Je kunt altijd wijzigingen aanbrengen via Instellingen > Accounts.</translation> +<translation id="9069665781180028115">Geselecteerde items zijn beschikbaar op deze Chromebook. Als je nieuw bent bij Chromebook, synchroniseer je alle items om een back-up van je voorkeuren te maken. Je kunt altijd wijzigingen aanbrengen via Instellingen > Accounts.</translation> <translation id="9070231741075992882">Rechten die je toestaat voor <ph name="APP_NAME" />, zijn ook toegestaan voor de geïnstalleerde en gestreamde versies van de app.</translation> <translation id="9070342919388027491">Tabblad naar links verplaatst</translation> <translation id="9074739597929991885">Bluetooth</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb index fc65abb..23be30e 100644 --- a/chrome/app/resources/generated_resources_no.xtb +++ b/chrome/app/resources/generated_resources_no.xtb
@@ -1727,6 +1727,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Åpne alle i &ny fanegruppe}=1{Åpne i &ny fanegruppe}other{Åpne alle ({COUNT}) i &ny fanegruppe}}</translation> <translation id="2285942871162473373">Gjenkjente ikke fingeravtrykket ditt. Prøv på nytt.</translation> <translation id="2287617382468007324">IPP-adresse for utskrift</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{For å beskytte dataene dine har vi fjernet tillatelsene fra et nettsted du ikke har besøkt i det siste}other{For å beskytte dataene dine har vi fjernet tillatelsene fra nettsteder du ikke har besøkt i det siste}}</translation> <translation id="2287944065963043964">Påloggingsskjerm</translation> <translation id="2290615375132886363">Navigeringsknapper i nettbrettmodus</translation> <translation id="2291452790265535215">Prøv å bruke sidepanelet for bokmerker, søkereiser med mer</translation> @@ -3303,6 +3304,7 @@ <translation id="3497560059572256875">Del doodlen</translation> <translation id="3497915391670770295">Send til &enhetene dine</translation> <translation id="3500417806337761827">Feil ved innsetting av delt nettverksressurs. Det er allerede satt inn for mange delte SMB-nettverksressurser.</translation> +<translation id="3500764001796099683">Aktiver isolerte nettapper</translation> <translation id="350397915809787283">Hvis du ikke har noen konto, velger du det første alternativet for å opprette en.</translation> <translation id="3503995387997205657">Du kan gjenopprette de tidligere appene dine</translation> <translation id="3505100368357440862">Handelsforslag</translation> @@ -4309,6 +4311,7 @@ <translation id="4275788652681621337">Lukk sidepanelet</translation> <translation id="4275830172053184480">Start enheten din på nytt</translation> <translation id="4277434192562187284">XML-konfigurasjonskilde</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{Tillatelsene er fjernet fra 1 nettsted}other{Tillatelsene er fjernet fra {NUM_SITES} nettsteder}}</translation> <translation id="4278390842282768270">Tillatt</translation> <translation id="4278498748067682896">Du kommer til å bruke en Kiosk og skilt-oppgradering, som gjør at enheten kun kan kjøres i kiosk- eller skiltmodus. Hvis du vil at brukere skal logge på enheten, må du gå tilbake og registrere den med Chrome Enterprise-oppgraderingen.</translation> <translation id="4278779213160967034">Denne prosessen kan ta noen minutter. Laster ned filer.</translation> @@ -7175,6 +7178,7 @@ <translation id="6551508934388063976">Kommandoen er utilgjengelig. Trykk på control-N for å åpne et nytt vindu.</translation> <translation id="6551606359270386381">Ellipseverktøy</translation> <translation id="6551612971599078809">Nettstedet bruker USB</translation> +<translation id="6551620030439692385">Blokkert. Tidssonen er for øyeblikket <ph name="TIMEZONE" />, og den kan bare oppdateres manuelt.</translation> <translation id="6551739526055143276">Administreres av Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> brukere</translation> <translation id="6555432686520421228">Fjern alle brukerkontoer og tilbakestill <ph name="IDS_SHORT_PRODUCT_NAME" />-enheten din til fabrikkstandard.</translation> @@ -7243,6 +7247,7 @@ <translation id="6608773371844092260">For å konfigurere fingeravtrykk, få barnet ditt til å trykke på fingeravtrykkssensoren på høyre side av <ph name="DEVICE_TYPE" />. Barnets fingeravtrykksdata lagres sikkert og sendes aldri fra <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Påloggingsdata blir lagret på denne enheten når du går ut av Inkognitomodus. Du kan logge på dette nettstedet med enheten din igjen senere.</translation> <translation id="6610002944194042868">Alternativer for oversettelse</translation> +<translation id="6610064275805055636">Administrer isolerte nettapper</translation> <translation id="6611972847767394631">Se fanene dine her</translation> <translation id="661266467055912436">Øker sikkerheten for deg og alle andre på nettet.</translation> <translation id="6613267708691765962">Skanner etter skadelig programvare …</translation> @@ -8607,6 +8612,7 @@ <translation id="7671472752213333268">«<ph name="EXTENSION_NAME" />» vil skanne fra «<ph name="SCANNER_NAME" />».</translation> <translation id="7672504401554182757">Velg hvilken enhet som har tilgangsnøkkelen for <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> på <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blokkert. Tidsplanen er for øyeblikket <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" />, og den kan bare oppdateres manuelt.</translation> <translation id="7673313156293624327">Logger for ChromeOS Shill (tilkoblingsbehandling)</translation> <translation id="7674416868315480713">Deaktiver alle porter som viderekobles i Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> apper</translation> @@ -9540,6 +9546,7 @@ <translation id="8376384591331888629">Inkludert informasjonskapsler fra tredjeparter på dette nettstedet</translation> <translation id="8376451933628734023">Hvis denne nettappen prøver å lure deg til å tro at det er en annen app, må du avinstallere det.</translation> <translation id="8376532149031784008">Laster inn <ph name="DOMAIN" /> på nytt …</translation> +<translation id="8376610503048439696">Utvidelser som administratoren din har installert, kan fremdeles lese og endre dette nettstedet</translation> <translation id="8376752431516546391">Google Søk-sidepanelet</translation> <translation id="8377625247046155446">Denne tilgangsnøkkelen lagres bare på denne enheten. Den blir værende på denne enheten når du har lukket alle inkognitovinduer.</translation> <translation id="8378714024927312812">Administreres av organisasjonen din</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb index 09f1ab5..e3e7cac 100644 --- a/chrome/app/resources/generated_resources_pa.xtb +++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -1018,7 +1018,7 @@ <translation id="1757301747492736405">ਅਣਸਥਾਪਨਾ ਵਿਚਾਰ-ਅਧੀਨ</translation> <translation id="175772926354468439">ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰੋ</translation> <translation id="1757786065507923842">ਮਾਂ-ਪਿਓ ਦੀ ਇਜਾਜ਼ਤ ਸੰਬੰਧੀ ਬੇਨਤੀ ਅਸਫਲ ਰਹੀ।</translation> -<translation id="17584710573359123">Chrome Web Store ਵਿੱਚ ਦੇਖੋ</translation> +<translation id="17584710573359123">Chrome ਵੈੱਬ ਸਟੋਰ ਵਿੱਚ ਦੇਖੋ</translation> <translation id="1761402971842586829"><ph name="BUTTON_NAME" /> ਨੂੰ <ph name="REMAPPING_OPTION" /> 'ਤੇ ਰੀਮੈਪ ਕੀਤਾ ਗਿਆ।</translation> <translation id="1761845175367251960"><ph name="NAME" /> ਦੇ ਖਾਤੇ</translation> <translation id="176272781006230109">ਖਰੀਦਦਾਰੀ ਸੰਬੰਧੀ ਸੁਝਾਅ</translation> @@ -1230,7 +1230,7 @@ <translation id="1904603806662441960">Chrome ਵਿੱਚ ਸਾਈਟ ਕੈਮਰਾ ਇਜਾਜ਼ਤਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ</translation> <translation id="1905375423839394163">Chromebook ਡੀਵਾਈਸ ਦਾ ਨਾਮ</translation> <translation id="1906181697255754968">ਸਾਈਟਾਂ ਆਮ ਤੌਰ 'ਤੇ ਤੁਹਾਡੇ ਕੰਮ ਨੂੰ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਰੱਖਿਅਤ ਕਰਨ ਜਿਹੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਲਈ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਵਿਚਲੀਆਂ ਫ਼ਾਈਲਾਂ ਅਤੇ ਫੋਲਡਰਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਦੀਆਂ ਹਨ</translation> -<translation id="1906488504371069394"><ph name="BEGIN_LINK" />Chrome Web Store<ph name="END_LINK" /> 'ਤੇ ਹੋਰ ਐਕਸਟੈਂਸ਼ਨਾਂ ਅਤੇ ਥੀਮ ਖੋਜੋ</translation> +<translation id="1906488504371069394"><ph name="BEGIN_LINK" />Chrome ਵੈੱਬ ਸਟੋਰ<ph name="END_LINK" /> 'ਤੇ ਹੋਰ ਐਕਸਟੈਂਸ਼ਨਾਂ ਅਤੇ ਥੀਮ ਖੋਜੋ</translation> <translation id="1907044622262489040">ਆਪਣੀ ਅਵਾਜ਼ ਨਾਲ ਟਾਈਪ ਕਰੋ। Search + D ਵਰਤੋ, ਫਿਰ ਬੋਲਣਾ ਸ਼ੁਰੂ ਕਰੋ।</translation> <translation id="1907659324308286326">ਕੁਝ Thunderbolt ਜਾਂ USB4 ਐਕਸੈਸਰੀਆਂ ਨੂੰ ਚੰਗੀ ਤਰ੍ਹਾਂ ਕੰਮ ਕਰਨ ਲਈ ਮੈਮੋਰੀ ਤੱਕ ਪਹੁੰਚ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।</translation> <translation id="1908591798274282246">ਬੰਦ ਕੀਤਾ ਗਰੁੱਪ ਟੈਬ ਦੁਬਾਰਾ ਖੋਲ੍ਹੋ</translation> @@ -2247,7 +2247,7 @@ <translation id="266079277508604648">ਪ੍ਰਿੰਟਰ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਇਹ ਜਾਂਚ ਕਰੋ ਕਿ ਪ੍ਰਿੰਟਰ ਚਾਲੂ ਹੈ ਅਤੇ ਵਾਈ-ਫਾਈ ਜਾਂ USB ਰਾਹੀਂ ਤੁਹਾਡੀ Chromebook ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ ਹੈ।</translation> <translation id="2661315027005813059">ਪੂਰੇ ਪੰਨੇ ਦੇ ਕੈਸ਼ੇ ਵਿੱਚ ਸਟੋਰ ਕੀਤਾ ਪੰਨਾ: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation> <translation id="2661714428027871023">ਲਾਈਟ ਮੋਡ ਨਾਲ ਵਧੇਰੇ ਤੇਜ਼ੀ ਨਾਲ ਬ੍ਰਾਊਜ਼ ਕਰੋ ਅਤੇ ਘੱਟ ਡਾਟਾ ਵਰਤੋ। ਹੋਰ ਜਾਣਨ ਲਈ ਕਲਿੱਕ ਕਰੋ।</translation> -<translation id="2662876636500006917">Chrome Web Store</translation> +<translation id="2662876636500006917">Chrome ਵੈੱਬ ਸਟੋਰ</translation> <translation id="2663253180579749458">ਈ-ਸਿਮ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ। ਇਸ ਵਿੱਚ ਕੁਝ ਮਿੰਟ ਲੱਗ ਸਕਦੇ ਹਨ।</translation> <translation id="2663302507110284145">ਭਾਸ਼ਾ</translation> <translation id="2665394472441560184">ਇੱਕ ਨਵਾਂ ਸ਼ਬਦ ਜੋੜੋ</translation> @@ -2268,7 +2268,7 @@ <translation id="2673873887296220733">ਕੀ ਖੋਲ੍ਹਣ ਲਈ 1 ਫ਼ਾਈਲ ਨੂੰ <ph name="CLOUD_PROVIDER" /> 'ਤੇ ਕਾਪੀ ਕਰਨਾ ਹੈ?</translation> <translation id="267442004702508783">ਰਿਫ੍ਰੈਸ਼ ਕਰੋ</translation> <translation id="2674764818721168631">ਬੰਦ</translation> -<translation id="2676084251379299915">ਇਸ ਐਕਸਟੈਂਸ਼ਨ ਨੂੰ ਐਂਟਰਪ੍ਰਾਈਜ਼ ਨੀਤੀ ਕਰਕੇ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ ਕਿਉਂਕਿ ਹੁਣ ਇਹ Chrome Web Store 'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।</translation> +<translation id="2676084251379299915">ਇਸ ਐਕਸਟੈਂਸ਼ਨ ਨੂੰ ਐਂਟਰਪ੍ਰਾਈਜ਼ ਨੀਤੀ ਕਰਕੇ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ ਕਿਉਂਕਿ ਹੁਣ ਇਹ Chrome ਵੈੱਬ ਸਟੋਰ 'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।</translation> <translation id="2678063897982469759">ਮੁੜ ਚਾਲੂ ਕਰੋ</translation> <translation id="2678100101831051676">ਕਾਸਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।</translation> <translation id="268053382412112343">ਇ&ਤਿਹਾਸ</translation> @@ -2691,7 +2691,7 @@ <translation id="2996286169319737844">ਡਾਟੇ ਨੂੰ ਤੁਹਾਡੇ ਸਿੰਕ ਪਾਸਫਰੇਜ਼ ਨਾਲ ਇਨਕ੍ਰਿਪਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਵਿੱਚ Google Pay ਦੀਆਂ ਭੁਗਤਾਨ ਵਿਧੀਆਂ ਅਤੇ ਪਤੇ ਸ਼ਾਮਲ ਨਹੀਂ ਹਨ।</translation> <translation id="2996722619877761919">ਕਿਤਾਬ ਵਾਂਗ ਪਲਟਣ ਲਈ</translation> <translation id="2996932914629936323">ਸਿੰਕ ਕੀਤੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ ਤੋਂ ਇਤਿਹਾਸ ਕਲੀਅਰ ਕਰਦਾ ਹੈ</translation> -<translation id="2998097899774209901">ਚਾਲੂ • ਇਹ ਸੈਟਿੰਗ 'Chrome Web Store' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ</translation> +<translation id="2998097899774209901">ਚਾਲੂ • ਇਹ ਸੈਟਿੰਗ 'Chrome ਵੈੱਬ ਸਟੋਰ' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ</translation> <translation id="2998267783395280091">ਨੈੱਟਵਰਕ ਮਿਲਿਆ</translation> <translation id="3000378525979847272"><ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /> ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਗਈ</translation> <translation id="3000461861112256445">ਮੋਨੋ ਆਡੀਓ</translation> @@ -2724,7 +2724,7 @@ <translation id="3012631534724231212">(Iframe)</translation> <translation id="3012804260437125868">ਸਿਰਫ਼ ਸਮਰੂਪ-ਸਾਈਟ ਕਨੈਕਸ਼ਨਾਂ ਨੂੰ ਰੱਖਿਅਤ ਕਰੋ</translation> <translation id="3012917896646559015">ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਕੰਪਿਊਟਰ ਨੂੰ ਕਿਸੇ ਮੁਰੰਮਤ ਕੇਂਦਰ ਵਿੱਚ ਭੇਜਣ ਲਈ ਤੁਰੰਤ ਆਪਣੇ ਹਾਰਡਵੇਅਰ ਨਿਰਮਾਤਾ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।</translation> -<translation id="3013652227108802944">ਬੰਦ • ਇਹ ਸੈਟਿੰਗ 'Chrome Web Store' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ</translation> +<translation id="3013652227108802944">ਬੰਦ • ਇਹ ਸੈਟਿੰਗ 'Chrome ਵੈੱਬ ਸਟੋਰ' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ</translation> <translation id="301525898020410885">ਭਾਸ਼ਾ ਨੂੰ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸੈੱਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation> <translation id="3015639418649705390">ਹੁਣੇ ਮੁੜ-ਲਾਂਚ ਕਰੋ</translation> <translation id="3016381065346027039">ਕੋਈ ਲੌਗ ਇੰਦਰਾਜ ਨਹੀਂ</translation> @@ -3310,6 +3310,7 @@ <translation id="3497560059572256875">ਡੂਡਲ ਸਾਂਝਾ ਕਰੋ</translation> <translation id="3497915391670770295">ਆਪਣੇ ਡੀ&ਵਾਈਸਾਂ 'ਤੇ ਭੇਜੋ</translation> <translation id="3500417806337761827">ਸਾਂਝਾਕਰਨ ਮਾਊਂਟ ਕਰਨ ਵਿੱਚ ਗੜਬੜ ਹੋਈ। ਬਹੁਤ ਸਾਰੇ SMB ਸਾਂਝਾਕਰਨਾਂ ਨੂੰ ਪਹਿਲਾਂ ਹੀ ਮਾਊਂਟ ਕੀਤਾ ਜਾ ਚੁੱਕਿਆ ਹੈ।</translation> +<translation id="3500764001796099683">ਆਇਸੋਲੇਟਿਡ ਵੈੱਬ ਐਪਾਂ ਚਾਲੂ ਕਰੋ</translation> <translation id="350397915809787283">ਜੇ ਤੁਹਾਡੇ ਕੋਲ ਖਾਤਾ ਨਹੀਂ ਹੈ, ਤਾਂ ਨਵਾਂ ਖਾਤਾ ਬਣਾਉਣ ਲਈ ਪਹਿਲਾ ਵਿਕਲਪ ਚੁਣੋ।</translation> <translation id="3503995387997205657">ਤੁਸੀਂ ਆਪਣੀਆਂ ਪਿਛਲੀਆਂ ਐਪਾਂ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰ ਸਕਦੇ ਹੋ</translation> <translation id="3505100368357440862">ਖਰੀਦਦਾਰੀ ਸੰਬੰਧੀ ਸੁਝਾਅ</translation> @@ -3674,7 +3675,7 @@ <translation id="3775432569830822555">SSL ਸਰਵਰ ਪ੍ਰਮਾਣ-ਪੱਤਰ</translation> <translation id="3775705724665058594">ਆਪਣੇ ਡੀਵਾਈਸਾਂ 'ਤੇ ਭੇਜੋ</translation> <translation id="3776508619697147021">ਸਾਈਟਾਂ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਕਈ ਫ਼ਾਈਲਾਂ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਪੁੱਛ ਸਕਦੀਆਂ ਹਨ</translation> -<translation id="3776796446459804932">ਇਹ ਸੈਟਿੰਗ 'Chrome Web Store' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ।</translation> +<translation id="3776796446459804932">ਇਹ ਸੈਟਿੰਗ 'Chrome ਵੈੱਬ ਸਟੋਰ' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ।</translation> <translation id="3777483481409781352">ਸੈਲਿਊਲਰ ਡੀਵਾਈਸ ਕਿਰਿਆਸ਼ੀਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ</translation> <translation id="3777796259512476958">ਤੁਹਾਨੂੰ ਜ਼ਿਆਦਾਤਰ ਸਾਈਟਾਂ ਤੋਂ ਸਾਈਨ-ਆਊਟ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ</translation> <translation id="3778208826288864398">ਸੁਰੱਖਿਆ ਕੁੰਜੀ ਲਾਕ ਹੋ ਗਈ ਹੈ ਕਿਉਂਕਿ ਗਲਤ ਪਿੰਨ ਬਹੁਤ ਵਾਰ ਦਾਖਲ ਕੀਤਾ ਗਿਆ। ਤੁਹਾਨੂੰ ਸੁਰੱਖਿਆ ਕੁੰਜੀ ਨੂੰ ਰੀਸੈੱਟ ਕਰਨਾ ਪਵੇਗਾ।</translation> @@ -5068,7 +5069,7 @@ <translation id="4870724079713069532">ਤੁਸੀਂ ਆਪਣੇ File Explorer ਜਾਂ ਹੋਰ ਐਪਾਂ ਤੋਂ ਇਸ ਐਪ ਨਾਲ ਸਮਰਥਿਤ ਫ਼ਾਈਲਾਂ ਨੂੰ ਖੋਲ੍ਹ ਸਕਦੇ ਹੋ ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰ ਸਕਦੇ ਹੋ। ਇਹ ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਕਿ ਕਿਹੜੀਆਂ ਫ਼ਾਈਲਾਂ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਤੌਰ 'ਤੇ ਇਸ ਐਪ ਨੂੰ ਖੋਲ੍ਹਣ, ਇਸ ਲਈ <ph name="BEGIN_LINK" />Windows ਸੈਟਿੰਗਾਂ<ph name="END_LINK" /> 'ਤੇ ਜਾਓ।</translation> <translation id="4870758487381879312">ਸੰਰੂਪਣ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਮੁਹੱਈਆ ਕੀਤਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ</translation> <translation id="4870995365819149457">ਕੁਝ ਸਮਰਥਿਤ ਲਿੰਕ ਹਾਲੇ ਵੀ <ph name="APP_NAME" />, <ph name="APP_NAME_2" />, <ph name="APP_NAME_3" /> ਅਤੇ 1 ਹੋਰ ਐਪ ਵਿੱਚ ਖੁੱਲ੍ਹਣਗੇ।</translation> -<translation id="4871308555310586478">'Chrome Web Store' ਤੋਂ ਨਹੀਂ।</translation> +<translation id="4871308555310586478">'Chrome ਵੈੱਬ ਸਟੋਰ' ਤੋਂ ਨਹੀਂ।</translation> <translation id="4871322859485617074">ਪਿੰਨ ਵਿੱਚ ਅਵੈਧ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਹਨ</translation> <translation id="4871370605780490696">ਬੁੱਕਮਾਰਕ ਸ਼ਾਮਿਲ ਕਰੋ</translation> <translation id="4871568871368204250">ਸਿੰਕ ਬੰਦ ਕਰੋ</translation> @@ -5820,7 +5821,7 @@ <translation id="5470735824776589490">ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਪਾਵਰਵਾਸ਼ ਨਾਲ ਰੀਸੈੱਟ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। <ph name="LINK_BEGIN" />ਹੋਰ ਜਾਣੋ<ph name="LINK_END" /></translation> <translation id="5471768120198416576">ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ! ਮੈਂ ਤੁਹਾਡੀ ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਵਿੱਚ ਬਦਲੀ ਹੋਈ ਅਵਾਜ਼ ਹਾਂ।</translation> <translation id="5472627187093107397">ਇਸ ਸਾਈਟ ਲਈ ਪਾਸਵਰਡ ਰੱਖਿਅਤ ਕਰੋ</translation> -<translation id="5473062644742711742">Chrome Web Store ਵਿੱਚ ਹੋਰ ਪਹੁੰਚਯੋਗਤਾ ਟੂਲ ਲੱਭੋ</translation> +<translation id="5473062644742711742">Chrome ਵੈੱਬ ਸਟੋਰ ਵਿੱਚ ਹੋਰ ਪਹੁੰਚਯੋਗਤਾ ਟੂਲ ਲੱਭੋ</translation> <translation id="5473075389972733037">IBM</translation> <translation id="5473099001878321374">ਜਾਰੀ ਰੱਖ ਕੇ, ਤੁਸੀਂ ਇਹ ਸਹਿਮਤੀ ਦਿੰਦੇ ਹੋ ਕਿ ਇਹ ਡੀਵਾਈਸ ਸੰਭਾਵੀ ਤੌਰ 'ਤੇ ਸੈਲਿਊਲਰ ਡਾਟੇ ਦੀ ਵਰਤੋਂ ਨਾਲ Google, ਤੁਹਾਡੇ ਬੱਚੇ ਦਾ ਕੈਰੀਅਰ ਅਤੇ ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਮਾਤਾ ਤੋਂ ਅੱਪਡੇਟ ਅਤੇ ਐਪਾਂ ਨੂੰ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਡਾਊਨਲੋਡ ਅਤੇ ਸਥਾਪਤ ਵੀ ਕਰ ਸਕਦਾ ਹੈ। ਇਨ੍ਹਾਂ ਵਿੱਚੋਂ ਕੁਝ ਐਪਾਂ ਐਪ-ਅੰਦਰ ਖਰੀਦਾਂ ਦੀ ਪੇਸ਼ਕਸ਼ ਕਰ ਸਕਦੀਆਂ ਹਨ।</translation> <translation id="5473156705047072749">{NUM_CHARACTERS,plural, =1{ਪਿੰਨ ਘੱਟੋ-ਘੱਟ ਇੱਕ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਦਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ}one{ਪਿੰਨ ਘੱਟੋ-ਘੱਟ # ਅੱਖਰ-ਚਿੰਨ੍ਹ ਦਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ}other{ਪਿੰਨ ਘੱਟੋ-ਘੱਟ # ਅੱਖਰ-ਚਿੰਨ੍ਹਾਂ ਦਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ}}</translation> @@ -6040,7 +6041,7 @@ <translation id="5636996382092289526"><ph name="NETWORK_ID" /> ਨੂੰ ਵਰਤਣ ਲਈ ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ <ph name="LINK_START" />ਨੈੱਟਵਰਕ ਦੇ ਸਾਈਨ-ਇਨ ਪੰਨੇ 'ਤੇ ਜਾਣ<ph name="LINK_END" /> ਦੀ ਲੋੜ ਹੋ ਸਕਦੀ ਹੈ, ਜੋ ਕੁਝ ਸਕਿੰਟਾਂ ਵਿੱਚ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਖੁੁੱਲ੍ਹ ਜਾਵੇਗਾ। ਜੇਕਰ ਅਜਿਹਾ ਨਹੀਂ ਹੁੰਦਾ, ਤਾਂ ਨੈੱਟਵਰਕ ਨਹੀਂ ਵਰਤਿਆ ਜਾ ਸਕਦਾ।</translation> <translation id="5637476008227280525">ਮੋਬਾਈਲ ਡਾਟਾ ਚਾਲੂ</translation> <translation id="563821631542362636">ਸਾਈਟ ਨੂੰ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ</translation> -<translation id="5638309510554459422"><ph name="BEGIN_LINK" />Chrome Web Store<ph name="END_LINK" /> ਵਿੱਚ ਐਕਸਟੈਂਸ਼ਨਾਂ ਅਤੇ ਥੀਮ ਲੱਭੋ</translation> +<translation id="5638309510554459422"><ph name="BEGIN_LINK" />Chrome ਵੈੱਬ ਸਟੋਰ<ph name="END_LINK" /> ਵਿੱਚ ਐਕਸਟੈਂਸ਼ਨਾਂ ਅਤੇ ਥੀਮ ਲੱਭੋ</translation> <translation id="5639549361331209298">ਇਸ ਪੰਨੇ ਨੂੰ ਰੀਲੋਡ ਕਰਨ ਲਈ, ਹੋਰ ਚੋਣਾਂ ਦੇਖਣ ਲਈ ਹੋਲਡ ਕਰੋ</translation> <translation id="5640133431808313291">ਸੁਰੱਖਿਆ ਕੁੰਜੀਆਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ</translation> <translation id="5640159004008030285">ਇਹ ਪਾਸਵਰਡ ਸਿਰਫ਼ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਦੂਜੇ ਡੀਵਾਈਸਾਂ 'ਤੇ ਵਰਤਣ ਲਈ, <ph name="BEGIN_LINK" />ਇਸਨੂੰ ਆਪਣੇ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੋ<ph name="END_LINK" />।</translation> @@ -7090,7 +7091,7 @@ <translation id="6476482583633999078">ਬੋਲਣ ਦੀ ਗਤੀ</translation> <translation id="6477822444490674459">ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਫ਼ੋਨਾਂ ਲਈ ਸੂਚਨਾ ਸਿੰਕ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ। <ph name="LINK_BEGIN" />ਹੋਰ ਜਾਣੋ<ph name="LINK_END" /></translation> <translation id="6478248366783946499">ਕੀ ਖਤਰਨਾਕ ਫ਼ਾਈਲ ਨੂੰ ਰੱਖਣਾ ਹੈ?</translation> -<translation id="6479881432656947268">Chrome Web Store 'ਤੇ ਜਾਓ</translation> +<translation id="6479881432656947268">Chrome ਵੈੱਬ ਸਟੋਰ 'ਤੇ ਜਾਓ</translation> <translation id="6480327114083866287"><ph name="MANAGER" /> ਵੱਲੋਂ ਪ੍ਰਬੰਧਨ ਕੀਤਾ ਗਿਆ</translation> <translation id="6481749622989211463">ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਨਾਲ ਫ਼ਾਈਲਾਂ ਅਤੇ ਹੋਰ ਚੀਜ਼ਾਂ ਨੂੰ ਸਾਂਝਾ ਕਰੋ। <ph name="LINK_BEGIN" />ਹੋਰ ਜਾਣੋ<ph name="LINK_END" /></translation> <translation id="6482559668224714696">ਪੂਰੀ-ਸਕ੍ਰੀਨ ਵੱਡਦਰਸ਼ੀ</translation> @@ -7186,6 +7187,7 @@ <translation id="6551508934388063976">ਕਮਾਂਡ ਅਣਉਪਲਬਧ। ਇੱਕ ਨਵੀਂ window ਖੋਲ੍ਹਣ ਲਈ control-N ਦਬਾਓ।</translation> <translation id="6551606359270386381">ਅੰਡਾਕਾਰ ਟੂਲ</translation> <translation id="6551612971599078809">ਸਾਈਟ USB ਨੂੰ ਵਰਤ ਰਹੀ ਹੈ</translation> +<translation id="6551620030439692385">ਪਹੁੰਚ ਬਲਾਕ ਕੀਤੀ ਗਈ। ਸਮਾਂ ਖੇਤਰ ਫ਼ਿਲਹਾਲ <ph name="TIMEZONE" /> 'ਤੇ ਸੈੱਟ ਹੈ ਅਤੇ ਇਸਨੂੰ ਸਿਰਫ਼ ਹੱਥੀਂ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।</translation> <translation id="6551739526055143276">Family Link ਵੱਲੋਂ ਪ੍ਰਬੰਧਨ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> ਉਪਭੋਗਤਾ</translation> <translation id="6555432686520421228">ਸਾਰੇ ਵਰਤੋਂਕਾਰ ਖਾਤੇ ਹਟਾਓ ਅਤੇ ਆਪਣੀ <ph name="IDS_SHORT_PRODUCT_NAME" /> ਡੀਵਾਈਸ ਨੂੰ ਬਿਲਕੁਲ ਨਵੀਂ ਵਾਂਗ ਰੀਸੈੱਟ ਕਰੋ।</translation> @@ -7256,6 +7258,7 @@ <translation id="6608773371844092260">ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ, ਆਪਣੇ ਬੱਚੇ ਨੂੰ ਇਸ <ph name="DEVICE_TYPE" /> ਦੇ ਸੱਜੇ ਪਾਸੇ 'ਤੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ 'ਤੇ ਸਪਰਸ਼ ਕਰਨ ਲਈ ਕਹੋ। ਤੁਹਾਡੇ ਬੱਚੇ ਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਡਾਟਾ ਸੁਰੱਖਿਅਤ ਤਰੀਕੇ ਨਾਲ ਸਟੋਰ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਅਤੇ ਕਦੇ ਵੀ ਇਸ <ph name="DEVICE_TYPE" /> ਤੋਂ ਬਾਹਰ ਨਹੀਂ ਜਾਂਦਾ।</translation> <translation id="6609478180749378879">ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਤੋਂ ਬਾਹਰ ਨਿਕਲਣ ਦੇ ਬਾਅਦ ਸਾਈਨ-ਇਨ ਡਾਟਾ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਸਟੋਰ ਕੀਤਾ ਜਾਵੇਗਾ। ਤੁਸੀਂ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਆਪਣੇ ਡੀਵਾਈਸ ਨਾਲ ਇਸ ਵੈੱਬਸਾਈਟ 'ਤੇ ਸਾਈਨ-ਇਨ ਕਰ ਸਕੋਗੋ।</translation> <translation id="6610002944194042868">ਅਨੁਵਾਦ ਵਿਕਲਪ</translation> +<translation id="6610064275805055636">ਆਇਸੋਲੇਟਿਡ ਵੈੱਬ ਐਪਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ</translation> <translation id="6611972847767394631">ਆਪਣੀਆਂ ਟੈਬਾਂ ਇੱਥੇ ਲੱਭੋ</translation> <translation id="661266467055912436">ਵੈੱਬ 'ਤੇ ਤੁਹਾਡੇ ਅਤੇ ਹਰ ਕਿਸੇ ਲਈ ਸੁਰੱਖਿਆ ਨੂੰ ਬਿਹਤਰ ਬਣਾਇਆ ਜਾਂਦਾ ਹੈ।</translation> <translation id="6613267708691765962">ਮਾਲਵੇਅਰ ਲਈ ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ...</translation> @@ -8219,7 +8222,7 @@ <translation id="737728204345822099">ਇਸ ਸਾਈਟ 'ਤੇ ਤੁਹਾਡੇ ਜਾਣ ਦਾ ਰਿਕਾਰਡ ਤੁਹਾਡੀ ਸੁਰੱਖਿਆ ਕੁੰਜੀ ਵਿੱਚ ਰੱਖਿਆ ਜਾ ਸਕਦਾ ਹੈ।</translation> <translation id="7377451353532943397">ਸੈਂਸਰ ਤੱਕ ਪਹੁੰਚ ਨੂੰ ਬਲਾਕ ਕਰਦੇ ਰਹੋ</translation> <translation id="7377481913241237033">ਕੋਡ ਨਾਲ ਕਨੈਕਟ ਕਰੋ</translation> -<translation id="73786666777299047">'Chrome Web Store' ਖੋਲ੍ਹੋ</translation> +<translation id="73786666777299047">'Chrome ਵੈੱਬ ਸਟੋਰ' ਖੋਲ੍ਹੋ</translation> <translation id="7380272457268061606">ਕੀ ਸਥਾਨਕ ਡਾਟਾ ਰਿਕਵਰੀ ਨੂੰ ਬੰਦ ਕਰਨਾ ਹੈ?</translation> <translation id="7380459290951585794">ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਹਾਡਾ ਫ਼ੋਨ ਨਜ਼ਦੀਕ ਹੈ, ਅਣਲਾਕ ਹੈ ਅਤੇ ਉਸਦਾ ਬਲੂਟੁੱਥ ਅਤੇ ਵਾਈ-ਫਾਈ ਚਾਲੂ ਹੈ</translation> <translation id="7380622428988553498">ਡੀਵਾਈਸ ਨਾਮ ਵਿੱਚ ਅਵੈਧ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਹਨ</translation> @@ -8306,7 +8309,7 @@ <translation id="7434509671034404296">ਵਿਕਾਸਕਾਰ</translation> <translation id="7434757724413878233">ਮਾਊਸ ਐਕਸੈੱਲਰੇਸ਼ਨ</translation> <translation id="7434969625063495310">ਪ੍ਰਿੰਟ ਸਰਵਰ ਨੂੰ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਸਰਵਰ ਦੇ ਸੰਰੂਪਣ ਦੀ ਜਾਂਚ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation> -<translation id="7436452443388501706">{NUM_EXTENSIONS,plural, =1{Chrome Web Store ਤੋਂ ਹਟਾਈ ਗਈ 1 ਐਕਸਟੈਂਸ਼ਨ ਦੀ ਸਮੀਖਿਆ ਕਰੋ}one{Chrome Web Store ਤੋਂ ਹਟਾਈ ਗਈ {NUM_EXTENSIONS} ਐਕਸਟੈਂਸ਼ਨ ਦੀ ਸਮੀਖਿਆ ਕਰੋ}other{Chrome Web Store ਤੋਂ ਹਟਾਈਆਂ ਗਈਆਂ {NUM_EXTENSIONS} ਐਕਸਟੈਂਸ਼ਨਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰੋ}}</translation> +<translation id="7436452443388501706">{NUM_EXTENSIONS,plural, =1{Chrome ਵੈੱਬ ਸਟੋਰ ਤੋਂ ਹਟਾਈ ਗਈ 1 ਐਕਸਟੈਂਸ਼ਨ ਦੀ ਸਮੀਖਿਆ ਕਰੋ}one{Chrome ਵੈੱਬ ਸਟੋਰ ਤੋਂ ਹਟਾਈ ਗਈ {NUM_EXTENSIONS} ਐਕਸਟੈਂਸ਼ਨ ਦੀ ਸਮੀਖਿਆ ਕਰੋ}other{Chrome ਵੈੱਬ ਸਟੋਰ ਤੋਂ ਹਟਾਈਆਂ ਗਈਆਂ {NUM_EXTENSIONS} ਐਕਸਟੈਂਸ਼ਨਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰੋ}}</translation> <translation id="7436921188514130341">ਓਹੋ! ਨਾਮ ਬਦਲਣ ਦੌਰਾਨ ਗੜਬੜ ਹੋ ਗਈ।</translation> <translation id="7439519621174723623">ਜਾਰੀ ਰੱਖਣ ਲਈ ਇੱਕ ਡੀਵਾਈਸ ਦਾ ਨਾਮ ਸ਼ਾਮਲ ਕਰੋ</translation> <translation id="7441736532026945583">ਆਪਣੀ ਟੈਬ ਪੱਟੀ ਤੋਂ ਗਰੁੱਪ ਨੂੰ ਹਟਾਉਣ ਲਈ "ਗਰੁੱਪ ਲੁਕਾਓ" ਨੂੰ ਚੁਣੋ</translation> @@ -8620,6 +8623,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />", "<ph name="SCANNER_NAME" />" ਤੋਂ ਸਕੈਨ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ।</translation> <translation id="7672504401554182757">ਚੁਣੋ ਕਿ <ph name="APP_NAME" /> ਲਈ ਕਿਹੜੇ ਡੀਵਾਈਸ ਕੋਲ ਪਾਸਕੀ ਹੋਵੇ</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> ਵਿੱਚ।</translation> +<translation id="7672726198839739113">ਪਹੁੰਚ ਬਲਾਕ ਕੀਤੀ ਗਈ। ਸਮਾਂ-ਸੂਚੀ ਫ਼ਿਲਹਾਲ <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> 'ਤੇ ਸੈੱਟ ਹੈ ਅਤੇ ਇਸਨੂੰ ਸਿਰਫ਼ ਹੱਥੀਂ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।</translation> <translation id="7673313156293624327">ChromeOS Shill (ਕਨੈਕਸ਼ਨ ਪ੍ਰਬੰਧਕ) ਲੌਗ</translation> <translation id="7674416868315480713">Linux ਵਿੱਚ ਅੱਗੇ ਭੇਜੇ ਜਾ ਰਹੇ ਸਾਰੇ ਪੋਰਟਾਂ ਨੂੰ ਅਕਿਰਿਆਸ਼ੀਲ ਕਰੋ</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> ਐਪ</translation> @@ -9551,6 +9555,7 @@ <translation id="8376384591331888629">ਇਸ ਸਾਈਟ 'ਤੇ ਤੀਜੀ-ਧਿਰ ਦੀਆਂ ਕੁਕੀਜ਼ ਸਮੇਤ</translation> <translation id="8376451933628734023">ਜੇ ਇਹ ਵੈੱਬ ਐਪ ਤੁਹਾਨੂੰ ਧੋਖਾ ਦੇਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਹੀ ਹੈ ਕਿ ਇਹ ਇੱਕ ਵੱਖਰੀ ਐਪ ਹੈ, ਤਾਂ ਇਸ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰੋ।</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> ਰੀਲੋਡ ਹੋ ਰਿਹਾ ਹੈ...</translation> +<translation id="8376610503048439696">ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਕਸਟੈਂਸ਼ਨਾਂ ਹਾਲੇ ਵੀ ਇਸ ਸਾਈਟ ਨੂੰ ਪੜ੍ਹ ਅਤੇ ਬਦਲ ਸਕਦੀਆਂ ਹਨ</translation> <translation id="8376752431516546391">Google Search ਦਾ ਸਾਈਡ ਪੈਨਲ</translation> <translation id="8377625247046155446">ਇਸ ਪਾਸਕੀ ਨੂੰ ਸਿਰਫ਼ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਵੇਗਾ। ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਰੀਆਂ ਇਨਕੋਗਨਿਟੋ ਵਿੰਡੋਆਂ ਨੂੰ ਬੰਦ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਵੀ ਇਹ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਮੌਜੂਦ ਰਹੇਗੀ।</translation> <translation id="8378714024927312812">ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਪ੍ਰਬੰਧਨ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation> @@ -9979,7 +9984,7 @@ <translation id="8708000541097332489">ਬਾਹਰ ਜਾਣ ਤੇ ਹਟਾਓ</translation> <translation id="870805141700401153">Microsoft ਵਿਅਕਤੀਗਤ ਕੋਡ ਸਾਈਨਿੰਗ</translation> <translation id="8708671767545720562">&ਹੋਰ ਜਾਣਕਾਰੀ</translation> -<translation id="8709368517685334931">ਤੁਹਾਨੂੰ Chrome Web Store ਵਿੱਚ ਪੁਰਾਣੇ ਰੰਗ ਮਿਲ ਸਕਦੇ ਹਨ</translation> +<translation id="8709368517685334931">ਤੁਹਾਨੂੰ Chrome ਵੈੱਬ ਸਟੋਰ ਵਿੱਚ ਪੁਰਾਣੇ ਰੰਗ ਮਿਲ ਸਕਦੇ ਹਨ</translation> <translation id="8710550057342691420">ਮਿਲਦੀਆਂ-ਜੁਲਦੀਆਂ ਟੈਬਾਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ</translation> <translation id="8711402221661888347">ਅਚਾਰ</translation> <translation id="8711538096655725662">ਤੁਹਾਡੇ ਵੱਲੋਂ ਦੇਖੀਆਂ ਗਈਆਂ ਸਾਰੀਆਂ ਸਾਈਟਾਂ 'ਤੇ ਆਪਣੇ ਆਪ ਚੱਲਦਾ ਹੈ</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb index 5fb4a7b..20c5d941 100644 --- a/chrome/app/resources/generated_resources_pl.xtb +++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -3527,7 +3527,7 @@ <translation id="3702797829026927713"><ph name="BEGIN_PARAGRAPH1" />Wpisz nazwę sprzedawcy i numer sklepu, dla którego konfigurujesz to urządzenie demonstracyjne*. <ph name="END_PARAGRAPH1" /> <ph name="BEGIN_PARAGRAPH2" />Aby kontynuować instalację trybu demonstracyjnego, gdy nie znasz numeru sklepu, możesz wpisać „0000”. <ph name="END_PARAGRAPH2" /> <ph name="BEGIN_PARAGRAPH3" />* Uwaga: Google używa tych informacji, aby określić, która wersja trybu demonstracyjnego powinna być dostępna na urządzeniu, i śledzić wykorzystanie tego trybu.<ph name="END_PARAGRAPH3" /></translation> -<translation id="3703166520839776970">Jeśli problem będzie się powtarzał, kliknij „Więcej szczegółów” poniżej, aby uzyskać więcej informacji od firmy <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" />.</translation> +<translation id="3703166520839776970">Jeśli problem będzie się powtarzał, kliknij „Więcej szczegółów” poniżej, aby uzyskać więcej informacji od <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" />.</translation> <translation id="3703699162703116302">Zgłoszenie odświeżone</translation> <translation id="370415077757856453">JavaScript zablokowany</translation> <translation id="3704331259350077894">Zaprzestanie działania</translation> @@ -4414,7 +4414,7 @@ <translation id="4378556263712303865">Przeznaczenie urządzenia</translation> <translation id="4379097572583973456">Witryna może też zawierać umieszczone treści z innych witryn, np. obrazy, reklamy i tekst. Te inne witryny również mogą zapisywać dane.</translation> <translation id="4379281552162875326">Odinstalować: „<ph name="APP_NAME" />”?</translation> -<translation id="4380055775103003110">Jeśli problem będzie się powtarzał, możesz wypróbować inne sposoby logowania w domenie <ph name="SITE_ETLD_PLUS_ONE" />.</translation> +<translation id="4380055775103003110">Jeśli problem będzie się powtarzał, możesz wypróbować inne sposoby logowania w witrynie <ph name="SITE_ETLD_PLUS_ONE" />.</translation> <translation id="4380648069038809855">Włączono tryb pełnego ekranu</translation> <translation id="4381902252848068865">Nie zezwalaj witrynie na zapisywanie danych</translation> <translation id="4383048856908088702">Gdy ta karta była nieaktywna, funkcja Oszczędzania pamięci zwolniła <ph name="MEMORY_VALUE" /> na inne zadania. Możesz to zmienić w dowolnym momencie, klikając <ph name="SETTINGS_LINK" />.</translation> @@ -4942,7 +4942,7 @@ <translation id="4804311503028830356">Kliknij strzałkę wstecz, aby zobaczyć inne opcje</translation> <translation id="4804818685124855865">Rozłącz</translation> <translation id="4804827417948292437">Awokado</translation> -<translation id="4806457879608775995">Przeczytaj te warunki i określ sposób użycia swoich danych</translation> +<translation id="4806457879608775995">Przeczytaj te warunki i określ sposób użycia swoich danych</translation> <translation id="4807098396393229769">Imię i nazwisko na karcie</translation> <translation id="4807122856660838973">Włącz Bezpieczne przeglądanie</translation> <translation id="4807514039636325497">Szczegóły DBus</translation> @@ -5236,7 +5236,7 @@ <translation id="5032430150487044192">Nie udało się utworzyć kodu QR</translation> <translation id="5033137252639132982">Nie zezwolono na używanie czujników ruchu</translation> <translation id="5033266061063942743">Kształty geometryczne</translation> -<translation id="5035846135112863536">Aby dowiedzieć się więcej od firmy <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" />, kliknij „Więcej szczegółów” poniżej.</translation> +<translation id="5035846135112863536">Aby dowiedzieć się więcej od <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" />, kliknij „Więcej szczegółów” poniżej.</translation> <translation id="5037676449506322593">Wybierz wszystko</translation> <translation id="5038818366306248416">Poprzednio nie zezwoliłeś(-aś) na żadne rozszerzenia na <ph name="ORIGIN" /></translation> <translation id="5039071832298038564">Informacje o sieci urządzenia</translation> @@ -5723,7 +5723,7 @@ <translation id="5425863515030416387">Łatwo loguj się na różnych urządzeniach</translation> <translation id="5427278936122846523">Zawsze tłumacz</translation> <translation id="5427459444770871191">Obróć w &prawo</translation> -<translation id="542750953150239272">Kontynuując, zgadzasz się na to, żeby to urządzenie mogło automatycznie pobierać oraz instalować aktualizacje i aplikacje od Google, operatora sieci komórkowej i producenta urządzenia, oraz żeby mogło używać w tym celu komórkowej transmisji danych. Niektóre z aplikacji umożliwiają robienie zakupów.</translation> +<translation id="542750953150239272">Kontynuując, zgadzasz się na to, żeby to urządzenie mogło automatycznie pobierać oraz instalować aktualizacje i aplikacje od Google, operatora sieci komórkowej i producenta urządzenia oraz żeby mogło używać w tym celu komórkowej transmisji danych. Niektóre z aplikacji umożliwiają robienie zakupów.</translation> <translation id="5428850089342283580"><ph name="ACCNAME_APP" /> (dostępna aktualizacja)</translation> <translation id="542948651837270806">Trzeba zainstalować aktualizację oprogramowania Trusted Platform Module. Zobacz: <ph name="TPM_FIRMWARE_UPDATE_LINK" /></translation> <translation id="5429818411180678468">Pełna szerokość</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb index f8dc1a38c..0336611 100644 --- a/chrome/app/resources/generated_resources_pt-BR.xtb +++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -1178,7 +1178,7 @@ <translation id="186612162884103683">"<ph name="EXTENSION" />" pode ler e gravar imagens, vídeos e arquivos de som nos locais marcados.</translation> <translation id="1867780286110144690">O <ph name="PRODUCT_NAME" /> está pronto para concluir a instalação</translation> <translation id="1868553836791672080">A verificação de senhas não está disponível no Chromium</translation> -<translation id="1868617395637139709">Use a localização para apps e serviços Android.</translation> +<translation id="1868617395637139709">Usar a localização para apps e serviços Android.</translation> <translation id="1869433484041798909">Botão de favorito</translation> <translation id="1871098866036088250">Abrir no navegador Chrome</translation> <translation id="1871131409931646355">Histórico completo de downloads</translation> @@ -3309,6 +3309,7 @@ <translation id="3497560059572256875">Compartilhar doodle</translation> <translation id="3497915391670770295">Enviar para seus dispositivos</translation> <translation id="3500417806337761827">Erro ao ativar o compartilhamento. Muitos compartilhamentos SMB já estão ativos.</translation> +<translation id="3500764001796099683">Ativar Apps Isolados da Web</translation> <translation id="350397915809787283">Se você não tem uma conta, selecione a primeira opção para criar uma.</translation> <translation id="3503995387997205657">Você pode restaurar seus apps anteriores</translation> <translation id="3505100368357440862">Sugestões de compras</translation> @@ -4356,7 +4357,7 @@ <translation id="4305817255990598646">Alternar</translation> <translation id="4306119971288449206">Os apps precisam ser veiculados com o tipo de conteúdo "<ph name="CONTENT_TYPE" />"</translation> <translation id="4307992518367153382">Básicas</translation> -<translation id="4309165024397827958">Permitir que apps e serviços do Android com permissão de localização usem o local do dispositivo. O Google pode coletar dados de local periodicamente e os usar de forma anônima para melhorar a precisão de local e os serviços com base em localização.</translation> +<translation id="4309165024397827958">Permita que apps e serviços do Android com permissão de localização usem o local do dispositivo. O Google pode coletar dados de local periodicamente e os usar de forma anônima para melhorar a precisão de local e os serviços com base em localização.</translation> <translation id="4309183709806093061">Compartilhar também o áudio do sistema. Este dispositivo vai ser silenciado para evitar feedback.</translation> <translation id="4309420042698375243"><ph name="NUM_KILOBYTES" /> K (<ph name="NUM_KILOBYTES_LIVE" /> K ativos)</translation> <translation id="4310132194679586591">Selecione um app no seu dispositivo para abrir este link</translation> @@ -5735,7 +5736,7 @@ <translation id="5411856344659127989">Se você quer adicionar uma conta para outra pessoa, <ph name="LINK_BEGIN" />adicione um novo usuário<ph name="LINK_END" /> ao <ph name="DEVICE_TYPE" />. As permissões que você já concedeu a sites e apps podem ser aplicadas a essa conta. É possível gerenciar suas Contas do Google nas <ph name="SETTINGS_LINK_BEGIN" />Configurações<ph name="SETTINGS_LINK_END" />.</translation> -<translation id="5413640305322530561">Saiba mais sobre dados de uso e diagnóstico.</translation> +<translation id="5413640305322530561">Saiba mais</translation> <translation id="5414198321558177633">Atualizando a lista de perfis. Pode levar alguns minutos..</translation> <translation id="5414566801737831689">Ler os ícones dos websites que você visitar</translation> <translation id="5414836363063783498">Verificando...</translation> @@ -6790,7 +6791,7 @@ <translation id="6234108445915742946">Os Termos de Serviço do Chrome serão atualizados em 31 de março</translation> <translation id="6234474535228214774">Instalação pendente</translation> <translation id="6235208551686043831">A câmera do dispositivo foi ativada. Posicione o QR code do eSIM na frente dela.</translation> -<translation id="6237297174664969437">Nas configurações do Chrome, você pode escolher a qualquer momento quais dados de navegação são sincronizados. Nas <ph name="LINK_BEGIN" />configurações do dispositivo<ph name="LINK_END" />, você pode controlar a sincronização dos apps da Web instalados no navegador Chrome. O Google pode personalizar a Pesquisa e outros serviços com base no seu histórico.</translation> +<translation id="6237297174664969437">Nas configurações do Chrome, você escolhe a qualquer momento quais dados de navegação são sincronizados. Nas <ph name="LINK_BEGIN" />configurações do dispositivo<ph name="LINK_END" />, controle a sincronização dos apps da Web instalados no navegador Chrome. O Google pode personalizar a Pesquisa e outros serviços com base no seu histórico.</translation> <translation id="6237474966939441970">App de anotações com a stylus</translation> <translation id="623755660902014047">Modo de leitura</translation> <translation id="6238767809035845642">Texto compartilhado de outro dispositivo</translation> @@ -7186,6 +7187,7 @@ <translation id="6551508934388063976">Comando não disponível. Pressione "Control-N" para abrir uma nova janela.</translation> <translation id="6551606359270386381">Ferramenta de elipse</translation> <translation id="6551612971599078809">O site está usando um dispositivo USB</translation> +<translation id="6551620030439692385">Bloqueado. O fuso horário está definido como <ph name="TIMEZONE" /> e só pode ser atualizado manualmente.</translation> <translation id="6551739526055143276">Com gerenciamento pelo Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> usuários</translation> <translation id="6555432686520421228">Remover todas as contas de usuário e redefinir seu dispositivo <ph name="IDS_SHORT_PRODUCT_NAME" /> para as condições de fábrica.</translation> @@ -7256,6 +7258,7 @@ <translation id="6608773371844092260">Para configurar a impressão digital, peça para a criança tocar no sensor no lado direito do <ph name="DEVICE_TYPE" />. Os dados de impressão digital dela são armazenados de forma segura e nunca saem do <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Depois que você sair do modo de navegação anônima, os dados de login serão armazenados no dispositivo. Você poderá usar o dispositivo para fazer login nesse site novamente mais tarde.</translation> <translation id="6610002944194042868">Opções de tradução</translation> +<translation id="6610064275805055636">Gerenciar Apps Isolados da Web</translation> <translation id="6611972847767394631">Veja suas guias aqui</translation> <translation id="661266467055912436">Melhora a segurança para você e para todos na Web.</translation> <translation id="6613267708691765962">Procurando malware...</translation> @@ -8298,7 +8301,7 @@ <translation id="7429415133937917139">Simula a saída de uma linha braille atualizável na parte superior da tela do painel do ChromeVox</translation> <translation id="7431719494109538750">Nenhum dispositivo HID encontrado</translation> -<translation id="7431991332293347422">Controla como o histórico de navegação é usado para personalizar a Pesquisa e muito mais</translation> +<translation id="7431991332293347422">Controlar como o histórico de navegação é usado para personalizar a Pesquisa e muito mais</translation> <translation id="7432200167665670017">Seu administrador bloqueou a extensão <ph name="EXTENSION_NAME" />: ID do app <ph name="EXTENSION_ID" /></translation> <translation id="7433708794692032816">Insira o cartão inteligente para continuar usando seu <ph name="DEVICE_TYPE" /></translation> <translation id="7433957986129316853">Manter assim</translation> @@ -8620,6 +8623,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" quer digitalizar usando "<ph name="SCANNER_NAME" />".</translation> <translation id="7672504401554182757">Escolha qual dispositivo tem a senha de acesso para o app <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, neste site: <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Bloqueado. No momento, a programação está definida como <ph name="SUNRISE_TIME" /> às <ph name="SUNSET_TIME" /> e só pode ser atualizada manualmente.</translation> <translation id="7673313156293624327">Registros do ChromeOS Shill (gerenciador de conexões)</translation> <translation id="7674416868315480713">Desativar todas as portas que estão sendo encaminhadas no Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> apps</translation> @@ -8860,8 +8864,8 @@ <translation id="784934925303690534">Período</translation> <translation id="7849656116606005620">Lembrete: a Proteção antirrastreamento está ativada</translation> <translation id="7850717413915978159"><ph name="BEGIN_PARAGRAPH1" />Ao autorizar que seus dispositivos ChromeOS enviem relatórios automáticos, você nos ajuda a priorizar o que precisamos corrigir e melhorar no ChromeOS. Esses relatórios podem incluir informações como falhas do ChromeOS, quais recursos e quanta memória você normalmente usa, e dados de uso e diagnóstico do app Android. Alguns dados agregados também ajudarão apps do Google e nossos parceiros, como os desenvolvedores Android.<ph name="END_PARAGRAPH1" /> - <ph name="BEGIN_PARAGRAPH2" />Você pode ativar ou desativar esses relatórios a qualquer momento nas configurações do dispositivo ChromeOS. Se você é um administrador do domínio, pode mudar essa configuração no Admin Console.<ph name="END_PARAGRAPH2" /> - <ph name="BEGIN_PARAGRAPH3" />Se a configuração "Atividade na Web e de apps" estiver ativada para sua Conta do Google, esses dados do Android vão poder ser salvos na sua Conta do Google. Você pode ver seus dados, excluí-los e mudar as configurações da sua conta em account.google.com.<ph name="END_PARAGRAPH3" /></translation> + <ph name="BEGIN_PARAGRAPH2" />Ative ou desative esses relatórios a qualquer momento nas configurações do dispositivo ChromeOS. Se você é um administrador do domínio, pode mudar essa configuração no Admin Console.<ph name="END_PARAGRAPH2" /> + <ph name="BEGIN_PARAGRAPH3" />Se a configuração "Atividade na Web e de apps" estiver ativada para sua Conta do Google, esses dados do Android serão salvos nela. Veja e exclua seus dados ou mude as configurações da conta em account.google.com.<ph name="END_PARAGRAPH3" /></translation> <translation id="7851021205959621355"><ph name="BEGIN_BOLD" />Observação<ph name="END_BOLD" />: uma voz parecida ou uma gravação pode conseguir acessar seus resultados personalizados ou o Google Assistente. Para economizar bateria, você pode acessar as configurações do Google Assistente e ativar o "Ok Google" apenas quando o dispositivo estiver conectado a uma fonte de energia.</translation> <translation id="7851457902707056880">O login foi restrito somente à conta do proprietário. Reinicie e faça login com a conta do proprietário. A máquina reiniciará automaticamente dentro de 30 segundos.</translation> <translation id="7851716364080026749">Sempre bloquear acesso à câmera e ao microfone</translation> @@ -9553,6 +9557,7 @@ <translation id="8376384591331888629">Incluir também os cookies de terceiros desse site</translation> <translation id="8376451933628734023">Se este app da Web estiver tentando se passar por outro app, desinstale-o.</translation> <translation id="8376532149031784008">Recarregando <ph name="DOMAIN" />…</translation> +<translation id="8376610503048439696">As extensões instaladas pelo administrador ainda podem ler e mudar este site</translation> <translation id="8376752431516546391">Painel lateral da Pesquisa Google</translation> <translation id="8377625247046155446">Esta senha de acesso é salva apenas neste dispositivo. Ela continua neste dispositivo depois que você fecha todas as janelas anônimas.</translation> <translation id="8378714024927312812">Gerenciado pela sua organização</translation> @@ -10425,7 +10430,7 @@ <translation id="9032097289595078011">Desativar "Pareamento rápido"</translation> <translation id="9033765790910064284">Continuar mesmo assim</translation> <translation id="9033857511263905942">&Colar</translation> -<translation id="9034408118624208974">Começou a usar o Chromebook agora? Ative a sincronização para que o backup das suas preferências seja feito.</translation> +<translation id="9034408118624208974">Começou a usar o Chromebook agora? Ative a sincronização para ativar o backup das suas preferências.</translation> <translation id="903480517321259405">Digite o PIN novamente</translation> <translation id="9036484080057916082">Lista de carimbos de data/hora do certificado assinado</translation> <translation id="9037054491984310631">Conectado ao dispositivo Bluetooth chamado <ph name="DEVICE" /></translation> @@ -10468,11 +10473,11 @@ <ph name="BREAK" /> Saiba mais sobre os dados que o Google coleta e por que em <ph name="BEGIN_LINK2" />policies.google.com<ph name="END_LINK2" />.</translation> <translation id="9066782832737749352">Conversão de texto em voz</translation> -<translation id="9068298336633421551">Permitir que apps e serviços do Android com permissão de localização usem o local do dispositivo. O Google pode coletar dados de local periodicamente e os usar de forma anônima para melhorar a precisão de local e os serviços com base em localização.</translation> +<translation id="9068298336633421551">Permita que apps e serviços do Android com permissão de localização usem o local do dispositivo. O Google pode coletar dados de local periodicamente e os usar de forma anônima para melhorar a precisão de local e os serviços com base em localização.</translation> <translation id="9068598199622656904">Pressione uma tecla de cada vez para usar os atalhos do teclado, em vez de as manter pressionadas ao mesmo tempo.</translation> <translation id="9068878141610261315">Tipo de arquivo incompatível</translation> <translation id="9069417381769492963">Nenhum favorito corresponde à sua pesquisa</translation> -<translation id="9069665781180028115">Os itens selecionados ficarão disponíveis neste Chromebook. Se você está começando a usar o Chromebook agora, sincronize todos os itens para que seja feito backup das suas preferências. Faça mudanças a qualquer momento em "Configurações > Contas".</translation> +<translation id="9069665781180028115">Os itens selecionados ficarão disponíveis neste dispositivo. Se você está começando a usar o Chromebook agora, sincronize todos os itens para que suas preferências sejam salvas aqui. Faça mudanças a qualquer momento em "Configurações > Contas".</translation> <translation id="9070231741075992882">As permissões dadas ao app <ph name="APP_NAME" /> também serão concedidas aos apps instalados e transmitidos por ele.</translation> <translation id="9070342919388027491">Guia movida para a esquerda</translation> <translation id="9074739597929991885">Bluetooth</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb index a83fec65..eebd712 100644 --- a/chrome/app/resources/generated_resources_ro.xtb +++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -3294,6 +3294,7 @@ <translation id="3497560059572256875">Trimite doodle-ul</translation> <translation id="3497915391670770295">Trimite pe &dispozitivele tale</translation> <translation id="3500417806337761827">Eroare la montarea dispozitivului de stocare în rețea. Au fost conectate deja prea multe dispozitive de stocare în rețea SMB.</translation> +<translation id="3500764001796099683">Activează aplicațiile web izolate</translation> <translation id="350397915809787283">Dacă nu ai un cont, selectează prima opțiune pentru a crea unul.</translation> <translation id="3503995387997205657">Poți restabili aplicațiile anterioare</translation> <translation id="3505100368357440862">Sugestii pentru cumpărături</translation> @@ -7169,6 +7170,7 @@ <translation id="6551508934388063976">Comanda nu este disponibilă. Pentru a deschide o fereastră nouă, apăsați pe Ctrl+N.</translation> <translation id="6551606359270386381">Instrument pentru elipsă</translation> <translation id="6551612971599078809">Site-ul folosește USB</translation> +<translation id="6551620030439692385">Blocat. Fusul orar este setat la <ph name="TIMEZONE" /> și poate fi actualizat numai manual.</translation> <translation id="6551739526055143276">Gestionate prin Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> (de) utilizatori</translation> <translation id="6555432686520421228">Eliminați toate conturile de utilizator și resetați gadgetul <ph name="IDS_SHORT_PRODUCT_NAME" /> la valorile din fabrică.</translation> @@ -7239,6 +7241,7 @@ <translation id="6608773371844092260">Pentru a configura amprenta, solicită-i copilului tău să atingă senzorul de amprentă în partea dreaptă a acestui <ph name="DEVICE_TYPE" />. Datele privind amprentele copilului sunt stocate în siguranță și nu părăsesc niciodată dispozitivul <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Datele de conectare vor fi stocate pe acest dispozitiv după ce ieși din modul incognito. Vei putea să te reconectezi la site folosind dispozitivul.</translation> <translation id="6610002944194042868">Opțiuni de traducere</translation> +<translation id="6610064275805055636">Gestionează aplicațiile web izolate</translation> <translation id="6611972847767394631">Regăsește filele aici</translation> <translation id="661266467055912436">Îmbunătățește securitatea pe web pentru tine și toți ceilalți.</translation> <translation id="6613267708691765962">Se caută programe malware...</translation> @@ -8603,6 +8606,7 @@ <translation id="7671472752213333268"><ph name="EXTENSION_NAME" /> solicită permisiunea să scaneze de la <ph name="SCANNER_NAME" />.</translation> <translation id="7672504401554182757">Alege dispozitivul care are cheia de acces pentru <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, în <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blocat. Programul este setat la <ph name="SUNRISE_TIME" /> – <ph name="SUNSET_TIME" /> și poate fi actualizat numai manual.</translation> <translation id="7673313156293624327">Jurnale Shill (Connection Manager) din ChromeOS</translation> <translation id="7674416868315480713">Dezactivează toate porturile care se redirecționează în Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> aplicații</translation> @@ -9536,6 +9540,7 @@ <translation id="8376384591331888629">Inclusiv cookie-urile terță parte de pe acest site</translation> <translation id="8376451933628734023">Dacă aplicația web încearcă să te facă să crezi că este o altă aplicație, dezinstaleaz-o.</translation> <translation id="8376532149031784008">Se reîncarcă <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Extensiile instalate de administrator pot în continuare să citească și să modifice acest site</translation> <translation id="8376752431516546391">Panoul lateral Căutare Google</translation> <translation id="8377625247046155446">Cheia de acces va fi salvată numai pe acest dispozitiv. Va rămâne pe acest dispozitiv după ce închizi toate ferestrele incognito.</translation> <translation id="8378714024927312812">Gestionat de organizația ta</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb index 59a788a9..4a0a059 100644 --- a/chrome/app/resources/generated_resources_ru.xtb +++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -1626,7 +1626,7 @@ <translation id="2204387456724731099">Не удалось перевести выбранный текст</translation> <translation id="2207116775853792104">Оставить расширение</translation> <translation id="2210462644007531147">Установка не выполнена</translation> -<translation id="2211245494465528624">Настроить синхронизацию</translation> +<translation id="2211245494465528624">Настройка синхронизации</translation> <translation id="2214018885812055163">Общие папки</translation> <translation id="2214884991347062907">Неверный пароль. Повторите попытку.</translation> <translation id="2214893006758804920">{LINE_COUNT,plural, =1{<1 строка скрыта>}one{<<ph name="NUMBER_OF_LINES" /> строка скрыта>}few{<<ph name="NUMBER_OF_LINES" /> строки скрыто>}many{<<ph name="NUMBER_OF_LINES" /> строк скрыто>}other{<<ph name="NUMBER_OF_LINES" /> строки скрыто>}}</translation> @@ -3743,7 +3743,7 @@ <translation id="3826440694796503677">Администратор запретил добавлять другие аккаунты Google.</translation> <translation id="3827774300009121996">Полноэкранный режим</translation> <translation id="3828029223314399057">Искать в закладках</translation> -<translation id="3828953470056652895">Я принимаю <ph name="BEGIN_LINK1" />Условия использования Google<ph name="END_LINK1" />, <ph name="BEGIN_LINK2" />Дополнительные условия использования Chrome и Chrome OS<ph name="END_LINK2" /> и <ph name="BEGIN_LINK3" />Условия использования Google Play<ph name="END_LINK3" /></translation> +<translation id="3828953470056652895">Я принимаю <ph name="BEGIN_LINK1" />Условия использования Google<ph name="END_LINK1" />, <ph name="BEGIN_LINK2" />Дополнительные условия использования Chrome и ChromeOS<ph name="END_LINK2" /> и <ph name="BEGIN_LINK3" />Условия использования Google Play<ph name="END_LINK3" /></translation> <translation id="3829530269338026191">Вкладка "<ph name="WINDOW_TITLE" />" использует много памяти: <ph name="MEMORY_VALUE" /></translation> <translation id="3829765597456725595">Общая папка SMB</translation> <translation id="3830470485672984938">Использовать другой ключ доступа</translation> @@ -9244,7 +9244,7 @@ <translation id="8146177459103116374">Вы уже зарегистрированы на этом устройстве и можете <ph name="LINK2_START" />войти, используя свои регистрационные данные<ph name="LINK2_END" />.</translation> <translation id="8146287226035613638">Добавьте и упорядочьте предпочтительные языки. Сайты будут по возможности показываться на них. Эти настройки синхронизированы с настройками браузера. <ph name="BEGIN_LINK_LEARN_MORE" />Подробнее…<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="8146793085009540321">Не удалось выполнить вход. Обратитесь к системному администратору или повторите попытку.</translation> -<translation id="8147346945017130012">Помогите нам повышать производительность и совершенствовать функции Chrome и Chrome OS, разрешив автоматическую отправку в Google отчетов о сбоях и информации об использовании и диагностике.</translation> +<translation id="8147346945017130012">Помогите нам повышать производительность и совершенствовать функции Chrome и ChromeOS, разрешив автоматическую отправку в Google отчетов о сбоях и информации об использовании и диагностике.</translation> <translation id="8147900440966275470">Найдена <ph name="NUM" /> вкладка</translation> <translation id="814870937590541483">Другие действия с файлами на Google Диске</translation> <translation id="8148760431881541277">Ограничение на вход</translation>
diff --git a/chrome/app/resources/generated_resources_si.xtb b/chrome/app/resources/generated_resources_si.xtb index 30210f9..daec421 100644 --- a/chrome/app/resources/generated_resources_si.xtb +++ b/chrome/app/resources/generated_resources_si.xtb
@@ -3297,6 +3297,7 @@ <translation id="3497560059572256875">Doodle බෙදා ගන්න</translation> <translation id="3497915391670770295">ඔබේ උපාංග වෙත යවන්න</translation> <translation id="3500417806337761827">පංගුව නැංවීමේ දෝෂය. දැනටමත් නංවා ඇත SMB පංගු සංඛ්යාව ඉතා වැඩියි.</translation> +<translation id="3500764001796099683">එකලා වෙබ් යෙදුම් සබල කරන්න</translation> <translation id="350397915809787283">ඔබට ගිණුමක් නොමැති නම්, එකක් තැනීම සඳහා පළමු විකල්පය තෝරන්න.</translation> <translation id="3503995387997205657">ඔබට ඔබගේ පෙර යෙදුම ප්රතිසාධනය කළ හැකිය</translation> <translation id="3505100368357440862">සාප්පු සවාරි යෝජනා</translation> @@ -7172,6 +7173,7 @@ <translation id="6551508934388063976">විධන නොමැත. නව කවුළුවක් විවෘත කිරීමට control-N ඔබන්න.</translation> <translation id="6551606359270386381">ඉලිප්ස මෙවලම</translation> <translation id="6551612971599078809">වෙබ් අඩවිය USB භාවිත කරයි</translation> +<translation id="6551620030439692385">අවහිර කර ඇත වේලා කලාපය දැනට <ph name="TIMEZONE" /> වෙත සකසා ඇති අතර එය යාවත්කාලීන කළ හැක්කේ හස්තීයව පමණි.</translation> <translation id="6551739526055143276">Family Link මගින් කළමනාකරණය කෙරේ</translation> <translation id="655384502888039633">පරිශීලකයන් <ph name="USER_COUNT" /> ක්</translation> <translation id="6555432686520421228">සියලු පරිශීලක ගිණුම් ඉවත් කර ඔබේ උපාංගය නව උපාංගයක් සේ පත්කිරීමට ඔබේ <ph name="IDS_SHORT_PRODUCT_NAME" /> නැවත සකසන්න.</translation> @@ -7242,6 +7244,7 @@ <translation id="6608773371844092260">ඇඟිලි සලකුණ පිහිටුවීම සඳහා, ඔබේ දරුවාට මෙම <ph name="DEVICE_TYPE" /> හි දකුණු පස ඇති ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කිරීමට සලස්වන්න. ඔබේ දරුවාගේ ඇඟිලි සලකුණු දත්ත ආරක්ෂිතව ගබඩා කෙරෙන අතර කිසි විටක ඔබේ <ph name="DEVICE_TYPE" /> හැර නොයයි.</translation> <translation id="6609478180749378879">ඔබ අප්රසිද්ධ ප්රකාරයෙන් පිට වූ පසු පුරන දත්ත මෙම උපාංගය තුළ ගබඩා කරනු ඇත. ඔබට ඔබගේ උපාංගය සමඟ නැවත මෙම වෙබ් අඩවියට පිරීමට හැකි වනු ඇත.</translation> <translation id="6610002944194042868">පරිවර්තන විකල්ප</translation> +<translation id="6610064275805055636">එකලා වෙබ් යෙදුම් කළමනා කරන්න</translation> <translation id="6611972847767394631">ඔබගේ පටිති මෙහි සොයන්න</translation> <translation id="661266467055912436">ඔබේ සහ වෙබය මත සියලු දෙනාගේම ආරක්ෂාව වැඩිදියුණු කරයි.</translation> <translation id="6613267708691765962">අනිෂ්ට මෘදුකාංග සඳහා ස්කෑන් කරමින්...</translation> @@ -8605,6 +8608,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" හට "<ph name="SCANNER_NAME" />" වෙතින් ස්කෑන් කිරීමට අවශ්යයි.</translation> <translation id="7672504401554182757"><ph name="APP_NAME" /> සඳහා මුරයතුර ඇත්තේ කුමන උපාංගයට ද යන්න තෝරා ගන්න</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> තුළ.</translation> +<translation id="7672726198839739113">අවහිර කර ඇත කාලසටහන දැනට <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> ලෙස සකසා ඇති අතර යාවත්කාලීන කළ හැක්කේ හස්තීයව පමණි.</translation> <translation id="7673313156293624327">ChromeOS Shill (සම්බන්ධතා කළමනාකරු) ලොග</translation> <translation id="7674416868315480713">ලිනක්ස් තුළ යොමු කෙරෙන සියලුම තොටවල් ක්රියා විරහිත කරන්න</translation> <translation id="7674537509496907005">යෙදුම් <ph name="APP_COUNT" /></translation> @@ -9536,6 +9540,7 @@ <translation id="8376384591331888629">මෙම අඩවියෙහි තෙවන පාර්ශ්ව කුකි ඇතුළුව</translation> <translation id="8376451933628734023">මෙම වෙබ් යෙදුම එය වෙනත් යෙදුමක් යැයි සිතීමට ඔබව රැවටීමට උත්සාහ කරන්නේ නම්, එය අස්ථාපනය කරන්න.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> නැවත පූරණය වේ...</translation> +<translation id="8376610503048439696">ඔබේ පරිපාලක විසින් ස්ථාපනය කරන ලද දිගුවලට තවමත් මෙම වෙබ් අඩවිය කියවා වෙනස් කළ හැක</translation> <translation id="8376752431516546391">Google සෙවීම් පැති පැනලය</translation> <translation id="8377625247046155446">මෙම මුරයතුර මෙම උපාංගයේ පමණක් සුරැකෙනු ඇත. ඔබ සියලු අප්රකට කවුළු වැසූ පසු එය මෙම උපාංගයේ පවතිනු ඇත.</translation> <translation id="8378714024927312812">ඔබේ ආයතනය විසින් කළමනා කෙරේ</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb index 3a4f1907..b5d6be2 100644 --- a/chrome/app/resources/generated_resources_sl.xtb +++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -3311,6 +3311,7 @@ <translation id="3497560059572256875">Deli priložnostni logotip z drugimi</translation> <translation id="3497915391670770295">Pošlji v &naprave</translation> <translation id="3500417806337761827">Napaka pri vpenjanju deljenja. Vpetih je preveč deljenj SMB.</translation> +<translation id="3500764001796099683">Omogočanje izoliranih spletnih aplikacij</translation> <translation id="350397915809787283">Če nimate računa, izberite prvo možnost, da ga ustvarite.</translation> <translation id="3503995387997205657">Obnovite lahko prejšnje aplikacije.</translation> <translation id="3505100368357440862">Predlogi za nakupovanje</translation> @@ -7189,6 +7190,7 @@ <translation id="6551508934388063976">Ukaz ni na voljo. Odprite novo okno s pritiskom tipk CTRL + N.</translation> <translation id="6551606359270386381">Orodje za elipse</translation> <translation id="6551612971599078809">Spletno mesto uporablja USB</translation> +<translation id="6551620030439692385">Blokirano. Časovni pas je trenutno nastavljen na <ph name="TIMEZONE" /> in ga je mogoče posodobiti samo ročno.</translation> <translation id="6551739526055143276">Upravljan s storitvijo Family Link</translation> <translation id="655384502888039633">št. uporabnikov: <ph name="USER_COUNT" /></translation> <translation id="6555432686520421228">Odstrani vse uporabniške račune in ponastavi napravo <ph name="IDS_SHORT_PRODUCT_NAME" /> na nastavitve kot pri novi.</translation> @@ -7263,6 +7265,7 @@ <translation id="6608773371844092260">Če želite nastaviti prstni odtis, naj se otrok dotakne tipala prstnih odtisov na desni strani te naprave <ph name="DEVICE_TYPE" />. Podatki o prstnih odtisih otroka so varno shranjeni in nikoli ne zapustijo naprave <ph name="DEVICE_TYPE" />.</translation> <translation id="6609478180749378879">Podatki za prijavo se bodo shranili v tej napravi, ko zaprete anonimni način. Pozneje se boste lahko z napravo znova prijavili v to spletno mesto.</translation> <translation id="6610002944194042868">Možnosti prevajanja</translation> +<translation id="6610064275805055636">Upravljanje izoliranih spletnih aplikacij</translation> <translation id="6611972847767394631">Poiščite svoje zavihke tukaj</translation> <translation id="661266467055912436">Izboljšuje varnost za vas in vse druge v spletu.</translation> <translation id="6613267708691765962">Iskanje zlonamerne programske opreme …</translation> @@ -8627,6 +8630,7 @@ <translation id="7671472752213333268">»<ph name="EXTENSION_NAME" />« želi iskati iz optičnega bralnika »<ph name="SCANNER_NAME" />«.</translation> <translation id="7672504401554182757">Izberite, katera naprava ima ključ za dostop za aplikacijo <ph name="APP_NAME" />.</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, na strani storitve <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blokirano. Razpored je trenutno nastavljen na <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" /> in ga je mogoče posodobiti samo ročno.</translation> <translation id="7673313156293624327">Dnevniki orodja Shill (upravitelj povezav) za ChromeOS</translation> <translation id="7674416868315480713">Onemogoči vsa vrata, posredovana v Linux</translation> <translation id="7674537509496907005">Št. aplikacij: <ph name="APP_COUNT" /></translation> @@ -9560,6 +9564,7 @@ <translation id="8376384591331888629">Vključno s piškotki drugih mest na tem spletnem mestu</translation> <translation id="8376451933628734023">Če vas ta spletni program poskuša zavesti, da gre za drug program, ga odmestite.</translation> <translation id="8376532149031784008">Vnovično nalaganje domene <ph name="DOMAIN" /> …</translation> +<translation id="8376610503048439696">Razširitve, ki jih namesti skrbnik, lahko še vedno berejo in spreminjajo to spletno mesto</translation> <translation id="8376752431516546391">Stransko podokno Iskanja Google</translation> <translation id="8377625247046155446">Ta ključ za dostop bo shranjen samo v tej napravi. V tej napravi bo ostal, ko zaprete vsa anonimna okna.</translation> <translation id="8378714024927312812">Upravlja vaša organizacija</translation>
diff --git a/chrome/app/resources/generated_resources_sq.xtb b/chrome/app/resources/generated_resources_sq.xtb index 0f39de14..93c16f1b 100644 --- a/chrome/app/resources/generated_resources_sq.xtb +++ b/chrome/app/resources/generated_resources_sq.xtb
@@ -7049,7 +7049,7 @@ <translation id="6459799433792303855">Dritarja aktive u zhvendos në një ekran tjetër.</translation> <translation id="6460601847208524483">Gjej tjetrin</translation> <translation id="6461170143930046705">Po kërkon për rrjete...</translation> -<translation id="6463596731306859179">Po merr dritare kërcyese të padëshiruara ose sjellje të tjera të papritura? Ndonjëherë, aplikacionet dhe shtesat që instalon mund të ndryshojnë cilësimet e ChromeOS pa të informuar.</translation> +<translation id="6463596731306859179">Po merr dritare kërcyese të padëshiruara ose sjellje të tjera të papritura? Ndonjëherë, aplikacionet dhe shtesat që instalon mund të ndryshojnë cilësimet e ChromeOS pa të të informuar.</translation> <translation id="6463795194797719782">&Redakto</translation> <translation id="6464825623202322042">Kjo pajisje</translation> <translation id="6465841119675156448">Pa internet</translation>
diff --git a/chrome/app/resources/generated_resources_sr-Latn.xtb b/chrome/app/resources/generated_resources_sr-Latn.xtb index 352bb2cf..7bc59f8 100644 --- a/chrome/app/resources/generated_resources_sr-Latn.xtb +++ b/chrome/app/resources/generated_resources_sr-Latn.xtb
@@ -3291,6 +3291,7 @@ <translation id="3497560059572256875">Deli dudl logotip</translation> <translation id="3497915391670770295">Pošalji na uređaje</translation> <translation id="3500417806337761827">Greška pri instalaciji deljene stavke. Previše SMB deljenih stavki je već instalirano.</translation> +<translation id="3500764001796099683">Omogući izolovane veb-aplikacije</translation> <translation id="350397915809787283">Ako nemate nalog, izaberite prvu opciju da biste ga otvorili.</translation> <translation id="3503995387997205657">Možete da vratite prethodne aplikacije</translation> <translation id="3505100368357440862">Predlozi za kupovinu</translation> @@ -7166,6 +7167,7 @@ <translation id="6551508934388063976">Komanda nije dostupna. Pritisnite control-N da biste otvorili novi prozor.</translation> <translation id="6551606359270386381">Alatka za elipse</translation> <translation id="6551612971599078809">Sajt koristi USB</translation> +<translation id="6551620030439692385">Blokirano. Vremenska zona je trenutno podešena na <ph name="TIMEZONE" /> i može da se ažurira samo ručno.</translation> <translation id="6551739526055143276">Nalogom upravlja Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> korisnika</translation> <translation id="6555432686520421228">Uklonite sve korisničke naloge i restartujte <ph name="IDS_SHORT_PRODUCT_NAME" /> uređaj da bi bio kao nov.</translation> @@ -7238,6 +7240,7 @@ <translation id="6608773371844092260">Da biste podesili otisak prsta, neka dete dodirne senzor za otisak prsta u gornjem desnom uglu ovog <ph name="DEVICE_TYPE" /> uređaja. Podaci o otisku prsta deteta se bezbedno čuvaju na ovom <ph name="DEVICE_TYPE" /> uređaju i uvek ostaju na njemu.</translation> <translation id="6609478180749378879">Podaci o prijavljivanju se čuvaju na ovom uređaju kada izađete iz režima bez arhiviranja. Kasnije ćete moći da se ponovo prijavite na ovaj veb-sajt pomoću svog uređaja.</translation> <translation id="6610002944194042868">Opcije prevoda</translation> +<translation id="6610064275805055636">Upravljajte izolovanim veb-aplikacijama</translation> <translation id="6611972847767394631">Pronađite kartice ovde</translation> <translation id="661266467055912436">Poboljšava bezbednost za vas i druge na vebu.</translation> <translation id="6613267708691765962">Traži se malver...</translation> @@ -8602,6 +8605,7 @@ <translation id="7671472752213333268"><ph name="EXTENSION_NAME" /> želi da skenira sa uređaja <ph name="SCANNER_NAME" />.</translation> <translation id="7672504401554182757">Odaberite koji uređaj ima pristupni kôd za aplikaciju <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, na stranici <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Blokirano. Raspored je trenutno podešen na <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" /> i može da se ažurira samo ručno.</translation> <translation id="7673313156293624327">Evidencije ChromeOS Shill-a (menadžer veze)</translation> <translation id="7674416868315480713">Deaktiviraj sve portove koji se prosleđuju u Linux-u</translation> <translation id="7674537509496907005">Aplikacija: <ph name="APP_COUNT" /></translation> @@ -9535,6 +9539,7 @@ <translation id="8376384591331888629">Uključujući kolačiće trećih strana na ovom sajtu</translation> <translation id="8376451933628734023">Ako ova veb-aplikacija pokušava da vas prevari da je neka druga aplikacija, deinstalirajte je.</translation> <translation id="8376532149031784008">Ponovo se učitava <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Dodaci koje je instalirao administrator i dalje mogu da čitaju i menjaju ovaj sajt</translation> <translation id="8376752431516546391">Bočna tabla Google pretrage</translation> <translation id="8377625247046155446">Ovaj pristupni kôd će se sačuvati samo na ovom uređaju. On će ostati na ovom uređaju kada zatvorite sve prozore bez arhiviranja.</translation> <translation id="8378714024927312812">Ovim upravlja organizacija</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb index bbc0c37..aae90e96 100644 --- a/chrome/app/resources/generated_resources_sr.xtb +++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -3291,6 +3291,7 @@ <translation id="3497560059572256875">Дели дудл логотип</translation> <translation id="3497915391670770295">Пошаљи на уређаје</translation> <translation id="3500417806337761827">Грешка при инсталацији дељене ставке. Превише SMB дељених ставки је већ инсталирано.</translation> +<translation id="3500764001796099683">Омогући изоловане веб-апликације</translation> <translation id="350397915809787283">Ако немате налог, изаберите прву опцију да бисте га отворили.</translation> <translation id="3503995387997205657">Можете да вратите претходне апликације</translation> <translation id="3505100368357440862">Предлози за куповину</translation> @@ -7166,6 +7167,7 @@ <translation id="6551508934388063976">Команда није доступна. Притисните control-N да бисте отворили нови прозор.</translation> <translation id="6551606359270386381">Алатка за елипсе</translation> <translation id="6551612971599078809">Сајт користи USB</translation> +<translation id="6551620030439692385">Блокирано. Временска зона је тренутно подешена на <ph name="TIMEZONE" /> и може да се ажурира само ручно.</translation> <translation id="6551739526055143276">Налогом управља Family Link</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> корисника</translation> <translation id="6555432686520421228">Уклоните све корисничке налоге и рестартујте <ph name="IDS_SHORT_PRODUCT_NAME" /> уређај да би био као нов.</translation> @@ -7238,6 +7240,7 @@ <translation id="6608773371844092260">Да бисте подесили отисак прста, нека дете додирне сензор за отисак прста у горњем десном углу овог <ph name="DEVICE_TYPE" /> уређаја. Подаци о отиску прста детета се безбедно чувају на овом <ph name="DEVICE_TYPE" /> уређају и увек остају на њему.</translation> <translation id="6609478180749378879">Подаци о пријављивању се чувају на овом уређају када изађете из режима без архивирања. Касније ћете моћи да се поново пријавите на овај веб-сајт помоћу свог уређаја.</translation> <translation id="6610002944194042868">Опције превода</translation> +<translation id="6610064275805055636">Управљајте изолованим веб-апликацијама</translation> <translation id="6611972847767394631">Пронађите картице овде</translation> <translation id="661266467055912436">Побољшава безбедност за вас и друге на вебу.</translation> <translation id="6613267708691765962">Тражи се малвер...</translation> @@ -8602,6 +8605,7 @@ <translation id="7671472752213333268"><ph name="EXTENSION_NAME" /> жели да скенира са уређаја <ph name="SCANNER_NAME" />.</translation> <translation id="7672504401554182757">Одаберите који уређај има приступни кôд за апликацију <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, на страници <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Блокирано. Распоред је тренутно подешен на <ph name="SUNRISE_TIME" />–<ph name="SUNSET_TIME" /> и може да се ажурира само ручно.</translation> <translation id="7673313156293624327">Евиденције ChromeOS Shill-а (менаџер везе)</translation> <translation id="7674416868315480713">Деактивирај све портове који се прослеђују у Linux-у</translation> <translation id="7674537509496907005">Апликација: <ph name="APP_COUNT" /></translation> @@ -9535,6 +9539,7 @@ <translation id="8376384591331888629">Укључујући колачиће трећих страна на овом сајту</translation> <translation id="8376451933628734023">Ако ова веб-апликација покушава да вас превари да је нека друга апликација, деинсталирајте је.</translation> <translation id="8376532149031784008">Поново се учитава <ph name="DOMAIN" />...</translation> +<translation id="8376610503048439696">Додаци које је инсталирао администратор и даље могу да читају и мењају овај сајт</translation> <translation id="8376752431516546391">Бочна табла Google претраге</translation> <translation id="8377625247046155446">Овај приступни кôд ће се сачувати само на овом уређају. Он ће остати на овом уређају када затворите све прозоре без архивирања.</translation> <translation id="8378714024927312812">Овим управља организација</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb index cff9b5d0..45d6bca1 100644 --- a/chrome/app/resources/generated_resources_sv.xtb +++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -5734,7 +5734,7 @@ <translation id="5411856344659127989">Om du vill lägga till ett konto åt någon annan <ph name="LINK_BEGIN" />lägger du till en ny person<ph name="LINK_END" /> på <ph name="DEVICE_TYPE" />. Behörigheter som du redan har gett webbplatser och appar kan gälla för det här kontot. Du kan hantera dina Google-konton i <ph name="SETTINGS_LINK_BEGIN" />inställningarna<ph name="SETTINGS_LINK_END" />.</translation> -<translation id="5413640305322530561">Läs mer om diagnostik och data om användning</translation> +<translation id="5413640305322530561">Läs mer om diagnostik- och användningsdata</translation> <translation id="5414198321558177633">Uppdaterar listan över profiler. Det kan ta några minuter.</translation> <translation id="5414566801737831689">Läsa in ikonerna för de webbplatser du besöker</translation> <translation id="5414836363063783498">Verifierar ...</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb index ed601c1..2669dfb 100644 --- a/chrome/app/resources/generated_resources_te.xtb +++ b/chrome/app/resources/generated_resources_te.xtb
@@ -1730,6 +1730,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{అన్నింటినీ కొత్త ట్యాబ్ గ్రూప్లో తెరవండి}=1{కొత్త ట్యాబ్ గ్రూప్లో తెరవండి}other{అన్నింటినీ ({COUNT}) కొత్త ట్యాబ్ గ్రూప్లో తెరవండి}}</translation> <translation id="2285942871162473373">మీ వేలిముద్రను గుర్తించలేకపోయాము. మళ్లీ ట్రై చేయండి.</translation> <translation id="2287617382468007324">ప్రింటింగ్ IPP అడ్రస్</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{మీ డేటాను సురక్షితంగా ఉంచడానికి, ఇటీవల మీరు ఉపయోగించని సైట్ నుండి అనుమతులు తీసివేయబడ్డాయి}other{మీ డేటాను సురక్షితంగా ఉంచడానికి, ఇటీవల మీరు ఉపయోగించని సైట్ల నుండి అనుమతులు తీసివేయబడ్డాయి}}</translation> <translation id="2287944065963043964">లాగిన్ స్క్రీన్</translation> <translation id="2290615375132886363">టాబ్లెట్ నావిగేషన్ బటన్లు</translation> <translation id="2291452790265535215">బుక్మార్క్లు, బ్రౌజింగ్ జర్నీ, ఇంకా మరిన్నింటి కోసం సైడ్ ప్యానెల్ను ఉపయోగించడానికి ట్రై చేయండి</translation> @@ -4315,6 +4316,7 @@ <translation id="4275788652681621337">సైడ్ ప్యానెల్ను మూసివేయండి</translation> <translation id="4275830172053184480">మీ పరికరాన్ని పునఃప్రారంభించండి</translation> <translation id="4277434192562187284">XML కాన్ఫిగరేషన్ సోర్స్</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{1 సైట్ నుండి అనుమతులు తీసివేయబడ్డాయి}other{{NUM_SITES} సైట్ల నుండి అనుమతులు తీసివేయబడ్డాయి}}</translation> <translation id="4278390842282768270">అనుమతించబడింది</translation> <translation id="4278498748067682896">మీరు కియోస్క్ & సంకేత చిహ్నాల అప్గ్రేడ్ను ఉపయోగిస్తారు, ఇది పరికరాన్ని కియోస్క్ లేదా సంకేత చిహ్నాల మోడ్లో మాత్రమే రన్ అయ్యేలా చేస్తుంది. యూజర్లు పరికరంలోకి సైన్ ఇన్ చేసే వీలును మీరు కల్పించాలనుకుంటే, దయచేసి వెనుకకు వెళ్లి, Chrome Enterpirse అప్గ్రేడ్ను ఉపయోగించి ఎన్రోల్ అవ్వండి.</translation> <translation id="4278779213160967034">ఈ ప్రాసెస్కు కొన్ని నిమిషాలు పట్టవచ్చు. ఫైల్స్ను డౌన్లోడ్ చేస్తోంది.</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb index a020e38..1100a16 100644 --- a/chrome/app/resources/generated_resources_th.xtb +++ b/chrome/app/resources/generated_resources_th.xtb
@@ -1717,6 +1717,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{เปิดทั้งหมดในกลุ่มแท็บใหม่}=1{เปิดในกลุ่มแท็บใหม่}other{เปิดทั้งหมด ({COUNT}) ในกลุ่มแท็บใหม่}}</translation> <translation id="2285942871162473373">จำลายนิ้วมือไม่ได้ โปรดลองอีกครั้ง</translation> <translation id="2287617382468007324">ที่อยู่ IPP ของการพิมพ์</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{ระบบได้นำสิทธิ์ออกจากเว็บไซต์ที่คุณไม่ได้เข้าชมเมื่อเร็วๆ นี้เพื่อปกป้องข้อมูลของคุณ}other{ระบบได้นำสิทธิ์ออกจากเว็บไซต์ที่คุณไม่ได้เข้าชมเมื่อเร็วๆ นี้เพื่อปกป้องข้อมูลของคุณ}}</translation> <translation id="2287944065963043964">หน้าจอการเข้าสู่ระบบ</translation> <translation id="2290615375132886363">ปุ่มนำทางในแท็บเล็ต</translation> <translation id="2291452790265535215">ลองใช้แผงด้านข้างสําหรับบุ๊กมาร์ก เส้นทางการท่องเว็บ และอื่นๆ</translation> @@ -3293,6 +3294,7 @@ <translation id="3497560059572256875">แชร์ Doodle</translation> <translation id="3497915391670770295">ส่งไปยังอุปกรณ์ของคุณ</translation> <translation id="3500417806337761827">เกิดข้อผิดพลาดในการต่อเชื่อมการแชร์ มีการต่อเชื่อม SMB เป็นจำนวนมากอยู่แล้ว</translation> +<translation id="3500764001796099683">เปิดใช้ Isolated Web App</translation> <translation id="350397915809787283">หากคุณไม่มีบัญชี ให้เลือกตัวเลือกแรกเพื่อสร้างบัญชี</translation> <translation id="3503995387997205657">คุณสามารถคืนค่าแอปก่อนหน้าได้</translation> <translation id="3505100368357440862">คำแนะนำการเลือกซื้อ</translation> @@ -4301,6 +4303,7 @@ <translation id="4275788652681621337">ปิดแผงด้านข้าง</translation> <translation id="4275830172053184480">รีสตาร์ทอุปกรณ์ของคุณ</translation> <translation id="4277434192562187284">แหล่งที่มาของการกำหนดค่า XML</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{นำสิทธิ์ออกจากเว็บไซต์แล้ว 1 รายการ}other{นำสิทธิ์ออกจากเว็บไซต์แล้ว {NUM_SITES} รายการ}}</translation> <translation id="4278390842282768270">อนุญาตแล้ว</translation> <translation id="4278498748067682896">คุณจะใช้ Kiosk & Signage Upgrade ซึ่งอนุญาตให้อุปกรณ์ทำงานในโหมดคีออสก์หรือป้ายเท่านั้น หากต้องการให้ผู้ใช้ลงชื่อเข้าใช้อุปกรณ์ โปรดย้อนกลับแล้วลงทะเบียนด้วย Chrome Enterprise Upgrade</translation> <translation id="4278779213160967034">ขั้นตอนนี้อาจใช้เวลาสักครู่ กำลังดาวน์โหลดไฟล์</translation> @@ -7165,6 +7168,7 @@ <translation id="6551508934388063976">คำสั่งไม่สามารถใช้งานได้ กด Control-N เพื่อเปิดหน้าต่างใหม่</translation> <translation id="6551606359270386381">เครื่องมือวงรี</translation> <translation id="6551612971599078809">เว็บไซต์กำลังใช้ USB</translation> +<translation id="6551620030439692385">ถูกบล็อก ปัจจุบันเขตเวลาตั้งค่าเป็น <ph name="TIMEZONE" /> และสามารถอัปเดตได้ด้วยตัวเองเท่านั้น</translation> <translation id="6551739526055143276">จัดการโดย Family Link</translation> <translation id="655384502888039633">ผู้ใช้ <ph name="USER_COUNT" /> คน</translation> <translation id="6555432686520421228">ลบบัญชีผู้ใช้ทั้งหมดและรีเซ็ตอุปกรณ์ <ph name="IDS_SHORT_PRODUCT_NAME" /> ของคุณให้เหมือนใหม่</translation> @@ -7233,6 +7237,7 @@ <translation id="6608773371844092260">หากต้องการตั้งค่าลายนิ้วมือ ให้บุตรหลานแตะเซ็นเซอร์ลายนิ้วมือที่ด้านขวาของ <ph name="DEVICE_TYPE" /> เครื่องนี้ ข้อมูลลายนิ้วมือของบุตรหลานจะจัดเก็บไว้อย่างปลอดภัยและอยู่ใน <ph name="DEVICE_TYPE" /> เครื่องนี้เสมอ</translation> <translation id="6609478180749378879">ข้อมูลการลงชื่อเข้าใช้จะจัดเก็บอยู่ในอุปกรณ์นี้หลังจากออกจากโหมดไม่ระบุตัวตน โดยจะลงชื่อเข้าใช้เว็บไซต์นี้ด้วยอุปกรณ์ของคุณอีกครั้งในภายหลังได้</translation> <translation id="6610002944194042868">ตัวเลือกการแปลภาษา</translation> +<translation id="6610064275805055636">จัดการ Isolated Web App</translation> <translation id="6611972847767394631">ค้นหาแท็บของคุณที่นี่</translation> <translation id="661266467055912436">ปรับปรุงความปลอดภัยให้คุณและทุกคนที่ใช้อินเทอร์เน็ต</translation> <translation id="6613267708691765962">กำลังสแกนหามัลแวร์...</translation> @@ -8596,6 +8601,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" ต้องการสแกนจาก "<ph name="SCANNER_NAME" />"</translation> <translation id="7672504401554182757">เลือกอุปกรณ์ที่มีพาสคีย์สําหรับ "<ph name="APP_NAME" />"</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> ใน <ph name="PAGE_TITLE" /></translation> +<translation id="7672726198839739113">ถูกบล็อก ปัจจุบันกำหนดเวลาตั้งค่าเป็น <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> และสามารถอัปเดตได้ด้วยตัวเองเท่านั้น</translation> <translation id="7673313156293624327">บันทึก ChromeOS Shill (โปรแกรมจัดการการเชื่อมต่อ)</translation> <translation id="7674416868315480713">ปิดใช้งานทุกพอร์ตที่กำลังส่งต่อใน Linux</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> แอป</translation> @@ -9529,6 +9535,7 @@ <translation id="8376384591331888629">รวมคุกกี้ของบุคคลที่สามในเว็บไซต์นี้</translation> <translation id="8376451933628734023">โปรดถอนการติดตั้งหากเว็บแอปนี้พยายามหลอกล่อคุณให้คิดว่าเป็นแอปอื่น</translation> <translation id="8376532149031784008">กำลังโหลด <ph name="DOMAIN" /> ซ้ำ...</translation> +<translation id="8376610503048439696">ส่วนขยายที่ติดตั้งโดยผู้ดูแลระบบจะยังคงอ่านและเปลี่ยนแปลงเว็บไซต์นี้ได้</translation> <translation id="8376752431516546391">แผงด้านข้างของ Google Search</translation> <translation id="8377625247046155446">พาสคีย์นี้จะบันทึกในอุปกรณ์นี้เท่านั้น และพาสคีย์จะยังคงอยู่ในอุปกรณ์นี้หลังจากที่คุณปิดหน้าต่างที่ไม่ระบุตัวตนทั้งหมด</translation> <translation id="8378714024927312812">จัดการโดยองค์กร</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb index 8000bd0..eaa5c6f 100644 --- a/chrome/app/resources/generated_resources_tr.xtb +++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -1623,7 +1623,7 @@ <translation id="2204387456724731099">Bu seçim çevrilemedi</translation> <translation id="2207116775853792104">Bu uzantıyı sakla</translation> <translation id="2210462644007531147">Yükleme işlemi tamamlanamadı</translation> -<translation id="2211245494465528624">Senkronizasyon seçeneklerini yönet</translation> +<translation id="2211245494465528624">Senkronizasyon seçeneklerini yönetin</translation> <translation id="2214018885812055163">Paylaşılan klasörler</translation> <translation id="2214884991347062907">Yanlış şifre, tekrar deneyin</translation> <translation id="2214893006758804920">{LINE_COUNT,plural, =1{<1 satır gösterilmiyor>}other{<<ph name="NUMBER_OF_LINES" /> satır gösterilmiyor>}}</translation> @@ -8133,7 +8133,7 @@ <translation id="7331646370422660166">alt + aşağı ok</translation> <translation id="7332053360324989309">Özel Çalışan: <ph name="SCRIPT_URL" /></translation> <translation id="7333388112938984914">Sayaçlı bağlantı kullanılırken dosya yüklenemez.</translation> -<translation id="7333669215417470379">Uygulamalarınız ile ayarlarınızı yedekleme ve geri yükleme</translation> +<translation id="7333669215417470379">Uygulamalarınız ile ayarlarınızı yedekleyin ve geri yükleyin</translation> <translation id="7335436113423103413">Yeni sekme sayfasındaki birleştirilmiş yan panelden Chrome'u özelleştir işlevini kullanmayı etkinleştirir.</translation> <translation id="7335974957018254119">Şu diller için yazım denetimi kullan:</translation> <translation id="7336799713063880535">Bildirimler engellendi.</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb index d150c691..e5f553c 100644 --- a/chrome/app/resources/generated_resources_uk.xtb +++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -3311,6 +3311,7 @@ <translation id="3497560059572256875">Поділитися дудлом</translation> <translation id="3497915391670770295">Надіслати на &пристрої</translation> <translation id="3500417806337761827">Помилка підключення спільного доступу. Підключено забагато файлообмінників SMB.</translation> +<translation id="3500764001796099683">Увімкнути ізольовані веб-додатки</translation> <translation id="350397915809787283">Якщо у вас немає облікового запису, виберіть перший варіант, щоб створити його.</translation> <translation id="3503995387997205657">Ви можете відновити попередні додатки</translation> <translation id="3505100368357440862">Пропозиції покупок</translation> @@ -7184,6 +7185,7 @@ <translation id="6551508934388063976">Команда недоступна. Натисніть клавіші Ctrl+N, щоб відкрити нове вікно.</translation> <translation id="6551606359270386381">Інструмент "Еліпс"</translation> <translation id="6551612971599078809">Сайт використовує USB</translation> +<translation id="6551620030439692385">Заблоковано. Вибраний часовий пояс (<ph name="TIMEZONE" />) можна оновити лише вручну.</translation> <translation id="6551739526055143276">Обліковим записом керують через Family Link</translation> <translation id="655384502888039633">Користувачів: <ph name="USER_COUNT" /></translation> <translation id="6555432686520421228">Видаліть усі облікові записи користувача та відновіть заводські налаштування пристрою <ph name="IDS_SHORT_PRODUCT_NAME" />.</translation> @@ -7258,6 +7260,7 @@ <translation id="6608773371844092260">Щоб налаштувати відбиток пальця, дитина має торкнутися сканера на правому боці цього пристрою <ph name="DEVICE_TYPE" />. <ph name="DEVICE_TYPE" /> надійно зберігає дані про відбиток і нікуди не надсилає їх.</translation> <translation id="6609478180749378879">Дані для входу зберігатимуться на цьому пристрої після виходу з режиму анонімного перегляду. Ви зможете знову ввійти на цей сайт зі свого пристрою пізніше.</translation> <translation id="6610002944194042868">Параметри перекладу</translation> +<translation id="6610064275805055636">Керувати ізольованими веб-додатками</translation> <translation id="6611972847767394631">Знайдіть свої вкладки тут</translation> <translation id="661266467055912436">Покращує захист усіх користувачів в Інтернеті.</translation> <translation id="6613267708691765962">Пошук зловмисного програмного забезпечення…</translation> @@ -8621,6 +8624,7 @@ <translation id="7671472752213333268">Розширення "<ph name="EXTENSION_NAME" />" хоче виконати сканування за допомогою пристрою "<ph name="SCANNER_NAME" />".</translation> <translation id="7672504401554182757">Виберіть пристрій, на якому є ключ доступу для додатка <ph name="APP_NAME" /></translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, на сторінці <ph name="PAGE_TITLE" />.</translation> +<translation id="7672726198839739113">Заблоковано. Вибраний розклад (<ph name="SUNRISE_TIME" /> – <ph name="SUNSET_TIME" />) можна оновити лише вручну.</translation> <translation id="7673313156293624327">Журнали Shill (диспетчера підключень) для ChromeOS</translation> <translation id="7674416868315480713">Деактивувати всі порти, запити для яких переадресовуються в Linux</translation> <translation id="7674537509496907005">Додатків: <ph name="APP_COUNT" /></translation> @@ -9554,6 +9558,7 @@ <translation id="8376384591331888629">Зокрема файли cookie третіх сторін на цьому сайті</translation> <translation id="8376451933628734023">Якщо цей веб-додаток намагається видати себе за інший, видаліть його.</translation> <translation id="8376532149031784008">Оновлення <ph name="DOMAIN" />…</translation> +<translation id="8376610503048439696">Розширення, установлені адміністратором, усе одно зможуть переглядати й змінювати дані на цьому сайті</translation> <translation id="8376752431516546391">Бічна панель Пошуку Google</translation> <translation id="8377625247046155446">Ключ доступу буде збережено лише на цьому пристрої й залишиться на ньому після того, як ви закриєте всі вікна в режимі анонімного перегляду.</translation> <translation id="8378714024927312812">Профілем керує ваша організація</translation>
diff --git a/chrome/app/resources/generated_resources_ur.xtb b/chrome/app/resources/generated_resources_ur.xtb index 23d4ea0..bd93df614 100644 --- a/chrome/app/resources/generated_resources_ur.xtb +++ b/chrome/app/resources/generated_resources_ur.xtb
@@ -3295,6 +3295,7 @@ <translation id="3497560059572256875">Doodle کا اشتراک کریں</translation> <translation id="3497915391670770295">اپنے آلات پر بھیجیں</translation> <translation id="3500417806337761827">اشتراک کو ماؤنٹ کرنے میں خرابی۔ بہت سارے SMB اشتراکات پہلے ہی ماؤنٹ کیے گئے ہیں۔</translation> +<translation id="3500764001796099683">عیلحدہ کردہ ویب ایپس کو فعال کریں</translation> <translation id="350397915809787283">اگر آپ کے پاس اکاؤنٹ نہیں ہے تو اسے تخلیق کرنے کے لیے پہلا اختیار منتخب کریں۔</translation> <translation id="3503995387997205657">آپ اپنی گزشتہ ایپس کو بحالی کر سکتے ہیں</translation> <translation id="3505100368357440862">خریداری کی تجاویز</translation> @@ -7169,6 +7170,7 @@ <translation id="6551508934388063976">کمانڈ دستیاب نہیں ہے۔ ایک نئی ونڈو کھولنے کیلئے control-N دبائیں۔</translation> <translation id="6551606359270386381">بیضوی ٹول</translation> <translation id="6551612971599078809">سائٹ USB کا استعمال کر رہی ہے</translation> +<translation id="6551620030439692385">مسدود ہے۔ ٹائم زون فی الحال <ph name="TIMEZONE" /> پر سیٹ ہے اور اسے صرف دستی طور پر اپ ڈیٹ کیا جا سکتا ہے۔</translation> <translation id="6551739526055143276">Family Link کے زیر انتظام ہے</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> صارفین</translation> <translation id="6555432686520421228">بالکل نئے کی طرح ہونے کیلئے صارف کے سبھی اکاؤنٹس ہٹائیں اور اپنا <ph name="IDS_SHORT_PRODUCT_NAME" /> دوبارہ ترتیب دیں۔</translation> @@ -7237,6 +7239,7 @@ <translation id="6608773371844092260">فنگر پرنٹ سیٹ اپ کرنے کے لیے، اپنے بچے سے اس <ph name="DEVICE_TYPE" /> کے دائیں ہاتھ کی طرف موجود فنگر پرنٹ سینسر کو ٹچ کرنے کو کہیں۔ آپ کے بچے کے فنگر پرنٹ ڈیٹا کو محفوظ طریقے سے اسٹور کیا جاتا ہے اور یہ کبھی بھی اس <ph name="DEVICE_TYPE" /> سے باہر نہیں جاتا۔</translation> <translation id="6609478180749378879">آپ کے پوشیدگی وضع سے باہر نکلنے کے بعد، سائن ان ڈیٹا اس آلے پر اسٹور کیا جائے گا۔ بعد میں، آپ اپنے آلے کی مدد سے اس ویب سائٹ پر دوبارہ سائن ان کر سکیں گے۔</translation> <translation id="6610002944194042868">ترجمہ کے اختیارات</translation> +<translation id="6610064275805055636">عیلحدہ کردہ ویب ایپس کا نظم کریں</translation> <translation id="6611972847767394631">یہاں اپنے ٹیبز تلاش کریں</translation> <translation id="661266467055912436">آپ کے لیے اور ویب پر ہر کسی کے لیے سیکیورٹی کو بہتر بناتا ہے۔</translation> <translation id="6613267708691765962">میلوئیر کے لیے اسکین کیا جا رہا ہے...</translation> @@ -8600,6 +8603,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" "<ph name="SCANNER_NAME" />" سے اسکین کرنا چاہتے ہیں۔</translation> <translation id="7672504401554182757">منتخب کریں کہ کس آلہ میں <ph name="APP_NAME" /> کے لئے پاس کی ہو</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />، <ph name="PAGE_TITLE" /> میں۔</translation> +<translation id="7672726198839739113">مسدود ہے۔ ٹائم زون فی الحال <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> پر سیٹ ہے اور اسے صرف دستی طور پر اپ ڈیٹ کیا جا سکتا ہے۔</translation> <translation id="7673313156293624327">ChromeOS Shill (کنکشن مینیجر) لاگز</translation> <translation id="7674416868315480713">Linux میں فارورڈ کی جا رہی سبھی پورٹس کو غیر فعال کریں</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> ایپس</translation> @@ -9532,6 +9536,7 @@ <translation id="8376384591331888629">اس سائٹ میں فریق ثالث کوکیز سمیت</translation> <translation id="8376451933628734023">اگر یہ ویب ایپ آپ کو سوچنے پر مجبور کر رہی ہو کہ یہ ایک مختلف ایپ ہے تو اسے اَن انسٹال کریں۔</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> کو دوبارہ لوڈ کیا جا رہا ہے...</translation> +<translation id="8376610503048439696">آپ کے منتظم کے ذریعے انسٹال کردہ ایکسٹینشنز اب بھی اس سائٹ کو پڑھ اور تبدیل کر سکتی ہیں</translation> <translation id="8376752431516546391">Google تلاش کا سائیڈ پینل</translation> <translation id="8377625247046155446">یہ پاس کی صرف اس آلہ میں محفوظ ہوگی۔ آپ کے تمام پوشیدگی ونڈوز بند کرنے بعد یہ اس آلہ پر باقی رہے گی۔</translation> <translation id="8378714024927312812">آپ کی تنظیم کے زیر نظم</translation>
diff --git a/chrome/app/resources/generated_resources_uz.xtb b/chrome/app/resources/generated_resources_uz.xtb index 76b307ac..f32643f 100644 --- a/chrome/app/resources/generated_resources_uz.xtb +++ b/chrome/app/resources/generated_resources_uz.xtb
@@ -1719,6 +1719,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Barchasini &yangi varaqlar guruhida ochish}=1{&Yangi varaqlar guruhida ochish}other{Barchasini ({COUNT}) &yangi varaqlar guruhida ochish}}</translation> <translation id="2285942871162473373">Barmoq izingiz qabul qilinmadi. Qayta urining.</translation> <translation id="2287617382468007324">IPP manzilini chop etish</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{Xavfsizlik yuzasidan yaqinda ochilmagan saytdan ruxsatlar olib tashlandi}other{Xavfsizlik yuzasidan yaqinda ochilmagan saytlardan ruxsatlar olib tashlandi}}</translation> <translation id="2287944065963043964">Kirish ekrani</translation> <translation id="2290615375132886363">Planshet rejimida navigatsiya tugmalari</translation> <translation id="2291452790265535215">Bukmarklar, sayohatlar va boshqalar uchun yon paneldan foydalaning</translation> @@ -3295,6 +3296,7 @@ <translation id="3497560059572256875">Doodle ulashish</translation> <translation id="3497915391670770295">&Qurilmalaringizga yuborish</translation> <translation id="3500417806337761827">Umumiy jild ulanmadi. Allaqachon juda koʻp umumiy SMB jildlar ulangan.</translation> +<translation id="3500764001796099683">Izolyatsiyalangan veb-ilovalarni yoqish</translation> <translation id="350397915809787283">Agar hisobingiz boʻlmasa, yaratish uchun birinchi variantni tanlang.</translation> <translation id="3503995387997205657">Avvalgi ilovalarni tiklash mumkin</translation> <translation id="3505100368357440862">Xarid tavsiyalari</translation> @@ -4303,6 +4305,7 @@ <translation id="4275788652681621337">Yon panelni yopish</translation> <translation id="4275830172053184480">Qurilmangizni qayta yuklang</translation> <translation id="4277434192562187284">XML konfiguratsiya manbasi</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{1 ta ishlatilmagan saytdan ruxsatlar olib tashlandi}other{{NUM_SITES} ta ishlatilmagan saytdan ruxsatlar olib tashlandi}}</translation> <translation id="4278390842282768270">Berilgan ruxsatnomalar</translation> <translation id="4278498748067682896">Bu qurilma faqat kiosk yoki reklama paneli rejimida ishlashi uchun Kiosk va Reklama panelini yangilash xizmatidan foydalaning. Agar qurilma foydalanuvchilari hisobiga kirishni istasa, ortga qayting va Chrome Korporativ yangilanish xizmatiga yoziling.</translation> <translation id="4278779213160967034">Bu jarayon bir necha daqiqa vaqt olishi mumkin. Fayllar yuklab olinmoqda.</translation> @@ -7171,6 +7174,7 @@ <translation id="6551508934388063976">Buyruq ish faoliyatida emas. Yangi oyna ochish uchun “Ctrl + N” tugmalarini bosing.</translation> <translation id="6551606359270386381">Ellips vositasi</translation> <translation id="6551612971599078809">Saytda USB ishlatilmoqda</translation> +<translation id="6551620030439692385">Bloklandi. Vaqt mintaqasi sozlangan (<ph name="TIMEZONE" />) va faqat mustaqil yangilanishi mumkin.</translation> <translation id="6551739526055143276">Family Link orqali boshqariladi</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> ta foydalanuvchi</translation> <translation id="6555432686520421228"><ph name="IDS_SHORT_PRODUCT_NAME" /> qurilmasida barcha foydalanuvchilar hisoblarini o‘chirish va zavod sozlamalarini tiklash.</translation> @@ -7239,6 +7243,7 @@ <translation id="6608773371844092260">Barmoq izini sozlash uchun farzandingiz <ph name="DEVICE_TYPE" /> qurilmasining oʻng orqasidagi barmoq izi skaneriga teginishiga ruxsat bering. Farzandingiz barmoq izlari yaxshi himoya ostida va faqat <ph name="DEVICE_TYPE" /> qurilmasida saqlanadi.</translation> <translation id="6609478180749378879">Inkognito rejimini tark etganingizdan keyin kirish maʼlumotlari shu qurilmada saqlanadi. Bu saytga keyinchalik shu qurilma orqali yana kira olasiz.</translation> <translation id="6610002944194042868">Tarjima parametrlari</translation> +<translation id="6610064275805055636">Izolyatsiyalangan veb-ilovalarni boshqarish</translation> <translation id="6611972847767394631">Varaqlarni bu yerdan toping</translation> <translation id="661266467055912436">Siz va yaqinlaringizni internetdan yaxshiroq himoyalaydi.</translation> <translation id="6613267708691765962">Zararli dasturga tekshirilmoqda...</translation> @@ -8602,6 +8607,7 @@ <translation id="7671472752213333268">"<ph name="EXTENSION_NAME" />" kengaytmasi "<ph name="SCANNER_NAME" />" orqali skanerlamoqchi.</translation> <translation id="7672504401554182757"><ph name="APP_NAME" /> kodi qaysi qurilmada saqlanishini tanlang</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> sahifasida.</translation> +<translation id="7672726198839739113">Bloklandi. Kun tartibi sozlangan <ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" /> va faqat mustaqil yangilanishi mumkin.</translation> <translation id="7673313156293624327">ChromeOS Shill (aloqa menejeri) jurnallari</translation> <translation id="7674416868315480713">Linuxdagi barcha yoʻnaltirilgan portlarni yopish</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> ta ilova</translation> @@ -9533,6 +9539,7 @@ <translation id="8376384591331888629">Bu saytdagi tashqi cookie fayllariga ham</translation> <translation id="8376451933628734023">Agar bu veb ilova shubhali ishlasa, uni oʻchirib tashlang.</translation> <translation id="8376532149031784008"><ph name="DOMAIN" /> qayta yuklanmoqda...</translation> +<translation id="8376610503048439696">Administrator oʻrnatgan kengaytmalar bu saytni oʻqishi va oʻzgartirishi mumkin</translation> <translation id="8376752431516546391">Google qidiruv yon paneli</translation> <translation id="8377625247046155446">Bu kod faqat shu qurilmada saqlanadi Barcha inkognito oynalari yopilganidan keyin kod shu qurilmada qoladi.</translation> <translation id="8378714024927312812">Tashkilotingiz tomonidan boshqariladi</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb index 2c7b953..c345000 100644 --- a/chrome/app/resources/generated_resources_vi.xtb +++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -923,7 +923,7 @@ <translation id="1682696837763999627">Con trỏ chuột lớn</translation> <translation id="1682867089915960590">Bật tính năng Duyệt web có con nháy?</translation> <translation id="1686550358074589746">Bật tính năng nhập bằng cách lướt</translation> -<translation id="168715261339224929">Để sử dụng dấu trang trên tất cả các thiết bị của bạn, hãy bật đồng bộ hóa.</translation> +<translation id="168715261339224929">Để sử dụng dấu trang trên tất cả các thiết bị của bạn, hãy bật tính năng đồng bộ hóa.</translation> <translation id="1688935057616748272">Nhập một chữ cái</translation> <translation id="1689333818294560261">Biệt hiệu</translation> <translation id="168991973552362966">Thêm máy in ở gần</translation> @@ -1017,7 +1017,7 @@ <translation id="1757301747492736405">Đang chờ gỡ cài đặt</translation> <translation id="175772926354468439">Bật chủ đề</translation> <translation id="1757786065507923842">Không thể yêu cầu cha mẹ cho phép.</translation> -<translation id="17584710573359123">Xem trong Chrome Web Store</translation> +<translation id="17584710573359123">Xem trong Cửa hàng Chrome trực tuyến</translation> <translation id="1761402971842586829">Đã liên kết lại <ph name="BUTTON_NAME" /> với <ph name="REMAPPING_OPTION" />.</translation> <translation id="1761845175367251960">Tài khoản của <ph name="NAME" /></translation> <translation id="176272781006230109">các đề xuất mua sắm</translation> @@ -1229,7 +1229,7 @@ <translation id="1904603806662441960">Quản lý quyền truy cập camera của các trang web trong Chrome</translation> <translation id="1905375423839394163">Tên thiết bị Chromebook</translation> <translation id="1906181697255754968">Các trang web thường truy cập vào tệp và thư mục trên thiết bị của bạn để áp dụng những tính năng như tự động lưu công việc</translation> -<translation id="1906488504371069394">Khám phá các tiện ích và giao diện khác trên <ph name="BEGIN_LINK" />Chrome Web Store<ph name="END_LINK" /></translation> +<translation id="1906488504371069394">Khám phá các tiện ích và giao diện khác trên <ph name="BEGIN_LINK" />Cửa hàng Chrome trực tuyến<ph name="END_LINK" /></translation> <translation id="1907044622262489040">Nhập dữ liệu bằng giọng nói. Nhấn tổ hợp phím Tìm kiếm + D, sau đó bắt đầu nói.</translation> <translation id="1907659324308286326">Một số phụ kiện Thunderbolt hoặc USB4 cần có quyền truy cập vào bộ nhớ để hoạt động đúng cách.</translation> <translation id="1908591798274282246">Mở lại nhóm đã đóng</translation> @@ -2246,7 +2246,7 @@ <translation id="266079277508604648">Không thể kết nối với máy in. Hãy kiểm tra để đảm bảo rằng bạn đã bật máy in cũng như đã kết nối máy in với Chromebook qua Wi-Fi hoặc USB.</translation> <translation id="2661315027005813059">Trang lưu trong bộ nhớ đệm cho thao tác tiến/lùi: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation> <translation id="2661714428027871023">Duyệt web nhanh hơn và sử dụng ít dữ liệu hơn nhờ Chế độ thu gọn. Nhấp để tìm hiểu thêm.</translation> -<translation id="2662876636500006917">Chrome Web Store</translation> +<translation id="2662876636500006917">Cửa hàng Chrome trực tuyến</translation> <translation id="2663253180579749458">Đang thêm hồ sơ eSIM. Quá trình này có thể mất vài phút.</translation> <translation id="2663302507110284145">Ngôn ngữ</translation> <translation id="2665394472441560184">Thêm từ mới</translation> @@ -2267,7 +2267,7 @@ <translation id="2673873887296220733">Sao chép 1 tệp vào <ph name="CLOUD_PROVIDER" /> để mở tệp đó?</translation> <translation id="267442004702508783">làm mới</translation> <translation id="2674764818721168631">Đang tắt</translation> -<translation id="2676084251379299915">Tiện ích này đã bị chính sách doanh nghiệp vô hiệu hoá vì không còn phát hành trên Chrome Web Store.</translation> +<translation id="2676084251379299915">Tiện ích này đã bị chính sách doanh nghiệp vô hiệu hoá vì không còn phát hành trên Cửa hàng Chrome trực tuyến.</translation> <translation id="2678063897982469759">Kích hoạt lại</translation> <translation id="2678100101831051676">Không truyền được.</translation> <translation id="268053382412112343">Lị&ch sử</translation> @@ -2689,7 +2689,7 @@ <translation id="2996286169319737844">Dữ liệu được mã hóa bằng cụm mật khẩu đồng bộ hóa của bạn. Dữ liệu này không bao gồm địa chỉ và phương thức thanh toán từ Google Pay.</translation> <translation id="2996722619877761919">Lật trên cạnh dài</translation> <translation id="2996932914629936323">Xóa nhật ký khỏi mọi thiết bị đã đồng bộ hóa</translation> -<translation id="2998097899774209901">Đang bật • Tiện ích này vi phạm chính sách của Chrome Web Store</translation> +<translation id="2998097899774209901">Đang bật • Tiện ích này vi phạm chính sách của Cửa hàng Chrome trực tuyến</translation> <translation id="2998267783395280091">Đã tìm thấy mạng</translation> <translation id="3000378525979847272">Đã cho phép <ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /></translation> <translation id="3000461861112256445">Đơn âm</translation> @@ -2722,7 +2722,7 @@ <translation id="3012631534724231212">(iframe)</translation> <translation id="3012804260437125868">Chỉ các kết nối cùng trang web an toàn</translation> <translation id="3012917896646559015">Vui lòng liên hệ ngay với nhà sản xuất phần cứng của bạn để gửi máy tính đến cơ sở sửa chữa.</translation> -<translation id="3013652227108802944">Đang tắt • Tiện ích này vi phạm chính sách của Chrome Web Store</translation> +<translation id="3013652227108802944">Đang tắt • Tiện ích này vi phạm chính sách của Cửa hàng Chrome trực tuyến</translation> <translation id="301525898020410885">Ngôn ngữ do tổ chức của bạn đặt</translation> <translation id="3015639418649705390">Chạy lại ngay</translation> <translation id="3016381065346027039">Không có mục nhật ký nào</translation> @@ -3673,7 +3673,7 @@ <translation id="3775432569830822555">Chứng chỉ Máy chủ SSL</translation> <translation id="3775705724665058594">Gửi đến thiết bị của bạn</translation> <translation id="3776508619697147021">Các trang web có thể yêu cầu tự động tải nhiều tệp xuống</translation> -<translation id="3776796446459804932">Tiện ích này vi phạm chính sách của Chrome Web Store.</translation> +<translation id="3776796446459804932">Tiện ích này vi phạm chính sách của Cửa hàng Chrome trực tuyến.</translation> <translation id="3777483481409781352">Không kích hoạt được thiết bị di động</translation> <translation id="3777796259512476958">Bạn sẽ bị đăng xuất khỏi hầu hết các trang web</translation> <translation id="3778208826288864398">Khóa bảo mật đã bị khóa do bạn nhập sai mã PIN quá nhiều lần. Bạn cần đặt lại khóa bảo mật.</translation> @@ -3835,7 +3835,7 @@ <translation id="3894123633473837029">Thêm lịch sử hoạt động gần đây của Trợ lý qua Sherlog. Lịch sử này có thể bao gồm thông tin gỡ lỗi, vị trí và danh tính của bạn. <ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /></translation> <translation id="3894427358181296146">Thêm thư mục</translation> <translation id="3894770151966614831">Di chuyển sang Tài khoản Google?</translation> -<translation id="3894983081771074056">Hành vi sử dụng bàn phím và chuột, lựa chọn ưu tiên về ngôn ngữ, v.v.</translation> +<translation id="3894983081771074056">Cách hoạt động của bàn phím và chuột, lựa chọn ưu tiên về ngôn ngữ, v.v.</translation> <translation id="3895076768659607631">&Quản lý công cụ tìm kiếm...</translation> <translation id="3895090224522145010">Tên người dùng Kerberos</translation> <translation id="389521680295183045">Trang web có thể xin phép phát hiện khi bạn đang dùng thiết bị của mình</translation> @@ -5067,7 +5067,7 @@ <translation id="4870724079713069532">Bạn có thể dùng ứng dụng này trên File Explorer hoặc các ứng dụng khác để mở và chỉnh sửa các tệp được hỗ trợ. Để kiểm soát tệp nào mở được trong ứng dụng này theo mặc định, hãy chuyển đến phần <ph name="BEGIN_LINK" />cài đặt Windows<ph name="END_LINK" />.</translation> <translation id="4870758487381879312">Nhập mật khẩu do quản trị viên cung cấp để lấy thông tin cấu hình</translation> <translation id="4870995365819149457">Một số đường liên kết được hỗ trợ vẫn sẽ mở trong <ph name="APP_NAME" />, <ph name="APP_NAME_2" />, <ph name="APP_NAME_3" /> và 1 ứng dụng khác.</translation> -<translation id="4871308555310586478">Không phải từ Chrome Web Store.</translation> +<translation id="4871308555310586478">Không phải từ Cửa hàng Chrome trực tuyến.</translation> <translation id="4871322859485617074">Mã PIN chứa ký tự không hợp lệ</translation> <translation id="4871370605780490696">Thêm dấu trang</translation> <translation id="4871568871368204250">Tắt đồng bộ hóa</translation> @@ -5372,7 +5372,7 @@ <translation id="5112577000029535889">&Công cụ dành cho Nhà phát triển</translation> <translation id="5112686815928391420">{NUM_OF_FILES,plural, =1{Đã di chuyển 1 tệp}other{Đã di chuyển {NUM_OF_FILES} tệp}}</translation> <translation id="511313294362309725">Bật tính năng Ghép nối nhanh</translation> -<translation id="5113384440341086023">Ứng dụng được cài đặt từ Cửa hàng Play và ứng dụng web từ trình duyệt Chrome</translation> +<translation id="5113384440341086023">Ứng dụng đã cài đặt từ Cửa hàng Play và ứng dụng web từ trình duyệt Chrome</translation> <translation id="51143538739122961">Cắm và chạm vào khóa bảo mật</translation> <translation id="5115309401544567011">Hãy cắm <ph name="DEVICE_TYPE" /> của bạn vào nguồn điện.</translation> <translation id="5115338116365931134">SSO</translation> @@ -5819,7 +5819,7 @@ <translation id="5470735824776589490">Bạn cần khởi động lại trước khi có thể đặt lại thiết bị của mình bằng Powerwash. <ph name="LINK_BEGIN" />Tìm hiểu thêm<ph name="LINK_END" /></translation> <translation id="5471768120198416576">Chào bạn! Đây là giọng nói của tính năng chuyển văn bản sang lời nói.</translation> <translation id="5472627187093107397">Lưu mật khẩu cho trang web này</translation> -<translation id="5473062644742711742">Tìm thêm công cụ hỗ trợ tiếp cận trong Chrome Web Store</translation> +<translation id="5473062644742711742">Tìm thêm công cụ hỗ trợ tiếp cận trong Cửa hàng Chrome trực tuyến</translation> <translation id="5473075389972733037">IBM</translation> <translation id="5473099001878321374">Bằng cách tiếp tục, bạn đồng ý rằng thiết bị này cũng có thể tự động tải xuống và cài đặt các bản cập nhật và ứng dụng của Google, nhà mạng của con bạn và nhà sản xuất thiết bị (có thể dùng dữ liệu di động). Một vài ứng dụng trong số này có thể cung cấp các lựa chọn mua hàng trong ứng dụng.</translation> <translation id="5473156705047072749">{NUM_CHARACTERS,plural, =1{Mã PIN phải có ít nhất 1 ký tự}other{Mã PIN phải có ít nhất # ký tự}}</translation> @@ -6039,7 +6039,7 @@ <translation id="5636996382092289526">Để sử dụng <ph name="NETWORK_ID" />, trước hết bạn cần <ph name="LINK_START" />truy cập vào trang đăng nhập của mạng<ph name="LINK_END" />. Trang này thường tự động mở sau vài giây. Nếu trang này không mở thì không thể sử dụng mạng này.</translation> <translation id="5637476008227280525">Bật dữ liệu di động</translation> <translation id="563821631542362636">Cho phép trang web lưu dữ liệu</translation> -<translation id="5638309510554459422">Tìm tiện ích và chủ đề trong <ph name="BEGIN_LINK" />Chrome Web Store<ph name="END_LINK" /></translation> +<translation id="5638309510554459422">Tìm tiện ích và chủ đề trong <ph name="BEGIN_LINK" />Cửa hàng Chrome trực tuyến<ph name="END_LINK" /></translation> <translation id="5639549361331209298">Tải lại trang này, giữ để xem các tùy chọn khác</translation> <translation id="5640133431808313291">Quản lý khóa bảo mật</translation> <translation id="5640159004008030285">Mật khẩu này chỉ được lưu trên thiết bị này. Để sử dụng mật khẩu này trên các thiết bị khác, hãy <ph name="BEGIN_LINK" />lưu mật khẩu vào Tài khoản Google của bạn<ph name="END_LINK" />.</translation> @@ -7089,7 +7089,7 @@ <translation id="6476482583633999078">Tốc độ lời nói</translation> <translation id="6477822444490674459">Không dùng được tính năng đồng bộ hóa thông báo trên điện thoại có hồ sơ công việc. <ph name="LINK_BEGIN" />Tìm hiểu thêm<ph name="LINK_END" /></translation> <translation id="6478248366783946499">Giữ tệp nguy hiểm?</translation> -<translation id="6479881432656947268">Truy cập Chrome Web Store</translation> +<translation id="6479881432656947268">Truy cập Cửa hàng Chrome trực tuyến</translation> <translation id="6480327114083866287">Do <ph name="MANAGER" /> quản lý</translation> <translation id="6481749622989211463">Chia sẻ tệp và nhiều nội dung khác với các thiết bị ở gần. <ph name="LINK_BEGIN" />Tìm hiểu thêm<ph name="LINK_END" /></translation> <translation id="6482559668224714696">Phóng to toàn màn hình</translation> @@ -8307,7 +8307,7 @@ <translation id="7434509671034404296">Nhà phát triển</translation> <translation id="7434757724413878233">Tăng tốc chuột</translation> <translation id="7434969625063495310">Không thể thêm máy chủ máy in. Vui lòng kiểm tra cấu hình của máy chủ rồi thử lại.</translation> -<translation id="7436452443388501706">{NUM_EXTENSIONS,plural, =1{Xem xét 1 tiện ích đã bị gỡ khỏi Chrome Web Store}other{Xem xét {NUM_EXTENSIONS} tiện ích đã bị gỡ khỏi Chrome Web Store}}</translation> +<translation id="7436452443388501706">{NUM_EXTENSIONS,plural, =1{Xem xét 1 tiện ích đã bị gỡ khỏi Cửa hàng Chrome trực tuyến}other{Xem xét {NUM_EXTENSIONS} tiện ích đã bị gỡ khỏi Cửa hàng Chrome trực tuyến}}</translation> <translation id="7436921188514130341">Ôi, hỏng! Đã xảy ra lỗi trong khi đổi tên.</translation> <translation id="7439519621174723623">Hãy thêm tên thiết bị để tiếp tục</translation> <translation id="7441736532026945583">Chọn "Ẩn nhóm" để xoá nhóm khỏi dải thẻ của bạn</translation> @@ -9984,7 +9984,7 @@ <translation id="8708000541097332489">Xóa khi thoát</translation> <translation id="870805141700401153">Ký Mã Cá nhân của Microsoft</translation> <translation id="8708671767545720562">&Thông tin khác</translation> -<translation id="8709368517685334931">Bạn có thể tìm các màu cũ hơn trong Chrome Web Store</translation> +<translation id="8709368517685334931">Bạn có thể tìm các màu cũ hơn trong Cửa hàng Chrome trực tuyến</translation> <translation id="8710550057342691420">Sắp xếp những thẻ tương tự nhau</translation> <translation id="8711402221661888347">Đồ chua</translation> <translation id="8711538096655725662">Tự động chạy trên tất cả trang web mà bạn truy cập</translation> @@ -10474,7 +10474,7 @@ <translation id="9068598199622656904">Nhấn lần lượt từng phím để sử dụng phím tắt thay vì nhấn và giữ nhiều phím cùng lúc</translation> <translation id="9068878141610261315">Loại tệp không được hỗ trợ</translation> <translation id="9069417381769492963">Không có dấu trang nào khớp với nội dung bạn tìm</translation> -<translation id="9069665781180028115">Các mục đã chọn sẽ có trên Chromebook này. Nếu bạn mới dùng Chromebook, hãy đồng bộ hoá tất cả các mục để sao lưu lựa chọn ưu tiên của bạn. Bạn có thể thay đổi bất cứ lúc nào trong phần Cài đặt > Tài khoản.</translation> +<translation id="9069665781180028115">Các mục mà bạn chọn sẽ có trên Chromebook này. Nếu bạn mới dùng Chromebook, hãy đồng bộ hoá tất cả các mục để sao lưu lựa chọn ưu tiên của bạn. Bạn có thể thay đổi bất cứ lúc nào trong phần Cài đặt > Tài khoản.</translation> <translation id="9070231741075992882">Các quyền bạn cấp cho <ph name="APP_NAME" /> cũng sẽ được cấp cho những ứng dụng mà ứng dụng này đã cài đặt và truyền trực tuyến.</translation> <translation id="9070342919388027491">Đã di chuyển thẻ sang trái</translation> <translation id="9074739597929991885">Bluetooth</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb index 9c521375..80394a2 100644 --- a/chrome/app/resources/generated_resources_zh-CN.xtb +++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -1290,7 +1290,7 @@ <translation id="1969654639948595766">WebRTC 文本日志 (<ph name="WEBRTC_TEXT_LOG_COUNT" />)</translation> <translation id="1970895205072379091"><ph name="BEGIN_PARAGRAPH1" />如果您允许 ChromeOS 设备自动发送报告,则可帮助我们确定 ChromeOS 中需要优先解决的问题和优先改进的方面。这些报告可能包含的内容有:ChromeOS 的崩溃时间、使用的功能、通常占用的内存量,等等。部分汇总数据还会对 Google 应用和合作伙伴(例如 Android 开发者)有所帮助。如果同时启用了应用同步,系统还会收集其他应用(包括 Android 应用和 Web 应用)的诊断数据和使用情况数据。<ph name="END_PARAGRAPH1" /> <ph name="BEGIN_PARAGRAPH2" />您随时可在 ChromeOS 设备的设置中开始或停止发送这些报告。如果您是网域管理员,则可在管理控制台中更改这一设置。<ph name="END_PARAGRAPH2" /> - <ph name="BEGIN_PARAGRAPH3" />如果您已为自己的 Google 账号开启“网络与应用活动记录”设置,您的 Android 数据可能会被保存到您的 Google 账号中。您可在 account.google.com 上查看和删除您的数据以及更改您的账号设置。<ph name="END_PARAGRAPH3" /></translation> + <ph name="BEGIN_PARAGRAPH3" />如果您已为自己的 Google 账号开启“网络与应用活动记录”设置,您的 Android 数据可能会保存到您的 Google 账号中。您可在 account.google.com 上查看和删除您的数据以及更改您的账号设置。<ph name="END_PARAGRAPH3" /></translation> <translation id="1972313920920745320">您添加的网站将始终保持活跃状态,且系统不会从它们中释放内存。<ph name="BEGIN_LINK" />详细了解如何让特定网站保持活跃状态<ph name="END_LINK" /></translation> <translation id="1972325230031091483">您的浏览速度会更快,因为系统会根据您当前访问的网页主动加载内容</translation> <translation id="197288927597451399">保留</translation> @@ -4815,7 +4815,7 @@ <translation id="4682481611456523884">此网站上的嵌入式内容无法使用它们保存的与您相关的信息</translation> <translation id="4683629100208651599">转换为小写</translation> <translation id="4683947955326903992"><ph name="PERCENTAGE" />%(默认)</translation> -<translation id="4684427112815847243">同步所有数据类型</translation> +<translation id="4684427112815847243">同步所有数据</translation> <translation id="4685096503970466594">关闭“<ph name="FEATURE_NAME" />”功能</translation> <translation id="4687238339694011189">请确保您的打印机已开机,且已连接到 Chromebook 所用网络或使用 USB 线</translation> <translation id="4687613760714619596">未知设备 (<ph name="DEVICE_ID" />)</translation> @@ -9564,7 +9564,7 @@ <translation id="8403807918453631441">您需要先保存密码,然后才能使用 <ph name="BRAND" />的密码检查功能</translation> <translation id="8405046151008197676">了解最近更新的主要内容</translation> <translation id="8407199357649073301">日志级别:</translation> -<translation id="8408270600235826886">您可以控制与 Google 分享哪些数据。您随时可在“设置”中更改此设置。我们会遵照 Google 的<ph name="BEGIN_LINK" />隐私权政策<ph name="END_LINK" />使用相关数据。</translation> +<translation id="8408270600235826886">您可以控制与 Google 分享哪些数据,并且随时可在“设置”中进行更改。我们会遵照 Google 的<ph name="BEGIN_LINK" />隐私权政策<ph name="END_LINK" />使用相关数据。</translation> <translation id="84098433273647700">您已安装的当前主题。</translation> <translation id="8410775397654368139">Google Play</translation> <translation id="8411043186249152291">全屏</translation>
diff --git a/chrome/app/resources/generated_resources_zh-HK.xtb b/chrome/app/resources/generated_resources_zh-HK.xtb index 868d476..7de7d86 100644 --- a/chrome/app/resources/generated_resources_zh-HK.xtb +++ b/chrome/app/resources/generated_resources_zh-HK.xtb
@@ -241,7 +241,7 @@ <translation id="1177073277575830464">Android 快速設定已完成。在你的 <ph name="DEVICE_TYPE" /> 上繼續設定。</translation> <translation id="1177440945615690056">你可在「設定」中連線至任何符合資格的流動網絡</translation> <translation id="1177863135347784049">自訂</translation> -<translation id="1178093605842850860">允許讀取及變更這個網站</translation> +<translation id="1178093605842850860">已允許讀取及變更此網站</translation> <translation id="1178581264944972037">暫停</translation> <translation id="1178601482396475810">管理裝置同步設定</translation> <translation id="117916940443676133">您的安全密鑰並未受 PIN 保護。請先建立 PIN 以管理登入資料。</translation> @@ -1732,6 +1732,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{在新分頁群組中開啟所有網址(&N)}=1{在新分頁群組中開啟所有網址(&N)}other{在新分頁群組中開啟所有 ({COUNT} 個) 網址(&N)}}</translation> <translation id="2285942871162473373">無法識別您的指紋。請再試一次。</translation> <translation id="2287617382468007324">列印 IPP 位址</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{為保護你的資料,系統已移除你最近沒有瀏覽的網站權限}other{為保護你的資料,系統已移除你最近沒有瀏覽的網站權限}}</translation> <translation id="2287944065963043964">登入畫面</translation> <translation id="2290615375132886363">平板電腦導覽按鈕</translation> <translation id="2291452790265535215">嘗試透過在側面板上使用書籤、瀏覽歷程及其他功能</translation> @@ -2618,7 +2619,7 @@ <translation id="2935314715123552088">停用使用中的 eSIM 設定檔</translation> <translation id="2935654492420446828">稍後新增學校帳戶</translation> <translation id="2936851848721175671">備份與還原</translation> -<translation id="2938981087412273365">不允許讀取及變更這個網站</translation> +<translation id="2938981087412273365">不允許讀取及變更此網站</translation> <translation id="2939908794993783865">其他無效網站</translation> <translation id="2939938020978911855">顯示可用的藍牙裝置</translation> <translation id="2941112035454246133">低</translation> @@ -3308,6 +3309,7 @@ <translation id="3497560059572256875">分享 Doodle</translation> <translation id="3497915391670770295">傳送至裝置(&D)</translation> <translation id="3500417806337761827">連接共用檔案時發生錯誤。已連接過多 SMB 共用檔案。</translation> +<translation id="3500764001796099683">啟用隔離的網絡應用程式</translation> <translation id="350397915809787283">如果沒有帳戶,請選取第一個選項建立帳戶。</translation> <translation id="3503995387997205657">您可還原先前的應用程式</translation> <translation id="3505100368357440862">購物建議</translation> @@ -3426,7 +3428,7 @@ <translation id="3602894439067790744">朗讀數字方式</translation> <translation id="3603622770190368340">取得網絡憑證</translation> <translation id="3605156246402033687">{COUNT,plural, =1{{COUNT} 個帳戶正在使用同一個密碼}other{{COUNT} 個帳戶正在使用同一個密碼}}</translation> -<translation id="3605515937536882518">表單值已更新</translation> +<translation id="3605515937536882518">更新咗表格數值</translation> <translation id="3605780360466892872">小員工</translation> <translation id="3607671391978830431">供子女使用</translation> <translation id="3608460311600621471">請提供列印這些資料的原因:</translation> @@ -4312,6 +4314,7 @@ <translation id="4275788652681621337">關閉側面板</translation> <translation id="4275830172053184480">重新啟動裝置</translation> <translation id="4277434192562187284">XML 設定來源</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{已從 1 個未使用的網站移除權限}other{已從 {NUM_SITES} 個未使用的網站移除權限}}</translation> <translation id="4278390842282768270">已允許</translation> <translation id="4278498748067682896">您將使用「Kiosk 和標牌升級」授權,此授權只允許裝置在 Kiosk 或標牌模式下運作。如果您想使用者登入裝置,請返回並使用「Chrome Enterprise 升級」註冊。</translation> <translation id="4278779213160967034">此程序可能需時幾分鐘。正在下載檔案。</translation> @@ -4488,7 +4491,7 @@ <translation id="4410545552906060960">您可以使用數字 (PIN) 來解鎖裝置。如要稍後才設定 PIN,請前往「設定」。</translation> <translation id="4411578466613447185">程式碼簽署者</translation> <translation id="4411719918614785832">這些密鑰會儲存在此電腦的 Windows Hello 上,並不會儲存至您的 Google 帳戶。</translation> -<translation id="4412544493002546580">請再試一次,或選擇下列其中一個靈感。</translation> +<translation id="4412544493002546580">請再試一次,或選取下方其中一個靈感。</translation> <translation id="4412547955014928315">要刪除 <ph name="SITE_NAME" /> 和當中所有網站的網站資料和權限嗎?</translation> <translation id="4412632005703201014">Chrome 應用程式正在轉移至漸進式網頁應用程式。此 Chrome 應用程式是由機構安裝在您的瀏覽器上。如要從「應用程式清單」開啟「漸進式網頁應用程式」,首先請聯絡管理員,並要求他們解除安裝 Chrome 應用程式。同時,您可前往 <ph name="EXTENSION_LAUNCH_URL" /> 以便在網絡上開啟 <ph name="EXTENSION_NAME" />。</translation> <translation id="4412698727486357573">說明中心</translation> @@ -4906,7 +4909,7 @@ <translation id="4744268813103118742">前往網站</translation> <translation id="4744571849207727284">Excel</translation> <translation id="4744981231093950366">{NUM_TABS,plural, =1{將單一網站取消靜音}other{將多個網站取消靜音}}</translation> -<translation id="4745500401920035244">你的管理員變更了系統設定,部分舊的設定檔因此遭到停用。你無法再存取這個設定檔,但仍可將其移除</translation> +<translation id="4745500401920035244">管理員實行的全系統變更停用了部分舊個人檔案。你無法再存取此個人檔案,但仍可將其移除</translation> <translation id="474609389162964566">說出「Ok Google」即可存取「Google 助理」</translation> <translation id="4748783296226936791">網站通常會連接 HID 裝置,以提供使用非標準鍵盤、遊戲控制器和其他裝置等功能</translation> <translation id="4749960740855309258">開啟新分頁</translation> @@ -5451,7 +5454,7 @@ <translation id="5178667623289523808">尋找上一個項目</translation> <translation id="5181140330217080051">下載中</translation> <translation id="5181172023548002891">儲存至 <ph name="ACCOUNT" /> 的「Google 密碼管理工具」</translation> -<translation id="5181551096188687373">這個密碼只會儲存到這部裝置。如要在其他裝置上使用,請儲存到 Google 帳戶 (<ph name="USER_EMAIL" />)。</translation> +<translation id="5181551096188687373">此密碼只會儲存至此裝置。如要在其他裝置上使用此書籤,請將書籤儲存至 Google 帳戶 (<ph name="USER_EMAIL" />)。</translation> <translation id="5183344263225877832">要重設所有 HID 裝置權限嗎?</translation> <translation id="5184063094292164363">JavaScript 控制器(&J)</translation> <translation id="5184209580557088469">已有票證使用此使用者名稱</translation> @@ -5738,7 +5741,7 @@ <translation id="5417312524372586921">瀏覽器主題背景</translation> <translation id="5417353542809767994">快速使用安全度高的密碼</translation> <translation id="541737483547792035">放大畫面</translation> -<translation id="541822678830750798">正在要求讀取及變更這個網站</translation> +<translation id="541822678830750798">正在要求讀取及變更此網站</translation> <translation id="5419405654816502573">Voice Match</translation> <translation id="5420061891386124792">啟用儲存及恢復分頁群組的功能。如要儲存分頁群組,請在群組上按一下右鍵;如要恢復分頁群組,請使用書籤列。</translation> <translation id="5420274697768050645">需要使用密碼解鎖裝置以提升安全性</translation> @@ -6668,7 +6671,7 @@ 顯示名稱:<ph name="QUICK_START_DEVICE_DISPLAY_NAME" />…</translation> <translation id="6146409560350811147">同步功能無法正常運作。請嘗試再次登入。</translation> <translation id="6147020289383635445">列印預覽失敗。</translation> -<translation id="6147253937684562370">如要解鎖設定檔,請使用你的主要帳戶電子郵件地址登入:<ph name="EMAIL" /></translation> +<translation id="6147253937684562370">如要解鎖個人檔案,請使用你的主要帳戶電郵 (<ph name="EMAIL" />) 登入</translation> <translation id="6148576794665275391">立即開啟</translation> <translation id="614890671148262506">一律允許此網站傳送通知</translation> <translation id="6149015141270619212">無法連線至互聯網</translation> @@ -7178,6 +7181,7 @@ <translation id="6551508934388063976">無法使用指令。按下 Ctrl + N 鍵可開啟新視窗。</translation> <translation id="6551606359270386381">橢圓形工具</translation> <translation id="6551612971599078809">網站正在使用 USB 裝置</translation> +<translation id="6551620030439692385">已封鎖。時區目前設定為「<ph name="TIMEZONE" />」,只能手動更新。</translation> <translation id="6551739526055143276">由 Family Link 管理</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> 位使用者</translation> <translation id="6555432686520421228">移除所有使用者帳戶,並將您的 <ph name="IDS_SHORT_PRODUCT_NAME" /> 裝置重設為原廠狀態。</translation> @@ -7246,6 +7250,7 @@ <translation id="6608773371844092260">如要設定指紋,請讓子女輕觸 <ph name="DEVICE_TYPE" /> 右側的指紋感應器。子女的指紋資料會安全儲存在此 <ph name="DEVICE_TYPE" /> 上,絕不會外洩。</translation> <translation id="6609478180749378879">離開無痕模式後,登入資料會儲存在此裝置中。您可在日後透過裝置再次登入此網站。</translation> <translation id="6610002944194042868">翻譯選項</translation> +<translation id="6610064275805055636">管理隔離的網絡應用程式</translation> <translation id="6611972847767394631">您的分頁會在這裡顯示</translation> <translation id="661266467055912436">為您和網絡上的所有使用者提高安全性。</translation> <translation id="6613267708691765962">正在掃瞄惡意軟件…</translation> @@ -7648,7 +7653,7 @@ <translation id="6918677045355889289">必須更新 Chrome OS</translation> <translation id="6919354101107095996">請嘗試登入網站,然後再次下載</translation> <translation id="6919952941889172531">要同時為這個 Chrome 設定檔開啟「強化安全瀏覽」嗎?</translation> -<translation id="6920473853105515518">請確認 <ph name="DEVICE_TYPE" /> 已連上網際網路,然後再試一次。你也可以在其他裝置上前往 play.google/play-terms。</translation> +<translation id="6920473853105515518">請確定你的 <ph name="DEVICE_TYPE" /> 已連線到互聯網,然後再試一次。你亦可使用其他裝置瀏覽 play.google/play-terms。</translation> <translation id="6920989436227028121">在一般分頁中開啟</translation> <translation id="6921104647315081813">清除活動</translation> <translation id="692114467174262153">無法開啟 <ph name="ALTERNATIVE_BROWSER_NAME" /></translation> @@ -8609,6 +8614,7 @@ <translation id="7671472752213333268">「<ph name="EXTENSION_NAME" />」要求使用「<ph name="SCANNER_NAME" />」掃瞄。</translation> <translation id="7672504401554182757">選擇哪一部裝置有 <ph name="APP_NAME" /> 的密鑰</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> (在 <ph name="PAGE_TITLE" /> 中)。</translation> +<translation id="7672726198839739113">已封鎖。時間表目前設定為<ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" />,只能手動更新。</translation> <translation id="7673313156293624327">ChromeOS Shill (連線管理員) 記錄</translation> <translation id="7674416868315480713">停用 Linux 入面所有轉送緊嘅連接埠</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> 個應用程式</translation> @@ -8775,7 +8781,7 @@ <ph name="EXTENSION_NAME" /></translation> <translation id="7789963078219276159">起始網頁背景改咗做<ph name="CATEGORY" />。</translation> -<translation id="7791269138074599214">輸入法</translation> +<translation id="7791269138074599214">輸入方法</translation> <translation id="7791429245559955092">此應用程式將安裝在你目前使用的 Chrome 個人檔案中</translation> <translation id="7791436592012979144">已啟用反向捲動功能</translation> <translation id="7791543448312431591">新增</translation> @@ -8868,7 +8874,7 @@ <translation id="7861215335140947162">下載(&D)</translation> <translation id="7861846108263890455">Google 帳戶語言</translation> <translation id="7864539943188674973">停用藍牙</translation> -<translation id="7864825798076155402">要儲存到 Google 帳戶嗎?</translation> +<translation id="7864825798076155402">要儲存在 Google 帳戶中嗎?</translation> <translation id="7865127013871431856">翻譯選項</translation> <translation id="786957569166715433"><ph name="DEVICE_NAME" /> - 已配對</translation> <translation id="7869655448736341731">不限</translation> @@ -9542,6 +9548,7 @@ <translation id="8376384591331888629">包括在此網站上的第三方 Cookie</translation> <translation id="8376451933628734023">如果此網絡應用程式試圖讓您誤認為其他應用程式,請解除安裝。</translation> <translation id="8376532149031784008">正在重新載入 <ph name="DOMAIN" />…</translation> +<translation id="8376610503048439696">管理員安裝的擴充程式仍可讀取及變更此網站</translation> <translation id="8376752431516546391">「Google 搜尋」側面板</translation> <translation id="8377625247046155446">此密鑰只會儲存在此裝置中。關閉所有無痕式視窗後,密鑰會保存在此裝置上。</translation> <translation id="8378714024927312812">由您的機構管理</translation> @@ -10561,7 +10568,7 @@ <translation id="9138978632494473300">在以下位置新增快速鍵:</translation> <translation id="9139988741193276691">設定 Linux</translation> <translation id="9140067245205650184">您使用的功能分支切換 (<ph name="BAD_FLAG" />) 目前不受支援,有可能會影響穩定性和安全性。</translation> -<translation id="914031120300235526">無法解鎖設定檔</translation> +<translation id="914031120300235526">無法解鎖個人檔案</translation> <translation id="9142637293078737510">圖片別名</translation> <translation id="9143298529634201539">要移除建議嗎?</translation> <translation id="9143922477019434797">保護您的密碼</translation> @@ -10690,7 +10697,7 @@ <translation id="951991426597076286">拒絕</translation> <translation id="952471655966876828">當裝置開啟,而且正在使用時,裝置將會自動連線</translation> <translation id="953434574221655299">允許偵測您使用裝置的時間</translation> -<translation id="954749761428814584">語言和輸入法</translation> +<translation id="954749761428814584">語言和輸入方法</translation> <translation id="956500788634395331">保護您免受可能有害的擴充程式影響</translation> <translation id="957179356621191750">6 點</translation> <translation id="957960681186851048">此網站曾嘗試自動下載多個檔案</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb index 5f906172..4338e873e 100644 --- a/chrome/app/resources/generated_resources_zh-TW.xtb +++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -1717,6 +1717,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{在新分頁群組中開啟所有網址(&N)}=1{在新分頁群組中開啟網址(&N)}other{在新分頁群組中開啟所有 ({COUNT} 個) 網址(&N)}}</translation> <translation id="2285942871162473373">無法辨識你的指紋,請再試一次。</translation> <translation id="2287617382468007324">列印 IPP 位址</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{為保護你的資料,系統已將權限從近期未造訪的網站中移除}other{為保護你的資料,系統已將權限從近期未造訪的網站中移除}}</translation> <translation id="2287944065963043964">登入畫面</translation> <translation id="2290615375132886363">平板電腦瀏覽按鈕</translation> <translation id="2291452790265535215">試著在側邊面板上使用書籤、瀏覽歷程和其他功能</translation> @@ -3293,6 +3294,7 @@ <translation id="3497560059572256875">分享 Doodle</translation> <translation id="3497915391670770295">傳送到你的裝置(&D)</translation> <translation id="3500417806337761827">掛接檔案共用區時發生錯誤。已掛接過多 SMB 檔案共用區。</translation> +<translation id="3500764001796099683">啟用隔離網頁應用程式</translation> <translation id="350397915809787283">如果沒有帳戶,請選取第一個選項建立帳戶。</translation> <translation id="3503995387997205657">你可以還原先前的應用程式</translation> <translation id="3505100368357440862">購物建議</translation> @@ -4300,6 +4302,7 @@ <translation id="4275788652681621337">關閉側邊面板</translation> <translation id="4275830172053184480">重新啟動裝置</translation> <translation id="4277434192562187284">XML 設定來源</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{已移除 1 個網站的權限}other{已移除 {NUM_SITES} 個網站的權限}}</translation> <translation id="4278390842282768270">允許</translation> <translation id="4278498748067682896">你將使用「資訊站或看板升級」授權,這項授權只允許裝置在資訊站或看板模式下運作。如果希望使用者登入裝置,請返回上一個畫面,然後使用「Chrome Enterprise 升級版」進行註冊。</translation> <translation id="4278779213160967034">這項程序可能需要幾分鐘才能完成。正在下載檔案。</translation> @@ -7163,6 +7166,7 @@ <translation id="6551508934388063976">無法使用指令。按下 Ctrl + N 鍵可開啟新視窗。</translation> <translation id="6551606359270386381">橢圓形工具</translation> <translation id="6551612971599078809">網站正在使用 USB 裝置</translation> +<translation id="6551620030439692385">系統已封鎖這項功能。時區目前設為「<ph name="TIMEZONE" />」,只能手動更新。</translation> <translation id="6551739526055143276">由 Family Link 管理</translation> <translation id="655384502888039633"><ph name="USER_COUNT" /> 位使用者</translation> <translation id="6555432686520421228">移除所有使用者帳戶,並將你的 <ph name="IDS_SHORT_PRODUCT_NAME" /> 裝置重設為原廠狀態。</translation> @@ -7231,6 +7235,7 @@ <translation id="6608773371844092260">如要設定指紋,請讓孩子輕觸這部「<ph name="DEVICE_TYPE" />」右側的指紋感應器。孩子的指紋資料會安全地儲存在這部「<ph name="DEVICE_TYPE" />」上,絕不會外洩。</translation> <translation id="6609478180749378879">系統會在無痕模式結束後將登入資料儲存在這部裝置上。你可以再次透過這部裝置登入這個網站。</translation> <translation id="6610002944194042868">翻譯選項</translation> +<translation id="6610064275805055636">管理隔離網頁應用程式</translation> <translation id="6611972847767394631">你可以在這裡找到已開啟的分頁</translation> <translation id="661266467055912436">可為你和所有網路使用者提供更完善的安全防護。</translation> <translation id="6613267708691765962">正在掃描惡意軟體...</translation> @@ -8595,6 +8600,7 @@ <translation id="7671472752213333268">「<ph name="EXTENSION_NAME" />」要求使用「<ph name="SCANNER_NAME" />」掃描。</translation> <translation id="7672504401554182757">選擇哪一部裝置有「<ph name="APP_NAME" />」的密碼金鑰</translation> <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> (在「<ph name="PAGE_TITLE" />」中)。</translation> +<translation id="7672726198839739113">系統已封鎖這項功能。時刻表目前設為<ph name="SUNRISE_TIME" /> - <ph name="SUNSET_TIME" />,只能手動更新。</translation> <translation id="7673313156293624327">ChromeOS Shill (連線管理員) 記錄</translation> <translation id="7674416868315480713">停用所有在 Linux 中轉接的連接埠</translation> <translation id="7674537509496907005"><ph name="APP_COUNT" /> 個應用程式</translation> @@ -9528,6 +9534,7 @@ <translation id="8376384591331888629">包括這個網站上的第三方 Cookie</translation> <translation id="8376451933628734023">如果這個網頁應用程式企圖讓你誤認為其他應用程式,請解除安裝。</translation> <translation id="8376532149031784008">正在重新載入 <ph name="DOMAIN" />…</translation> +<translation id="8376610503048439696">系統管理員安裝的擴充功能仍可讀取及變更這個網站</translation> <translation id="8376752431516546391">Google 搜尋側邊面板</translation> <translation id="8377625247046155446">這個密碼金鑰只會儲存在這部裝置中。關閉所有無痕視窗後,密碼金鑰會保存在這部裝置上。</translation> <translation id="8378714024927312812">由貴機構管理</translation>
diff --git a/chrome/app/resources/generated_resources_zu.xtb b/chrome/app/resources/generated_resources_zu.xtb index 222d2416..5cf3709 100644 --- a/chrome/app/resources/generated_resources_zu.xtb +++ b/chrome/app/resources/generated_resources_zu.xtb
@@ -1732,6 +1732,7 @@ <translation id="2285109769884538519">{COUNT,plural, =0{Vula konke eqenjini lethebhu &entsha}=1{Vula eqenjini lethebhu &entsha}one{Vula konke okungu-({COUNT}) eqenjini lethebhu &entsha}other{Vula konke okungu-({COUNT}) eqenjini lethebhu &entsha}}</translation> <translation id="2285942871162473373">Izigxivizo zakho zeminwe azikwazanga ukubonwa. Zama futhi.</translation> <translation id="2287617382468007324">Ikheli le-IPP lokuphrinta</translation> +<translation id="2287704681286152065">{NUM_SITES,plural, =1{Ukuze kuvikelwe idatha yakho, izimvume zisusiwe kusayithi ongakaze ulivakashele kamuva nje}one{Ukuze kuvikelwe idatha yakho, izimvume zisusiwe kumasayithi ongazange uwavakashele kamuva nje}other{Ukuze kuvikelwe idatha yakho, izimvume zisusiwe kumasayithi ongazange uwavakashele kamuva nje}}</translation> <translation id="2287944065963043964">Isikrini sokungena ngemvume</translation> <translation id="2290615375132886363">Izinkinobho zokuzulazula zethebulethi</translation> <translation id="2291452790265535215">Zama ukusebenzisa iphaneli eseceleni ukuze uthole amabhukhimakhi, uhambo, nokunye okwengeziwe</translation> @@ -4316,6 +4317,7 @@ <translation id="4275788652681621337">Khetha iphaneli yohlangothi</translation> <translation id="4275830172053184480">Qalisa kabusha idivayisi yakho</translation> <translation id="4277434192562187284">Umthombo wokulungiselelwa kwe-XML</translation> +<translation id="4278348589087554892">{NUM_SITES,plural, =1{Imvume isusiwe kusayithi engu-1}one{Izimvume zisusiwe kumasayithi angu-{NUM_SITES}}other{Izimvume zisusiwe kumasayithi angu-{NUM_SITES}}}</translation> <translation id="4278390842282768270">Kuvunyelwe</translation> <translation id="4278498748067682896">Uzosebenzisa i-Kiosk ne-Signage Upgrade evumela kuphela idivayisi ukuthi isebenze kukhiyoski noma kumodi yezimpawu. Uma ungathanda ukuthi abasebenzisi bangene ngemvume kudivayisi, sicela ubuyele emuva bese ubhalisa usebenzisa i-Chrome Enterprise Upgrade.</translation> <translation id="4278779213160967034">Le nqubo ingathatha imizuzu embalwa. Idawuniloda amafayela.</translation>
diff --git a/chrome/app/resources/google_chrome_strings_be.xtb b/chrome/app/resources/google_chrome_strings_be.xtb index 7e2bd8a7..3230162 100644 --- a/chrome/app/resources/google_chrome_strings_be.xtb +++ b/chrome/app/resources/google_chrome_strings_be.xtb
@@ -235,7 +235,7 @@ <translation id="4627412468266359539">Дапамагаць паляпшаць функцыі і прадукцыйнасць Chrome OS Flex шляхам аўтаматычнай адпраўкі ў Google даных пра выкарыстанне і дыягностыку (неабавязкова).</translation> <translation id="4633000520311261472">У мэтах бяспекі Chrome мы выключылі некаторыя пашырэнні, якія не значацца ў спісе <ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> і маглі быць дададзены без вашага ведама.</translation> <translation id="4680828127924988555">Скасаваць усталяванне</translation> -<translation id="469553575393225953">Пашырэнні, праграмы і тэмы з невядомых крыніц могуць прычыніць шкоду вашай прыладзе. Chrome рэкамендуе ўсталёўваць іх толькі з Chrome Web Store</translation> +<translation id="469553575393225953">Пашырэнні, праграмы і тэмы з невядомых крыніц могуць прычыніць шкоду вашай прыладзе. Chrome рэкамендуе ўсталёўваць іх толькі з Вэб-крамы Chrome</translation> <translation id="4724676981607797757">Выканаць усталяванне не ўдалося з-за памылкі: пратакол не падтрымліваецца.</translation> <translation id="4728575227883772061">Збой усталявання з-за нявызначанай памылкі. Калі Google Chrome зараз запушчаны, закрыйце яго і паўтарыце спробу.</translation> <translation id="4747730611090640388">Chrome можа ацэньваць, якія вы маеце інтарэсы. Пасля гэтага сайты, якія вы наведваеце, могуць запытваць у браўзера Chrome інфармацыю пра вашы інтарэсы, каб персаналізаваць для вас рэкламу.</translation>
diff --git a/chrome/app/resources/google_chrome_strings_ky.xtb b/chrome/app/resources/google_chrome_strings_ky.xtb index c24e386..4143410 100644 --- a/chrome/app/resources/google_chrome_strings_ky.xtb +++ b/chrome/app/resources/google_chrome_strings_ky.xtb
@@ -236,7 +236,7 @@ <translation id="4627412468266359539">Милдеттүү эмес: Google'га мүчүлүштүктөрдү аныктоо маалыматын жана колдонуу статистикасын автоматтык түрдө жөнөтүү менен, Chrome жана ChromeOS Flex тутумунун функцияларын жана майнаптуулугун жакшыртууга жардам бересиз.</translation> <translation id="4633000520311261472">Жеке маалыматыңызды коргоо үчүн, айрым Chromium кеңейтүүлөрүн өчүрүп койдук, себеби <ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> ичинде аларга байланыштуу маалымат жок. Демек, бул курамдык бөлүктөр тымызын орнотулган.</translation> <translation id="4680828127924988555">Орнотууну токтотуу</translation> -<translation id="469553575393225953">Белгисиз булактардан алынган кеңейтүүлөр, колдонмолор жана темалар түзмөгүңүзгө зыян келтириши мүмкүн. Chrome аларды Chrome Интернет дүкөнүнөн гана орнотууну сунуштайт</translation> +<translation id="469553575393225953">Белгисиз булактардан алынган кеңейтүүлөр, колдонмолор жана темалар түзмөгүңүзгө зыян келтириши мүмкүн. Chrome аларды Chrome Web Store'дон гана орнотууну сунуштайт</translation> <translation id="4724676981607797757">Орнотулган жок, анткени протокол колдоого алынбайт.</translation> <translation id="4728575227883772061">Күтүлбөгөн катадан орнотулбай калды. Учурда Google Chrome иштеп жатса, аны жаап туруп кайталап көрүңүз.</translation> <translation id="4747730611090640388">Chrome сиз кызыккан нерселерди болжолдойт. Кийинчерээк сиз баш баккан сайттар Chrome'дон кызыккан нерселериңиз тууралуу маалымат алып, ылайыктуу жарнамаларды көрсөтө алат.</translation>
diff --git a/chrome/app/resources/google_chrome_strings_pa.xtb b/chrome/app/resources/google_chrome_strings_pa.xtb index 7b0115f..8644165 100644 --- a/chrome/app/resources/google_chrome_strings_pa.xtb +++ b/chrome/app/resources/google_chrome_strings_pa.xtb
@@ -90,7 +90,7 @@ <translation id="2359808026110333948">ਜਾਰੀ ਰੱਖੋ</translation> <translation id="2401189691232800402">ChromeOS ਸਿਸਟਮ</translation> <translation id="2409816192575564775">{NUM_DEVICES,plural, =0{ਇੱਕ ਜਾਂ ਇੱਕ ਤੋਂ ਵੱਧ Chrome ਐਕਸਟੈਂਸ਼ਨਾਂ ਵੱਲੋਂ 1 HID ਡੀਵਾਈਸ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ ਜਾ ਰਹੀ ਸੀ}=1{ਇੱਕ ਜਾਂ ਇੱਕ ਤੋਂ ਵੱਧ Chrome ਐਕਸਟੈਂਸ਼ਨਾਂ ਵੱਲੋਂ 1 HID ਡੀਵਾਈਸ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ ਜਾ ਰਹੀ ਸੀ}other{ਇੱਕ ਜਾਂ ਇੱਕ ਤੋਂ ਵੱਧ Chrome ਐਕਸਟੈਂਸ਼ਨਾਂ ਵੱਲੋਂ # HID ਡੀਵਾਈਸਾਂ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ ਜਾ ਰਹੀ ਸੀ}}</translation> -<translation id="2424440923901031101">ਇਹ ਐਕਸਟੈਂਸ਼ਨ 'Chrome Web Store' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ ਅਤੇ ਇਹ ਅਸੁਰੱਖਿਅਤ ਹੋ ਸਕਦੀ ਹੈ। ਇਸਨੂੰ Chrome ਤੋਂ ਹਟਾਓ, ਤਾਂ ਜੋ ਇਹ ਹੁਣ ਤੁਹਾਡੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਸਮੇਤ ਤੁਹਾਡੇ ਵੱਲੋਂ ਦੇਖੀਆਂ ਗਈਆਂ ਸਾਈਟਾਂ 'ਤੇ ਮੌਜੂਦ ਤੁਹਾਡੇ ਡਾਟੇ ਨੂੰ ਦੇਖ ਅਤੇ ਬਦਲ ਨਾ ਸਕੇ।</translation> +<translation id="2424440923901031101">ਇਹ ਐਕਸਟੈਂਸ਼ਨ 'Chrome ਵੈੱਬ ਸਟੋਰ' ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕਰਦੀ ਹੈ ਅਤੇ ਇਹ ਅਸੁਰੱਖਿਅਤ ਹੋ ਸਕਦੀ ਹੈ। ਇਸਨੂੰ Chrome ਤੋਂ ਹਟਾਓ, ਤਾਂ ਜੋ ਇਹ ਹੁਣ ਤੁਹਾਡੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਸਮੇਤ ਤੁਹਾਡੇ ਵੱਲੋਂ ਦੇਖੀਆਂ ਗਈਆਂ ਸਾਈਟਾਂ 'ਤੇ ਮੌਜੂਦ ਤੁਹਾਡੇ ਡਾਟੇ ਨੂੰ ਦੇਖ ਅਤੇ ਬਦਲ ਨਾ ਸਕੇ।</translation> <translation id="2467438592969358367">Google Chrome ਤੁਹਾਡੇ ਪਾਸਵਰਡ ਨਿਰਯਾਤ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। ਇਹ ਕਰਨ ਦੇਣ ਲਈ ਆਪਣਾ Windows ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ।</translation> <translation id="2472092250898121027">ਇਸ ਐਕਸਟੈਂਸ਼ਨ ਵਿੱਚ ਮਾਲਵੇਅਰ ਹੈ ਅਤੇ ਇਹ ਅਸੁਰੱਖਿਅਤ ਹੈ। ਇਸਨੂੰ Chrome ਤੋਂ ਹਟਾਓ, ਤਾਂ ਜੋ ਇਹ ਹੁਣ ਤੁਹਾਡੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਸਮੇਤ ਤੁਹਾਡੇ ਵੱਲੋਂ ਦੇਖੀਆਂ ਗਈਆਂ ਸਾਈਟਾਂ 'ਤੇ ਮੌਜੂਦ ਤੁਹਾਡੇ ਡਾਟੇ ਨੂੰ ਦੇਖ ਅਤੇ ਬਦਲ ਨਾ ਸਕੇ।</translation> <translation id="2472163211318554013">Chrome ਦਾ ਵੱਧ ਤੋਂ ਵੱਧ ਲਾਹਾ ਲੈਣ ਲਈ ਸਾਈਨ-ਇਨ ਕਰੋ</translation> @@ -236,7 +236,7 @@ <translation id="4627412468266359539">ਵਿਕਲਪਿਕ: ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਤਸ਼ਖੀਸ ਅਤੇ ਵਰਤੋਂ ਡਾਟਾ Google ਨੂੰ ਭੇਜ ਕੇ ChromeOS Flex ਦੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਕਾਰਗੁਜ਼ਾਰੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਵਿੱਚ ਮਦਦ ਕਰੋ।</translation> <translation id="4633000520311261472">Chrome ਨੂੰ ਵੱਧ ਸੁਰੱਖਿਅਤ ਬਣਾਉਣ ਲਈ, ਅਸੀਂ ਕੁਝ ਐਕਸਟੈਂਸ਼ਨਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਹੈ, ਜੋ <ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> ਵਿੱਚ ਸੂਚੀਬੱਧ ਨਹੀਂ ਹਨ ਅਤੇ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸ਼ਾਮਲ ਕੀਤੀਆਂ ਗਈਆਂ ਹੋ ਸਕਦੀਆਂ ਹਨ।</translation> <translation id="4680828127924988555">ਸਥਾਪਨਾ ਰੱਦ ਕਰੋ</translation> -<translation id="469553575393225953">ਅਗਿਆਤ ਸਰੋਤਾਂ ਤੋਂ ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਐਕਸਟੈਂਸ਼ਨਾਂ, ਐਪਾਂ ਅਤੇ ਥੀਮਾਂ ਨਾਲ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ। Chrome ਸਿਰਫ਼ Chrome Web Store ਤੋਂ ਇਨ੍ਹਾਂ ਨੂੰ ਸਥਾਪਤ ਕਰਨ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕਰਦਾ ਹੈ</translation> +<translation id="469553575393225953">ਅਗਿਆਤ ਸਰੋਤਾਂ ਤੋਂ ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਐਕਸਟੈਂਸ਼ਨਾਂ, ਐਪਾਂ ਅਤੇ ਥੀਮਾਂ ਨਾਲ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ। Chrome ਸਿਰਫ਼ Chrome ਵੈੱਬ ਸਟੋਰ ਤੋਂ ਇਨ੍ਹਾਂ ਨੂੰ ਸਥਾਪਤ ਕਰਨ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕਰਦਾ ਹੈ</translation> <translation id="4724676981607797757">ਅਸਮਰਥਿਤ ਪ੍ਰੋਟੋਕੋਲ ਕਾਰਨ ਸਥਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ।</translation> <translation id="4728575227883772061">ਅਨਿਸ਼ਚਿਤ ਗੜਬੜ ਕਾਰਨ ਸਥਾਪਨਾ ਅਸਫਲ ਹੋ ਗਈ। ਜੇਕਰ ਇਸ ਵੇਲੇ Google Chrome ਚੱਲ ਰਿਹਾ ਹੈ, ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਬੰਦ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation> <translation id="4747730611090640388">Chrome ਤੁਹਾਡੀਆਂ ਦਿਲਚਸਪੀਆਂ ਦਾ ਅੰਦਾਜ਼ਾ ਲਗਾ ਸਕਦਾ ਹੈ। ਬਾਅਦ ਵਿੱਚ, ਤੁਸੀਂ ਜਿਹੜੀ ਸਾਈਟ 'ਤੇ ਜਾਂਦੇ ਹੋ ਉਹ Chrome ਨੂੰ ਤੁਹਾਡੇ ਵੱਲੋਂ ਦੇਖੇ ਜਾਣ ਵਾਲੇ ਵਿਗਿਆਪਨਾਂ ਨੂੰ ਵਿਅਕਤੀਗਤ ਬਣਾਉਣ ਵਾਸਤੇ ਤੁਹਾਡੀਆਂ ਦਿਲਚਸਪੀਆਂ ਨੂੰ ਦੇਖਣ ਲਈ ਕਹਿ ਸਕਦੀ ਹੈ।</translation>
diff --git a/chrome/app/resources/google_chrome_strings_pt-BR.xtb b/chrome/app/resources/google_chrome_strings_pt-BR.xtb index 9ca09b7..809c9d31 100644 --- a/chrome/app/resources/google_chrome_strings_pt-BR.xtb +++ b/chrome/app/resources/google_chrome_strings_pt-BR.xtb
@@ -306,7 +306,7 @@ <translation id="6022659036123304283">Deixe o Chrome do seu jeito</translation> <translation id="6025087594896450715">O Google Chrome será reiniciado em <ph name="REMAINING_TIME" /></translation> <translation id="6040143037577758943">Fechar</translation> -<translation id="6070348360322141662">Para maior segurança, o Google Chrome criptografará seus dados</translation> +<translation id="6070348360322141662">Para aumentar a segurança, seus dados serão criptografados pelo Google Chrome</translation> <translation id="608006075545470555">Adicionar um perfil de trabalho a este navegador</translation> <translation id="6113794647360055231">O Chrome ficou ainda melhor</translation> <translation id="6145313976051292476">Abrir PDFs no Chrome</translation>
diff --git a/chrome/app/resources/google_chrome_strings_vi.xtb b/chrome/app/resources/google_chrome_strings_vi.xtb index 4523ba5a..8c4b7f9 100644 --- a/chrome/app/resources/google_chrome_strings_vi.xtb +++ b/chrome/app/resources/google_chrome_strings_vi.xtb
@@ -88,7 +88,7 @@ <translation id="2359808026110333948">Tiếp tục</translation> <translation id="2401189691232800402">Hệ thống ChromeOS</translation> <translation id="2409816192575564775">{NUM_DEVICES,plural, =0{Một hoặc nhiều tiện ích của Chrome đã truy cập vào 1 thiết bị HID}=1{Một hoặc nhiều tiện ích của Chrome đang truy cập vào 1 thiết bị HID}other{Một hoặc nhiều tiện ích của Chrome đang truy cập vào # thiết bị HID}}</translation> -<translation id="2424440923901031101">Tiện ích này vi phạm chính sách của Chrome Web Store và có thể không an toàn. Hãy xoá khỏi Chrome để tiện ích này không thể xem và thay đổi dữ liệu của bạn (bao gồm cả thông tin cá nhân) trên các trang web bạn truy cập nữa.</translation> +<translation id="2424440923901031101">Tiện ích này vi phạm chính sách của Cửa hàng Chrome trực tuyến và có thể không an toàn. Hãy xoá khỏi Chrome để tiện ích này không thể xem và thay đổi dữ liệu của bạn (bao gồm cả thông tin cá nhân) trên các trang web bạn truy cập nữa.</translation> <translation id="2467438592969358367">Google Chrome muốn xuất các mật khẩu của bạn. Hãy nhập mật khẩu Windows để cho phép thực hiện việc này.</translation> <translation id="2472092250898121027">Tiện ích này chứa phần mềm độc hại và không an toàn. Hãy xoá khỏi Chrome để tiện ích này không thể xem và thay đổi dữ liệu của bạn (bao gồm cả thông tin cá nhân) trên các trang web bạn truy cập nữa.</translation> <translation id="2472163211318554013">Đăng nhập để khai thác tối đa Chrome</translation> @@ -234,7 +234,7 @@ <translation id="4627412468266359539">Không bắt buộc: Giúp cải thiện các tính năng và hiệu suất của ChromeOS Flex bằng cách tự động gửi dữ liệu sử dụng và thông tin chẩn đoán cho Google.</translation> <translation id="4633000520311261472">Để làm cho Chrome an toàn hơn, chúng tôi đã vô hiệu hóa một số tiện ích không được liệt kê trong <ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> và có thể đã được thêm mà bạn không biết.</translation> <translation id="4680828127924988555">Huỷ cài đặt</translation> -<translation id="469553575393225953">Các tiện ích, ứng dụng và giao diện không rõ nguồn gốc có thể làm hại thiết bị của bạn. Chrome đề xuất chỉ cài đặt những mục trên qua Chrome Web Store</translation> +<translation id="469553575393225953">Các tiện ích, ứng dụng và giao diện không rõ nguồn gốc có thể làm hại thiết bị của bạn. Chrome đề xuất chỉ cài đặt những mục trên qua Cửa hàng Chrome trực tuyến</translation> <translation id="4724676981607797757">Không cài đặt được do lỗi giao thức không được hỗ trợ.</translation> <translation id="4728575227883772061">Không cài đặt được do lỗi chưa xác định. Nếu Google Chrome hiện đang chạy, vui lòng đóng Google Chrome và thử lại.</translation> <translation id="4747730611090640388">Chrome có thể ước đoán mối quan tâm của bạn. Sau đó, trang web mà bạn truy cập có thể đề nghị Chrome cho biết mối quan tâm của bạn nhằm cá nhân hoá quảng cáo mà bạn thấy.</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 70fdd370..8e919e7 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1370,6 +1370,8 @@ "process_singleton.h", "process_singleton_internal.cc", "process_singleton_internal.h", + "profiles/allowed_domains_for_apps_policy_handler.cc", + "profiles/allowed_domains_for_apps_policy_handler.h", "profiles/bookmark_model_loaded_observer.cc", "profiles/bookmark_model_loaded_observer.h", "profiles/chrome_browser_main_extra_parts_profiles.cc", @@ -5792,6 +5794,8 @@ "performance_manager/policies/report_page_processes_policy.h", "policy/restricted_mgs_policy_provider.cc", "policy/restricted_mgs_policy_provider.h", + "policy/screen_capture_location_policy_handler.cc", + "policy/screen_capture_location_policy_handler.h", "policy/system_features_disable_list_policy_handler.cc", "policy/system_features_disable_list_policy_handler.h", "renderer_context_menu/quick_answers_menu_observer.cc", @@ -7097,6 +7101,8 @@ if (enable_dice_support) { sources += [ + "signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.cc", + "signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.h", "signin/bound_session_credentials/dice_bound_session_cookie_service.cc", "signin/bound_session_credentials/dice_bound_session_cookie_service.h", "signin/bound_session_credentials/dice_bound_session_cookie_service_factory.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1cf122a4..6c60447 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3955,22 +3955,10 @@ {"enable-webassembly-baseline", flag_descriptions::kEnableWasmBaselineName, flag_descriptions::kEnableWasmBaselineDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebAssemblyBaseline)}, - {"enable-webassembly-garbage-collection", - flag_descriptions::kEnableWasmGarbageCollectionName, - flag_descriptions::kEnableWasmGarbageCollectionDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kWebAssemblyGarbageCollection)}, {"enable-webassembly-lazy-compilation", flag_descriptions::kEnableWasmLazyCompilationName, flag_descriptions::kEnableWasmLazyCompilationDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebAssemblyLazyCompilation)}, - {"enable-webassembly-relaxed-simd", - flag_descriptions::kEnableWasmRelaxedSimdName, - flag_descriptions::kEnableWasmRelaxedSimdDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kWebAssemblyRelaxedSimd)}, - {"enable-webassembly-stringref", - flag_descriptions::kEnableWasmStringrefName, - flag_descriptions::kEnableWasmStringrefDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kWebAssemblyStringref)}, {"enable-webassembly-tiering", flag_descriptions::kEnableWasmTieringName, flag_descriptions::kEnableWasmTieringDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebAssemblyTiering)}, @@ -9680,12 +9668,6 @@ kOsDesktop, FEATURE_VALUE_TYPE(features::kSafetyCheckNotificationPermissions)}, - {"notification-interaction-history", - flag_descriptions::kNotificationInteractionHistoryName, - flag_descriptions::kNotificationInteractionHistoryDescription, kOsDesktop, - FEATURE_VALUE_TYPE( - permissions::features::kNotificationInteractionHistory)}, - {"safety-check-unused-site-permissions", flag_descriptions::kSafetyCheckUnusedSitePermissionsName, flag_descriptions::kSafetyCheckUnusedSitePermissionsDescription,
diff --git a/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_unittest.cc b/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_unittest.cc index c95fbf04..5464039c 100644 --- a/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_unittest.cc +++ b/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_unittest.cc
@@ -111,8 +111,7 @@ } TEST_F(AXMediaAppUntrustedHandlerTest, PageMetadataDocumentFirstLoad) { - const std::vector<const std::string> kPageIds{"five", "page", "ids", "in", - "list"}; + const std::vector<std::string> kPageIds{"five", "page", "ids", "in", "list"}; const size_t kTestNumPages = kPageIds.size(); std::vector<PageMetadataPtr> fakeMetadata; for (size_t i = 0; i < kTestNumPages; ++i) { @@ -160,7 +159,7 @@ } TEST_F(AXMediaAppUntrustedHandlerTest, PageMetadataWithDeleteAndUndoDelete) { - const std::vector<const std::string> kPageIds{"pageX", "pageY", "pageZ"}; + const std::vector<std::string> kPageIds{"pageX", "pageY", "pageZ"}; const size_t kTestNumPages = kPageIds.size(); std::vector<PageMetadataPtr> fakeMetadata; for (size_t i = 0; i < kTestNumPages; ++i) { @@ -205,7 +204,7 @@ TEST_F(AXMediaAppUntrustedHandlerTest, PageMetadataWithNewPages) { mojo::FakeMessageDispatchContext fake_dispatch_context; mojo::test::BadMessageObserver bad_message_observer; - const std::vector<const std::string> kPageIds{"pageX", "pageY"}; + const std::vector<std::string> kPageIds{"pageX", "pageY"}; const size_t kTestNumPages = kPageIds.size(); std::vector<PageMetadataPtr> fakeMetadata; for (size_t i = 0; i < kTestNumPages; ++i) { @@ -238,8 +237,7 @@ mojo::FakeMessageDispatchContext fake_dispatch_context; mojo::test::BadMessageObserver bad_message_observer; - const std::vector<const std::string> kPageIds{"pageW", "pageX", "pageY", - "pageZ"}; + const std::vector<std::string> kPageIds{"pageW", "pageX", "pageY", "pageZ"}; const size_t kTestNumPages = kPageIds.size(); std::vector<PageMetadataPtr> fakeMetadata; for (size_t i = 0; i < kTestNumPages; ++i) {
diff --git a/chrome/browser/accessibility/media_app/test/fake_ax_media_app.h b/chrome/browser/accessibility/media_app/test/fake_ax_media_app.h index 7bb76669..47e18c64 100644 --- a/chrome/browser/accessibility/media_app/test/fake_ax_media_app.h +++ b/chrome/browser/accessibility/media_app/test/fake_ax_media_app.h
@@ -27,7 +27,7 @@ bool IsOcrServiceEnabled() const { return ocr_service_enabled_; } bool IsAccessibilityEnabled() const { return accessibility_enabled_; } - const std::vector<const std::string>& PageIdsWithBitmap() const { + const std::vector<std::string>& PageIdsWithBitmap() const { return page_ids_with_bitmap_; } const gfx::Insets& GetViewportBox() const { return viewport_box_; } @@ -42,7 +42,7 @@ private: bool ocr_service_enabled_ = false; bool accessibility_enabled_ = false; - std::vector<const std::string> page_ids_with_bitmap_; + std::vector<std::string> page_ids_with_bitmap_; gfx::Insets viewport_box_; };
diff --git a/chrome/browser/apps/app_service/launch_utils.cc b/chrome/browser/apps/app_service/launch_utils.cc index 33fb123..84d987fc 100644 --- a/chrome/browser/apps/app_service/launch_utils.cc +++ b/chrome/browser/apps/app_service/launch_utils.cc
@@ -295,6 +295,7 @@ case LaunchSource::kFromFullRestore: case LaunchSource::kFromSmartTextContextMenu: case LaunchSource::kFromDiscoverTabNotification: + case LaunchSource::kFromFirstRun: return extensions::AppLaunchSource::kSourceChromeInternal; case LaunchSource::kFromInstalledNotification: return extensions::AppLaunchSource::kSourceInstalledNotification;
diff --git a/chrome/browser/apps/app_service/metrics/app_service_metrics.cc b/chrome/browser/apps/app_service/metrics/app_service_metrics.cc index 6bdf5cf..9f21430 100644 --- a/chrome/browser/apps/app_service/metrics/app_service_metrics.cc +++ b/chrome/browser/apps/app_service/metrics/app_service_metrics.cc
@@ -156,6 +156,10 @@ base::UmaHistogramEnumeration("Apps.DefaultAppLaunch.FromInstaller", default_app_name); break; + case apps::LaunchSource::kFromFirstRun: + base::UmaHistogramEnumeration("Apps.DefaultAppLaunch.FromFirstRun", + default_app_name); + break; case apps::LaunchSource::kFromCommandLine: case apps::LaunchSource::kFromBackgroundMode: case apps::LaunchSource::kFromAppHomePage:
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_base.cc b/chrome/browser/apps/app_service/publishers/extension_apps_base.cc index a1c6df1b..7cf1438 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps_base.cc +++ b/chrome/browser/apps/app_service/publishers/extension_apps_base.cc
@@ -350,6 +350,7 @@ case apps::LaunchSource::kFromProfileMenu: case apps::LaunchSource::kFromSysTrayCalendar: case apps::LaunchSource::kFromInstaller: + case apps::LaunchSource::kFromFirstRun: break; }
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc index b7f17695..20c2a35 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc +++ b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
@@ -171,6 +171,7 @@ case apps::LaunchSource::kFromProfileMenu: case apps::LaunchSource::kFromSysTrayCalendar: case apps::LaunchSource::kFromInstaller: + case apps::LaunchSource::kFromFirstRun: return ash::LAUNCH_FROM_UNKNOWN; } }
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 5ef2ef4..4d1757a7 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3915,17 +3915,7 @@ } }; -// TODO(crbug.com/1087381): Flaky on mac -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) || \ - ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ - defined(ADDRESS_SANITIZER)) -#define MAYBE_Shim_TestZoomAPI DISABLED_Shim_TestZoomAPI -#else -#define MAYBE_Shim_TestZoomAPI Shim_TestZoomAPI -#endif -IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_Shim_TestZoomAPI) { +IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestZoomAPI) { TestHelper("testZoomAPI", "web_view/shim", NO_TEST_SERVER); } @@ -4017,8 +4007,7 @@ TestHelper("testPerOriginZoomMode", "web_view/shim", NO_TEST_SERVER); } -// TODO(crbug.com/935665): Test has flaky failures on all platforms. -IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_Shim_TestPerViewZoomMode) { +IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPerViewZoomMode) { TestHelper("testPerViewZoomMode", "web_view/shim", NO_TEST_SERVER); }
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc index aee01c39..6a4f441 100644 --- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc +++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -112,6 +112,7 @@ #include "chrome/browser/ash/login/session/chrome_session_manager.h" #include "chrome/browser/ash/login/session/user_session_manager.h" #include "chrome/browser/ash/login/startup_utils.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/login/wizard_controller.h" #include "chrome/browser/ash/memory_metrics.h" @@ -1590,6 +1591,10 @@ // Let the UserManager unregister itself as an observer of the CrosSettings // singleton before it is destroyed. This also ensures that the UserManager // has no URLRequest pending (see http://crbug.com/276659). + if (auto* user_image_manager_registry = + ash::UserImageManagerRegistry::Get()) { + user_image_manager_registry->Shutdown(); + } if (g_browser_process->platform_part()->user_manager()) { g_browser_process->platform_part()->user_manager()->Shutdown(); }
diff --git a/chrome/browser/ash/crosapi/prefs_ash.cc b/chrome/browser/ash/crosapi/prefs_ash.cc index 339a57d6..6cf0c87 100644 --- a/chrome/browser/ash/crosapi/prefs_ash.cc +++ b/chrome/browser/ash/crosapi/prefs_ash.cc
@@ -114,8 +114,6 @@ ash::prefs::kAccessibilitySwitchAccessEnabled}, {mojom::PrefPath::kAccessibilityVirtualKeyboardEnabled, ash::prefs::kAccessibilityVirtualKeyboardEnabled}, - {mojom::PrefPath::kProtectedContentDefault, - prefs::kProtectedContentDefault}, {mojom::PrefPath::kProxy, ash::prefs::kProxy}}); auto* pref_name = kExtensionPrefPathToName.find(path); DCHECK(pref_name != kExtensionPrefPathToName.end()); @@ -272,6 +270,7 @@ std::optional<PrefsAsh::State> PrefsAsh::GetState(mojom::PrefPath path) { switch (path) { case mojom::PrefPath::kUnknown: + case mojom::PrefPath::kProtectedContentDefaultDeprecated: LOG(WARNING) << "Unknown pref path: " << path; return std::nullopt; case mojom::PrefPath::kMetricsReportingEnabled: @@ -347,7 +346,6 @@ case mojom::PrefPath::kAccessibilityStickyKeysEnabled: case mojom::PrefPath::kAccessibilitySwitchAccessEnabled: case mojom::PrefPath::kAccessibilityVirtualKeyboardEnabled: - case mojom::PrefPath::kProtectedContentDefault: case mojom::PrefPath::kProxy: { if (!profile_prefs_registrar_) { LOG(WARNING) << "Primary profile is not yet initialized";
diff --git a/chrome/browser/ash/first_run/first_run.cc b/chrome/browser/ash/first_run/first_run.cc index f094bbe..5b857036 100644 --- a/chrome/browser/ash/first_run/first_run.cc +++ b/chrome/browser/ash/first_run/first_run.cc
@@ -40,6 +40,7 @@ #include "ui/display/screen.h" #include "ui/events/event_constants.h" #include "ui/gfx/geometry/rect.h" +#include "url/gurl.h" namespace ash { namespace first_run { @@ -101,7 +102,9 @@ AppLauncher& operator=(const AppLauncher&) = delete; void LaunchHelpApp() { - LaunchSystemWebAppAsync(profile_, SystemWebAppType::HELP); + ash::SystemAppLaunchParams params; + params.launch_source = apps::LaunchSource::kFromFirstRun; + LaunchSystemWebAppAsync(profile_, SystemWebAppType::HELP, params); profile_->GetPrefs()->SetBoolean(prefs::kFirstRunTutorialShown, true); delete this; }
diff --git a/chrome/browser/ash/login/lock/screen_locker_browsertest.cc b/chrome/browser/ash/login/lock/screen_locker_browsertest.cc index 0eafd95..88947d0d 100644 --- a/chrome/browser/ash/login/lock/screen_locker_browsertest.cc +++ b/chrome/browser/ash/login/lock/screen_locker_browsertest.cc
@@ -18,9 +18,9 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/ash/components/dbus/biod/fake_biod_client.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" #include "components/prefs/pref_service.h" @@ -121,12 +121,7 @@ BrowserWindow* browser_window = browser()->window(); auto* window_state = WindowState::Get(browser_window->GetNativeWindow()); { - FullscreenNotificationObserver fullscreen_waiter(browser()); - browser() - ->exclusive_access_manager() - ->fullscreen_controller() - ->ToggleBrowserFullscreenMode(); - fullscreen_waiter.Wait(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_window->IsFullscreen()); EXPECT_FALSE(window_state->GetHideShelfWhenFullscreen()); EXPECT_FALSE(tester.IsLocked()); @@ -151,14 +146,14 @@ // fullscreen. The fullscreen window has all of the pixels when in tab // fullscreen. { - FullscreenNotificationObserver fullscreen_waiter(browser()); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); browser() ->exclusive_access_manager() ->fullscreen_controller() ->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame()); - fullscreen_waiter.Wait(); + waiter.Wait(); EXPECT_TRUE(browser_window->IsFullscreen()); EXPECT_TRUE(window_state->GetHideShelfWhenFullscreen()); EXPECT_FALSE(tester.IsLocked());
diff --git a/chrome/browser/ash/login/screens/user_creation_screen.cc b/chrome/browser/ash/login/screens/user_creation_screen.cc index 9133d40..1c520e8d 100644 --- a/chrome/browser/ash/login/screens/user_creation_screen.cc +++ b/chrome/browser/ash/login/screens/user_creation_screen.cc
@@ -83,15 +83,14 @@ } bool UserCreationScreen::MaybeSkip(WizardContext& context) { - if (g_browser_process->platform_part() - ->browser_policy_connector_ash() - ->IsDeviceEnterpriseManaged() || - context.skip_to_login_for_tests) { - context.is_user_creation_enabled = false; + const bool is_managed = g_browser_process->platform_part() + ->browser_policy_connector_ash() + ->IsDeviceEnterpriseManaged(); + context.is_user_creation_enabled = !is_managed; + if (context.skip_to_login_for_tests || is_managed) { RunExitCallback(Result::SKIPPED); return true; } - context.is_user_creation_enabled = true; return false; }
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc index 67409e9..f08eec3 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
@@ -32,8 +32,8 @@ #include "chrome/browser/ash/login/test/device_state_mixin.h" #include "chrome/browser/ash/login/test/login_manager_mixin.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h" -#include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h" #include "chrome/browser/ash/policy/core/device_policy_builder.h" @@ -289,7 +289,7 @@ user_manager::UserManager::Get()->GetActiveUser(); ASSERT_TRUE(user); UserImageManagerImpl* uim = static_cast<UserImageManagerImpl*>( - ChromeUserManager::Get()->GetUserImageManager(user->GetAccountId())); + UserImageManagerRegistry::Get()->GetManager(user->GetAccountId())); if (uim->job_.get()) { run_loop_ = std::make_unique<base::RunLoop>(); run_loop_->Run(); @@ -345,7 +345,7 @@ run_loop_ = std::make_unique<base::RunLoop>(); const gfx::ImageSkia& image = default_user_image::GetStubDefaultImage(); UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(test_account_id1_); + UserImageManagerRegistry::Get()->GetManager(test_account_id1_); user_image_manager->SaveUserImage(user_manager::UserImage::CreateAndEncode( image, user_manager::UserImage::FORMAT_JPEG)); run_loop_->Run(); @@ -377,7 +377,7 @@ UserImageManagerImpl::SkipDefaultUserImageDownloadForTesting(); UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(test_account_id1_); + UserImageManagerRegistry::Get()->GetManager(test_account_id1_); user_image_manager->SaveUserDefaultImageIndex( default_user_image::kFirstDefaultImageIndex); @@ -405,7 +405,7 @@ run_loop_ = std::make_unique<base::RunLoop>(); UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(test_account_id1_); + UserImageManagerRegistry::Get()->GetManager(test_account_id1_); user_image_manager->SaveUserImage(user_manager::UserImage::CreateAndEncode( custom_image, user_manager::UserImage::FORMAT_JPEG)); run_loop_->Run(); @@ -442,7 +442,7 @@ run_loop_ = std::make_unique<base::RunLoop>(); UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(test_account_id1_); + UserImageManagerRegistry::Get()->GetManager(test_account_id1_); user_image_manager->SaveUserImageFromFile(custom_image_path); run_loop_->Run(); @@ -506,7 +506,7 @@ run_loop_ = std::make_unique<base::RunLoop>(); UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(test_account_id1_); + UserImageManagerRegistry::Get()->GetManager(test_account_id1_); user_image_manager->SaveUserImageFromProfileImage(); run_loop_->Run(); @@ -702,7 +702,7 @@ EXPECT_TRUE(default_user_image::IsInCurrentImageSet(user_image_index)); UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(enterprise_account_id_); + UserImageManagerRegistry::Get()->GetManager(enterprise_account_id_); user_image_manager->SaveUserDefaultImageIndex(user_image_index); EXPECT_TRUE(user->HasDefaultImage()); @@ -730,7 +730,7 @@ // Choose a user image. Verify that the chosen user image is set and // persisted. UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(enterprise_account_id_); + UserImageManagerRegistry::Get()->GetManager(enterprise_account_id_); user_image_manager->SaveUserDefaultImageIndex( default_user_image::kFirstDefaultImageIndex); @@ -810,7 +810,7 @@ // Choose a different user image. Verify that the user image does not change // as policy takes precedence. UserImageManager* user_image_manager = - ChromeUserManager::Get()->GetUserImageManager(enterprise_account_id_); + UserImageManagerRegistry::Get()->GetManager(enterprise_account_id_); user_image_manager->SaveUserDefaultImageIndex( default_user_image::kFirstDefaultImageIndex);
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc index 23fc4ec..09af593 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc
@@ -11,14 +11,27 @@ #include "components/user_manager/user_type.h" namespace ash { +namespace { +UserImageManagerRegistry* g_instance = nullptr; +} // namespace + +// static +UserImageManagerRegistry* UserImageManagerRegistry::Get() { + return g_instance; +} UserImageManagerRegistry::UserImageManagerRegistry( user_manager::UserManager* user_manager) : user_manager_(user_manager) { + CHECK(!g_instance); + g_instance = this; observation_.Observe(user_manager); } -UserImageManagerRegistry::~UserImageManagerRegistry() = default; +UserImageManagerRegistry::~UserImageManagerRegistry() { + CHECK_EQ(g_instance, this); + g_instance = nullptr; +} UserImageManager* UserImageManagerRegistry::GetManager( const AccountId& account_id) {
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h index b0cec21..de1f7a63 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h
@@ -27,6 +27,10 @@ // This is effectively a singleton in production. class UserImageManagerRegistry : public user_manager::UserManager::Observer { public: + // Returns the global UserImageManagerRegistry instance. + static UserImageManagerRegistry* Get(); + + // Given user_manager's lifetime needs to outlive this instance. explicit UserImageManagerRegistry(user_manager::UserManager* user_manager); UserImageManagerRegistry(const UserImageManagerRegistry&) = delete; UserImageManagerRegistry operator=(UserImageManagerRegistry&) = delete;
diff --git a/chrome/browser/ash/login/users/avatar/user_image_sync_observer.cc b/chrome/browser/ash/login/users/avatar/user_image_sync_observer.cc index 5ffdb45..bc30908 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_sync_observer.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_sync_observer.cc
@@ -10,7 +10,7 @@ #include "ash/constants/ash_features.h" #include "base/functional/bind.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager.h" -#include "chrome/browser/ash/login/users/chrome_user_manager.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" @@ -159,7 +159,7 @@ return; } UserImageManager* image_manager = - ChromeUserManager::Get()->GetUserImageManager(user_->GetAccountId()); + UserImageManagerRegistry::Get()->GetManager(user_->GetAccountId()); if (synced_index == user_manager::User::USER_IMAGE_PROFILE) { image_manager->SaveUserImageFromProfileImage(); } else {
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc index a68733a..65c3ac0a 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -47,7 +47,6 @@ #include "chrome/browser/ash/login/signin/auth_error_observer.h" #include "chrome/browser/ash/login/signin/auth_error_observer_factory.h" #include "chrome/browser/ash/login/users/affiliation.h" -#include "chrome/browser/ash/login/users/avatar/user_image_manager.h" #include "chrome/browser/ash/login/users/chrome_user_manager_util.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" #include "chrome/browser/ash/login/users/multi_profile_user_controller.h" @@ -292,7 +291,6 @@ : nullptr), cros_settings_(CrosSettings::Get()), device_local_account_policy_service_(nullptr), - user_image_manager_registry_(this), multi_profile_user_controller_(GetLocalState(), this), mount_performer_(std::make_unique<MountPerformer>()) { UpdateNumberOfUsers(); @@ -434,8 +432,6 @@ device_local_account_policy_service_->RemoveObserver(this); } - user_image_manager_registry_.Shutdown(); - multi_profile_user_controller_.Shutdown(); cloud_external_data_policy_handlers_.clear(); session_observation_.Reset(); @@ -446,11 +442,6 @@ return &multi_profile_user_controller_; } -UserImageManager* ChromeUserManagerImpl::GetUserImageManager( - const AccountId& account_id) { - return user_image_manager_registry_.GetManager(account_id); -} - user_manager::UserList ChromeUserManagerImpl::GetUsersAllowedForMultiProfile() const { // Supervised users are not allowed to use multi-profiles.
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.h b/chrome/browser/ash/login/users/chrome_user_manager_impl.h index 9c826dea..4c2cdba8 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_impl.h +++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.h
@@ -17,7 +17,6 @@ #include "base/scoped_observation.h" #include "base/synchronization/lock.h" #include "chrome/browser/ash/login/users/affiliation.h" -#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/policy/core/device_local_account.h" @@ -72,7 +71,6 @@ // UserManagerInterface implementation: MultiProfileUserController* GetMultiProfileUserController() override; - UserImageManager* GetUserImageManager(const AccountId& account_id) override; // UserManager implementation: void Shutdown() override; @@ -221,9 +219,6 @@ session_manager::SessionManagerObserver> session_observation_{this}; - // TODO(b/278643115): Move this out from ChromeUserManagerImpl. - UserImageManagerRegistry user_image_manager_registry_; - // Session length limiter. std::unique_ptr<SessionLengthLimiter> session_length_limiter_;
diff --git a/chrome/browser/ash/login/users/fake_chrome_user_manager.cc b/chrome/browser/ash/login/users/fake_chrome_user_manager.cc index a407860..c8067509 100644 --- a/chrome/browser/ash/login/users/fake_chrome_user_manager.cc +++ b/chrome/browser/ash/login/users/fake_chrome_user_manager.cc
@@ -14,7 +14,6 @@ #include "base/ranges/algorithm.h" #include "base/system/sys_info.h" #include "base/task/single_thread_task_runner.h" -#include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/login/users/chrome_user_manager_util.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" @@ -205,19 +204,6 @@ return multi_profile_user_controller_; } -UserImageManager* FakeChromeUserManager::GetUserImageManager( - const AccountId& account_id) { - UserImageManagerMap::iterator user_image_manager_it = - user_image_managers_.find(account_id); - if (user_image_manager_it != user_image_managers_.end()) { - return user_image_manager_it->second.get(); - } - auto mgr = std::make_unique<UserImageManagerImpl>(account_id, this); - UserImageManagerImpl* mgr_raw = mgr.get(); - user_image_managers_[account_id] = std::move(mgr); - return mgr_raw; -} - void FakeChromeUserManager::SwitchActiveUser(const AccountId& account_id) { active_account_id_ = account_id; active_user_ = nullptr; @@ -319,10 +305,6 @@ void FakeChromeUserManager::Shutdown() { ChromeUserManager::Shutdown(); - - for (auto& user_image_manager : user_image_managers_) { - user_image_manager.second->Shutdown(); - } } const user_manager::UserList& FakeChromeUserManager::GetUsers() const {
diff --git a/chrome/browser/ash/login/users/fake_chrome_user_manager.h b/chrome/browser/ash/login/users/fake_chrome_user_manager.h index f91c3706..df12aeb9a 100644 --- a/chrome/browser/ash/login/users/fake_chrome_user_manager.h +++ b/chrome/browser/ash/login/users/fake_chrome_user_manager.h
@@ -148,7 +148,6 @@ // UserManagerInterface override. MultiProfileUserController* GetMultiProfileUserController() override; - UserImageManager* GetUserImageManager(const AccountId& account_id) override; // ChromeUserManager override. void SetUserAffiliation( @@ -191,9 +190,6 @@ bool IsEphemeralAccountIdByPolicy(const AccountId& account_id) const override; private: - using UserImageManagerMap = - std::map<AccountId, std::unique_ptr<UserImageManager>>; - // Returns the active user. user_manager::User* GetActiveUserInternal() const; @@ -214,9 +210,6 @@ // Whether the current user can lock. bool current_user_can_lock_ = false; - - // User avatar managers. - UserImageManagerMap user_image_managers_; }; } // namespace ash
diff --git a/chrome/browser/ash/login/users/user_manager_interface.h b/chrome/browser/ash/login/users/user_manager_interface.h index 2693bf2b..4f18cbb2 100644 --- a/chrome/browser/ash/login/users/user_manager_interface.h +++ b/chrome/browser/ash/login/users/user_manager_interface.h
@@ -5,12 +5,9 @@ #ifndef CHROME_BROWSER_ASH_LOGIN_USERS_USER_MANAGER_INTERFACE_H_ #define CHROME_BROWSER_ASH_LOGIN_USERS_USER_MANAGER_INTERFACE_H_ -class AccountId; - namespace ash { class MultiProfileUserController; -class UserImageManager; // ChromeOS specific add-ons interface for the UserManager. class UserManagerInterface { @@ -23,8 +20,6 @@ virtual ~UserManagerInterface() = default; virtual MultiProfileUserController* GetMultiProfileUserController() = 0; - virtual UserImageManager* GetUserImageManager( - const AccountId& account_id) = 0; }; } // namespace ash
diff --git a/chrome/browser/ash/login/users/user_manager_unittest.cc b/chrome/browser/ash/login/users/user_manager_unittest.cc index 913cf796..3127efd 100644 --- a/chrome/browser/ash/login/users/user_manager_unittest.cc +++ b/chrome/browser/ash/login/users/user_manager_unittest.cc
@@ -17,6 +17,7 @@ #include "base/run_loop.h" #include "base/values.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/chrome_user_manager_impl.h" #include "chrome/browser/ash/policy/core/device_local_account.h" #include "chrome/browser/ash/profiles/profile_helper.h" @@ -204,7 +205,10 @@ void ResetUserManager() { // Initialize the UserManager singleton to a fresh ChromeUserManagerImpl // instance. + user_image_manager_registry_.reset(); user_manager_.Reset(ChromeUserManagerImpl::CreateChromeUserManager()); + user_image_manager_registry_ = + std::make_unique<ash::UserImageManagerRegistry>(user_manager_.Get()); // ChromeUserManagerImpl ctor posts a task to reload policies. // Also ensure that all existing ongoing user manager tasks are completed. @@ -283,6 +287,7 @@ std::unique_ptr<ScopedTestingLocalState> local_state_; user_manager::TypedScopedUserManager<ChromeUserManager> user_manager_; + std::unique_ptr<ash::UserImageManagerRegistry> user_image_manager_registry_; base::ScopedTempDir temp_dir_; };
diff --git a/chrome/browser/ash/login/webview_login_browsertest.cc b/chrome/browser/ash/login/webview_login_browsertest.cc index 9ef99e10..10ff016a 100644 --- a/chrome/browser/ash/login/webview_login_browsertest.cc +++ b/chrome/browser/ash/login/webview_login_browsertest.cc
@@ -11,6 +11,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" #include "ash/public/cpp/login_screen_test_api.h" +#include "ash/shell.h" #include "base/check_deref.h" #include "base/files/file_util.h" #include "base/functional/bind.h" @@ -68,6 +69,7 @@ #include "chrome/browser/ui/webui/ash/login/gaia_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/marketing_opt_in_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/quick_start_screen_handler.h" +#include "chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h" #include "chrome/browser/ui/webui/signin/signin_utils.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" @@ -132,6 +134,9 @@ #include "services/network/public/mojom/network_context.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/event_constants.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/events/test/event_generator.h" namespace ash { @@ -361,6 +366,15 @@ base::test::ScopedFeatureList scoped_feature_list_; }; +IN_PROC_BROWSER_TEST_F(WebviewLoginTest, BackButtonOobeFlow) { + WaitForGaiaPageLoadAndPropertyUpdate(); + ExpectIdentifierPage(); + + // Click back to reload (unreachable) identifier page. + test::OobeJS().ClickOnPath(kBackButton); + OobeScreenWaiter(UserCreationView::kScreenId).Wait(); +} + IN_PROC_BROWSER_TEST_F(WebviewLoginTest, ErrorScreenOnGaiaError) { WaitForGaiaPageLoadAndPropertyUpdate(); ExpectIdentifierPage(); @@ -370,8 +384,9 @@ GaiaUrls::GetInstance()->embedded_setup_chromeos_url(), net::HTTP_NOT_FOUND); - // Click back to reload (unreachable) identifier page. - test::OobeJS().ClickOnPath(kBackButton); + // Click ESC key to reload (unreachable) identifier page. + ui::test::EventGenerator generator(Shell::Get()->GetPrimaryRootWindow()); + generator.PressAndReleaseKey(ui::VKEY_ESCAPE, ui::EF_NONE); OobeScreenWaiter(ErrorScreenView::kScreenId).Wait(); } @@ -470,9 +485,11 @@ // later if it has been cleared. InjectCookie(signin_frame_partition_1); - // Press the back button at a sign-in screen without pre-existing users to + // Press ESC key at a sign-in screen without pre-existing users to // start a new sign-in attempt. - test::OobeJS().ClickOnPath(kBackButton); + ui::test::EventGenerator generator(Shell::Get()->GetPrimaryRootWindow()); + generator.PressAndReleaseKey(ui::VKEY_ESCAPE, ui::EF_NONE); + WaitForGaiaPageBackButtonUpdate(); // Expect that we got back to the identifier page, as there are no known users // so the sign-in screen will not display user pods.
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc index 34932d9..75f29426 100644 --- a/chrome/browser/ash/login/wizard_controller.cc +++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -1365,8 +1365,10 @@ case GaiaScreen::Result::CANCEL: { if (features::IsOobeSoftwareUpdateEnabled()) { // When `OobeSoftwareUpdate` is enabled, clicking the back button should - // return the user to the user creation screen if it was enabled. - if (wizard_context_->is_user_creation_enabled && + // return the user to the user creation screen if it is enabled or the + // user is still in the oobe flow. + if ((wizard_context_->is_user_creation_enabled || + !wizard_context_->is_add_person_flow) && result == GaiaScreen::Result::BACK) { AdvanceToScreen(UserCreationView::kScreenId); break;
diff --git a/chrome/browser/ash/policy/external_data/handlers/user_avatar_image_external_data_handler.cc b/chrome/browser/ash/policy/external_data/handlers/user_avatar_image_external_data_handler.cc index 1b03b907..eb25e888 100644 --- a/chrome/browser/ash/policy/external_data/handlers/user_avatar_image_external_data_handler.cc +++ b/chrome/browser/ash/policy/external_data/handlers/user_avatar_image_external_data_handler.cc
@@ -7,7 +7,7 @@ #include <utility> #include "chrome/browser/ash/login/users/avatar/user_image_manager.h" -#include "chrome/browser/ash/login/users/chrome_user_manager.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/settings/cros_settings.h" #include "components/policy/policy_constants.h" @@ -16,7 +16,7 @@ namespace { ash::UserImageManager* GetUserImageManager(const std::string& user_id) { - return ash::ChromeUserManager::Get()->GetUserImageManager( + return ash::UserImageManagerRegistry::Get()->GetManager( CloudExternalDataPolicyHandler::GetAccountId(user_id)); } @@ -58,8 +58,8 @@ void UserAvatarImageExternalDataHandler::RemoveForAccountId( const AccountId& account_id, base::OnceClosure on_removed) { - ash::ChromeUserManager::Get() - ->GetUserImageManager(account_id) + ash::UserImageManagerRegistry::Get() + ->GetManager(account_id) ->DeleteUserImage(); std::move(on_removed).Run();
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/enterprise_policy_delegate_impl.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/enterprise_policy_delegate_impl.cc index 072538c..481fc55 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/enterprise_policy_delegate_impl.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/enterprise_policy_delegate_impl.cc
@@ -7,7 +7,7 @@ #include "ash/public/cpp/wallpaper/wallpaper_controller.h" #include "ash/shell.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager.h" -#include "chrome/browser/ash/login/users/chrome_user_manager.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_utils.h" #include "chrome/browser/profiles/profile.h" #include "components/user_manager/user.h" @@ -19,7 +19,7 @@ namespace { ash::UserImageManager* GetUserImageManager(const Profile* profile) { - return ash::ChromeUserManager::Get()->GetUserImageManager( + return ash::UserImageManagerRegistry::Get()->GetManager( GetAccountId(profile)); }
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_integration_browsertest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_integration_browsertest.cc index 9bfb00e..2cafd5f 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_integration_browsertest.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_integration_browsertest.cc
@@ -23,8 +23,8 @@ #include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/ash/system_web_apps/test_support/system_web_app_integration_test.h" #include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/ui/base/window_properties.h" #include "components/user_manager/user_manager.h" @@ -218,7 +218,7 @@ DCHECK(widget); EXPECT_FALSE(widget->IsFullscreen()); - FullscreenNotificationObserver waiter(browser); + ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = true}); web_contents->GetPrimaryMainFrame() ->ExecuteJavaScriptWithUserGestureForTests( u"personalizationTestApi.enterFullscreen();", base::NullCallback());
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc index b38d116..490bbb4 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc
@@ -19,8 +19,8 @@ #include "chrome/browser/ash/camera_presence_notifier.h" #include "chrome/browser/ash/login/users/avatar/user_image_file_selector.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/avatar/user_image_prefs.h" -#include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_manager.h" @@ -93,8 +93,7 @@ {base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})) { ash::UserImageManager* user_image_manager = - ash::ChromeUserManager::Get()->GetUserImageManager( - GetAccountId(profile_)); + ash::UserImageManagerRegistry::Get()->GetManager(GetAccountId(profile_)); user_image_manager->DownloadProfileImage(); user_image_file_selector_ = std::make_unique<ash::UserImageFileSelector>(web_ui); @@ -138,8 +137,7 @@ OnUserImageChanged(*user); ash::UserImageManager* user_image_manager = - ash::ChromeUserManager::Get()->GetUserImageManager( - GetAccountId(profile_)); + ash::UserImageManagerRegistry::Get()->GetManager(GetAccountId(profile_)); const gfx::ImageSkia& profile_image = user_image_manager->DownloadedProfileImage(); OnUserProfileImageUpdated(*user, profile_image); @@ -186,8 +184,8 @@ ash::UserImageManager::ImageIndexToHistogramIndex(index)); } - auto* user_image_manager = ash::ChromeUserManager::Get()->GetUserImageManager( - GetAccountId(profile_)); + auto* user_image_manager = + ash::UserImageManagerRegistry::Get()->GetManager(GetAccountId(profile_)); user_image_manager->SaveUserDefaultImageIndex(index); } @@ -205,8 +203,7 @@ } ash::UserImageManager* user_image_manager = - ash::ChromeUserManager::Get()->GetUserImageManager( - GetAccountId(profile_)); + ash::UserImageManagerRegistry::Get()->GetManager(GetAccountId(profile_)); user_image_manager->SaveUserImageFromProfileImage(); } @@ -249,8 +246,7 @@ } ash::UserImageManager* user_image_manager = - ash::ChromeUserManager::Get()->GetUserImageManager( - GetAccountId(profile_)); + ash::UserImageManagerRegistry::Get()->GetManager(GetAccountId(profile_)); user_image_manager->SaveUserImage(std::move(last_external_user_image_)); } @@ -263,8 +259,7 @@ ash::default_user_image::kHistogramImageExternal); ash::UserImageManager* user_image_manager = - ash::ChromeUserManager::Get()->GetUserImageManager( - GetAccountId(profile_)); + ash::UserImageManagerRegistry::Get()->GetManager(GetAccountId(profile_)); user_image_manager->SaveUserImageFromFile(path); } @@ -387,8 +382,8 @@ // Image was successfully decoded so it is valid png data. user_image->MarkAsSafe(); - auto* user_image_manager = ash::ChromeUserManager::Get()->GetUserImageManager( - GetAccountId(profile_)); + auto* user_image_manager = + ash::UserImageManagerRegistry::Get()->GetManager(GetAccountId(profile_)); user_image_manager->SaveUserImage(std::move(user_image)); }
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc index 9adbcb8a..5f68900f 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ash/login/users/avatar/fake_user_image_file_selector.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/avatar/user_image_prefs.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" @@ -225,7 +226,7 @@ ash::UserImageManagerImpl* user_image_manager() { return static_cast<ash::UserImageManagerImpl*>( - ash::ChromeUserManager::Get()->GetUserImageManager( + ash::UserImageManagerRegistry::Get()->GetManager( GetAccountId(profile_))); } @@ -277,6 +278,8 @@ base::test::ScopedFeatureList scoped_feature_list_; content::BrowserTaskEnvironment task_environment_; user_manager::ScopedUserManager scoped_user_manager_; + UserImageManagerRegistry user_image_manager_registry_{ + user_manager::UserManager::Get()}; TestingProfileManager profile_manager_; data_decoder::test::InProcessDataDecoder data_decoder_; content::TestWebUI web_ui_;
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc index 83304843..bd5e60fb 100644 --- a/chrome/browser/background/background_mode_manager.cc +++ b/chrome/browser/background/background_mode_manager.cc
@@ -256,7 +256,7 @@ // Copy all current extensions into our list of |current_extensions_|. for (const auto& application : *applications_) { const extensions::ExtensionId& id = application->id(); - if (current_extensions_.count(id) == 0) { + if (!current_extensions_.contains(id)) { // Not found in our set yet - add it and maybe return as a previously // unseen extension. current_extensions_.insert(id); @@ -327,8 +327,8 @@ optimizer_ = BackgroundModeOptimizer::Create(); } - // If the -keep-alive-for-test flag is passed, then always keep chrome running - // in the background until the user explicitly terminates it. + // If the --keep-alive-for-test flag is passed, then always keep the browser + // running in the background until the user explicitly terminates it. if (command_line.HasSwitch(switches::kKeepAliveForTest)) keep_alive_for_test_ = true;
diff --git a/chrome/browser/background/background_mode_optimizer.cc b/chrome/browser/background/background_mode_optimizer.cc index 00d21d7b..2d925a3 100644 --- a/chrome/browser/background/background_mode_optimizer.cc +++ b/chrome/browser/background/background_mode_optimizer.cc
@@ -24,8 +24,8 @@ // static std::unique_ptr<BackgroundModeOptimizer> BackgroundModeOptimizer::Create() { - // If the -keep-alive-for-test flag is passed, then always keep chrome running - // in the background until the user explicitly terminates it. + // If the --keep-alive-for-test flag is passed, then always keep the browser + // running in the background until the user explicitly terminates it. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kKeepAliveForTest)) { return nullptr; @@ -33,6 +33,7 @@ #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) if (base::FeatureList::IsEnabled(features::kBackgroundModeAllowRestart)) { + // Private ctor. return base::WrapUnique(new BackgroundModeOptimizer()); } #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/background/background_mode_optimizer.h b/chrome/browser/background/background_mode_optimizer.h index 46fe225..3ed1843 100644 --- a/chrome/browser/background/background_mode_optimizer.h +++ b/chrome/browser/background/background_mode_optimizer.h
@@ -7,7 +7,6 @@ #include <memory> -#include "base/time/time.h" #include "chrome/browser/ui/browser_list_observer.h" #include "components/keep_alive_registry/keep_alive_state_observer.h" @@ -20,15 +19,15 @@ class BackgroundModeOptimizer : public KeepAliveStateObserver, BrowserListObserver { public: + // Creates a new BackgroundModeOptimizer. Can return null if optimizations + // are not supported. + static std::unique_ptr<BackgroundModeOptimizer> Create(); + BackgroundModeOptimizer(const BackgroundModeOptimizer&) = delete; BackgroundModeOptimizer& operator=(const BackgroundModeOptimizer&) = delete; ~BackgroundModeOptimizer() override; - // Creates a new BackgroundModeOptimizer. Can return null if optimizations - // are not supported. - static std::unique_ptr<BackgroundModeOptimizer> Create(); - // KeepAliveStateObserver implementation void OnKeepAliveStateChanged(bool is_keeping_alive) override; void OnKeepAliveRestartStateChanged(bool can_restart) override; @@ -39,6 +38,7 @@ private: friend class DummyBackgroundModeOptimizer; + // Use `Create()` above. BackgroundModeOptimizer(); // Calls DoRestart() if the current state of the process allows it.
diff --git a/chrome/browser/background/background_mode_optimizer_unittest.cc b/chrome/browser/background/background_mode_optimizer_unittest.cc index 5308cef1..0cf373d 100644 --- a/chrome/browser/background/background_mode_optimizer_unittest.cc +++ b/chrome/browser/background/background_mode_optimizer_unittest.cc
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/background/background_mode_optimizer.h" + #include <memory> -#include "chrome/browser/background/background_mode_optimizer.h" #include "chrome/browser/lifetime/browser_shutdown.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,11 +14,12 @@ // friend with BackgroundModeOptimizer, can't be in the anonymous namespace. class DummyBackgroundModeOptimizer : public BackgroundModeOptimizer { public: - DummyBackgroundModeOptimizer() {} + DummyBackgroundModeOptimizer() = default; + MOCK_METHOD0(DoRestart, void()); }; -TEST(BackgroundModeOptimizerTest, Foo) { +TEST(BackgroundModeOptimizerTest, OnKeepAliveRestartStateChanged) { // Strict mock, will fail the test if a non expected call is made. testing::StrictMock<DummyBackgroundModeOptimizer> optimizer;
diff --git a/chrome/browser/bookmarks/chrome_bookmark_client.cc b/chrome/browser/bookmarks/chrome_bookmark_client.cc index 74e2bc2..bf64ebe 100644 --- a/chrome/browser/bookmarks/chrome_bookmark_client.cc +++ b/chrome/browser/bookmarks/chrome_bookmark_client.cc
@@ -194,24 +194,33 @@ managed_bookmark_service_->IsNodeManaged(node); } -std::string ChromeBookmarkClient::EncodeBookmarkSyncMetadata() { - // TODO(crbug.com/1520418): Also encode metadata produced by - // `account_bookmark_sync_service_` once BookmarkClient API allows it. +std::string ChromeBookmarkClient::EncodeLocalOrSyncableBookmarkSyncMetadata() { return local_or_syncable_bookmark_sync_service_->EncodeBookmarkSyncMetadata(); } -void ChromeBookmarkClient::DecodeBookmarkSyncMetadata( +std::string ChromeBookmarkClient::EncodeAccountBookmarkSyncMetadata() { + if (!account_bookmark_sync_service_) { + return std::string(); + } + + return account_bookmark_sync_service_->EncodeBookmarkSyncMetadata(); +} + +void ChromeBookmarkClient::DecodeLocalOrSyncableBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) { local_or_syncable_bookmark_sync_service_->DecodeBookmarkSyncMetadata( metadata_str, schedule_save_closure, std::make_unique< sync_bookmarks::BookmarkModelViewUsingLocalOrSyncableNodes>(model_)); - // TODO(crbug.com/1520418): Pass along sync metadata once BookmarkClient API - // is capable of reading it from BookmarkModel. +} + +void ChromeBookmarkClient::DecodeAccountBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) { if (account_bookmark_sync_service_) { account_bookmark_sync_service_->DecodeBookmarkSyncMetadata( - std::string(), schedule_save_closure, + metadata_str, schedule_save_closure, std::make_unique<sync_bookmarks::BookmarkModelViewUsingAccountNodes>( model_)); }
diff --git a/chrome/browser/bookmarks/chrome_bookmark_client.h b/chrome/browser/bookmarks/chrome_bookmark_client.h index 5a06354..6b6ab1a 100644 --- a/chrome/browser/bookmarks/chrome_bookmark_client.h +++ b/chrome/browser/bookmarks/chrome_bookmark_client.h
@@ -71,8 +71,12 @@ bool CanSetPermanentNodeTitle( const bookmarks::BookmarkNode* permanent_node) override; bool IsNodeManaged(const bookmarks::BookmarkNode* node) override; - std::string EncodeBookmarkSyncMetadata() override; - void DecodeBookmarkSyncMetadata( + std::string EncodeLocalOrSyncableBookmarkSyncMetadata() override; + std::string EncodeAccountBookmarkSyncMetadata() override; + void DecodeLocalOrSyncableBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) override; + void DecodeAccountBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) override; void OnBookmarkNodeRemovedUndoable(
diff --git a/chrome/browser/browser_process_platform_part_ash.cc b/chrome/browser/browser_process_platform_part_ash.cc index ad278df..9a70619 100644 --- a/chrome/browser/browser_process_platform_part_ash.cc +++ b/chrome/browser/browser_process_platform_part_ash.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ash/crosapi/browser_manager.h" #include "chrome/browser/ash/login/saml/in_session_password_change_manager.h" #include "chrome/browser/ash/login/session/chrome_session_manager.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/chrome_user_manager_impl.h" #include "chrome/browser/ash/net/ash_proxy_monitor.h" #include "chrome/browser/ash/net/delay_network_call.h" @@ -103,6 +104,9 @@ void BrowserProcessPlatformPart::InitializeChromeUserManager() { DCHECK(!chrome_user_manager_); chrome_user_manager_ = ash::ChromeUserManagerImpl::CreateChromeUserManager(); + user_image_manager_registry_ = + std::make_unique<ash::UserImageManagerRegistry>( + chrome_user_manager_.get()); // LoginState and DeviceCloudPolicyManager outlives UserManager, so on // their initialization, there's no way to start observing UserManager. // This is the earliest timing to do so. @@ -127,6 +131,7 @@ login_state->OnUserManagerWillBeDestroyed(chrome_user_manager_.get()); } + user_image_manager_registry_.reset(); chrome_user_manager_.reset(); }
diff --git a/chrome/browser/browser_process_platform_part_ash.h b/chrome/browser/browser_process_platform_part_ash.h index cc4cfa2..5f78048 100644 --- a/chrome/browser/browser_process_platform_part_ash.h +++ b/chrome/browser/browser_process_platform_part_ash.h
@@ -25,6 +25,7 @@ class ProfileHelper; class SchedulerConfigurationManager; class TimeZoneResolver; +class UserImageManagerRegistry; namespace system { class AutomaticRebootManager; @@ -168,6 +169,8 @@ std::unique_ptr<ash::ChromeUserManager> chrome_user_manager_; + std::unique_ptr<ash::UserImageManagerRegistry> user_image_manager_registry_; + std::unique_ptr<ash::system::DeviceDisablingManagerDefaultDelegate> device_disabling_manager_delegate_; std::unique_ptr<ash::system::DeviceDisablingManager>
diff --git a/chrome/browser/chained_back_navigation_tracker_unittest.cc b/chrome/browser/chained_back_navigation_tracker_unittest.cc index 7f1ee35..e3deae9 100644 --- a/chrome/browser/chained_back_navigation_tracker_unittest.cc +++ b/chrome/browser/chained_back_navigation_tracker_unittest.cc
@@ -21,6 +21,14 @@ base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} protected: + std::vector<GURL> test_urls() { + std::vector<GURL> urls; + for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) { + urls.push_back(GURL("http://foo/" + base::NumberToString(i))); + } + return urls; + } + const uint32_t min_navigation_cnt_ = ChainedBackNavigationTracker::kMinimumChainedBackNavigationLength; const int64_t max_navigation_interval_ = ChainedBackNavigationTracker:: @@ -28,10 +36,7 @@ }; TEST_F(ChainedBackNavigationTrackerTest, ChainedBackNavigationStatus) { - std::vector<const GURL> urls; - for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) { - urls.push_back(GURL("http://foo/" + base::NumberToString(i))); - } + const std::vector<GURL> urls = test_urls(); for (const GURL& url : urls) { NavigateAndCommit(url); } @@ -64,10 +69,7 @@ TEST_F(ChainedBackNavigationTrackerTest, ChainedBackNavigationStatus_ResetCountIfIntervalIsTooLong) { - std::vector<const GURL> urls; - for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) { - urls.push_back(GURL("http://foo/" + base::NumberToString(i))); - } + const std::vector<GURL> urls = test_urls(); for (const GURL& url : urls) { NavigateAndCommit(url); } @@ -107,10 +109,7 @@ TEST_F( ChainedBackNavigationTrackerTest, ChainedBackNavigationStatus_ResetCountIfNonBackForwardNavigationHappens) { - std::vector<const GURL> urls; - for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) { - urls.push_back(GURL("http://foo/" + base::NumberToString(i))); - } + const std::vector<GURL> urls = test_urls(); for (const GURL& url : urls) { NavigateAndCommit(url); } @@ -145,10 +144,7 @@ TEST_F(ChainedBackNavigationTrackerTest, ChainedBackNavigationStatus_BackButtonClicked) { - std::vector<const GURL> urls; - for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) { - urls.push_back(GURL("http://foo/" + base::NumberToString(i))); - } + const std::vector<GURL> urls = test_urls(); for (const GURL& url : urls) { NavigateAndCommit(url); }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index bb34a18..6db2e8d 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1523,6 +1523,8 @@ registry->RegisterBooleanPref( policy::policy_prefs::kForcePermissionPolicyUnloadDefaultEnabled, false); + registry->RegisterStringPref(prefs::kAllowedDomainsForApps, std::string()); + #if BUILDFLAG(IS_CHROMEOS) registry->RegisterListPref(prefs::kMandatoryExtensionsForIncognitoNavigation); #endif
diff --git a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc index 8383410..48e3f86 100644 --- a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc +++ b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc
@@ -495,10 +495,10 @@ (*test_api(main_autofill_manager()).mutable_form_structures())[form_id()] = std::move(form_structure); - std::vector<const FormFieldData* const> filled_fields_by_autofill = { + const std::vector<const FormFieldData*> filled_fields_by_autofill = { {&form.fields[0], &form.fields[1]}}; - // Enabled events and emit event about form being filled. + // Enable events and emit event about form being filled. SendCommandSync("Autofill.enable"); main_autofill_manager().NotifyObservers( &autofill::AutofillManager::Observer::OnFillOrPreviewDataModelForm,
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc index 284d55c..fee62136 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
@@ -214,18 +214,16 @@ std::u16string custom_rule_message = GetCustomRuleString(custom_rule_message_); if (!custom_rule_message.empty()) { - return custom_rule_message; + return l10n_util::GetStringFUTF16(IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE, + custom_rule_message); } } auto element = data_.settings.tags.find(final_result_tag_); if (element != data_.settings.tags.end() && !element->second.custom_message.message.empty()) { - return IsDialogCustomRuleMessageEnabled() - ? element->second.custom_message.message - : l10n_util::GetStringFUTF16( - IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE, - element->second.custom_message.message); + return l10n_util::GetStringFUTF16(IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE, + element->second.custom_message.message); } return std::nullopt; @@ -244,8 +242,11 @@ std::optional<std::vector<std::pair<gfx::Range, GURL>>> ContentAnalysisDelegate::GetCustomRuleMessageRanges() const { + size_t offset; + l10n_util::GetStringFUTF16(IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE, + std::u16string{}, &offset); std::vector<std::pair<gfx::Range, GURL>> custom_rule_message_ranges = - GetCustomRuleStyles(custom_rule_message_); + GetCustomRuleStyles(custom_rule_message_, offset); if (!custom_rule_message_ranges.empty()) { return custom_rule_message_ranges; }
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc index 4ebba47c..d501177 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
@@ -980,7 +980,7 @@ } } -void ContentAnalysisDialog::AddLinksToDialogMessage(size_t offset) { +void ContentAnalysisDialog::AddLinksToDialogMessage() { if (!has_custom_message_ranges()) { return; } @@ -992,7 +992,7 @@ continue; } message_->AddStyleRange( - gfx::Range(offset + range.first.start(), offset + range.first.end()), + gfx::Range(range.first.start(), range.first.end()), views::StyledLabel::RangeStyleInfo::CreateForLink(base::BindRepeating( [](base::WeakPtr<content::WebContents> web_contents, GURL url, const ui::Event& event) { @@ -1012,13 +1012,9 @@ void ContentAnalysisDialog::UpdateDialogMessage(std::u16string new_message) { if (IsDialogCustomRuleMessageEnabled() && (is_failure() || is_warning()) && has_custom_message()) { - size_t offset; - std::u16string admin_message = l10n_util::GetStringFUTF16( - IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE, {new_message}, &offset); - - message_->SetText(admin_message); - AddLinksToDialogMessage(offset); - message_->GetViewAccessibility().AnnounceText(std::move(admin_message)); + message_->SetText(new_message); + AddLinksToDialogMessage(); + message_->GetViewAccessibility().AnnounceText(std::move(new_message)); } else { message_->SetText(new_message); message_->GetViewAccessibility().AnnounceText(std::move(new_message));
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h index 89fd479..6457e5d8 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h
@@ -276,10 +276,8 @@ // Helper that indicates if the dialog corresponds to a print scan. bool is_print_scan() const; - // Helper methods to get the admin message shown in dialog. As we are - // inserting it into IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE, offset here is - // the start index for the custom message. - void AddLinksToDialogMessage(size_t offset); + // Helper methods to get the admin message shown in dialog. + void AddLinksToDialogMessage(); void UpdateDialogMessage(std::u16string new_message); void AcceptButtonCallback();
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc index 43a3254..0379513 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc
@@ -984,8 +984,7 @@ dialog->ShowResult(FinalContentAnalysisResult::WARNING); EXPECT_TRUE(dialog->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); - EXPECT_EQ(dialog->GetMessageForTesting()->GetText(), - u"Your administrator says: \"Test\""); + EXPECT_EQ(dialog->GetMessageForTesting()->GetText(), u"Test"); } IN_PROC_BROWSER_TEST_F(ContentAnalysisDialogPlainTests, TestCustomRuleMessage) { @@ -1001,8 +1000,7 @@ dialog->ShowResult(FinalContentAnalysisResult::WARNING); EXPECT_TRUE(dialog->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); - EXPECT_EQ(dialog->GetMessageForTesting()->GetText(), - u"Your administrator says: \"Test\""); + EXPECT_EQ(dialog->GetMessageForTesting()->GetText(), u"Test"); } IN_PROC_BROWSER_TEST_F(ContentAnalysisDialogPlainTests,
diff --git a/chrome/browser/enterprise/connectors/common.cc b/chrome/browser/enterprise/connectors/common.cc index ebb1110..932514f 100644 --- a/chrome/browser/enterprise/connectors/common.cc +++ b/chrome/browser/enterprise/connectors/common.cc
@@ -169,19 +169,18 @@ std::vector<std::pair<gfx::Range, GURL>> GetCustomRuleStyles( const ContentAnalysisResponse::Result::TriggeredRule::CustomRuleMessage& - custom_rule_message) { - int curr_index = 0; + custom_rule_message, + size_t offset) { std::vector<std::pair<gfx::Range, GURL>> linked_ranges; for (const auto& custom_segment : custom_rule_message.message_segments()) { if (custom_segment.has_link()) { GURL url(custom_segment.link()); if (url.is_valid()) { linked_ranges.emplace_back( - gfx::Range(curr_index, curr_index + custom_segment.text().length()), - url); + gfx::Range(offset, offset + custom_segment.text().length()), url); } } - curr_index += custom_segment.text().length(); + offset += custom_segment.text().length(); } return linked_ranges; }
diff --git a/chrome/browser/enterprise/connectors/common.h b/chrome/browser/enterprise/connectors/common.h index 3f72e95..e34625f 100644 --- a/chrome/browser/enterprise/connectors/common.h +++ b/chrome/browser/enterprise/connectors/common.h
@@ -227,10 +227,12 @@ // Extracts the ranges and their corresponding links from the custom rule // message field in the content analysis response. Used to style the custom rule -// message in the content analysis dialog. +// message in the content analysis dialog. `offset` corresponds to its start +// index as we are inserting it in another message. std::vector<std::pair<gfx::Range, GURL>> GetCustomRuleStyles( const ContentAnalysisResponse::Result::TriggeredRule::CustomRuleMessage& - custom_rule_message); + custom_rule_message, + size_t offset); // User data to persist a save package's final callback allowing/denying // completion. This is used since the callback can be called either when
diff --git a/chrome/browser/enterprise/connectors/common_unittest.cc b/chrome/browser/enterprise/connectors/common_unittest.cc index fb8bbe75..d0b63c61 100644 --- a/chrome/browser/enterprise/connectors/common_unittest.cc +++ b/chrome/browser/enterprise/connectors/common_unittest.cc
@@ -43,6 +43,9 @@ ], "block_large_files": 1 })"; +// Offset to first placeholder index for +// IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE. +constexpr size_t kRuleMessageOffset = 26; ContentAnalysisResponse CreateContentAnalysisResponse( const std::vector<CustomMessageTestCase>& triggered_rules, @@ -208,7 +211,7 @@ std::u16string custom_message = GetCustomRuleString(result.custom_rule_message); std::vector<std::pair<gfx::Range, GURL>> custom_ranges = - GetCustomRuleStyles(result.custom_rule_message); + GetCustomRuleStyles(result.custom_rule_message, kRuleMessageOffset); EXPECT_EQ(custom_message, expected_message()); @@ -230,7 +233,7 @@ std::u16string custom_message = GetCustomRuleString(result.custom_rule_message); std::vector<std::pair<gfx::Range, GURL>> custom_ranges = - GetCustomRuleStyles(result.custom_rule_message); + GetCustomRuleStyles(result.custom_rule_message, kRuleMessageOffset); EXPECT_EQ(custom_message, expected_message()); EXPECT_TRUE(custom_ranges.empty());
diff --git a/chrome/browser/enterprise/watermark/BUILD.gn b/chrome/browser/enterprise/watermark/BUILD.gn index b593117..812c3f8 100644 --- a/chrome/browser/enterprise/watermark/BUILD.gn +++ b/chrome/browser/enterprise/watermark/BUILD.gn
@@ -1,3 +1,16 @@ +# 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. + +source_set("watermark_view_lib") { + sources = [ + "watermark_view.cc", + "watermark_view.h", + ] + + deps = [ "//ui/views" ] +} + executable("watermark_app") { testonly = true @@ -5,17 +18,17 @@ "example_app.cc", "watermark_example.cc", "watermark_example.h", - "watermark_view.cc", - "watermark_view.h", ] deps = [ + ":watermark_view_lib", "//base", "//base/test:test_support", "//build/win:default_exe_manifest", + "//ui/base/metadata:metadata", "//ui/color:mixers", + "//ui/gfx:gfx", "//ui/resources:ui_test_pak", - "//ui/views", "//ui/views/examples:views_examples_lib", "//ui/views/examples:views_examples_proc", ]
diff --git a/chrome/browser/enterprise/watermark/watermark_view.cc b/chrome/browser/enterprise/watermark/watermark_view.cc index 1369a5a..a188df4 100644 --- a/chrome/browser/enterprise/watermark/watermark_view.cc +++ b/chrome/browser/enterprise/watermark/watermark_view.cc
@@ -26,6 +26,12 @@ WatermarkView::~WatermarkView() = default; void WatermarkView::OnPaint(gfx::Canvas* canvas) { + // Trying to render an empty string in Skia will fail. A string is required + // to create the command buffer for the renderer. + if (text_.empty()) { + return; + } + // Get ptr to Skia canvas cc::PaintCanvas* sk_canvas = canvas->sk_canvas();
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chrome/browser/extensions/api/cookies/cookies_helpers.cc index d9ecab9..1b8fba82 100644 --- a/chrome/browser/extensions/api/cookies/cookies_helpers.cc +++ b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -24,7 +24,6 @@ #include "chrome/common/extensions/api/cookies.h" #include "chrome/common/url_constants.h" #include "content/public/browser/web_contents.h" -#include "cookies_helpers.h" #include "extensions/common/extension.h" #include "extensions/common/permissions/permissions_data.h" #include "net/cookies/canonical_cookie.h"
diff --git a/chrome/browser/extensions/api/image_writer_private/test_utils.h b/chrome/browser/extensions/api/image_writer_private/test_utils.h index 2b88f77..a47f19c 100644 --- a/chrome/browser/extensions/api/image_writer_private/test_utils.h +++ b/chrome/browser/extensions/api/image_writer_private/test_utils.h
@@ -37,7 +37,7 @@ const char kDummyExtensionId[] = "DummyExtension"; // Default file size to use in tests. Currently 32kB. -const int kTestFileSize = 32 * 1024; +const size_t kTestFileSize = 32 * 1024; // Pattern to use in the image file. const uint8_t kImagePattern = 0x55; // 01010101 // Pattern to use in the device file.
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc index b37ec554..5740289 100644 --- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc +++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
@@ -200,10 +200,11 @@ } TEST_F(ImageWriterWriteFromUrlOperationTest, VerifyFile) { - std::unique_ptr<char[]> data_buffer(new char[kTestFileSize]); - base::ReadFile(test_utils_.GetImagePath(), data_buffer.get(), kTestFileSize); + std::unique_ptr<char[]> char_buffer(new char[kTestFileSize]); + base::span<char> chars = base::make_span(char_buffer.get(), kTestFileSize); + base::ReadFile(test_utils_.GetImagePath(), chars); base::MD5Digest expected_digest; - base::MD5Sum(data_buffer.get(), kTestFileSize, &expected_digest); + base::MD5Sum(base::as_bytes(chars), &expected_digest); std::string expected_hash = base::MD5DigestToBase16(expected_digest); scoped_refptr<WriteFromUrlOperationForTest> operation =
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc index 271d351..059d833d 100644 --- a/chrome/browser/extensions/api/preference/preference_api.cc +++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -632,13 +632,6 @@ crosapi::mojom::PrefPath pref_path = PrefMapping::GetInstance()->GetPrefPathForPrefName(cached_browser_pref_); if (!IsBrowserScopePrefOperation(pref_path, profile)) { - // Exclude chrome.privacy.website.protectedContentID (mapped to - // kProtectedContentDefault) from secondary profile access - // (crbug.com/1450718). - if (!profile->IsMainProfile() && - pref_path == crosapi::mojom::PrefPath::kProtectedContentDefault) { - return RespondNow(Error(kPrimaryProfileOnlyErrorMessage, pref_key)); - } // This pref should be read from ash. auto* lacros_service = chromeos::LacrosService::Get(); if (!lacros_service ||
diff --git a/chrome/browser/extensions/api/preference/preference_apitest.cc b/chrome/browser/extensions/api/preference/preference_apitest.cc index db2f797..d23f240b 100644 --- a/chrome/browser/extensions/api/preference/preference_apitest.cc +++ b/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -218,11 +218,12 @@ prefs->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, true); prefs->SetBoolean(prefs::kPrivacySandboxRelatedWebsiteSetsEnabled, true); - // The 'protectedContentEnabled' pref is only available on ChromeOS and - // Windows, so pass a JSON array object with any unsupported prefs into - // the test , so it can skip those. + // The 'protectedContentEnabled' pref is only available as browser pref + // associated with browser profile on ChromeOS and Windows, so pass a JSON + // array object with any unsupported prefs into the test , so it can skip + // those. static constexpr char kMissingPrefs[] = -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) "[ ]"; #else "[ \"protectedContentEnabled\" ]";
diff --git a/chrome/browser/extensions/pref_mapping.cc b/chrome/browser/extensions/pref_mapping.cc index 51fc7ed..cacf72d3 100644 --- a/chrome/browser/extensions/pref_mapping.cc +++ b/chrome/browser/extensions/pref_mapping.cc
@@ -57,7 +57,6 @@ password_manager::prefs::kCredentialsEnableService, APIPermissionID::kPrivacy, APIPermissionID::kPrivacy}, - // Note in Lacros this is Ash-controlled. {"protectedContentEnabled", prefs::kProtectedContentDefault, APIPermissionID::kPrivacy, APIPermissionID::kPrivacy}, @@ -223,39 +222,38 @@ static const auto name_to_extension_prefpath = base::MakeFixedFlatMapNonConsteval<base::StringPiece, crosapi::mojom::PrefPath>( - {{chromeos::prefs::kDockedMagnifierEnabled, - crosapi::mojom::PrefPath::kDockedMagnifierEnabled}, - {chromeos::prefs::kAccessibilityAutoclickEnabled, - crosapi::mojom::PrefPath::kAccessibilityAutoclickEnabled}, - {chromeos::prefs::kAccessibilityCaretHighlightEnabled, - crosapi::mojom::PrefPath::kAccessibilityCaretHighlightEnabled}, - {chromeos::prefs::kAccessibilityCursorColorEnabled, - crosapi::mojom::PrefPath::kAccessibilityCursorColorEnabled}, - {chromeos::prefs::kAccessibilityCursorHighlightEnabled, - crosapi::mojom::PrefPath::kAccessibilityCursorHighlightEnabled}, - {chromeos::prefs::kAccessibilityDictationEnabled, - crosapi::mojom::PrefPath::kAccessibilityDictationEnabled}, - {chromeos::prefs::kAccessibilityFocusHighlightEnabled, - crosapi::mojom::PrefPath::kAccessibilityFocusHighlightEnabled}, - {chromeos::prefs::kAccessibilityHighContrastEnabled, - crosapi::mojom::PrefPath::kAccessibilityHighContrastEnabled}, - {chromeos::prefs::kAccessibilityLargeCursorEnabled, - crosapi::mojom::PrefPath::kAccessibilityLargeCursorEnabled}, - {chromeos::prefs::kAccessibilityScreenMagnifierEnabled, - crosapi::mojom::PrefPath::kAccessibilityScreenMagnifierEnabled}, - {chromeos::prefs::kAccessibilitySelectToSpeakEnabled, - crosapi::mojom::PrefPath::kAccessibilitySelectToSpeakEnabled}, - {chromeos::prefs::kAccessibilitySpokenFeedbackEnabled, - crosapi::mojom::PrefPath::kExtensionAccessibilitySpokenFeedbackEnabled}, - {chromeos::prefs::kAccessibilityStickyKeysEnabled, - crosapi::mojom::PrefPath::kAccessibilityStickyKeysEnabled}, - {chromeos::prefs::kAccessibilitySwitchAccessEnabled, - crosapi::mojom::PrefPath::kAccessibilitySwitchAccessEnabled}, - {chromeos::prefs::kAccessibilityVirtualKeyboardEnabled, - crosapi::mojom::PrefPath::kAccessibilityVirtualKeyboardEnabled}, - {prefs::kProtectedContentDefault, - crosapi::mojom::PrefPath::kProtectedContentDefault}, - {proxy_config::prefs::kProxy, crosapi::mojom::PrefPath::kProxy}}); + {{chromeos::prefs::kDockedMagnifierEnabled, + crosapi::mojom::PrefPath::kDockedMagnifierEnabled}, + {chromeos::prefs::kAccessibilityAutoclickEnabled, + crosapi::mojom::PrefPath::kAccessibilityAutoclickEnabled}, + {chromeos::prefs::kAccessibilityCaretHighlightEnabled, + crosapi::mojom::PrefPath::kAccessibilityCaretHighlightEnabled}, + {chromeos::prefs::kAccessibilityCursorColorEnabled, + crosapi::mojom::PrefPath::kAccessibilityCursorColorEnabled}, + {chromeos::prefs::kAccessibilityCursorHighlightEnabled, + crosapi::mojom::PrefPath::kAccessibilityCursorHighlightEnabled}, + {chromeos::prefs::kAccessibilityDictationEnabled, + crosapi::mojom::PrefPath::kAccessibilityDictationEnabled}, + {chromeos::prefs::kAccessibilityFocusHighlightEnabled, + crosapi::mojom::PrefPath::kAccessibilityFocusHighlightEnabled}, + {chromeos::prefs::kAccessibilityHighContrastEnabled, + crosapi::mojom::PrefPath::kAccessibilityHighContrastEnabled}, + {chromeos::prefs::kAccessibilityLargeCursorEnabled, + crosapi::mojom::PrefPath::kAccessibilityLargeCursorEnabled}, + {chromeos::prefs::kAccessibilityScreenMagnifierEnabled, + crosapi::mojom::PrefPath::kAccessibilityScreenMagnifierEnabled}, + {chromeos::prefs::kAccessibilitySelectToSpeakEnabled, + crosapi::mojom::PrefPath::kAccessibilitySelectToSpeakEnabled}, + {chromeos::prefs::kAccessibilitySpokenFeedbackEnabled, + crosapi::mojom::PrefPath:: + kExtensionAccessibilitySpokenFeedbackEnabled}, + {chromeos::prefs::kAccessibilityStickyKeysEnabled, + crosapi::mojom::PrefPath::kAccessibilityStickyKeysEnabled}, + {chromeos::prefs::kAccessibilitySwitchAccessEnabled, + crosapi::mojom::PrefPath::kAccessibilitySwitchAccessEnabled}, + {chromeos::prefs::kAccessibilityVirtualKeyboardEnabled, + crosapi::mojom::PrefPath::kAccessibilityVirtualKeyboardEnabled}, + {proxy_config::prefs::kProxy, crosapi::mojom::PrefPath::kProxy}}); auto* pref_iter = name_to_extension_prefpath.find(pref_name); return pref_iter == name_to_extension_prefpath.end() ? crosapi::mojom::PrefPath::kUnknown
diff --git a/chrome/browser/fast_checkout/fast_checkout_trigger_validator_impl_unittest.cc b/chrome/browser/fast_checkout/fast_checkout_trigger_validator_impl_unittest.cc index aa7c741..f1fa0a3 100644 --- a/chrome/browser/fast_checkout/fast_checkout_trigger_validator_impl_unittest.cc +++ b/chrome/browser/fast_checkout/fast_checkout_trigger_validator_impl_unittest.cc
@@ -16,6 +16,7 @@ #include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/test_autofill_driver.h" #include "components/autofill/core/browser/test_browser_autofill_manager.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -68,15 +69,6 @@ (const override)); }; -class MockPersonalDataManager : public autofill::PersonalDataManager { - public: - MockPersonalDataManager() : PersonalDataManager("en-US") {} - ~MockPersonalDataManager() override = default; - - MOCK_METHOD(bool, IsAutofillProfileEnabled, (), (const override)); - MOCK_METHOD(bool, IsAutofillPaymentMethodsEnabled, (), (const override)); -}; - class FastCheckoutTriggerValidatorTest : public ChromeRenderViewHostTestHarness { public: @@ -86,7 +78,6 @@ void SetUp() override { content::RenderViewHostTestHarness::SetUp(); - pdm_ = std::make_unique<MockPersonalDataManager>(); capabilities_fetcher_ = std::make_unique<MockFastCheckoutCapabilitiesFetcher>(); personal_data_helper_ = std::make_unique<MockPersonalDataHelper>(); @@ -107,16 +98,16 @@ .WillByDefault( Return(std::vector<autofill::AutofillProfile*>{&profile_})); ON_CALL(*personal_data_helper(), GetPersonalDataManager) - .WillByDefault(Return(pdm())); - ON_CALL(*pdm(), IsAutofillPaymentMethodsEnabled) - .WillByDefault(Return(true)); - ON_CALL(*pdm(), IsAutofillProfileEnabled).WillByDefault(Return(true)); + .WillByDefault(Return(&pdm())); ON_CALL(*autofill_client(), IsContextSecure).WillByDefault(Return(true)); ON_CALL(*autofill_client(), GetVariationConfigCountryCode) .WillByDefault(Return(GeoIpCountryCode("US"))); + + pdm().SetAutofillProfileEnabled(true); + pdm().SetAutofillPaymentMethodsEnabled(true); } - MockPersonalDataManager* pdm() { return pdm_.get(); } + autofill::TestPersonalDataManager& pdm() { return pdm_; } MockAutofillClient* autofill_client() { return autofill_client_injector_[web_contents()]; } @@ -156,7 +147,7 @@ std::unique_ptr<FastCheckoutTriggerValidatorImpl> validator_; std::unique_ptr<MockFastCheckoutCapabilitiesFetcher> capabilities_fetcher_; std::unique_ptr<MockPersonalDataHelper> personal_data_helper_; - std::unique_ptr<MockPersonalDataManager> pdm_; + autofill::TestPersonalDataManager pdm_; }; TEST_F(FastCheckoutTriggerValidatorTest, ShouldRun_AllChecksPass_ReturnsTrue) { @@ -212,14 +203,14 @@ TEST_F(FastCheckoutTriggerValidatorTest, ShouldRun_AutofillProfileDisabled_ReturnsFalse) { - ON_CALL(*pdm(), IsAutofillProfileEnabled).WillByDefault(Return(false)); + pdm().SetAutofillProfileEnabled(false); EXPECT_EQ(ShouldRun(), FastCheckoutTriggerOutcome::kFailureAutofillProfileDisabled); } TEST_F(FastCheckoutTriggerValidatorTest, ShouldRun_CreditCardDisabled_ReturnsFalse) { - ON_CALL(*pdm(), IsAutofillPaymentMethodsEnabled).WillByDefault(Return(false)); + pdm().SetAutofillPaymentMethodsEnabled(false); EXPECT_EQ(ShouldRun(), FastCheckoutTriggerOutcome::kFailureAutofillCreditCardDisabled); }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index c772a76..52ceac7 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -3866,11 +3866,6 @@ "expiry_milestone": -1 }, { - "name": "enable-webassembly-garbage-collection", - "owners": [ "adamk@chromium.org", "jkummerow@chromium.org", "wasm-team@google.com" ], - "expiry_milestone": 122 - }, - { "name": "enable-webassembly-lazy-compilation", "owners": [ "clemensb@chromium.org", "wasm-team@google.com" ], // This flag is often used by developers and partners to test @@ -3879,16 +3874,6 @@ "expiry_milestone": -1 }, { - "name": "enable-webassembly-relaxed-simd", - "owners": [ "gdeepti@chromium.org", "wasm-team@google.com" ], - "expiry_milestone": 120 - }, - { - "name": "enable-webassembly-stringref", - "owners": [ "adamk@chromium.org", "jkummerow@chromium.org", "wasm-team@google.com" ], - "expiry_milestone": 122 - }, - { "name": "enable-webassembly-tiering", "owners": [ "clemensb@chromium.org", "wasm-team@google.com" ], // This flag is often used by developers and partners to test @@ -5574,15 +5559,6 @@ "expiry_milestone": 115 }, { - "name": "notification-interaction-history", - "owners": [ - "sideyilmaz@chromium.org", - "msramek@chromium.org", - "chrome-privacy-controls@google.com" - ], - "expiry_milestone": 120 - }, - { "name": "notification-one-tap-unsubscribe", "owners": [ "engedy@chromium.org" ], "expiry_milestone": 126 @@ -8312,8 +8288,8 @@ }, { "name": "video-conference", - "owners": [ "shafron@chromium.org", "newcomer@chromium.org", "charleszhao@chromium.org", "jmpollock@chromium.org" ], - "expiry_milestone": 120 + "owners": [ "newcomer@chromium.org", "charleszhao@chromium.org", "jmpollock@chromium.org", "chromeos-camera-eng@google.com" ], + "expiry_milestone": 129 }, { "name": "view-transition-on-navigation",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index f38fe66..dd1462e 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2343,11 +2343,6 @@ "network connectivity to use the system-proxy daemon for authentication to " "remote HTTP web proxies."; -const char kNotificationInteractionHistoryName[] = - "Notification Interaction History"; -const char kNotificationInteractionHistoryDescription[] = - "Enable recording notification count and interaction."; - const char kNotificationSchedulerName[] = "Notification scheduler"; const char kNotificationSchedulerDescription[] = "Enable notification scheduler feature.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 4a6e64ab..d117194 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1338,9 +1338,6 @@ extern const char kWebMachineLearningNeuralNetworkName[]; extern const char kWebMachineLearningNeuralNetworkDescription[]; -extern const char kNotificationInteractionHistoryName[]; -extern const char kNotificationInteractionHistoryDescription[]; - extern const char kNotificationSchedulerName[]; extern const char kNotificationSchedulerDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index f9c78f52..e676d6b 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -717,7 +717,7 @@ BASE_FEATURE(kQuickDeleteForAndroid, "QuickDeleteForAndroid", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kQuickDeleteAndroidAnimation, "QuickDeleteAndroidAnimation",
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 f56aca0..6ec06b6 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
@@ -771,7 +771,7 @@ public static final MutableFlagWithSafeDefault sPageInsightsResizeInSync = newMutableFlagWithSafeDefault(CCT_PAGE_INSIGHTS_HUB_BETTER_SCROLL, false); public static final MutableFlagWithSafeDefault sQuickDeleteForAndroid = - newMutableFlagWithSafeDefault(QUICK_DELETE_FOR_ANDROID, false); + newMutableFlagWithSafeDefault(QUICK_DELETE_FOR_ANDROID, true); public static final MutableFlagWithSafeDefault sQuickDeleteAndroidAnimation = newMutableFlagWithSafeDefault(QUICK_DELETE_ANDROID_ANIMATION, false); public static final MutableFlagWithSafeDefault sReaderModeCct =
diff --git a/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc index 7635b3d..87e42706 100644 --- a/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc +++ b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc
@@ -133,8 +133,8 @@ ResultCatcher catcher; // Set observer to watch for fullscreen. - FullscreenNotificationObserver fullscreen_waiter(browser()); - + ui_test_utils::FullscreenWaiter fullscreen_waiter(browser(), + {.tab_fullscreen = true}); ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/testFullscreenEscape.csv")));
diff --git a/chrome/browser/headless/BUILD.gn b/chrome/browser/headless/BUILD.gn index 1724d52..f8cf6fc 100644 --- a/chrome/browser/headless/BUILD.gn +++ b/chrome/browser/headless/BUILD.gn
@@ -76,7 +76,6 @@ if (is_linux || is_win || is_mac) { sources += [ - "headless_mode_browsertest_utils.cc", "headless_mode_browsertest_utils.h", "headless_mode_command_browsertest.cc", "headless_mode_devtooled_browsertest.cc",
diff --git a/chrome/browser/headless/headless_mode_browsertest_mac.mm b/chrome/browser/headless/headless_mode_browsertest_mac.mm index 585c4c6..0ee443c 100644 --- a/chrome/browser/headless/headless_mode_browsertest_mac.mm +++ b/chrome/browser/headless/headless_mode_browsertest_mac.mm
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/test/base/ui_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/mac/coordinate_conversion.h" #include "ui/gfx/native_widget_types.h" @@ -78,13 +79,13 @@ EXPECT_FALSE(ns_window.visible); // Verify fullscreen state. - test::ToggleFullscreenModeSync(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(browser()->window()->IsFullscreen()); EXPECT_TRUE(browser()->window()->IsVisible()); EXPECT_FALSE(ns_window.visible); // Verify back to normal state. - test::ToggleFullscreenModeSync(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_FALSE(browser()->window()->IsFullscreen()); EXPECT_TRUE(browser()->window()->IsVisible()); EXPECT_FALSE(ns_window.visible);
diff --git a/chrome/browser/headless/headless_mode_browsertest_utils.cc b/chrome/browser/headless/headless_mode_browsertest_utils.cc deleted file mode 100644 index 134a2e5c..0000000 --- a/chrome/browser/headless/headless_mode_browsertest_utils.cc +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/headless/headless_mode_browsertest_utils.h" - -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" - -namespace headless::test { - -void ToggleFullscreenModeSync(Browser* browser) { - FullscreenNotificationObserver observer(browser); - chrome::ToggleFullscreenMode(browser); - observer.Wait(); -} - -} // namespace headless::test
diff --git a/chrome/browser/headless/headless_mode_browsertest_utils.h b/chrome/browser/headless/headless_mode_browsertest_utils.h index 1a781bb..3d7db20 100644 --- a/chrome/browser/headless/headless_mode_browsertest_utils.h +++ b/chrome/browser/headless/headless_mode_browsertest_utils.h
@@ -7,8 +7,6 @@ #include "ui/gfx/geometry/rect.h" -class Browser; - namespace views { class Widget; } @@ -23,9 +21,6 @@ // widget. This method has platform specific implementations. gfx::Rect GetPlatformWindowExpectedBounds(views::Widget* widget); -// Toggles browser fullscreen mode synchronously. -void ToggleFullscreenModeSync(Browser* browser); - } // namespace headless::test #endif // CHROME_BROWSER_HEADLESS_HEADLESS_MODE_BROWSERTEST_UTILS_H_
diff --git a/chrome/browser/headless/headless_mode_browsertest_win.cc b/chrome/browser/headless/headless_mode_browsertest_win.cc index e8974d05..2737d9d 100644 --- a/chrome/browser/headless/headless_mode_browsertest_win.cc +++ b/chrome/browser/headless/headless_mode_browsertest_win.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/headless/headless_mode_browsertest_utils.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/test/base/ui_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/window_tree_host_platform.h" #include "ui/gfx/geometry/rect.h" @@ -93,13 +94,13 @@ EXPECT_FALSE(::IsWindowVisible(desktop_window_hwnd)); // Verify fullscreen state. - test::ToggleFullscreenModeSync(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(browser()->window()->IsFullscreen()); EXPECT_TRUE(browser()->window()->IsVisible()); EXPECT_FALSE(::IsWindowVisible(desktop_window_hwnd)); // Verify back to normal state. - test::ToggleFullscreenModeSync(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_FALSE(browser()->window()->IsFullscreen()); EXPECT_TRUE(browser()->window()->IsVisible()); EXPECT_FALSE(::IsWindowVisible(desktop_window_hwnd));
diff --git a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc index c35ff08..fd00c0c 100644 --- a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc +++ b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc
@@ -134,7 +134,11 @@ /*Default value for visibility threshold*/ 0.5))), categories_blocklist_(GetTabResumptionCategories( ntp_features::kNtpTabResumptionModuleCategoriesBlocklistParam, - {kCategoryBlockList.begin(), kCategoryBlockListCount})) { + {kCategoryBlockList.begin(), kCategoryBlockListCount})), + time_limit_(base::GetFieldTrialParamByFeatureAsInt( + ntp_features::kNtpTabResumptionModuleTimeLimit, + ntp_features::kNtpTabResumptionModuleTimeLimitParam, + /*Default value for time limit*/ 24)) { DCHECK(profile_); DCHECK(web_contents_); } @@ -147,8 +151,10 @@ std::vector<history::QueryURLResult> results) { history::VisitVector visit_rows; for (auto result : results) { - for (auto visit : result.visits) { - visit_rows.push_back(visit); + if ((base::Time::Now() - result.row.last_visit()).InHours() < time_limit_) { + for (auto visit : result.visits) { + visit_rows.push_back(visit); + } } } auto* history_service = HistoryServiceFactory::GetForProfile(
diff --git a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h index 43d0234..9f2a3ba 100644 --- a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h +++ b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h
@@ -78,6 +78,9 @@ // If `categories_blocklist`is empty, the returned tabs will not be filtered. base::flat_set<std::string> categories_blocklist_; + // Amount of hours in the past that tabs are able to be shown. + const int time_limit_; + base::WeakPtrFactory<TabResumptionPageHandler> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/notifications/non_persistent_notification_handler.cc b/chrome/browser/notifications/non_persistent_notification_handler.cc index cd85892..8389b05 100644 --- a/chrome/browser/notifications/non_persistent_notification_handler.cc +++ b/chrome/browser/notifications/non_persistent_notification_handler.cc
@@ -65,13 +65,10 @@ weak_ptr_factory_.GetWeakPtr(), profile, origin, notification_id, std::move(completed_closure))); - if (base::FeatureList::IsEnabled( - permissions::features::kNotificationInteractionHistory)) { - auto* service = - NotificationsEngagementServiceFactory::GetForProfile(profile); - // This service might be missing for incognito profiles and in tests. - if (service) - service->RecordNotificationInteraction(origin); + auto* service = NotificationsEngagementServiceFactory::GetForProfile(profile); + // This service might be missing for incognito profiles and in tests. + if (service) { + service->RecordNotificationInteraction(origin); } }
diff --git a/chrome/browser/notifications/notification_interactive_uitest.cc b/chrome/browser/notifications/notification_interactive_uitest.cc index 3dbeb4e7..c0dabc86 100644 --- a/chrome/browser/notifications/notification_interactive_uitest.cc +++ b/chrome/browser/notifications/notification_interactive_uitest.cc
@@ -645,13 +645,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetTestPageURL())); // Set the page fullscreen - browser()->exclusive_access_manager()->fullscreen_controller()-> - ToggleBrowserFullscreenMode(); - - { - FullscreenStateWaiter fs_state(browser(), true); - fs_state.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow( browser()->window()->GetNativeWindow())); @@ -686,24 +680,13 @@ EXPECT_NE("-1", result); // Set the notification page fullscreen - browser()->exclusive_access_manager()->fullscreen_controller()-> - ToggleBrowserFullscreenMode(); - { - FullscreenStateWaiter fs_state(browser(), true); - fs_state.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); // Set the other browser fullscreen - other_browser->exclusive_access_manager()->fullscreen_controller()-> - ToggleBrowserFullscreenMode(); - { - FullscreenStateWaiter fs_state(other_browser, true); - fs_state.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(other_browser); - ASSERT_TRUE(browser()->exclusive_access_manager()->context()->IsFullscreen()); - ASSERT_TRUE( - other_browser->exclusive_access_manager()->context()->IsFullscreen()); + ASSERT_TRUE(browser()->window()->IsFullscreen()); + ASSERT_TRUE(other_browser->window()->IsFullscreen()); ui_test_utils::BrowserActivationWaiter waiter(other_browser); waiter.WaitForActivation(); @@ -733,13 +716,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetTestPageURL())); // Set the page fullscreen - browser()->exclusive_access_manager()->fullscreen_controller()-> - ToggleBrowserFullscreenMode(); - - { - FullscreenStateWaiter fs_state(browser(), true); - fs_state.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow( browser()->window()->GetNativeWindow()));
diff --git a/chrome/browser/notifications/notification_test_util.cc b/chrome/browser/notifications/notification_test_util.cc index 9395b57..ddee9a8 100644 --- a/chrome/browser/notifications/notification_test_util.cc +++ b/chrome/browser/notifications/notification_test_util.cc
@@ -5,9 +5,6 @@ #include "chrome/browser/notifications/notification_test_util.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "content/public/test/test_utils.h" #include "url/origin.h" StubNotificationUIManager::StubNotificationUIManager() {} @@ -138,15 +135,3 @@ is_shutdown_started_ = true; CancelAll(); } - -FullscreenStateWaiter::FullscreenStateWaiter( - Browser* browser, bool desired_state) - : browser_(browser), - desired_state_(desired_state) {} - -void FullscreenStateWaiter::Wait() { - while (desired_state_ != - browser_->exclusive_access_manager()->context()->IsFullscreen()) { - content::RunAllPendingInMessageLoop(); - } -}
diff --git a/chrome/browser/notifications/notification_test_util.h b/chrome/browser/notifications/notification_test_util.h index e7ea8c2..21dd85f 100644 --- a/chrome/browser/notifications/notification_test_util.h +++ b/chrome/browser/notifications/notification_test_util.h
@@ -10,14 +10,10 @@ #include <utility> #include <vector> -#include "base/functional/callback.h" -#include "base/memory/raw_ptr.h" -#include "build/build_config.h" #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/notifications/profile_notification.h" #include "ui/message_center/public/cpp/notification.h" -class Browser; class Profile; class StubNotificationUIManager : public NotificationUIManager { @@ -72,19 +68,4 @@ GURL last_canceled_source_; }; -// Helper class that has to be created in the stack to check if the fullscreen -// setting of a browser is in the desired state. -class FullscreenStateWaiter { - public: - FullscreenStateWaiter(Browser* browser, bool desired_state); - FullscreenStateWaiter(const FullscreenStateWaiter&) = delete; - FullscreenStateWaiter& operator=(const FullscreenStateWaiter&) = delete; - - void Wait(); - - private: - const raw_ptr<Browser> browser_; - bool desired_state_; -}; - #endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_TEST_UTIL_H_
diff --git a/chrome/browser/notifications/persistent_notification_handler.cc b/chrome/browser/notifications/persistent_notification_handler.cc index de615c2d..e3d50a80a 100644 --- a/chrome/browser/notifications/persistent_notification_handler.cc +++ b/chrome/browser/notifications/persistent_notification_handler.cc
@@ -137,14 +137,11 @@ site_engagement::SiteEngagementService::Get(profile) ->HandleNotificationInteraction(origin); - if (base::FeatureList::IsEnabled( - permissions::features::kNotificationInteractionHistory)) { - auto* service = - NotificationsEngagementServiceFactory::GetForProfile(profile); - // This service might be missing for incognito profiles and in tests. - if (service) { - service->RecordNotificationInteraction(origin); - } + auto* service = + NotificationsEngagementServiceFactory::GetForProfile(profile); + // This service might be missing for incognito profiles and in tests. + if (service) { + service->RecordNotificationInteraction(origin); } }
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 100dba0..b6f6c6a 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -228,14 +228,11 @@ ContentSettingsType::NOTIFICATIONS, profile_, nullptr, notification.origin_url()); - if (base::FeatureList::IsEnabled( - permissions::features::kNotificationInteractionHistory)) { auto* service = NotificationsEngagementServiceFactory::GetForProfile(profile_); // This service might be missing for incognito profiles and in tests. if (service) service->RecordNotificationDisplayed(notification.origin_url()); - } } void PlatformNotificationServiceImpl::DisplayPersistentNotification( @@ -273,13 +270,11 @@ ->LogPersistentNotificationSize(profile_, notification_data, origin); } - if (base::FeatureList::IsEnabled( - permissions::features::kNotificationInteractionHistory)) { - auto* service = - NotificationsEngagementServiceFactory::GetForProfile(profile_); - // This service might be missing for incognito profiles and in tests. - if (service) - service->RecordNotificationDisplayed(notification.origin_url()); + auto* service = + NotificationsEngagementServiceFactory::GetForProfile(profile_); + // This service might be missing for incognito profiles and in tests. + if (service) { + service->RecordNotificationDisplayed(notification.origin_url()); } permissions::PermissionUmaUtil::RecordPermissionUsage(
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index f611298..c6eb00c 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -886,17 +886,12 @@ GrantNotificationPermissionForTest(); // Set the page fullscreen - browser()->exclusive_access_manager()->fullscreen_controller()-> - ToggleBrowserFullscreenMode(); - - { - FullscreenStateWaiter fs_state(browser(), true); - fs_state.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow( browser()->window()->GetNativeWindow())); + ui_test_utils::BrowserActivationWaiter(browser()).WaitForActivation(); ASSERT_TRUE(browser()->window()->IsActive()) << "Browser is active after going fullscreen"; @@ -920,25 +915,16 @@ EXPECT_EQ("ok", RunScript("DisplayPersistentNotification('display_normal')")); // Set the notifcation page fullscreen - browser()->exclusive_access_manager()->fullscreen_controller()-> - ToggleBrowserFullscreenMode(); - { - FullscreenStateWaiter fs_state(browser(), true); - fs_state.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); // Set the other browser fullscreen - other_browser->exclusive_access_manager()->fullscreen_controller()-> - ToggleBrowserFullscreenMode(); - { - FullscreenStateWaiter fs_state(other_browser, true); - fs_state.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(other_browser); ASSERT_TRUE(browser()->exclusive_access_manager()->context()->IsFullscreen()); ASSERT_TRUE( other_browser->exclusive_access_manager()->context()->IsFullscreen()); + ui_test_utils::BrowserActivationWaiter(other_browser).WaitForActivation(); ASSERT_FALSE(browser()->window()->IsActive()); ASSERT_TRUE(other_browser->window()->IsActive());
diff --git a/chrome/browser/password_manager/android/password_manager_android_util.cc b/chrome/browser/password_manager/android/password_manager_android_util.cc index c640f86..86bd027 100644 --- a/chrome/browser/password_manager/android/password_manager_android_util.cc +++ b/chrome/browser/password_manager/android/password_manager_android_util.cc
@@ -21,6 +21,7 @@ #include "components/sync/base/pref_names.h" #include "third_party/abseil-cpp/absl/base/attributes.h" +using password_manager::prefs::kCurrentMigrationVersionToGoogleMobileServices; using password_manager::prefs::UseUpmLocalAndSeparateStoresState; namespace password_manager_android_util { @@ -86,6 +87,13 @@ case browser_sync::SyncToSigninMigrationDataTypeDecision:: kDontMigrateTypeNotActive: case browser_sync::SyncToSigninMigrationDataTypeDecision::kMigrate: + // Unhealthy UPM users (unenrolled or didn't complete initial migration) + // can't be part of the experiment to prevent any potential data loss. + if (password_manager_upm_eviction::IsCurrentUserEvicted(pref_service) || + pref_service->GetInteger( + kCurrentMigrationVersionToGoogleMobileServices) == 0) { + return LocalUpmUserType::kNotEligible; + } return LocalUpmUserType::kSyncing; case browser_sync::SyncToSigninMigrationDataTypeDecision:: kDontMigrateTypeDisabled:
diff --git a/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc b/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc index 5bd4987c..c069b8b 100644 --- a/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc +++ b/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc
@@ -44,6 +44,7 @@ #include "components/sync/service/sync_service_impl.h" #include "components/sync/service/sync_user_settings.h" #include "components/sync/test/fake_server.h" +#include "components/sync/test/fake_server_http_post_provider.h" #include "components/sync/test/fake_server_network_resources.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/browser_task_environment.h" @@ -399,7 +400,7 @@ SignInAndEnableSync(); ASSERT_TRUE( SyncDataTypeActiveWaiter(sync_service(), syncer::PREFERENCES).Wait()); - // TODO(crbug.com/1509058): Re-implement sync suppression and uncomment. + // TODO(b/321217859): Re-implement sync suppression and uncomment. // ASSERT_FALSE(sync_service()->GetActiveDataTypes().Has(syncer::PASSWORDS)); // Pretend the migration finished. @@ -447,7 +448,7 @@ } } -TEST_F(UsesSplitStoresAndUPMForLocalTest, Syncing) { +TEST_F(UsesSplitStoresAndUPMForLocalTest, SyncingCompletedInitialMigration) { { base::test::ScopedFeatureList disable_local_upm; disable_local_upm.InitAndDisableFeature( @@ -458,6 +459,9 @@ SignInAndEnableSync(); ASSERT_TRUE( SyncDataTypeActiveWaiter(sync_service(), syncer::PASSWORDS).Wait()); + pref_service()->SetInteger( + password_manager::prefs::kCurrentMigrationVersionToGoogleMobileServices, + 1); ASSERT_FALSE(UsesSplitStoresAndUPMForLocal(pref_service())); DestroyProfile(); } @@ -479,6 +483,79 @@ EXPECT_EQ(account_store_observer.WaitForResults().size(), 1u); DestroyProfile(); } + + { + // Disabling the flag again should move the data back to the "profile" + // database. To rule out that data is just being redownloaded from the + // fake server, disable network. + base::test::ScopedFeatureList disable_local_upm; + disable_local_upm.InitAndDisableFeature( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration); + fake_server::FakeServerHttpPostProvider::DisableNetwork(); + CreateProfile(); + EXPECT_FALSE(UsesSplitStoresAndUPMForLocal(pref_service())); + password_manager::PasswordStoreResultsObserver profile_store_observer; + profile_password_store()->GetAllLogins(profile_store_observer.GetWeakPtr()); + EXPECT_EQ(profile_store_observer.WaitForResults().size(), 1u); + EXPECT_FALSE(account_password_store()); + DestroyProfile(); + } +} + +TEST_F(UsesSplitStoresAndUPMForLocalTest, SyncingButUnenrolled) { + // Set that initial migration is complete but user got unenrolled. + { + CreateProfile(); + pref_service()->SetInteger( + password_manager::prefs::kCurrentMigrationVersionToGoogleMobileServices, + 1); + pref_service()->SetBoolean( + password_manager::prefs::kUnenrolledFromGoogleMobileServicesDueToErrors, + true); + SignInAndEnableSync(); + ASSERT_TRUE( + SyncDataTypeActiveWaiter(sync_service(), syncer::PASSWORDS).Wait()); + DestroyProfile(); + } + { + base::test::ScopedFeatureList enable_local_upm( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration); + CreateProfile(); + ASSERT_TRUE( + SyncDataTypeActiveWaiter(sync_service(), syncer::PASSWORDS).Wait()); + EXPECT_FALSE(UsesSplitStoresAndUPMForLocal(pref_service())); + DestroyProfile(); + } +} + +TEST_F(UsesSplitStoresAndUPMForLocalTest, + SyncingButDidNotFinishInitialMigration) { + // Set that initial migration was not complete. + { + CreateProfile(); + pref_service()->SetInteger( + password_manager::prefs::kCurrentMigrationVersionToGoogleMobileServices, + 0); + base::test::ScopedFeatureList enable_local_upm( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration); + SignInAndEnableSync(); + ASSERT_TRUE( + SyncDataTypeActiveWaiter(sync_service(), syncer::PASSWORDS).Wait()); + DestroyProfile(); + } + { + base::test::ScopedFeatureList enable_local_upm( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration); + CreateProfile(); + ASSERT_TRUE( + SyncDataTypeActiveWaiter(sync_service(), syncer::PASSWORDS).Wait()); + EXPECT_FALSE(UsesSplitStoresAndUPMForLocal(pref_service())); + DestroyProfile(); + } } } // namespace
diff --git a/chrome/browser/password_manager/android/password_store_android_account_backend.cc b/chrome/browser/password_manager/android/password_store_android_account_backend.cc index b7adc6bf..4b1fd57 100644 --- a/chrome/browser/password_manager/android/password_store_android_account_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_account_backend.cc
@@ -16,6 +16,7 @@ #include "components/password_manager/core/browser/affiliation/affiliations_prefetcher.h" #include "components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler.h" #include "components/password_manager/core/browser/password_store/password_store_backend_error.h" +#include "components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h" #include "components/password_manager/core/browser/password_sync_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/sync/base/features.h" @@ -367,6 +368,12 @@ return GetSyncingAccount(sync_service_); } +PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType +PasswordStoreAndroidAccountBackend::GetStoreType() { + return PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kAccount; +} + void PasswordStoreAndroidAccountBackend::OnSyncServiceInitialized( syncer::SyncService* sync_service) { // TODO(crbug.com/1335387) Check if this might be called multiple times
diff --git a/chrome/browser/password_manager/android/password_store_android_account_backend.h b/chrome/browser/password_manager/android/password_store_android_account_backend.h index f40506c9..3735b52 100644 --- a/chrome/browser/password_manager/android/password_store_android_account_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_account_backend.h
@@ -91,6 +91,8 @@ AndroidBackendAPIErrorCode error) override; void OnCallToGMSCoreSucceeded() override; std::string GetAccountToRetryOperation() override; + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType + GetStoreType() override; // If |forms_or_error| contains forms, it retrieves and fills in affiliation // and branding information for Android credentials in the forms and invokes
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.cc b/chrome/browser/password_manager/android/password_store_android_backend.cc index 3a83b665..9fee8e8 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend.cc
@@ -374,7 +374,6 @@ } // namespace - PasswordStoreAndroidBackend::PasswordStoreAndroidBackend( std::unique_ptr<PasswordStoreAndroidBackendBridgeHelper> bridge_helper, std::unique_ptr<PasswordManagerLifecycleHelper> lifecycle_helper, @@ -509,7 +508,8 @@ // Record FillMatchingLoginsAsync metrics prior to invoking |callback|. LoginsOrErrorReply record_metrics_and_reply = ReportMetricsAndInvokeCallbackForLoginsRetrieval( - MethodName("FillMatchingLoginsAsync"), std::move(callback)); + MethodName("FillMatchingLoginsAsync"), std::move(callback), + GetStoreType()); // Create a barrier callback that aggregates results of a multiple // calls to GetLoginsInternal. @@ -552,7 +552,8 @@ // Record metrics prior to invoking |callback|. PasswordChangesOrErrorReply record_metrics_and_reply = ReportMetricsAndInvokeCallbackForStoreModifications( - MethodName("RemoveLoginsByURLAndTimeAsync"), std::move(callback)); + MethodName("RemoveLoginsByURLAndTimeAsync"), std::move(callback), + GetStoreType()); GetAllLoginsInternal( account, @@ -571,7 +572,8 @@ // Record metrics prior to invoking |callback|. PasswordChangesOrErrorReply record_metrics_and_reply = ReportMetricsAndInvokeCallbackForStoreModifications( - MethodName("RemoveLoginsCreatedBetweenAsync"), std::move(callback)); + MethodName("RemoveLoginsCreatedBetweenAsync"), std::move(callback), + GetStoreType()); GetAllLoginsInternal( account, @@ -588,22 +590,22 @@ std::string account, const base::RepeatingCallback<bool(const GURL&)>& origin_filter, base::OnceClosure completion) { - // TODO(https://crbug.com/1229655) Switch to using base::PassThrough to handle - // this callback more gracefully when it's implemented. + // TODO(https://crbug.com/1229655) Switch to using base::PassThrough to + // handle this callback more gracefully when it's implemented. PasswordChangesOrErrorReply record_metrics_and_run_completion = base::BindOnce( [](PasswordStoreBackendMetricsRecorder metrics_recorder, base::OnceClosure completion, PasswordChangesOrError changes) { // Errors are not recorded at the moment. - // TODO(https://crbug.com/1278807): Implement error handling, when - // actual store changes will be received from the store. + // TODO(https://crbug.com/1278807): Implement error handling, + // when actual store changes will be received from the store. metrics_recorder.RecordMetrics(SuccessStatus::kSuccess, /*error=*/std::nullopt); std::move(completion).Run(); }, PasswordStoreBackendMetricsRecorder( BackendInfix("AndroidBackend"), - MethodName("DisableAutoSignInForOriginsAsync")), + MethodName("DisableAutoSignInForOriginsAsync"), GetStoreType()), std::move(completion)); GetAllLoginsInternal( @@ -896,11 +898,11 @@ base::TimeDelta delay) { DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); request_for_job_.emplace( - job_id, JobReturnHandler( - std::move(callback), - PasswordStoreBackendMetricsRecorder( - BackendInfix("AndroidBackend"), std::move(method_name)), - delay, operation)); + job_id, JobReturnHandler(std::move(callback), + PasswordStoreBackendMetricsRecorder( + BackendInfix("AndroidBackend"), + std::move(method_name), GetStoreType()), + delay, operation)); } std::optional<PasswordStoreAndroidBackend::JobReturnHandler> @@ -993,7 +995,9 @@ LoginsOrErrorReply PasswordStoreAndroidBackend::ReportMetricsAndInvokeCallbackForLoginsRetrieval( const MethodName& method_name, - LoginsOrErrorReply callback) { + LoginsOrErrorReply callback, + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType + store_type) { // TODO(https://crbug.com/1229655) Switch to using base::PassThrough to handle // this callback more gracefully when it's implemented. return base::BindOnce( @@ -1007,7 +1011,7 @@ std::move(callback).Run(std::move(results)); }, PasswordStoreBackendMetricsRecorder(BackendInfix("AndroidBackend"), - method_name), + method_name, store_type), std::move(callback)); } @@ -1015,7 +1019,9 @@ PasswordChangesOrErrorReply PasswordStoreAndroidBackend:: ReportMetricsAndInvokeCallbackForStoreModifications( const MethodName& method_name, - PasswordChangesOrErrorReply callback) { + PasswordChangesOrErrorReply callback, + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType + store_type) { // TODO(https://crbug.com/1229655) Switch to using base::PassThrough to handle // this callback more gracefully when it's implemented. return base::BindOnce( @@ -1029,7 +1035,7 @@ std::move(callback).Run(std::move(results)); }, PasswordStoreBackendMetricsRecorder(BackendInfix("AndroidBackend"), - method_name), + method_name, store_type), std::move(callback)); }
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.h b/chrome/browser/password_manager/android/password_store_android_backend.h index 0e591b7..0831471 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_backend.h
@@ -175,6 +175,10 @@ virtual void OnCallToGMSCoreSucceeded() = 0; // Subclasses have to provide an account which will be used for retries. virtual std::string GetAccountToRetryOperation() = 0; + // Subclasses have to provide a store type that is used for tracking metrics + // that are split for local and account. + virtual PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType + GetStoreType() = 0; private: SEQUENCE_CHECKER(main_sequence_checker_); @@ -332,7 +336,9 @@ // |callback|. static LoginsOrErrorReply ReportMetricsAndInvokeCallbackForLoginsRetrieval( const MethodName& method_name, - LoginsOrErrorReply callback); + LoginsOrErrorReply callback, + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType + store_type); // Creates a metrics recorder that records latency and success metrics for // store modification operation with |method_name| name prior to @@ -340,7 +346,9 @@ static PasswordChangesOrErrorReply ReportMetricsAndInvokeCallbackForStoreModifications( const MethodName& method_name, - PasswordChangesOrErrorReply callback); + PasswordChangesOrErrorReply callback, + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType + store_type); // Invoked synchronously by `lifecycle_helper_` when Chrome is foregrounded. // This should not cover the initial startup since the registration for the
diff --git a/chrome/browser/password_manager/android/password_store_android_local_backend.cc b/chrome/browser/password_manager/android/password_store_android_local_backend.cc index 80e01fe..ec3541cf 100644 --- a/chrome/browser/password_manager/android/password_store_android_local_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_local_backend.cc
@@ -178,4 +178,10 @@ return std::string(); } +PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType +PasswordStoreAndroidLocalBackend::GetStoreType() { + return PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kLocal; +} + } // namespace password_manager
diff --git a/chrome/browser/password_manager/android/password_store_android_local_backend.h b/chrome/browser/password_manager/android/password_store_android_local_backend.h index 163ea78..c964b5ff 100644 --- a/chrome/browser/password_manager/android/password_store_android_local_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_local_backend.h
@@ -84,6 +84,8 @@ AndroidBackendAPIErrorCode error) override; void OnCallToGMSCoreSucceeded() override; std::string GetAccountToRetryOperation() override; + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType + GetStoreType() override; base::WeakPtrFactory<PasswordStoreAndroidLocalBackend> weak_ptr_factory_{ this};
diff --git a/chrome/browser/password_manager/android/pwd_migration/BUILD.gn b/chrome/browser/password_manager/android/pwd_migration/BUILD.gn index 942d241..69ec08bb 100644 --- a/chrome/browser/password_manager/android/pwd_migration/BUILD.gn +++ b/chrome/browser/password_manager/android/pwd_migration/BUILD.gn
@@ -48,6 +48,8 @@ "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningUtil.java", "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java", "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewBinder.java", + "java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediator.java", + "java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetProperties.java", "java/src/org/chromium/chrome/browser/pwd_migration/ScrollablePasswordMigrationWarningContent.java", ] @@ -57,7 +59,10 @@ robolectric_library("junit") { testonly = true - sources = [ "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediatorTest.java" ] + sources = [ + "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediatorTest.java", + "java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediatorTest.java", + ] deps = [ ":java",
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediator.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediator.java new file mode 100644 index 0000000..f3ea74b --- /dev/null +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediator.java
@@ -0,0 +1,35 @@ +// 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. + +package org.chromium.chrome.browser.pwd_migration; + +import static org.chromium.chrome.browser.pwd_migration.PostPasswordMigrationSheetProperties.VISIBLE; + +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; +import org.chromium.ui.modelutil.PropertyModel; + +/** + * Contains the logic for the post password migration sheet. It sets the state of the model and + * reacts to events. + */ +class PostPasswordMigrationSheetMediator { + private PropertyModel mModel; + + void initialize(PropertyModel model) { + mModel = model; + } + + void showSheet() { + mModel.set(VISIBLE, true); + } + + void onDismissed(@StateChangeReason int reason) { + if (!mModel.get(VISIBLE)) return; // Dismiss only if not dismissed yet. + mModel.set(VISIBLE, false); + } + + PropertyModel getModel() { + return mModel; + } +}
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediatorTest.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediatorTest.java new file mode 100644 index 0000000..7ffb37d --- /dev/null +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetMediatorTest.java
@@ -0,0 +1,74 @@ +// 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. + +package org.chromium.chrome.browser.pwd_migration; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import static org.chromium.chrome.browser.pwd_migration.PostPasswordMigrationSheetProperties.DISMISS_HANDLER; +import static org.chromium.chrome.browser.pwd_migration.PostPasswordMigrationSheetProperties.VISIBLE; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.mockito.quality.Strictness; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Batch; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; +import org.chromium.ui.modelutil.PropertyModel; + +/** Tests for {@link PostPasswordMigrationSheetMediator}. */ +@RunWith(BaseRobolectricTestRunner.class) +@Batch(Batch.PER_CLASS) +public class PostPasswordMigrationSheetMediatorTest { + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); + + private PostPasswordMigrationSheetMediator mMediator = new PostPasswordMigrationSheetMediator(); + + @Mock private BottomSheetController mBottomSheetController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mMediator.initialize( + PostPasswordMigrationSheetProperties.createDefaultModel(mMediator::onDismissed)); + } + + @Test + public void testShowWarningChangesVisibility() { + PropertyModel model = mMediator.getModel(); + assertFalse(model.get(VISIBLE)); + mMediator.showSheet(); + assertTrue(model.get(VISIBLE)); + } + + @Test + public void testOnDismissedChangesVisibility() { + PropertyModel model = mMediator.getModel(); + mMediator.showSheet(); + assertTrue(model.get(VISIBLE)); + mMediator.onDismissed(StateChangeReason.NONE); + assertFalse(model.get(VISIBLE)); + } + + @Test + public void testDismissHandlerChangesVisibility() { + PropertyModel model = mMediator.getModel(); + assertNotNull(model.get(DISMISS_HANDLER)); + assertFalse(model.get(VISIBLE)); + mMediator.showSheet(); + assertTrue(model.get(VISIBLE)); + model.get(DISMISS_HANDLER).onResult(StateChangeReason.NONE); + assertFalse(model.get(VISIBLE)); + } +}
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetProperties.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetProperties.java new file mode 100644 index 0000000..9dd687f1 --- /dev/null +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PostPasswordMigrationSheetProperties.java
@@ -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. + +package org.chromium.chrome.browser.pwd_migration; + +import org.chromium.base.Callback; +import org.chromium.ui.modelutil.PropertyModel; + +/** Properties defined here reflect the visible state of the post password migration sheet */ +class PostPasswordMigrationSheetProperties { + static final PropertyModel.WritableBooleanPropertyKey VISIBLE = + new PropertyModel.WritableBooleanPropertyKey("visible"); + static final PropertyModel.ReadableObjectPropertyKey<Callback<Integer>> DISMISS_HANDLER = + new PropertyModel.ReadableObjectPropertyKey<>("dismiss_handler"); + + static PropertyModel createDefaultModel(Callback<Integer> dismissHandler) { + return new PropertyModel.Builder(VISIBLE, DISMISS_HANDLER) + .with(VISIBLE, false) + .with(DISMISS_HANDLER, dismissHandler) + .build(); + } + + private PostPasswordMigrationSheetProperties() {} +}
diff --git a/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h b/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h index bd7533c2..66d063c 100644 --- a/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h +++ b/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h
@@ -60,9 +60,6 @@ // Raised when the count of janky intervals reaches X. // Can be used by the UI to show a promo virtual void OnJankThresholdReached() {} - - // Raised when memory metrics for a discarded page becomes available to read - virtual void OnMemoryMetricsRefreshed() {} }; class PreDiscardResourceUsage @@ -142,7 +139,6 @@ void NotifyTabCountThresholdReached() override; void NotifyMemoryThresholdReached() override; - void NotifyMemoryMetricsRefreshed(ProxyAndPmfKbVector) override; }; explicit UserPerformanceTuningManager(
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc index 5689e95..66dcc116 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc
@@ -180,34 +180,6 @@ })); } -void UserPerformanceTuningManager::UserPerformanceTuningReceiverImpl:: - NotifyMemoryMetricsRefreshed(ProxyAndPmfKbVector proxies_and_pmf) { - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce( - [](ProxyAndPmfKbVector web_contents_memory_usage) { - if (base::FeatureList::IsEnabled( - performance_manager::features::kMemoryUsageInHovercards)) { - for (const auto& [contents_proxy, pmf] : - web_contents_memory_usage) { - content::WebContents* web_contents = contents_proxy.Get(); - if (web_contents) { - TabResourceUsageTabHelper* const helper = - TabResourceUsageTabHelper::FromWebContents(web_contents); - if (helper) { - helper->SetMemoryUsageInBytes(pmf * 1024); - } - } - } - } - // Hitting this CHECK would mean this task is running after - // PostMainMessageLoopRun, which shouldn't happen. - CHECK(g_user_performance_tuning_manager); - GetInstance()->NotifyMemoryMetricsRefreshed(); - }, - std::move(proxies_and_pmf))); -} - UserPerformanceTuningManager::UserPerformanceTuningManager( PrefService* local_state, std::unique_ptr<UserPerformanceTuningNotifier> notifier, @@ -292,12 +264,6 @@ } } -void UserPerformanceTuningManager::NotifyMemoryMetricsRefreshed() { - for (auto& obs : observers_) { - obs.OnMemoryMetricsRefreshed(); - } -} - void UserPerformanceTuningManager::DiscardPageForTesting( content::WebContents* web_contents) { base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.cc b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.cc index 9439a32..98eadaa 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.cc +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.cc
@@ -67,21 +67,6 @@ } } -void UserPerformanceTuningNotifier::OnLoadingStateChanged( - const PageNode* page_node, - PageNode::LoadingState previous_state) { - if (features::kMemoryUsageInHovercardsUpdateTrigger.Get() == - features::MemoryUsageInHovercardsUpdateTrigger::kNavigation && - page_node->GetType() == PageType::kTab && - page_node->GetLoadingState() == PageNode::LoadingState::kLoadedIdle) { - auto* metrics_decorator = - page_node->GetGraph() - ->GetRegisteredObjectAs< - performance_manager::ProcessMetricsDecorator>(); - metrics_decorator->RequestImmediateMetrics(); - } -} - void UserPerformanceTuningNotifier::OnProcessMemoryMetricsAvailable( const SystemNode* system_node) { uint64_t total_rss = 0; @@ -106,8 +91,6 @@ proxies_and_pmf.emplace_back(page_node->GetContentsProxy(), page_node->EstimatePrivateFootprintSize()); } - - receiver_->NotifyMemoryMetricsRefreshed(std::move(proxies_and_pmf)); } void UserPerformanceTuningNotifier::MaybeAddTabAndNotify(
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.h b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.h index c448bc50..68b69ef 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.h +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.h
@@ -44,9 +44,6 @@ // Called when the current total resident set size of all processes exceeds // `resident_set_threshold_kb`. virtual void NotifyMemoryThresholdReached() = 0; - - // Called when the memory metrics for a discarded tab is available to read - virtual void NotifyMemoryMetricsRefreshed(ProxyAndPmfKbVector) = 0; }; UserPerformanceTuningNotifier(std::unique_ptr<Receiver> delegate, @@ -63,8 +60,6 @@ void OnBeforePageNodeRemoved(const PageNode* page_node) override; void OnTypeChanged(const PageNode* page_node, PageType previous_type) override; - void OnLoadingStateChanged(const PageNode* page_node, - PageNode::LoadingState previous_state) override; // SystemNode::ObserverDefaultImpl: void OnProcessMemoryMetricsAvailable(const SystemNode* system_node) override;
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier_unittest.cc b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier_unittest.cc index 78cdd3c..c133b75 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier_unittest.cc +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier_unittest.cc
@@ -38,19 +38,8 @@ ++memory_percent_threshold_reached_count_; } - void NotifyMemoryMetricsRefreshed( - ProxyAndPmfKbVector proxies_and_pmf) override { - pages_pmf_kb_.clear(); - - base::ranges::transform(proxies_and_pmf, - std::back_inserter(pages_pmf_kb_), - &std::pair<WebContentsProxy, uint64_t>::second); - ++memory_refreshed_count_; - } - int tab_count_threshold_reached_count_ = 0; int memory_percent_threshold_reached_count_ = 0; - int memory_refreshed_count_ = 0; std::vector<uint64_t> pages_pmf_kb_; }; @@ -144,58 +133,4 @@ ->OnProcessMemoryMetricsAvailable(); EXPECT_EQ(1, receiver_->memory_percent_threshold_reached_count_); } - -TEST_F(UserPerformanceTuningNotifierTest, TestMemoryAvailableTriggered) { - // Memory Metrics are available - auto process1 = CreateNode<ProcessNodeImpl>(); - auto page1 = CreateNode<PageNodeImpl>(); - auto frame1 = CreateFrameNodeAutoId(process1.get(), page1.get()); - frame1->SetPrivateFootprintKbEstimate(10); - - auto process2 = CreateNode<ProcessNodeImpl>(); - auto page2 = CreateNode<PageNodeImpl>(); - auto frame2 = CreateFrameNodeAutoId(process2.get(), page2.get()); - frame2->SetPrivateFootprintKbEstimate(20); - - SystemNodeImpl::FromNode(graph()->GetSystemNode()) - ->OnProcessMemoryMetricsAvailable(); - EXPECT_EQ(1, receiver_->memory_refreshed_count_); - - std::vector<uint64_t> expected_pmf_kb{ - frame1->GetPrivateFootprintKbEstimate(), - frame2->GetPrivateFootprintKbEstimate()}; - EXPECT_EQ(std::size(expected_pmf_kb), receiver_->pages_pmf_kb_.size()); - EXPECT_THAT(expected_pmf_kb, - testing::UnorderedElementsAreArray(receiver_->pages_pmf_kb_)); - - // When memory metrics are available again, the notifier should be - // triggered again - SystemNodeImpl::FromNode(graph()->GetSystemNode()) - ->OnProcessMemoryMetricsAvailable(); - EXPECT_EQ(2, receiver_->memory_refreshed_count_); -} - -TEST_F(UserPerformanceTuningNotifierTest, - TestRequestImmediateMetricsTriggered) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeatureWithParameters( - features::kMemoryUsageInHovercards, - {{"memory_update_trigger", "navigation"}}); - - // Memory Metrics are available - auto process = CreateNode<ProcessNodeImpl>(); - auto page = CreateNode<PageNodeImpl>(); - page->SetType(PageType::kTab); - auto frame = CreateFrameNodeAutoId(process.get(), page.get()); - frame->SetPrivateFootprintKbEstimate(30); - - // No memory refresh should occur while loading. - page->SetLoadingState(PageNode::LoadingState::kLoading); - EXPECT_EQ(0, decorator_->request_immediate_metrics_count_); - - // Memory refresh should occur after MainFrameDocumentCommitted. - page->SetLoadingState(PageNode::LoadingState::kLoadedIdle); - EXPECT_EQ(1, decorator_->request_immediate_metrics_count_); -} - } // namespace performance_manager::user_tuning
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc index 10bda6e..7d1997a 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc
@@ -235,10 +235,13 @@ embedded_test_server_.StartAcceptingConnections(); - account_info_ = - signin::MakeAccountAvailable(identity_manager(), kTestEmail); - signin::SetRefreshTokenForAccount( - identity_manager(), account_info_.account_id, kTestRefreshToken); + account_info_ = MakeAccountAvailable( + identity_manager(), signin::AccountAvailabilityOptionsBuilder() + .AsPrimary(signin::ConsentLevel::kSignin) + .WithRefreshToken(kTestRefreshToken) + .Build(kTestEmail)); + // signin::SetRefreshTokenForAccount( + // identity_manager(), account_info_.account_id, kTestRefreshToken); SetupFakeGaiaResponses(); } @@ -457,9 +460,7 @@ CreateTurnSyncOnHelper(); WaitForPolicyHanging(); - // User is not signed in, policy is not applied. - EXPECT_EQ(std::nullopt, - signin::GetPrimaryAccountConsentLevel(identity_manager())); + // Policy hanging, policy is not applied. EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kShowHomeButton)); EXPECT_TRUE(signin_client()->IsClearPrimaryAccountAllowed( /*has_sync_account=*/false));
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index abda4d3..9919baa 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/policy/webhid_device_policy_handler.h" #include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h" #include "chrome/browser/prefetch/pref_names.h" +#include "chrome/browser/profiles/allowed_domains_for_apps_policy_handler.h" #include "chrome/browser/profiles/force_safe_search_policy_handler.h" #include "chrome/browser/profiles/force_youtube_safety_mode_policy_handler.h" #include "chrome/browser/profiles/guest_mode_policy_handler.h" @@ -188,6 +189,7 @@ #include "chrome/browser/policy/default_geolocation_policy_handler.h" #include "chrome/browser/policy/device_login_screen_geolocation_access_level_policy_handler.h" #include "chrome/browser/policy/os_color_mode_policy_handler.h" +#include "chrome/browser/policy/screen_capture_location_policy_handler.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/services/assistant/public/cpp/assistant_prefs.h" #include "chromeos/ash/services/multidevice_setup/public/cpp/prefs.h" @@ -906,9 +908,6 @@ { key::kSSLErrorOverrideAllowedForOrigins, prefs::kSSLErrorOverrideAllowedForOrigins, base::Value::Type::LIST }, - { key::kAllowedDomainsForApps, - prefs::kAllowedDomainsForApps, - base::Value::Type::STRING }, { key::kEnableMediaRouter, prefs::kEnableMediaRouter, base::Value::Type::BOOLEAN }, @@ -2799,6 +2798,7 @@ std::make_unique<bruschetta::BruschettaInstallerPolicyHandler>( chrome_schema)); handlers->AddHandler(std::make_unique<DriveFileSyncAvailablePolicyHandler>()); + handlers->AddHandler(std::make_unique<ScreenCaptureLocationPolicyHandler>()); #endif // BUILDFLAG(IS_CHROMEOS_ASH) // On most platforms, there is a legacy policy @@ -2939,6 +2939,8 @@ chrome_schema)); #endif // BUILDFLAG(IS_CHROMEOS_ASH) + handlers->AddHandler(std::make_unique<AllowedDomainsForAppsPolicyHandler>()); + return handlers; }
diff --git a/chrome/browser/policy/profile_policy_connector.cc b/chrome/browser/policy/profile_policy_connector.cc index 441c56e2..3472267 100644 --- a/chrome/browser/policy/profile_policy_connector.cc +++ b/chrome/browser/policy/profile_policy_connector.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/browser_switcher/browser_switcher_policy_migrator.h" #include "chrome/browser/infobars/simple_alert_infobar_creator.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" +#include "chrome/browser/profiles/allowed_domains_for_apps_policy_handler.h" #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_delegate.h" @@ -448,6 +449,7 @@ migrators.push_back( std::make_unique<browser_switcher::BrowserSwitcherPolicyMigrator>()); #endif + migrators.push_back(std::make_unique<AllowedDomainsForAppsPolicyMigrator>()); #if BUILDFLAG(IS_CHROMEOS_ASH) ConfigurationPolicyProvider* user_policy_delegate_candidate =
diff --git a/chrome/browser/policy/screen_capture_location_policy_handler.cc b/chrome/browser/policy/screen_capture_location_policy_handler.cc new file mode 100644 index 0000000..4860702 --- /dev/null +++ b/chrome/browser/policy/screen_capture_location_policy_handler.cc
@@ -0,0 +1,82 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/policy/screen_capture_location_policy_handler.h" + +#include <string> +#include <utility> + +#include "base/values.h" +#include "components/policy/core/browser/policy_error_map.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/schema.h" +#include "components/policy/policy_constants.h" +#include "components/prefs/pref_value_map.h" +#include "components/strings/grit/components_strings.h" + +namespace policy { + +namespace { + +const char kGoogleDriveNamePolicyVariableName[] = "${google_drive}"; +const char kOneDriveNamePolicyVariableName[] = "${onedrive}"; + +bool IsValidLocationString(const std::string& str) { + const size_t google_drive_position = + str.find(kGoogleDriveNamePolicyVariableName); + if (google_drive_position != std::string::npos && + google_drive_position != 0) { + return false; + } + const size_t onedrive_position = str.find(kOneDriveNamePolicyVariableName); + if (onedrive_position != std::string::npos && onedrive_position != 0) { + return false; + } + return true; +} + +} // namespace + +ScreenCaptureLocationPolicyHandler::ScreenCaptureLocationPolicyHandler() + : TypeCheckingPolicyHandler(policy::key::kScreenCaptureLocation, + base::Value::Type::STRING) {} + +ScreenCaptureLocationPolicyHandler::~ScreenCaptureLocationPolicyHandler() = + default; + +bool ScreenCaptureLocationPolicyHandler::CheckPolicySettings( + const PolicyMap& policies, + PolicyErrorMap* errors) { + const base::Value* value = nullptr; + if (!CheckAndGetValue(policies, errors, &value)) { + return false; + } + + if (value && !IsValidLocationString(value->GetString())) { + errors->AddError(policy_name(), IDS_POLICY_VALUE_FORMAT_ERROR, + value->GetString()); + return false; + } + + return true; +} + +void ScreenCaptureLocationPolicyHandler::ApplyPolicySettings( + const PolicyMap& policies, + PrefValueMap* prefs) { + const base::Value* value = nullptr; + if (!CheckAndGetValue(policies, nullptr, &value)) { + return; + } + + if (!value || !value->is_string()) { + return; + } + + // TODO(b/323146997): Set Screen Capture custom path expanding the policy. + // prefs->SetString(ash::kCustomCapturePathPrefName, + // value->GetString()); +} + +} // namespace policy
diff --git a/chrome/browser/policy/screen_capture_location_policy_handler.h b/chrome/browser/policy/screen_capture_location_policy_handler.h new file mode 100644 index 0000000..6813f56 --- /dev/null +++ b/chrome/browser/policy/screen_capture_location_policy_handler.h
@@ -0,0 +1,35 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_POLICY_SCREEN_CAPTURE_LOCATION_POLICY_HANDLER_H_ +#define CHROME_BROWSER_POLICY_SCREEN_CAPTURE_LOCATION_POLICY_HANDLER_H_ + +#include "components/policy/core/browser/configuration_policy_handler.h" + +class PrefValueMap; + +namespace policy { + +class PolicyMap; + +// Handles the ScreenCaptureLocation policy. +class ScreenCaptureLocationPolicyHandler : public TypeCheckingPolicyHandler { + public: + ScreenCaptureLocationPolicyHandler(); + ScreenCaptureLocationPolicyHandler( + const ScreenCaptureLocationPolicyHandler&) = delete; + ScreenCaptureLocationPolicyHandler& operator=( + const ScreenCaptureLocationPolicyHandler&) = delete; + ~ScreenCaptureLocationPolicyHandler() override; + + // TypeCheckingPolicyHandler implementation: + bool CheckPolicySettings(const PolicyMap& policies, + PolicyErrorMap* error) override; + void ApplyPolicySettings(const PolicyMap& policies, + PrefValueMap* prefs) override; +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_SCREEN_CAPTURE_LOCATION_POLICY_HANDLER_H_
diff --git a/chrome/browser/policy/screen_capture_location_policy_handler_unittest.cc b/chrome/browser/policy/screen_capture_location_policy_handler_unittest.cc new file mode 100644 index 0000000..a8748cf3 --- /dev/null +++ b/chrome/browser/policy/screen_capture_location_policy_handler_unittest.cc
@@ -0,0 +1,64 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/policy/screen_capture_location_policy_handler.h" + +#include <memory> +#include <string> + +#include "base/values.h" +#include "components/policy/core/browser/policy_error_map.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/policy_types.h" +#include "components/policy/policy_constants.h" +#include "components/prefs/pref_value_map.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +class ScreenCaptureLocationPolicyHandlerTest : public testing::Test { + protected: + PolicyMap policy_; + ScreenCaptureLocationPolicyHandler handler_; + PrefValueMap prefs_; +}; + +TEST_F(ScreenCaptureLocationPolicyHandlerTest, Default) { + PolicyErrorMap errors; + EXPECT_TRUE(handler_.CheckPolicySettings(policy_, &errors)); + EXPECT_EQ(0u, errors.size()); +} + +TEST_F(ScreenCaptureLocationPolicyHandlerTest, SetPolicyInvalid) { + const std::string path = "/root/${google_drive}/foo"; + policy_.Set(key::kScreenCaptureLocation, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false), + nullptr); + PolicyErrorMap errors; + EXPECT_FALSE(handler_.CheckPolicySettings(policy_, &errors)); + EXPECT_EQ(1u, errors.size()); + + constexpr char16_t kExpected[] = u"Expected string value."; + EXPECT_EQ(kExpected, errors.GetErrorMessages(key::kScreenCaptureLocation)); +} + +class ScreenCaptureLocationPolicyHandlerTestWithParam + : public ScreenCaptureLocationPolicyHandlerTest, + public testing::WithParamInterface<const char*> {}; + +TEST_P(ScreenCaptureLocationPolicyHandlerTestWithParam, SetPolicyValid) { + const std::string in = GetParam(); + policy_.Set(key::kScreenCaptureLocation, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(in), nullptr); + PolicyErrorMap errors; + EXPECT_TRUE(handler_.CheckPolicySettings(policy_, &errors)); + EXPECT_EQ(0u, errors.size()); +} + +INSTANTIATE_TEST_SUITE_P( + ScreenCaptureLocationPolicyHandlerTestWithParamInstance, + ScreenCaptureLocationPolicyHandlerTestWithParam, + testing::Values("${onedrive}/foo", "${google_drive}", "", "Downloads")); + +} // namespace policy
diff --git a/chrome/browser/policy/test/user_avatar_customization_selectors_enabled_policy_browsertest.cc b/chrome/browser/policy/test/user_avatar_customization_selectors_enabled_policy_browsertest.cc index a8721f6..fc8cbdc 100644 --- a/chrome/browser/policy/test/user_avatar_customization_selectors_enabled_policy_browsertest.cc +++ b/chrome/browser/policy/test/user_avatar_customization_selectors_enabled_policy_browsertest.cc
@@ -5,8 +5,8 @@ #include "base/memory/raw_ptr.h" #include "base/path_service.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h" -#include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" #include "chrome/browser/policy/policy_test_utils.h" #include "chrome/common/chrome_paths.h" @@ -31,8 +31,8 @@ // Fetch User, which can be used to check the currently set user image user_ = user_manager::UserManager::Get()->GetActiveUser(); // Fetch UserImageManager, which can be used to save a new user image - user_image_manager_ = ash::ChromeUserManager::Get()->GetUserImageManager( - user_->GetAccountId()); + user_image_manager_ = + ash::UserImageManagerRegistry::Get()->GetManager(user_->GetAccountId()); ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_)); }
diff --git a/chrome/browser/profiles/allowed_domains_for_apps_policy_handler.cc b/chrome/browser/profiles/allowed_domains_for_apps_policy_handler.cc new file mode 100644 index 0000000..099115ea --- /dev/null +++ b/chrome/browser/profiles/allowed_domains_for_apps_policy_handler.cc
@@ -0,0 +1,71 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/profiles/allowed_domains_for_apps_policy_handler.h" + +#include "base/strings/string_split.h" +#include "base/values.h" +#include "chrome/common/pref_names.h" +#include "components/policy/policy_constants.h" +#include "components/prefs/pref_value_map.h" + +namespace policy { + +BASE_FEATURE(kAllowedDomainsForAppsNewPolicyHandler, + "kAllowedDomainsForAppsNewPolicyHandler", + base::FEATURE_ENABLED_BY_DEFAULT); + +bool UseAllowedDomainsForAppsNewPolicyHandler() { + return base::FeatureList::IsEnabled(kAllowedDomainsForAppsNewPolicyHandler); +} + +AllowedDomainsForAppsPolicyHandler::AllowedDomainsForAppsPolicyHandler() + : policy::ListPolicyHandler(policy::key::kAllowedDomainsForAppsList, + base::Value::Type::STRING) {} +AllowedDomainsForAppsPolicyHandler::~AllowedDomainsForAppsPolicyHandler() {} + +void AllowedDomainsForAppsPolicyHandler::ApplyList( + base::Value::List filtered_list, + PrefValueMap* prefs) { + std::string list_str; + for (const auto& item : filtered_list) { + if (!item.is_string()) { + NOTREACHED() << "Only string values expected here"; + } + if (!list_str.empty()) { + list_str += ","; + } + list_str += item.GetString(); + } + prefs->SetValue(prefs::kAllowedDomainsForApps, base::Value(list_str)); +} + +// static +void AllowedDomainsForAppsPolicyMigrator::StringToList(base::Value* val) { + base::Value::List list; + std::vector<std::string> tokens = base::SplitString( + val->GetString(), ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + for (const auto& token : tokens) { + list.Append(token); + } + *val = base::Value(std::move(list)); +} + +void AllowedDomainsForAppsPolicyMigrator::Migrate(PolicyBundle* bundle) { + policy::PolicyMap& chrome_map = + bundle->Get(policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, "")); + + const PolicyMigrator::Migration migration = Migration( + key::kAllowedDomainsForApps, policy::key::kAllowedDomainsForAppsList, + base::BindRepeating(&StringToList)); + + if (!UseAllowedDomainsForAppsNewPolicyHandler()) { + // If we should revert to only the old policy we need to clear the new one. + chrome_map.Erase(policy::key::kAllowedDomainsForAppsList); + } + + CopyPolicyIfUnset(chrome_map, &chrome_map, migration); +} + +} // namespace policy
diff --git a/chrome/browser/profiles/allowed_domains_for_apps_policy_handler.h b/chrome/browser/profiles/allowed_domains_for_apps_policy_handler.h new file mode 100644 index 0000000..9af3c9c --- /dev/null +++ b/chrome/browser/profiles/allowed_domains_for_apps_policy_handler.h
@@ -0,0 +1,40 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PROFILES_ALLOWED_DOMAINS_FOR_APPS_POLICY_HANDLER_H_ +#define CHROME_BROWSER_PROFILES_ALLOWED_DOMAINS_FOR_APPS_POLICY_HANDLER_H_ + +#include "base/feature_list.h" +#include "components/policy/core/browser/configuration_policy_handler.h" +#include "components/policy/core/common/policy_migrator.h" + +namespace policy { + +BASE_DECLARE_FEATURE(kAllowedDomainsForAppsNewPolicyHandler); + +bool UseAllowedDomainsForAppsNewPolicyHandler(); + +class AllowedDomainsForAppsPolicyHandler : public ListPolicyHandler { + public: + AllowedDomainsForAppsPolicyHandler(); + AllowedDomainsForAppsPolicyHandler( + const AllowedDomainsForAppsPolicyHandler&) = delete; + AllowedDomainsForAppsPolicyHandler& operator=( + const AllowedDomainsForAppsPolicyHandler&) = delete; + ~AllowedDomainsForAppsPolicyHandler() override; + + void ApplyList(base::Value::List filtered_list, PrefValueMap* prefs) override; +}; + +class AllowedDomainsForAppsPolicyMigrator : public PolicyMigrator { + public: + void Migrate(PolicyBundle* bundle) final; + + private: + static void StringToList(base::Value* val); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_PROFILES_ALLOWED_DOMAINS_FOR_APPS_POLICY_HANDLER_H_
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 472d8411..2933117 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -381,7 +381,6 @@ false); registry->RegisterIntegerPref(policy::policy_prefs::kForceYouTubeRestrict, safe_search_api::YOUTUBE_RESTRICT_OFF); - registry->RegisterStringPref(prefs::kAllowedDomainsForApps, std::string()); registry->RegisterIntegerPref(prefs::kProfileAvatarIndex, -1); // Whether a profile is using an avatar without having explicitely chosen it
diff --git a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts index 681a507..eb5b917b 100644 --- a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts +++ b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts
@@ -253,6 +253,11 @@ } private geolocationAllowedForSystem_(): boolean { + if (!this.prefs) { + // Won't show blocked services and apps in case that the geolocation pref + // is not yet loaded. + return true; + } return this.getPref<GeolocationAccessLevel>( 'ash.user.geolocation_access_level') .value !== GeolocationAccessLevel.DISALLOWED;
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ky.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ky.xtb index cd3c8ca3..f064fa5 100644 --- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ky.xtb +++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ky.xtb
@@ -358,7 +358,7 @@ <translation id="3300733168898541351">артка кайтаруу</translation> <translation id="3307886118343381874">Жадыбалдын аягына өтүү</translation> <translation id="3312997241656799641">Кийинки каралган шилтеме.</translation> -<translation id="3313245066383501820">ChromeVox өзгөртүү баскычы</translation> +<translation id="3313245066383501820">ChromeVox өзгөртүүчү баскыч</translation> <translation id="3317212938060708859">Сыдырма</translation> <translation id="3321460131042519426">Сөз боюнча ташымалдоо</translation> <translation id="3322936298410871309">Мурунку 1-деңгээлдеги баш аты жок</translation>
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn index ad5e381..8fd1425 100644 --- a/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -237,6 +237,7 @@ "//ash/webui/common/resources:load_time_data.m", ] extra_deps = [ ":copy_js" ] + externs_list = [ "$externs_path/chrome_send.js" ] } js_library("display_manager") { @@ -246,8 +247,6 @@ deps = [ ":multi_tap_detector", "components:display_manager_types", - "components:keyboard_utils", - "components:keyboard_utils_oobe", "components:oobe_types", ] extra_deps = [ ":copy_js" ] @@ -303,9 +302,9 @@ ] deps = [ "//ash/webui/common/resources:build_ts", + "//ash/webui/common/resources/cr_elements:build_ts", "//third_party/polymer/v3_0:library", "//ui/webui/resources/cr_components/color_change_listener:build_ts", - "//ash/webui/common/resources/cr_elements:build_ts", "//ui/webui/resources/js:build_ts", "//ui/webui/resources/mojo:build_ts", ]
diff --git a/chrome/browser/resources/chromeos/login/components/BUILD.gn b/chrome/browser/resources/chromeos/login/components/BUILD.gn index d1c1e00..b1f4012 100644 --- a/chrome/browser/resources/chromeos/login/components/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/components/BUILD.gn
@@ -42,10 +42,6 @@ ":api_keys_notice", ":display_manager_types", ":hd_iron_icon", - ":keyboard_utils", - ":keyboard_utils_oobe", - ":long_touch_detector", - ":notification_card", ":oobe_a11y_option", ":oobe_carousel", ":oobe_cr_lottie", @@ -59,7 +55,6 @@ ":oobe_slide", ":oobe_types", ":progress_list_item", - ":security_token_pin", ":web_view_loader", ] } @@ -89,25 +84,6 @@ extra_deps = [ ":web_components" ] } -js_library("keyboard_utils") { - externs_list = [ "$externs_path/chrome_send.js" ] -} - -js_library("keyboard_utils_oobe") { -} - -js_library("long_touch_detector") { - sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/components/long_touch_detector.js" ] - deps = [] - extra_deps = [ ":copy_js" ] -} - -js_library("notification_card") { - sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/components/notification_card.js" ] - deps = [] - extra_deps = [ ":web_components" ] -} - js_library("oobe_a11y_option") { sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/components/oobe_a11y_option.js" ] deps = [] @@ -209,22 +185,6 @@ extra_deps = [ ":web_components" ] } -js_library("security_token_pin") { - sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/components/security_token_pin.js" ] - deps = [ - ":oobe_types", - "./behaviors:oobe_i18n_behavior", - ] - extra_deps = [ ":web_components" ] - externs_list = [ - # pin_keyboard_externs.js is a band-aid to let this closure-compiled JS - # library depend on the typescript file pin_keyboard.ts. If you remove this - # dependency, consider deleting the externs file if it's not used - # elsewhere. - "//ash/webui/common/resources/quick_unlock/pin_keyboard_externs.js", - ] -} - js_library("web_view_loader") { sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/components/web_view_loader.js" ] deps = [] @@ -235,8 +195,6 @@ copy("copy_js") { sources = [ "display_manager_types.js", - "keyboard_utils.js", - "long_touch_detector.js", "oobe_select.js", "oobe_types.js", "web_view_loader.js", @@ -257,7 +215,6 @@ js_files = [ "api_keys_notice.js", "hd_iron_icon.js", - "notification_card.js", "oobe_a11y_option.js", "oobe_carousel.js", "oobe_cr_lottie.js", @@ -266,6 +223,5 @@ "oobe_screens_list.js", "oobe_slide.js", "progress_list_item.js", - "security_token_pin.js", ] }
diff --git a/chrome/browser/resources/chromeos/login/components/keyboard_utils.js b/chrome/browser/resources/chromeos/login/components/keyboard_utils.ts similarity index 67% rename from chrome/browser/resources/chromeos/login/components/keyboard_utils.js rename to chrome/browser/resources/chromeos/login/components/keyboard_utils.ts index af4c570..8c6d6ded 100644 --- a/chrome/browser/resources/chromeos/login/components/keyboard_utils.js +++ b/chrome/browser/resources/chromeos/login/components/keyboard_utils.ts
@@ -4,21 +4,20 @@ /** * Enum for setting the focus direction. - * @enum {string} */ -const FocusDirection = { - Forward: 'forwardFocus', - Backward: 'backwardFocus', -}; +enum FocusDirection { + FORWARD = 'forwardFocus', + BACKWARD = 'backwardFocus', +} export class KeyboardUtils { /** * Initializes event handling for arrow keys driven focus flow. */ - initializeKeyboardFlow() { - document.addEventListener('keydown', this.onKeyDown_.bind(this), true); - document.addEventListener('keypress', this.onKeyIgnore_.bind(this), true); - document.addEventListener('keyup', this.onKeyIgnore_.bind(this), true); + initializeKeyboardFlow(): void { + document.addEventListener('keydown', this.onKeyDown.bind(this), true); + document.addEventListener('keypress', this.onKeyIgnore.bind(this), true); + document.addEventListener('keyup', this.onKeyIgnore.bind(this), true); } /** @@ -26,15 +25,15 @@ * about to be shown. That screen injects a modified version of this class * `InjectedKeyboardUtils` into the WebView that hosts the Gaia page. */ - enableHandlingOfInjectedKeyboardUtilsMessages() { + enableHandlingOfInjectedKeyboardUtilsMessages(): void { window.addEventListener( 'message', this.handleMessageFromInjectedKeyboardUtils.bind(this)); } - handleMessageFromInjectedKeyboardUtils(event) { + private handleMessageFromInjectedKeyboardUtils(event: MessageEvent) { const focusDir = event.data; - if (focusDir == FocusDirection.Forward || - focusDir == FocusDirection.Backward) { + if (focusDir == FocusDirection.FORWARD || + focusDir == FocusDirection.BACKWARD) { this.onAdvanceFocus(focusDir); } } @@ -42,21 +41,18 @@ /** * Handles the actual focus advancing by raising tab/shift-tab key events * on C++ side. - * @param {FocusDirection} focusDir The direction to change focus to. + * @param focusDir The direction to change focus to. */ - onAdvanceFocus(focusDir) { - const reverse = focusDir === FocusDirection.Backward; + onAdvanceFocus(focusDir: FocusDirection): void { + const reverse = focusDir === FocusDirection.BACKWARD; chrome.send('raiseTabKeyEvent', [reverse]); } /** * Swallows keypress and keyup events of arrow keys. - * @param {!Event} event Raised event. - * @private + * @param event Raised event. */ - onKeyIgnore_(event) { - event = /** @type {!KeyboardEvent} */ (event); - + private onKeyIgnore(event: KeyboardEvent): void { if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) { return; } @@ -70,12 +66,9 @@ /** * Handles arrow key events. - * @param {!Event} event Raised event. - * @private + * @param event Raised event. */ - onKeyDown_(event) { - event = /** @type {!KeyboardEvent} */ (event); - + private onKeyDown(event: KeyboardEvent): void { if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) { return; } @@ -85,7 +78,7 @@ // See crbug.com/1083145 if (document.activeElement === document.getElementById('network-selection') && - document.activeElement.shadowRoot.activeElement.tagName == + document.activeElement?.shadowRoot?.activeElement?.tagName == 'NETWORK-SELECT-LOGIN' && (event.key == 'ArrowUp' || event.key == 'ArrowDown')) { return; @@ -99,14 +92,14 @@ // Do not map arrow key events to tab events if the user is currently // focusing an input element and presses on the left or right arrows. - if (document.activeElement.tagName == 'INPUT' && + if (document.activeElement?.tagName == 'INPUT' && (event.key == 'ArrowLeft' || event.key == 'ArrowRight')) { // Default event handling will occur. return; } this.onAdvanceFocus( - arrowBackwards ? FocusDirection.Backward : FocusDirection.Forward); + arrowBackwards ? FocusDirection.BACKWARD : FocusDirection.FORWARD); event.preventDefault(); } } @@ -118,11 +111,14 @@ * overrides the 'onAdvanceFocus' method to send a message to OOBE instead. */ export class InjectedKeyboardUtils extends KeyboardUtils { + private hostWindow: chrome.webviewTag.ContentWindow|null; + private hostOrigin: string|null; + /** * Initial Message that should be sent by the WebView in which * InjectedKeyboardUtils lives in order to start communicating. */ - static get INITIAL_MSG() { + static get INITIAL_MSG(): string { return 'initialMessage'; } @@ -135,20 +131,18 @@ /** * Initializes event handling for arrow keys driven focus flow in the base * class and listens for 'message' events that come from OOBE. - * @override */ - initializeKeyboardFlow() { + override initializeKeyboardFlow(): void { super.initializeKeyboardFlow(); - window.addEventListener('message', this.onInitMessage_.bind(this)); + window.addEventListener('message', this.onInitMessage.bind(this)); } /** * Send a message to OOBE to advance the focus forwards, or backwards. - * @param {FocusDirection} focusDir The direction to change focus to. - * @override + * @param focusDir The direction to change focus to. */ - onAdvanceFocus(focusDir) { - if (this.hostWindow) { + override onAdvanceFocus(focusDir: FocusDirection): void { + if (this.hostWindow && this.hostOrigin) { this.hostWindow.postMessage(focusDir, this.hostOrigin); } } @@ -156,13 +150,12 @@ /** * Handles the initial messaging posted from webview, where this script is * injected. - * @param {Event} event Message event posted from webview. - * @private + * @param event Message event posted from webview. */ - onInitMessage_(event) { + private onInitMessage(event: MessageEvent): void { if (event.data == InjectedKeyboardUtils.INITIAL_MSG && event.origin == 'chrome://oobe') { - this.hostWindow = event.source; + this.hostWindow = event.source as chrome.webviewTag.ContentWindow; this.hostOrigin = event.origin; } }
diff --git a/chrome/browser/resources/chromeos/login/components/keyboard_utils_oobe.js b/chrome/browser/resources/chromeos/login/components/keyboard_utils_oobe.ts similarity index 84% rename from chrome/browser/resources/chromeos/login/components/keyboard_utils_oobe.js rename to chrome/browser/resources/chromeos/login/components/keyboard_utils_oobe.ts index 7d2b0d8..e5e06eb 100644 --- a/chrome/browser/resources/chromeos/login/components/keyboard_utils_oobe.js +++ b/chrome/browser/resources/chromeos/login/components/keyboard_utils_oobe.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assert} from '//resources/ash/common/assert.js'; +import {assert} from '//resources/js/assert.js'; import {KeyboardUtils} from './keyboard_utils.js'; @@ -21,11 +21,7 @@ DATA: '', }; -/** - * - * @param {string} sourceCode - */ -function prepareKeyboardUtilsForInjection(sourceCode) { +function prepareKeyboardUtilsForInjection(sourceCode: string): void { // The closure compiler version is outdated. // TODO(b:260015147) Remove during TS migration. assert(typeof sourceCode.replaceAll == 'function'); @@ -43,15 +39,15 @@ KEYBOARD_UTILS_FOR_INJECTION.DATA = finalSourceCode; } -function fetchKeyboardUtilsSource() { +function fetchKeyboardUtilsSource(): void { const keyboardUtilsUrl = 'components/keyboard_utils.js'; const xhr = new XMLHttpRequest(); xhr.responseType = 'text'; xhr.onreadystatechange = function() { if (xhr.readyState === 4 /* DONE */) { assert(200 === xhr.status); - assert(typeof xhr.response == 'string'); - prepareKeyboardUtilsForInjection(xhr.response); + assert(xhr.responseType === 'text'); + prepareKeyboardUtilsForInjection(xhr.responseText); } }; xhr.open('GET', keyboardUtilsUrl, true);
diff --git a/chrome/browser/resources/chromeos/login/components/long_touch_detector.js b/chrome/browser/resources/chromeos/login/components/long_touch_detector.js deleted file mode 100644 index 730a47b2..0000000 --- a/chrome/browser/resources/chromeos/login/components/long_touch_detector.js +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -const LONG_TOUCH_TIME_MS = 1000; - -export class LongTouchDetector { - constructor(element, callback) { - this.callback_ = callback; - /** - * This is timeout ID used to kill window timeout that fires "detected" - * callback if touch event was cancelled. - * - * @private {number|null} - */ - this.timeoutId_ = null; - - element.addEventListener('touchstart', () => void this.onTouchStart_()); - element.addEventListener('touchend', () => void this.killTimer_()); - element.addEventListener('touchcancel', () => void this.killTimer_()); - - element.addEventListener('mousedown', () => void this.onTouchStart_()); - element.addEventListener('mouseup', () => void this.killTimer_()); - element.addEventListener('mouseleave', () => void this.killTimer_()); - } - - /** - * window.setTimeout() callback. - * - * @private - */ - onTimeout_() { - this.killTimer_(); - this.callback_(); - } - - /** - * @private - */ - onTouchStart_() { - this.killTimer_(); - this.timeoutId_ = - window.setTimeout(() => void this.onTimeout_(), LONG_TOUCH_TIME_MS); - } - - /** - * @private - */ - killTimer_() { - if (this.timeoutId_ === null) { - return; - } - - window.clearTimeout(this.timeoutId_); - this.timeoutId_ = null; - } -}
diff --git a/chrome/browser/resources/chromeos/login/components/long_touch_detector.ts b/chrome/browser/resources/chromeos/login/components/long_touch_detector.ts new file mode 100644 index 0000000..73a00873 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/components/long_touch_detector.ts
@@ -0,0 +1,47 @@ +// Copyright 2019 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +const LONG_TOUCH_TIME_MS = 1000; + +export class LongTouchDetector { + private callback: () => void; + /** + * This is timeout ID used to kill window timeout that fires "detected" + * callback if touch event was cancelled. + */ + private timeoutId: null|number; + + constructor(element: HTMLElement, callback: () => void) { + this.callback = callback; + this.timeoutId = null; + + element.addEventListener('touchstart', () => void this.onTouchStart()); + element.addEventListener('touchend', () => void this.killTimer()); + element.addEventListener('touchcancel', () => void this.killTimer()); + + element.addEventListener('mousedown', () => void this.onTouchStart()); + element.addEventListener('mouseup', () => void this.killTimer()); + element.addEventListener('mouseleave', () => void this.killTimer()); + } + + private onTimeout(): void { + this.killTimer(); + this.callback(); + } + + private onTouchStart(): void { + this.killTimer(); + this.timeoutId = + window.setTimeout(() => void this.onTimeout(), LONG_TOUCH_TIME_MS); + } + + private killTimer(): void { + if (this.timeoutId === null) { + return; + } + + window.clearTimeout(this.timeoutId); + this.timeoutId = null; + } +}
diff --git a/chrome/browser/resources/chromeos/login/components/notification_card.html b/chrome/browser/resources/chromeos/login/components/notification_card.html index 62afefe..b33ab7b 100644 --- a/chrome/browser/resources/chromeos/login/components/notification_card.html +++ b/chrome/browser/resources/chromeos/login/components/notification_card.html
@@ -72,11 +72,11 @@ </div> </div> <div class="self-stretch horizontal-reverse layout justified center"> - <gaia-button id="submitButton" on-click="buttonClicked_" + <gaia-button id="submitButton" on-click="buttonClicked" hidden$="[[!buttonLabel]]"> <span>[[buttonLabel]]</span> </gaia-button> - <a on-click="linkClicked_" hidden$="{{!linkLabel}}" is="action-link" + <a on-click="linkClicked" hidden$="{{!linkLabel}}" is="action-link" class="oobe-local-link"> <span>[[linkLabel]]</span> </a>
diff --git a/chrome/browser/resources/chromeos/login/components/notification_card.js b/chrome/browser/resources/chromeos/login/components/notification_card.js deleted file mode 100644 index 54bce211..0000000 --- a/chrome/browser/resources/chromeos/login/components/notification_card.js +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import '//resources/ash/common/cr_elements/icons.html.js'; -import '//resources/js/action_link.js'; -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; -import '//resources/polymer/v3_0/paper-styles/color.js'; -import './oobe_icons.html.js'; -import './common_styles/oobe_common_styles.css.js'; - -import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -/** @polymer */ -class NotificationCard extends PolymerElement { - static get is() { - return 'notification-card'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - buttonLabel: {type: String, value: ''}, - - linkLabel: {type: String, value: ''}, - }; - } - - /** @private */ - buttonClicked_() { - this.dispatchEvent(new CustomEvent('buttonclick', - { bubbles: true, composed: true })); - } - - /** - * @param {Event} e - * @private - */ - linkClicked_(e) { - this.dispatchEvent(new CustomEvent('linkclick', - { bubbles: true, composed: true })); - e.preventDefault(); - } - - /** @type {Element} */ - get submitButton() { - return this.$.submitButton; - } -} - -customElements.define(NotificationCard.is, NotificationCard);
diff --git a/chrome/browser/resources/chromeos/login/components/notification_card.ts b/chrome/browser/resources/chromeos/login/components/notification_card.ts new file mode 100644 index 0000000..f351a59 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/components/notification_card.ts
@@ -0,0 +1,70 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '//resources/ash/common/cr_elements/icons.html.js'; +import '//resources/js/action_link.js'; +import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import '//resources/polymer/v3_0/paper-styles/color.js'; +import './oobe_icons.html.js'; +import './common_styles/oobe_common_styles.css.js'; + +import {GaiaButton} from './gaia_button.js'; + +import {assert} from '//resources/js/assert.js'; + +import {PolymerElementProperties} from '//resources/polymer/v3_0/polymer/interfaces.js'; +import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './notification_card.html.js'; + +class NotificationCard extends PolymerElement { + static get is() { + return 'notification-card' as const; + } + + static get template(): HTMLTemplateElement { + return getTemplate(); + } + + static get properties(): PolymerElementProperties { + return { + buttonLabel: { + type: String, + value: '', + }, + linkLabel: { + type: String, + value: '', + }, + }; + } + + private buttonLabel: string; + private linkLabel: string; + + private buttonClicked(): void { + this.dispatchEvent(new CustomEvent('buttonclick', + { bubbles: true, composed: true })); + } + + private linkClicked(e: MouseEvent): void { + this.dispatchEvent(new CustomEvent('linkclick', + { bubbles: true, composed: true })); + e.preventDefault(); + } + + get submitButton(): GaiaButton { + const button = this.shadowRoot?.querySelector('#submitButton'); + assert(button instanceof GaiaButton); + return button; + } +} + +declare global { + interface HTMLElementTagNameMap { + [NotificationCard.is]: NotificationCard; + } +} + +customElements.define(NotificationCard.is, NotificationCard);
diff --git a/chrome/browser/resources/chromeos/login/components/security_token_pin.html b/chrome/browser/resources/chromeos/login/components/security_token_pin.html index 7cbd8bc..9591081 100644 --- a/chrome/browser/resources/chromeos/login/components/security_token_pin.html +++ b/chrome/browser/resources/chromeos/login/components/security_token_pin.html
@@ -60,35 +60,35 @@ [[i18nDynamic(locale, 'securityTokenPinDialogTitle')]] </h1> <div slot="subtitle" id="subtitle"> - <span id="description" hidden="[[processingCompletion_]]"> + <span id="description" hidden="[[processingCompletion]]"> [[i18nDynamic(locale, 'securityTokenPinDialogSubtitle')]] </span> </div> <paper-progress slot="progress" id="progress" - hidden="[[!processingCompletion_]]" - indeterminate="[[processingCompletion_]]"> + hidden="[[!processingCompletion]]" + indeterminate="[[processingCompletion]]"> </paper-progress> <div slot="content" class="content-centered"> - <div id="pinKeyboardContainer" hidden="[[processingCompletion_]]"> + <div id="pinKeyboardContainer" hidden="[[processingCompletion]]"> <pin-keyboard id="pinKeyboard" allow-non-digit - has-error="[[isErrorLabelVisible_(parameters, userEdited_)]]" - aria-label="[[getLabel_(parameters, userEdited_)]]" - on-pin-change="onPinChange_" on-submit="onSubmit_" - disabled="[[!canEdit_]]"> + has-error="[[isErrorLabelVisible(parameters, userEdited)]]" + aria-label="[[getLabel(parameters, userEdited)]]" + on-pin-change="onPinChange" on-submit="onSubmit" + disabled="[[!canEdit]]"> <div id="errorContainer" role="alert" problem - invisible$="[[!isLabelVisible_(parameters, userEdited_)]]"> + invisible$="[[!isLabelVisible(parameters, userEdited)]]"> <iron-icon id="errorIcon" icon="cr:error-outline"></iron-icon> - <span id="error">[[getLabel_(parameters, userEdited_)]]</span> + <span id="error">[[getLabel(parameters, userEdited)]]</span> </div> </pin-keyboard> </div> </div> <div slot="back-navigation"> - <oobe-back-button id="back" on-click="onBackClicked_"> + <oobe-back-button id="back" on-click="onBackClicked"> </oobe-back-button> </div> <div slot="bottom-buttons"> - <oobe-next-button id="submit" on-click="onSubmit_" - disabled="[[!canSubmit_]]"></oobe-next-button> + <oobe-next-button id="submit" on-click="onSubmit" + disabled="[[!canSubmit]]"></oobe-next-button> </div> </oobe-adaptive-dialog>
diff --git a/chrome/browser/resources/chromeos/login/components/security_token_pin.js b/chrome/browser/resources/chromeos/login/components/security_token_pin.js deleted file mode 100644 index 0fbade2..0000000 --- a/chrome/browser/resources/chromeos/login/components/security_token_pin.js +++ /dev/null
@@ -1,246 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for the security token PIN dialog shown during - * sign-in. - */ - -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; -import '//resources/ash/common/quick_unlock/pin_keyboard.js'; -import '//resources/ash/common/cr_elements/icons.html.js'; -import './oobe_icons.html.js'; -import './buttons/oobe_back_button.js'; -import './buttons/oobe_next_button.js'; -import './common_styles/oobe_common_styles.css.js'; -import './common_styles/oobe_dialog_host_styles.css.js'; -import './dialogs/oobe_adaptive_dialog.js'; - -import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {OobeDialogHostBehavior} from './behaviors/oobe_dialog_host_behavior.js'; -import {OobeI18nBehavior, OobeI18nBehaviorInterface} from './behaviors/oobe_i18n_behavior.js'; -import {OobeTypes} from './oobe_types.js'; - - -/** - * @constructor - * @extends {PolymerElement} - * @implements {OobeI18nBehaviorInterface} - */ -const SecurityTokenPinBase = - mixinBehaviors([OobeI18nBehavior, OobeDialogHostBehavior], PolymerElement); - -/** - * @polymer - */ -export class SecurityTokenPin extends SecurityTokenPinBase { - static get is() { - return 'security-token-pin'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - /** - * Contains the OobeTypes.SecurityTokenPinDialogParameters object. It can - * be null when our element isn't used. - * - * Changing this field resets the dialog state. (Please note that, due to - * the Polymer's limitation, only assigning a new object is observed; - * changing just a subproperty won't work.) - */ - parameters: { - type: Object, - observer: 'onParametersChanged_', - }, - - /** - * Whether the current state is the wait for the processing completion - * (i.e., the backend is verifying the entered PIN). - * @private - */ - processingCompletion_: { - type: Boolean, - value: false, - }, - - /** - * Whether the input is currently non-empty. - * @private - */ - hasValue_: { - type: Boolean, - value: false, - }, - - /** - * Whether the user has made changes in the input field since the dialog - * was initialized or reset. - * @private - */ - userEdited_: { - type: Boolean, - value: false, - }, - - /** - * Whether the user can change the value in the input field. - * @private - */ - canEdit_: { - type: Boolean, - computed: - 'computeCanEdit_(parameters.enableUserInput, processingCompletion_)', - }, - - /** - * Whether the user can submit a login request. - * @private - */ - canSubmit_: { - type: Boolean, - computed: 'computeCanSubmit_(parameters.enableUserInput, ' + - 'hasValue_, processingCompletion_)', - }, - }; - } - - focus() { - // Note: setting the focus synchronously, to avoid flakiness in tests due to - // racing between the asynchronous caret positioning and the PIN characters - // input. - this.$.pinKeyboard.focusInputSynchronously(); - } - - /** - * Computes the value of the canEdit_ property. - * @param {boolean} enableUserInput - * @param {boolean} processingCompletion - * @return {boolean} - * @private - */ - computeCanEdit_(enableUserInput, processingCompletion) { - return enableUserInput && !processingCompletion; - } - - /** - * Computes the value of the canSubmit_ property. - * @param {boolean} enableUserInput - * @param {boolean} hasValue - * @param {boolean} processingCompletion - * @return {boolean} - * @private - */ - computeCanSubmit_(enableUserInput, hasValue, processingCompletion) { - return enableUserInput && hasValue && !processingCompletion; - } - - /** - * Invoked when the "Back" button is clicked. - * @private - */ - onBackClicked_() { - this.dispatchEvent( - new CustomEvent('cancel', {bubbles: true, composed: true})); - } - - /** - * Invoked when the "Next" button is clicked or Enter is pressed. - * @private - */ - onSubmit_() { - if (!this.canSubmit_) { - // Disallow submitting when it's not allowed or while proceeding the - // previous submission. - return; - } - this.processingCompletion_ = true; - this.dispatchEvent(new CustomEvent( - 'completed', - {bubbles: true, composed: true, detail: this.$.pinKeyboard.value})); - } - - /** - * Observer that is called when the |parameters| property gets changed. - * @private - */ - onParametersChanged_() { - // Reset the dialog to the initial state. - this.$.pinKeyboard.value = ''; - this.processingCompletion_ = false; - this.hasValue_ = false; - this.userEdited_ = false; - - this.focus(); - } - - /** - * Observer that is called when the user changes the PIN input field. - * @param {!CustomEvent<{pin: string}>} e - * @private - */ - onPinChange_(e) { - this.hasValue_ = e.detail.pin.length > 0; - this.userEdited_ = true; - } - - /** - * Returns whether the error label should be shown. - * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters - * @param {boolean} userEdited - * @return {boolean} - * @private - */ - isErrorLabelVisible_(parameters, userEdited) { - return parameters && parameters.hasError && !userEdited; - } - - /** - * Returns whether the PIN attempts left count should be shown. - * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters - * @return {boolean} - * @private - */ - isAttemptsLeftVisible_(parameters) { - return parameters && parameters.formattedAttemptsLeft !== ''; - } - - /** - * Returns whether there is a visible label for the PIN input field - * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters - * @param {boolean} userEdited - * @return {boolean} - * @private - */ - isLabelVisible_(parameters, userEdited) { - return this.isErrorLabelVisible_(parameters, userEdited) || - this.isAttemptsLeftVisible_(parameters); - } - - /** - * Returns the label to be used for the PIN input field. - * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters - * @param {boolean} userEdited - * @return {string} - * @private - */ - getLabel_(parameters, userEdited) { - if (!this.isLabelVisible_(parameters, userEdited)) { - // Neither error nor the number of left attempts are to be displayed. - return ''; - } - if (!this.isErrorLabelVisible_(parameters, userEdited) && - this.isAttemptsLeftVisible_(parameters)) { - // There's no error, but the number of left attempts has to be displayed. - return parameters.formattedAttemptsLeft; - } - return parameters.formattedError; - } -} - -customElements.define(SecurityTokenPin.is, SecurityTokenPin);
diff --git a/chrome/browser/resources/chromeos/login/components/security_token_pin.ts b/chrome/browser/resources/chromeos/login/components/security_token_pin.ts new file mode 100644 index 0000000..2838a0b7 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/components/security_token_pin.ts
@@ -0,0 +1,248 @@ +// Copyright 2019 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Polymer element for the security token PIN dialog shown during + * sign-in. + */ + +import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import '//resources/ash/common/quick_unlock/pin_keyboard.js'; +import '//resources/ash/common/cr_elements/icons.html.js'; +import './oobe_icons.html.js'; +import './buttons/oobe_back_button.js'; +import './buttons/oobe_next_button.js'; +import './common_styles/oobe_common_styles.css.js'; +import './common_styles/oobe_dialog_host_styles.css.js'; +import './dialogs/oobe_adaptive_dialog.js'; + +import {PinKeyboardElement} from '//resources/ash/common/quick_unlock/pin_keyboard.js'; +import {PolymerElementProperties} from '//resources/polymer/v3_0/polymer/interfaces.js'; +import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {assert} from 'chrome://resources/js/assert.js'; + +import {OobeDialogHostBehavior, OobeDialogHostBehaviorInterface} from './behaviors/oobe_dialog_host_behavior.js'; +import {OobeI18nBehavior, OobeI18nBehaviorInterface} from './behaviors/oobe_i18n_behavior.js'; +import {OobeTypes} from './oobe_types.js'; +import {getTemplate} from './security_token_pin.html.js'; + +const SecurityTokenPinBase = mixinBehaviors( + [ + OobeI18nBehavior, + OobeDialogHostBehavior, + ], + PolymerElement) as { + new (): PolymerElement & OobeI18nBehaviorInterface & + OobeDialogHostBehaviorInterface, +}; + +/** + * @polymer + */ +export class SecurityTokenPin extends SecurityTokenPinBase { + static get is() { + return 'security-token-pin' as const; + } + + static get template(): HTMLTemplateElement { + return getTemplate(); + } + + static get properties(): PolymerElementProperties { + return { + /** + * Contains the OobeTypes.SecurityTokenPinDialogParameters object. It can + * be null when our element isn't used. + * + * Changing this field resets the dialog state. (Please note that, due to + * the Polymer's limitation, only assigning a new object is observed; + * changing just a subproperty won't work.) + */ + parameters: { + type: Object, + observer: 'onParametersChanged', + }, + + /** + * Whether the current state is the wait for the processing completion + * (i.e., the backend is verifying the entered PIN). + */ + processingCompletion: { + type: Boolean, + value: false, + }, + + /** + * Whether the input is currently non-empty. + */ + hasValue: { + type: Boolean, + value: false, + }, + + /** + * Whether the user has made changes in the input field since the dialog + * was initialized or reset. + */ + userEdited: { + type: Boolean, + value: false, + }, + + /** + * Whether the user can change the value in the input field. + */ + canEdit: { + type: Boolean, + computed: + 'computeCanEdit(parameters.enableUserInput, processingCompletion)', + }, + + /** + * Whether the user can submit a login request. + */ + canSubmit: { + type: Boolean, + computed: 'computeCanSubmit(parameters.enableUserInput, ' + + 'hasValue, processingCompletion)', + }, + }; + } + + parameters: object; + private processingCompletion: boolean; + private hasValue: boolean; + private userEdited: boolean; + private canEdit: boolean; + private canSubmit: boolean; + + override focus(): void { + // Note: setting the focus synchronously, to avoid flakiness in tests due to + // racing between the asynchronous caret positioning and the PIN characters + // input. + this.getPinKeyboard().focusInputSynchronously(); + } + + /** + * Computes the value of the canEdit property. + */ + private computeCanEdit( + enableUserInput: boolean, processingCompletion: boolean): boolean { + return enableUserInput && !processingCompletion; + } + + /** + * Computes the value of the canSubmit property. + */ + private computeCanSubmit( + enableUserInput: boolean, hasValue: boolean, + processingCompletion: boolean): boolean { + return enableUserInput && hasValue && !processingCompletion; + } + + /** + * Invoked when the "Back" button is clicked. + */ + private onBackClicked(): void { + this.dispatchEvent( + new CustomEvent('cancel', {bubbles: true, composed: true})); + } + + private getPinKeyboard(): PinKeyboardElement { + const pinKeyboard = + this.shadowRoot?.querySelector<PinKeyboardElement>('#pinKeyboard'); + assert(pinKeyboard instanceof PinKeyboardElement); + return pinKeyboard; + } + + /** + * Invoked when the "Next" button is clicked or Enter is pressed. + */ + private onSubmit(): void { + if (!this.canSubmit) { + // Disallow submitting when it's not allowed or while proceeding the + // previous submission. + return; + } + this.processingCompletion = true; + + this.dispatchEvent(new CustomEvent( + 'completed', + {bubbles: true, composed: true, detail: this.getPinKeyboard().value})); + } + + /** + * Observer that is called when the |parameters| property gets changed. + */ + private onParametersChanged(): void { + // Reset the dialog to the initial state. + this.getPinKeyboard().value = ''; + this.processingCompletion = false; + this.hasValue = false; + this.userEdited = false; + + this.focus(); + } + + /** + * Observer that is called when the user changes the PIN input field. + */ + private onPinChange(e: CustomEvent<{pin: string}>): void { + this.hasValue = e.detail.pin.length > 0; + this.userEdited = true; + } + + /** + * Returns whether the error label should be shown. + */ + private isErrorLabelVisible( + parameters: OobeTypes.SecurityTokenPinDialogParameters, + userEdited: boolean): boolean { + return parameters && parameters.hasError && !userEdited; + } + + /** + * Returns whether the PIN attempts left count should be shown. + */ + private isAttemptsLeftVisible( + parameters: OobeTypes.SecurityTokenPinDialogParameters): boolean { + return parameters && parameters.formattedAttemptsLeft !== ''; + } + + /** + * Returns whether there is a visible label for the PIN input field + */ + private isLabelVisible( + parameters: OobeTypes.SecurityTokenPinDialogParameters, + userEdited: boolean): boolean { + return this.isErrorLabelVisible(parameters, userEdited) || + this.isAttemptsLeftVisible(parameters); + } + + /** + * Returns the label to be used for the PIN input field. + */ + private getLabel( + parameters: OobeTypes.SecurityTokenPinDialogParameters, + userEdited: boolean): string { + if (!this.isLabelVisible(parameters, userEdited)) { + // Neither error nor the number of left attempts are to be displayed. + return ''; + } + if (!this.isErrorLabelVisible(parameters, userEdited) && + this.isAttemptsLeftVisible(parameters)) { + // There's no error, but the number of left attempts has to be displayed. + return parameters.formattedAttemptsLeft; + } + return parameters.formattedError; + } +} + +declare global { + interface HTMLElementTagNameMap { + [SecurityTokenPin.is]: SecurityTokenPin; + } +} + +customElements.define(SecurityTokenPin.is, SecurityTokenPin);
diff --git a/chrome/browser/resources/chromeos/login/display_manager.js b/chrome/browser/resources/chromeos/login/display_manager.js index 153ce4b..aa319082 100644 --- a/chrome/browser/resources/chromeos/login/display_manager.js +++ b/chrome/browser/resources/chromeos/login/display_manager.js
@@ -168,6 +168,8 @@ /** * Forces keyboard based OOBE navigation. + * TODO(b/322301624): Remove suppress once during TS migration. + * @suppress {missingProperties} keyboard_utils_oobe is now migrated to TS. * @param {boolean} value True if keyboard navigation flow is forced. */ set forceKeyboardFlow(value) {
diff --git a/chrome/browser/resources/chromeos/login/login.gni b/chrome/browser/resources/chromeos/login/login.gni index 46260828..56c0b74 100644 --- a/chrome/browser/resources/chromeos/login/login.gni +++ b/chrome/browser/resources/chromeos/login/login.gni
@@ -14,9 +14,6 @@ unconditional_existing_files = [ "components/display_manager_types.js", - "components/keyboard_utils.js", - "components/keyboard_utils_oobe.js", - "components/long_touch_detector.js", "components/oobe_select.js", "components/oobe_types.js", "components/web_view_loader.js", @@ -53,7 +50,6 @@ "components/oobe_vars/oobe_shared_vars.css.js", "components/api_keys_notice.js", "components/hd_iron_icon.js", - "components/notification_card.js", "components/oobe_a11y_option.js", "components/oobe_carousel.js", "components/oobe_cr_lottie.js", @@ -65,7 +61,6 @@ "components/oobe_screens_list.js", "components/oobe_slide.js", "components/progress_list_item.js", - "components/security_token_pin.js", ] oobe_screens_js_files = [ @@ -235,7 +230,9 @@ "components/gaia_button.ts", "components/gaia_dialog.ts", "components/network_select_login.ts", + "components/notification_card.ts", "components/oobe_apps_list.ts", + "components/security_token_pin.ts", "components/throbber_notice.ts", "components/quick_start_pin.ts", "components/quick_start_entry_point.ts", @@ -251,11 +248,14 @@ components_html_wrapped_files += [ string_replace(f, ".html", ".html.ts") ] } -# the following components don't have corresponding html files, we're adding +# The following components don't have corresponding html files, we're adding # them after the list of html files has been populated components_ts_files += [ - "components/qr_code_canvas.ts", + "components/keyboard_utils.ts", + "components/keyboard_utils_oobe.ts", + "components/long_touch_detector.ts", "components/web_view_helper.ts", + "components/qr_code_canvas.ts", ] unconditional_autogenerated_files +=
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn index 87101e5..c45f854b 100644 --- a/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn
@@ -50,7 +50,6 @@ js_library("welcome_dialog") { sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.js" ] deps = [ - "../../components:long_touch_detector", "../../components:oobe_cr_lottie", "../../components/behaviors:oobe_i18n_behavior", "../../components/dialogs:oobe_modal_dialog",
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.js b/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.js index b6f3cf5..54ce7f6 100644 --- a/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.js +++ b/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.js
@@ -121,9 +121,6 @@ this.currentLanguage = ''; this.timezoneButtonVisible = false; - /** - * @private {LongTouchDetector} - */ this.titleLongTouchDetector_ = null; /** * This is stored ID of currently focused element to restore id on returns
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts index 70a9a20..e8bbfa08 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.ts +++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -476,6 +476,7 @@ onSpeechRateChange(rate: number) { this.rate = rate; + this.resetSpeechPostSettingChange_(); } getSpeechSynthesisVoice(): SpeechSynthesisVoice|undefined { @@ -938,6 +939,25 @@ this.selectedVoice = event.detail.selectedVoice; chrome.readingMode.onVoiceChange( this.selectedVoice.name, this.selectedVoice.lang.split('-')[0]); + + this.resetSpeechPostSettingChange_(); + } + + private resetSpeechPostSettingChange_() { + // Don't call stopSpeech() if initAXPositionWithNode hasn't been called + if (!this.speechStarted) { + return; + } + + const playSpeechOnChange = !this.paused; + + // Cancel the queued up Utterance using the old speech settings + this.stopSpeech(); + + // If speech was playing when a setting was changed, continue playing speech + if (playSpeechOnChange) { + this.playSpeech(); + } } // TODO(b/1465029): Once the IsReadAnythingWebUIEnabled flag is removed
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html index ded51e9..d24d542 100644 --- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html +++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
@@ -2,6 +2,8 @@ /* TODO look at UI with inspector to see which lines are overridden by the shared config. */ :host { + --button-container-height: calc(2 * var(--action-container-padding) + + var(--cr-button-height)); --sync-benefits-list-color: var(--google-grey-50); --sync-benefit-icon-color: var(--google-blue-600); color: var(--cr-primary-text-color); @@ -128,8 +130,6 @@ } .main-container:not(.dialog) { - --button-container-height: calc(2 * var(--action-container-padding) + - var(--cr-button-height)); display: flex; height: calc(100vh - var(--button-container-height)); width: 100vw; @@ -209,6 +209,10 @@ animation: 500ms ease-in-out fade-in-animation; } + .action-container { + height: var(--button-container-height); /* Prevent the container from shrinking when buttons are hidden. */ + } + @media (prefers-color-scheme: dark) { :host { --sync-benefits-list-color: var(--google-grey-800); @@ -246,8 +250,13 @@ hidden="[[isModalDialog_]]"> <div id="contentContainer" class$="[[animationClasses_]]"> <div id="avatarContainer"> - <img id="avatar" alt="" src="[[accountImageSrc_]]"> - <div id="badge" class="work-badge" hidden="[[!showEnterpriseBadge_]]"> + <iron-icon src="chrome://resources/images/throbber_small.svg" + hidden="[[!isPending_(screenMode_)]]"> + </iron-icon> + <img id="avatar" alt="" src="[[accountImageSrc_]]" + hidden="[[isPending_(screenMode_)]]"> + <div id="badge" class="work-badge" + hidden="[[shouldHideEnterpriseBadge_(screenMode_, showEnterpriseBadge_)]]"> <iron-icon icon="cr:domain" alt=""></iron-icon> </div> </div> @@ -285,7 +294,10 @@ <paper-spinner-lite active="[[anyButtonClicked_]]"></paper-spinner-lite> <div class$="action-container tangible-sync-style [[getMaybeDialogClass_(isModalDialog_)]]"> - <cr-button id="confirmButton" on-click="onConfirm_" + <cr-button id="confirmButton" + class$="[[getConfirmButtonClass_(screenMode_)]]" + hidden="[[isPending_(screenMode_)]]" + on-click="onConfirm_" disabled="[[anyButtonClicked_]]" consent-confirmation autofocus="[[isModalDialog_]]"> $i18n{syncConfirmationConfirmLabel} @@ -296,8 +308,9 @@ $i18n{syncConfirmationSettingsLabel} </cr-button> </if> - <cr-button id="notNowButton" on-click="onUndo_" - disabled="[[anyButtonClicked_]]"> + <cr-button id="notNowButton" + hidden="[[isPending_(screenMode_)]]" + on-click="onUndo_" disabled="[[anyButtonClicked_]]"> $i18n{syncConfirmationUndoLabel} </cr-button> <if expr="not (is_macosx or is_linux or chromeos_ash or chromeos_lacros)">
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts index b62d8ff..be8b853 100644 --- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts +++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts
@@ -24,12 +24,29 @@ import type {SyncBenefit, SyncConfirmationBrowserProxy} from './sync_confirmation_browser_proxy.js'; import {SyncConfirmationBrowserProxyImpl} from './sync_confirmation_browser_proxy.js'; +// LINT.IfChange(screen_mode) +/** + * In PENDING mode, the screen should not show consent buttons and indicate that + * some loading is pending. In RESTRICTED mode, the button must not be weighted, + * and in UNRESTRICTED mode they can be. + * + * In UNSUPPORTED mode, the client take any behavior. + */ +enum ScreenMode { + UNSUPPORTED = 0, + PENDING = 1, + RESTRICTED = 2, + UNRESTRICTED = 3, +} +// LINT.ThenChange(//chrome/browser/ui/webui/signin/sync_confirmation_handler.h:screen_mode) interface AccountInfo { src: string; showEnterpriseBadge: boolean; + screenMode: ScreenMode; } + const SyncConfirmationAppElementBase = WebUiListenerMixin(I18nMixin(PolymerElement)); @@ -86,20 +103,11 @@ }, }, - /** - * Reflects CanShowHistorySyncOptInsWithoutMinorModeRestrictions - * capability value. - * - * True iff the value of the capability was determined to be true before - * this screen was requested. - * False otherwise, ie.: the value of the capability was false or it was - * impossible to read its value before deadline. - * - */ - unrestrictedMode_: { - type: Boolean, + /** Determines the screen mode. */ + screenMode_: { + type: ScreenMode, value() { - return loadTimeData.getBoolean('unrestrictedMode'); + return loadTimeData.getInteger('screenMode') as ScreenMode; }, }, }; @@ -113,7 +121,7 @@ private syncConfirmationBrowserProxy_: SyncConfirmationBrowserProxy = SyncConfirmationBrowserProxyImpl.getInstance(); private useClickableSyncInfoDesc_: boolean; - private unrestrictedMode_: boolean; + private screenMode_: ScreenMode; override connectedCallback() { @@ -123,10 +131,9 @@ 'account-info-changed', this.handleAccountInfoChanged_.bind(this)); this.syncConfirmationBrowserProxy_.requestAccountInfo(); - if (this.unrestrictedMode_) { - this.shadowRoot!.querySelector('#confirmButton')!.classList.add( - 'action-button'); - } + setTimeout(() => { + this.defaultToRestrictedModeIfStillPending(); + }, /*delay in ms=*/ 2000); } private onConfirm_(e: Event) { @@ -180,10 +187,36 @@ return consentDescription; } - // Called when the account image changes. + // Called when the account information changes: it might be either the image + // or determined mode of screen restriction (derived from the + // canShowHistorySyncOptInsWithoutMinorModeRestriction capability). private handleAccountInfoChanged_(accountInfo: AccountInfo) { this.accountImageSrc_ = accountInfo.src; this.showEnterpriseBadge_ = accountInfo.showEnterpriseBadge; + + // Only allow this change once, from PENDING mode to (UN)RESTRICTED. + if (this.screenMode_ === ScreenMode.PENDING) { + this.screenMode_ = accountInfo.screenMode as ScreenMode; + } + } + + private defaultToRestrictedModeIfStillPending() { + if (this.screenMode_ === ScreenMode.PENDING) { + this.screenMode_ = ScreenMode.RESTRICTED; + } + } + + private getConfirmButtonClass_(screenMode: ScreenMode) { + return screenMode === ScreenMode.UNRESTRICTED ? 'action-button' : ''; + } + + private isPending_(screenMode: ScreenMode) { + return screenMode === ScreenMode.PENDING; + } + + private shouldHideEnterpriseBadge_( + screenMode: ScreenMode, showEnterpriseBadge: boolean) { + return !showEnterpriseBadge || screenMode === ScreenMode.PENDING; } /**
diff --git a/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.cc b/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.cc index 87d49eb..75f7a6b 100644 --- a/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.cc +++ b/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.cc
@@ -43,4 +43,9 @@ return nullptr; } +bool ChromeClientSideDetectionServiceDelegate::ShouldSendModelToBrowserContext( + content::BrowserContext* context) { + return context == profile_; +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.h b/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.h index 648d078..de49f45f 100644 --- a/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.h +++ b/chrome/browser/safe_browsing/chrome_client_side_detection_service_delegate.h
@@ -10,6 +10,10 @@ class Profile; +namespace content { +class BrowserContext; +} + namespace safe_browsing { // Delegate class which implements chrome specific bits for configuring @@ -31,6 +35,8 @@ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; scoped_refptr<network::SharedURLLoaderFactory> GetSafeBrowsingURLLoaderFactory() override; + bool ShouldSendModelToBrowserContext( + content::BrowserContext* context) override; private: raw_ptr<Profile> profile_;
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_browsertest.cc b/chrome/browser/safe_browsing/client_side_detection_host_browsertest.cc index 3e140be..d877fd8 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host_browsertest.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host_browsertest.cc
@@ -21,6 +21,7 @@ #include "components/safe_browsing/content/browser/ui_manager.h" #include "components/safe_browsing/core/common/features.h" #include "components/safe_browsing/core/common/proto/client_model.pb.h" +#include "content/public/browser/browser_context.h" #include "content/public/test/browser_test.h" #include "content/public/test/mock_navigation_handle.h" #include "content/public/test/prerender_test_util.h" @@ -36,10 +37,28 @@ using ::testing::_; using ::testing::StrictMock; +class FakeDelegate : public ClientSideDetectionService::Delegate { + PrefService* GetPrefs() override { return nullptr; } + scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() + override { + return nullptr; + } + scoped_refptr<network::SharedURLLoaderFactory> + GetSafeBrowsingURLLoaderFactory() override { + return nullptr; + } + bool ShouldSendModelToBrowserContext( + content::BrowserContext* context) override { + return true; + } +}; + class FakeClientSideDetectionService : public ClientSideDetectionService { public: FakeClientSideDetectionService() - : ClientSideDetectionService(nullptr, nullptr, nullptr) {} + : ClientSideDetectionService(std::make_unique<FakeDelegate>(), + nullptr, + nullptr) {} void SendClientReportPhishingRequest( std::unique_ptr<ClientPhishingRequest> verdict,
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc index 085058a..324aeb8 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/safe_browsing/extension_telemetry/tabs_api_signal_processor.h" #include "chrome/browser/safe_browsing/extension_telemetry/tabs_execute_script_signal_processor.h" #include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h" @@ -727,6 +728,8 @@ // - no stale extension entry is left over in the extension store. extension_store_.clear(); + telemetry_report_pb->set_developer_mode_enabled( + profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode)); telemetry_report_pb->set_creation_timestamp_msec( base::Time::Now().InMillisecondsSinceUnixEpoch()); return telemetry_report_pb; @@ -754,6 +757,7 @@ ss << "Report creation time: " << base::UTF16ToUTF8(TimeFormatShortDateAndTimeWithTimeZone(creation_time)) << "\n"; + ss << "Developer mode enabled: " << report.developer_mode_enabled() << "\n"; const RepeatedPtrField<ExtensionTelemetryReportRequest_Report>& reports = report.reports();
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc index dadb52da..608726a 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_uploader.h" #include "chrome/browser/safe_browsing/extension_telemetry/tabs_execute_script_signal.h" +#include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/crx_file/id_util.h" #include "components/prefs/pref_service.h" @@ -395,6 +396,29 @@ EXPECT_TRUE(IsExtensionStoreEmpty()); } +TEST_F(ExtensionTelemetryServiceTest, + GeneratesTelemetryReportWithDeveloperMode) { + // Generate a telemetry report with developer mode disabled. + task_environment_.FastForwardBy( + telemetry_service_->current_reporting_interval()); + std::unique_ptr<TelemetryReport> telemetry_report_pb = GetTelemetryReport(); + ASSERT_NE(telemetry_report_pb, nullptr); + + // Verify developer mode is disabled. + EXPECT_FALSE(telemetry_report_pb->developer_mode_enabled()); + + // Set developer mode pref to true and generate another telemetry report. + profile_.GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, true); + task_environment_.FastForwardBy( + telemetry_service_->current_reporting_interval()); + + std::unique_ptr<TelemetryReport> telemetry_report_pb_2 = GetTelemetryReport(); + ASSERT_NE(telemetry_report_pb_2, nullptr); + + // Verify developer is enabled and collected. + EXPECT_TRUE(telemetry_report_pb_2->developer_mode_enabled()); +} + TEST_F(ExtensionTelemetryServiceTest, TestExtensionInfoProtoConstruction) { // Clear out registered extensions first. UnregisterExtensionWithExtensionService(kExtensionId[0]);
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.cc b/chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.cc new file mode 100644 index 0000000..72d1f1d --- /dev/null +++ b/chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.cc
@@ -0,0 +1,30 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.h" + +#include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service.h" +#include "google_apis/gaia/oauth_multilogin_result.h" + +BoundSessionOAuthMultiLoginDelegateImpl:: + BoundSessionOAuthMultiLoginDelegateImpl( + base::WeakPtr<BoundSessionCookieRefreshService> + bound_session_cookie_refresh_service) + : bound_session_cookie_refresh_service_( + bound_session_cookie_refresh_service) {} + +BoundSessionOAuthMultiLoginDelegateImpl:: + ~BoundSessionOAuthMultiLoginDelegateImpl() = default; + +void BoundSessionOAuthMultiLoginDelegateImpl::BeforeSetCookies( + const OAuthMultiloginResult& result) { + // TODO(msalama): Check `result` for `DbscMetaData`and call + // `bound_session_cookie_service_` accordingly. + // This could result in pausing cookie rotation for Google bound sessions. + // Requests waiting on cookies must remain blocked till cookies are set. +} + +void BoundSessionOAuthMultiLoginDelegateImpl::OnCookiesSet() { + // TODO(msalama): Start/Override Google DBSC session if needed. +}
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.h b/chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.h new file mode 100644 index 0000000..0792b514 --- /dev/null +++ b/chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.h
@@ -0,0 +1,31 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SIGNIN_BOUND_SESSION_CREDENTIALS_BOUND_SESSION_OAUTH_MULTILOGIN_DELEGATE_IMPL_H_ +#define CHROME_BROWSER_SIGNIN_BOUND_SESSION_CREDENTIALS_BOUND_SESSION_OAUTH_MULTILOGIN_DELEGATE_IMPL_H_ + +#include "base/memory/weak_ptr.h" +#include "components/signin/public/base/bound_session_oauth_multilogin_delegate.h" + +class BoundSessionCookieRefreshService; + +class BoundSessionOAuthMultiLoginDelegateImpl + : public signin::BoundSessionOAuthMultiLoginDelegate { + public: + explicit BoundSessionOAuthMultiLoginDelegateImpl( + base::WeakPtr<BoundSessionCookieRefreshService> + bound_session_cookie_refresh_service); + + ~BoundSessionOAuthMultiLoginDelegateImpl() override; + + // signin::BoundSessionOauthMultiLoginDelegate: + void BeforeSetCookies(const OAuthMultiloginResult& result) override; + void OnCookiesSet() override; + + private: + base::WeakPtr<BoundSessionCookieRefreshService> + bound_session_cookie_refresh_service_; +}; + +#endif // CHROME_BROWSER_SIGNIN_BOUND_SESSION_CREDENTIALS_BOUND_SESSION_OAUTH_MULTILOGIN_DELEGATE_IMPL_H_
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 8919b0a..ac33374 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -102,6 +102,7 @@ #if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) #include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service.h" #include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_factory.h" +#include "chrome/browser/signin/bound_session_credentials/bound_session_oauth_multilogin_delegate_impl.h" #include "chrome/browser/signin/bound_session_credentials/bound_session_request_throttled_handler_browser_impl.h" #include "chrome/browser/signin/bound_session_credentials/throttled_gaia_auth_fetcher.h" #endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) @@ -410,6 +411,19 @@ } } +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +std::unique_ptr<signin::BoundSessionOAuthMultiLoginDelegate> +ChromeSigninClient::CreateBoundSessionOAuthMultiloginDelegate() const { + if (BoundSessionCookieRefreshService* bound_session_cookie_refresh_service = + BoundSessionCookieRefreshServiceFactory::GetForProfile(profile_); + bound_session_cookie_refresh_service) { + return std::make_unique<BoundSessionOAuthMultiLoginDelegateImpl>( + bound_session_cookie_refresh_service->GetWeakPtr()); + } + return nullptr; +} +#endif + SigninClient::SignoutDecision ChromeSigninClient::GetSignoutDecision( bool has_sync_account, const std::optional<signin_metrics::ProfileSignout> signout_source) const {
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h index bb2df0d..3146044 100644 --- a/chrome/browser/signin/chrome_signin_client.h +++ b/chrome/browser/signin/chrome_signin_client.h
@@ -82,6 +82,11 @@ absl::variant<signin_metrics::AccessPoint, signin_metrics::ProfileSignout> event_source) override; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + std::unique_ptr<signin::BoundSessionOAuthMultiLoginDelegate> + CreateBoundSessionOAuthMultiloginDelegate() const override; +#endif + #if BUILDFLAG(IS_CHROMEOS_LACROS) std::optional<account_manager::Account> GetInitialPrimaryAccount() override; std::optional<bool> IsInitialPrimaryAccountChild() const override;
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc index 96b6888f..6f809a7 100644 --- a/chrome/browser/signin/signin_ui_util.cc +++ b/chrome/browser/signin/signin_ui_util.cc
@@ -524,10 +524,6 @@ base::TimeTicks::Now()); } -void RecordAvatarIconHighlighted(Profile* profile) { - base::RecordAction(base::UserMetricsAction("AvatarToolbarButtonHighlighted")); -} - void RecordProfileMenuViewShown(Profile* profile) { base::RecordAction(base::UserMetricsAction("ProfileMenu_Opened")); if (profile->IsRegularProfile()) {
diff --git a/chrome/browser/signin/signin_ui_util.h b/chrome/browser/signin/signin_ui_util.h index 3bafea2c..c5adafe 100644 --- a/chrome/browser/signin/signin_ui_util.h +++ b/chrome/browser/signin/signin_ui_util.h
@@ -127,10 +127,6 @@ // used for metrics and to decide whether/when the animation can be shown again. void RecordAnimatedIdentityTriggered(Profile* profile); -// Records that the avatar icon was highlighted for the given profile. This is -// used for metrics. -void RecordAvatarIconHighlighted(Profile* profile); - // Called when the ProfileMenuView is opened. Used for metrics. void RecordProfileMenuViewShown(Profile* profile);
diff --git a/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc b/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc index d55e7fc..e1406fcea 100644 --- a/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc +++ b/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" @@ -1113,10 +1112,10 @@ AddResizeListener(child, GetScreenSize()); { content::DOMMessageQueue queue(web_contents); - FullscreenNotificationObserver observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); EXPECT_TRUE(ExecJs(child, "activateFullscreen()")); WaitForMultipleFullscreenEvents(expected_events, queue); - observer.Wait(); + waiter.Wait(); } // Verify that the browser has entered fullscreen for the current tab. @@ -1145,10 +1144,11 @@ AddResizeListener(child, original_child_size); { content::DOMMessageQueue queue(web_contents); - FullscreenNotificationObserver observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); EXPECT_TRUE(ExecJs(child, "exitFullscreen()")); WaitForMultipleFullscreenEvents(expected_events, queue); - observer.Wait(); + waiter.Wait(); } EXPECT_FALSE(browser()->window()->IsFullscreen()); @@ -1208,10 +1208,10 @@ std::set<std::string> expected_events = {"main_frame", "child", "grandchild"}; { content::DOMMessageQueue queue(web_contents); - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); EXPECT_TRUE(ExecJs(grandchild, "activateFullscreen()")); WaitForMultipleFullscreenEvents(expected_events, queue); - fullscreen_observer.Wait(); + waiter.Wait(); } // Verify that the browser has entered fullscreen for the current tab. @@ -1235,7 +1235,8 @@ AddResizeListener(grandchild, original_grandchild_size); { content::DOMMessageQueue queue(web_contents); - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); switch (exit_method) { case FullscreenExitMethod::JS_CALL: EXPECT_TRUE(ExecJs(grandchild, "exitFullscreen()")); @@ -1248,7 +1249,7 @@ NOTREACHED(); } WaitForMultipleFullscreenEvents(expected_events, queue); - fullscreen_observer.Wait(); + waiter.Wait(); } EXPECT_FALSE(browser()->window()->IsFullscreen()); @@ -1365,10 +1366,10 @@ // browser finishes the fullscreen transition. { content::DOMMessageQueue queue(web_contents); - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); EXPECT_TRUE(ExecJs(c_middle, "activateFullscreen()")); WaitForMultipleFullscreenEvents(expected_events, queue); - fullscreen_observer.Wait(); + waiter.Wait(); } // Verify that the browser has entered fullscreen for the current tab. @@ -1402,11 +1403,12 @@ AddResizeListener(c_middle, c_middle_original_size); { content::DOMMessageQueue queue(web_contents); - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, false, false, false, false)); WaitForMultipleFullscreenEvents(expected_events, queue); - fullscreen_observer.Wait(); + waiter.Wait(); } EXPECT_FALSE(browser()->window()->IsFullscreen());
diff --git a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc index 63ffd787..7ad19ffa 100644 --- a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
@@ -1748,7 +1748,7 @@ .Wait()); // Mimic the user being offline (until the next restart), to make sure the - // entity is unsync-ed upon brower startup (next test). + // entity is unsync-ed upon browser startup (next test). fake_server::FakeServerHttpPostProvider::DisableNetwork(); SetTitle(kSingleProfileIndex, bookmark, new_title); @@ -2305,6 +2305,7 @@ EXPECT_THAT(model->bookmark_bar_node()->children(), ElementsAre(IsFolderWithTitle(kLocalOnlyTitle))); + ASSERT_THAT(model->account_bookmark_bar_node(), NotNull()); EXPECT_THAT(model->account_bookmark_bar_node()->children(), ElementsAre(IsFolderWithTitle(kAccountOnlyTitle))); @@ -2322,7 +2323,7 @@ IN_PROC_BROWSER_TEST_F(SingleClientBookmarksWithAccountStorageSyncTest, ShouldHandleMovesAcrossStorageBoundaries) { const std::string kInitiallyLocalTitle = "Initially Local"; - const std::string kInitiallyAccountTitle = "Initiall Account"; + const std::string kInitiallyAccountTitle = "Initially Account"; fake_server::EntityBuilderFactory entity_builder_factory; fake_server::BookmarkEntityBuilder bookmark_builder = @@ -2357,6 +2358,7 @@ ASSERT_THAT(model->bookmark_bar_node()->children(), ElementsAre(IsFolderWithTitle(kInitiallyLocalTitle))); + ASSERT_THAT(model->account_bookmark_bar_node(), NotNull()); ASSERT_THAT(model->account_bookmark_bar_node()->children(), ElementsAre(IsFolderWithTitle(kInitiallyAccountTitle))); @@ -2385,6 +2387,83 @@ EXPECT_THAT(model->bookmark_bar_node()->children(), ElementsAre(IsFolderWithTitle(kInitiallyAccountTitle))); } + +// Android doesn't currently support PRE_ tests, see crbug.com/1117345. +#if !BUILDFLAG(IS_ANDROID) +IN_PROC_BROWSER_TEST_F(SingleClientBookmarksWithAccountStorageSyncTest, + PRE_PersistAccountBookmarksAcrossRestarts) { + const std::string kInitiallyLocalTitle = "Initially Local"; + const std::string kInitiallyAccountTitle = "Initially Account"; + + fake_server::EntityBuilderFactory entity_builder_factory; + fake_server::BookmarkEntityBuilder bookmark_builder = + entity_builder_factory.NewBookmarkEntityBuilder(kInitiallyAccountTitle); + fake_server_->InjectEntity(bookmark_builder.BuildFolder()); + + ASSERT_TRUE(SetupClients()); + + BookmarkModel* model = GetBookmarkModel(kSingleProfileIndex); + + model->AddFolder(/*parent=*/model->bookmark_bar_node(), /*index=*/0, + base::UTF8ToUTF16(kInitiallyLocalTitle)); + + // Setup a primary account, but don't actually enable Sync-the-feature (so + // that Sync will start in transport mode). + ASSERT_TRUE(GetClient(kSingleProfileIndex)->SignInPrimaryAccount()); + // Note: Depending on the state of feature flags (specifically + // kReplaceSyncPromosWithSignInPromos), Bookmarks may or may not be considered + // selected by default. + GetSyncService(kSingleProfileIndex) + ->GetUserSettings() + ->SetSelectedType(syncer::UserSelectableType::kBookmarks, true); + ASSERT_TRUE(GetClient(kSingleProfileIndex)->AwaitSyncTransportActive()); + ASSERT_FALSE(GetSyncService(kSingleProfileIndex)->IsSyncFeatureEnabled()); + ASSERT_TRUE(GetSyncService(kSingleProfileIndex) + ->GetUserSettings() + ->GetSelectedTypes() + .Has(syncer::UserSelectableType::kBookmarks)); + ASSERT_TRUE(GetSyncService(kSingleProfileIndex) + ->GetActiveDataTypes() + .Has(syncer::BOOKMARKS)); + + ASSERT_THAT(model->bookmark_bar_node()->children(), + ElementsAre(IsFolderWithTitle(kInitiallyLocalTitle))); + ASSERT_THAT(model->account_bookmark_bar_node(), NotNull()); + ASSERT_THAT(model->account_bookmark_bar_node()->children(), + ElementsAre(IsFolderWithTitle(kInitiallyAccountTitle))); +} + +IN_PROC_BROWSER_TEST_F(SingleClientBookmarksWithAccountStorageSyncTest, + PersistAccountBookmarksAcrossRestarts) { + // Same values as in the PRE_ test. + const std::string kInitiallyLocalTitle = "Initially Local"; + const std::string kInitiallyAccountTitle = "Initially Account"; + + // Mimic the user being offline to verify that account bookmarks are loaded + // from disk instead of being redownloaded. + fake_server::FakeServerHttpPostProvider::DisableNetwork(); + + ASSERT_TRUE(SetupClients()); + ASSERT_TRUE(GetClient(kSingleProfileIndex)->AwaitEngineInitialization()); + ASSERT_FALSE(GetSyncService(kSingleProfileIndex)->IsSyncFeatureEnabled()); + ASSERT_TRUE(GetSyncService(kSingleProfileIndex) + ->GetUserSettings() + ->GetSelectedTypes() + .Has(syncer::UserSelectableType::kBookmarks)); + + BookmarkModel* model = GetBookmarkModel(kSingleProfileIndex); + + // Local bookmarks should continue to exist (sanity-checking fixture). + ASSERT_THAT(model->bookmark_bar_node()->children(), + ElementsAre(IsFolderWithTitle(kInitiallyLocalTitle))); + + // Account bookmarks should continue existing even while offline. + ASSERT_THAT(model->account_bookmark_bar_node(), NotNull()); + EXPECT_THAT(model->account_bookmark_bar_node()->children(), + ElementsAre(IsFolderWithTitle(kInitiallyAccountTitle))); +} +#endif // !BUILDFLAG(IS_ANDROID) + #endif // !BUILDFLAG(IS_CHROMEOS_ASH) } // namespace
diff --git a/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc b/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc index bc70bc0..67ad8c2 100644 --- a/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc
@@ -62,7 +62,7 @@ void WaitForNumberOfOffers(size_t expected_count, autofill::PersonalDataManager* pdm) { while (pdm->GetAutofillOffers().size() != expected_count || - pdm->HasPendingQueriesForTesting()) { + pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); } } @@ -187,7 +187,7 @@ // changes from sync in the DB propagate into pdm. As we don't expect anything // to change, we have no better specific condition to wait for. pdm->Refresh(); - while (pdm->HasPendingQueriesForTesting()) { + while (pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); }
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_credential_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_credential_test.cc index cc4bea6..fae431a 100644 --- a/chrome/browser/sync/test/integration/single_client_wallet_credential_test.cc +++ b/chrome/browser/sync/test/integration/single_client_wallet_credential_test.cc
@@ -106,14 +106,14 @@ void WaitForNumberOfCards(size_t expected_count, autofill::PersonalDataManager* pdm) { while (pdm->GetCreditCards().size() != expected_count || - pdm->HasPendingQueriesForTesting()) { + pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); } } void WaitForNoPaymentsCustomerData(autofill::PersonalDataManager* pdm) { while (pdm->GetPaymentsCustomerData() != nullptr || - pdm->HasPendingQueriesForTesting()) { + pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); } }
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc index 3c3cbe15..eb57ee3 100644 --- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -190,7 +190,7 @@ void WaitForNumberOfCards(size_t expected_count, autofill::PersonalDataManager* pdm) { while (pdm->GetCreditCards().size() != expected_count || - pdm->HasPendingQueriesForTesting()) { + pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); } } @@ -199,14 +199,14 @@ autofill::PersonalDataManager* pdm) { while (pdm->GetPaymentsCustomerData() == nullptr || pdm->GetPaymentsCustomerData()->customer_id != customer_id || - pdm->HasPendingQueriesForTesting()) { + pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); } } void WaitForNoPaymentsCustomerData(autofill::PersonalDataManager* pdm) { while (pdm->GetPaymentsCustomerData() != nullptr || - pdm->HasPendingQueriesForTesting()) { + pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); } } @@ -501,7 +501,7 @@ // changes from sync in the DB propagate into pdm. As we don't expect anything // to change, we have no better specific condition to wait for. pdm->Refresh(); - while (pdm->HasPendingQueriesForTesting()) { + while (pdm->HasPendingPaymentQueriesForTesting()) { WaitForOnPersonalDataChanged(pdm); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index c7d2944..8ef27f6 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1165,6 +1165,8 @@ "download/download_bubble_row_list_view_info.h", "download/download_bubble_row_view_info.cc", "download/download_bubble_row_view_info.h", + "download/download_bubble_security_view_info.cc", + "download/download_bubble_security_view_info.h", "download/download_display.cc", "download/download_display.h", "download/download_item_mode.cc", @@ -1365,6 +1367,8 @@ "performance_controls/performance_controls_hats_service_factory.h", "performance_controls/performance_controls_metrics.cc", "performance_controls/performance_controls_metrics.h", + "performance_controls/tab_resource_usage_collector.cc", + "performance_controls/tab_resource_usage_collector.h", "performance_controls/tab_resource_usage_tab_helper.cc", "performance_controls/tab_resource_usage_tab_helper.h", "permission_bubble/permission_prompt.h", @@ -4537,7 +4541,10 @@ "Carbon.framework", "Quartz.framework", ] - weak_frameworks = [ "ScreenTime.framework" ] + weak_frameworks = [ + "LocalAuthenticationEmbeddedUI.framework", # macOS 12+ + "ScreenTime.framework", # macOS 11+ + ] } if (is_win) { @@ -6368,6 +6375,8 @@ "views/chrome_views_delegate_mac.cc", "views/policy/enterprise_startup_dialog_mac_util.h", "views/policy/enterprise_startup_dialog_mac_util.mm", + "views/webauthn/mac_authentication_view.h", + "views/webauthn/mac_authentication_view.mm", ] deps += [ "//components/crash/core/common:crash_key" ] } else {
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinator.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinator.java index a0e15386..b6c5940c 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinator.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinator.java
@@ -23,11 +23,11 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.ExpandedSheetHelper; import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController; +import org.chromium.content_public.browser.NavigationEntry; import org.chromium.content_public.browser.NavigationHandle; import org.chromium.ui.base.ApplicationViewportInsetSupplier; import java.util.function.BooleanSupplier; -import java.util.function.Function; /** * Coordinator for PageInsights bottom sheet module. Provides API, and initializes @@ -35,6 +35,12 @@ */ public class PageInsightsCoordinator { + public static interface ConfigProvider { + PageInsightsConfig get( + @Nullable NavigationHandle navigationHandle, + @Nullable NavigationEntry navigationEntry); + } + private final Context mContext; private final ObservableSupplier<Tab> mTabProvider; @@ -68,8 +74,8 @@ * @param inMotionSupplier Supplier for whether the compositor is in motion. * @param appViewportInsetSupplier App-wide viewport inset supplier. * @param intentParams params specified in the custom tabs intent - * @param isPageInsightsHubEnabled Supplier of the feature flag. - * @param firstLoadTimeMs Timestamp for the first page load completion. + * @param isPageInsightsEnabledSupplier Supplier of the feature enablement status. + * @param pageInsightsConfigProvider provider of {@link PageInsightsConfig}. */ public PageInsightsCoordinator( Context context, @@ -87,7 +93,7 @@ ApplicationViewportInsetSupplier appViewportInsetSupplier, PageInsightsIntentParams intentParams, BooleanSupplier isPageInsightsEnabledSupplier, - Function<NavigationHandle, PageInsightsConfig> pageInsightsConfigProvider) { + ConfigProvider pageInsightsConfigProvider) { mContext = context; mTabProvider = tabProvider; mBottomSheetController = bottomSheetController;
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java index 6053e9f..3ab1404 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java
@@ -246,11 +246,13 @@ mAppInsetSupplier, PageInsightsIntentParams.getDefaultInstance(), mIsPageInsightsHubEnabled, - (navigationHandle) -> + (navigationHandle, navigationEntry) -> PageInsightsConfig.newBuilder() + .setIsInitialPage(true) .setShouldAutoTrigger(true) .setShouldXsurfaceLog(true) - .setShouldAttachGaiaToRequest(true) + .setServerShouldNotLogOrPersonalize(false) + .setNavigationTimestampMs(1234L) .build())); verify(mTab).addObserver(mTabObserverCaptor.capture()); mTabObserverCaptor
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoader.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoader.java index 94935685..ac22e34 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoader.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoader.java
@@ -62,7 +62,6 @@ void loadInsightsData( GURL url, boolean isUserInitiated, - @Nullable Long navigationTimestampMs, PageInsightsConfig config, Callback<PageInsightsMetadata> callback) { mCurrentCallback = callback; @@ -82,8 +81,8 @@ builder.setIsUserInitiated(isUserInitiated) .setIsInitialPage(config.getIsInitialPage()) .setShouldNotLogOrPersonalize(config.getServerShouldNotLogOrPersonalize()); - if (mSendTimestamp && navigationTimestampMs != null) { - builder.setNavigationTimestampMs(navigationTimestampMs); + if (mSendTimestamp && config.hasNavigationTimestampMs()) { + builder.setNavigationTimestampMs(config.getNavigationTimestampMs()); } requestContextMetadataBuilder.setPageInsightsHubMetadata(builder); }
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoaderTest.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoaderTest.java index df1cf7d..e5ac60a 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoaderTest.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsDataLoaderTest.java
@@ -96,7 +96,6 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> { assertEquals(data, mPageInsightsMetadata); @@ -115,7 +114,6 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> { fail("Callback should not have been called after cancelled."); @@ -137,7 +135,6 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> { assertNull(data); @@ -150,7 +147,6 @@ mPageInsightsDataLoader.loadInsightsData( null, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> { assertNull(data); @@ -169,7 +165,6 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.newBuilder().setServerShouldNotLogOrPersonalize(false).build(), (data) -> {}); @@ -196,7 +191,6 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.newBuilder().setServerShouldNotLogOrPersonalize(true).build(), (data) -> {}); @@ -229,10 +223,10 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ 1234L, PageInsightsConfig.newBuilder() .setIsInitialPage(true) .setServerShouldNotLogOrPersonalize(true) + .setNavigationTimestampMs(1234L) .build(), (data) -> {}); @@ -272,10 +266,10 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ 1234L, PageInsightsConfig.newBuilder() .setIsInitialPage(true) .setServerShouldNotLogOrPersonalize(true) + .setNavigationTimestampMs(1234L) .build(), (data) -> {}); @@ -303,14 +297,12 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> {}); mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> {}); @@ -330,14 +322,12 @@ mPageInsightsDataLoader.loadInsightsData( mUrl, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> {}); mPageInsightsDataLoader.loadInsightsData( mUrl2, /* isUserInitiated= */ true, - /* navigationTimestampMs= */ null, PageInsightsConfig.getDefaultInstance(), (data) -> {});
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java index f9ae7d5..3917cc55 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java
@@ -67,7 +67,6 @@ import java.util.HashMap; import java.util.function.BooleanSupplier; -import java.util.function.Function; /** * PageInsights mediator component listening to various external events to update UI, internal @@ -120,7 +119,7 @@ private View mSheetContainer; private final BooleanSupplier mIsPageInsightsEnabledSupplier; - private final Function<NavigationHandle, PageInsightsConfig> mPageInsightsConfigProvider; + private final PageInsightsCoordinator.ConfigProvider mPageInsightsConfigProvider; private final Handler mHandler; private final Runnable mAutoTriggerTimerRunnable = this::onAutoTriggerTimerFinished; private final Callback<Boolean> mInMotionCallback = inMotion -> maybeAutoTrigger(); @@ -243,7 +242,7 @@ ApplicationViewportInsetSupplier appViewportInsetSupplier, PageInsightsIntentParams intentParams, BooleanSupplier isPageInsightsEnabledSupplier, - Function<NavigationHandle, PageInsightsConfig> pageInsightsConfigProvider) { + PageInsightsCoordinator.ConfigProvider pageInsightsConfigProvider) { mContext = context; mTabObservable = tabObservable; mProfileSupplier = profileSupplier; @@ -470,14 +469,17 @@ mAutoTriggerStage = AutoTriggerStage.AWAITING_NAV_HANDLE; return; } - PageInsightsConfig config = mPageInsightsConfigProvider.apply(mCurrentNavigationHandle); - if (!shouldFetchDataForAutoTrigger(config)) { + Tab tab = mTabObservable.get(); + if (tab == null) { + Log.e(TAG, "Cancelling auto-trigger because Tab is unexpectedly null."); mAutoTriggerStage = AutoTriggerStage.CANCELLED_OR_NOT_STARTED; return; } - if (mTabObservable.get() == null) { - Log.e(TAG, "Cancelling auto-trigger because Tab is unexpectedly null."); + PageInsightsConfig config = + mPageInsightsConfigProvider.get( + mCurrentNavigationHandle, getLastCommittedNavigationEntry(tab)); + if (!shouldFetchDataForAutoTrigger(config)) { mAutoTriggerStage = AutoTriggerStage.CANCELLED_OR_NOT_STARTED; return; } @@ -485,9 +487,8 @@ mAutoTriggerStage = AutoTriggerStage.FETCHING_DATA; Log.v(TAG, "Fetching data for auto-trigger"); mPageInsightsDataLoader.loadInsightsData( - mTabObservable.get().getUrl(), + tab.getUrl(), /* isUserInitiated= */ false, - getNavigationTimestampMs(mTabObservable.get()), config, metadata -> { if (mAutoTriggerStage != AutoTriggerStage.FETCHING_DATA) { @@ -576,18 +577,20 @@ } void launch() { - if (mTabObservable.get() == null) { + Tab tab = mTabObservable.get(); + if (tab == null) { Log.e(TAG, "Can't launch Page Insights because Tab is null."); return; } cancelAutoTrigger(); mSheetContent.showLoadingIndicator(); mSheetController.requestShowContent(mSheetContent, true); - PageInsightsConfig config = mPageInsightsConfigProvider.apply(mCurrentNavigationHandle); + PageInsightsConfig config = + mPageInsightsConfigProvider.get( + mCurrentNavigationHandle, getLastCommittedNavigationEntry(tab)); mPageInsightsDataLoader.loadInsightsData( - mTabObservable.get().getUrl(), + tab.getUrl(), /* isUserInitiated= */ true, - getNavigationTimestampMs(mTabObservable.get()), config, metadata -> { mCurrentMetadata = metadata; @@ -848,7 +851,7 @@ } @Nullable - private static Long getNavigationTimestampMs(Tab tab) { + private static NavigationEntry getLastCommittedNavigationEntry(Tab tab) { WebContents webContents = tab.getWebContents(); if (webContents == null) { return null; @@ -857,13 +860,7 @@ if (navigationController == null) { return null; } - NavigationEntry lastCommittedEntry = - navigationController.getEntryAtIndex( - navigationController.getLastCommittedEntryIndex()); - if (lastCommittedEntry == null) { - return null; - } - // TODO(b/319407873): Update the below method's name to specify its unit. - return lastCommittedEntry.getTimestamp(); + return navigationController.getEntryAtIndex( + navigationController.getLastCommittedEntryIndex()); } }
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediatorTest.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediatorTest.java index 97f2fbf..fb4d44b 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediatorTest.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediatorTest.java
@@ -120,7 +120,6 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.function.Function; /** Unit tests for {@link PageInsightsMediator}. */ @LooperMode(Mode.PAUSED) @@ -157,7 +156,7 @@ @Mock private DomDistillerUrlUtils.Natives mDistillerUrlUtilsJniMock; @Mock private BackPressManager mBackPressManager; @Mock private BackPressHandler mBackPressHandler; - @Mock private Function<NavigationHandle, PageInsightsConfig> mPageInsightsConfigProvider; + @Mock private PageInsightsCoordinator.ConfigProvider mPageInsightsConfigProvider; @Mock private NavigationHandle mNavigationHandle; @Mock private ObservableSupplier<Boolean> mInMotionSupplier; @Mock private ApplicationViewportInsetSupplier mAppInsetSupplier; @@ -208,12 +207,11 @@ IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider); when(mIdentityServicesProvider.getIdentityManager(mProfile)).thenReturn(mIdentityManager); when(mBottomSheetController.getBottomSheetBackPressHandler()).thenReturn(mBackPressHandler); - when(mPageInsightsConfigProvider.apply(any())) + when(mPageInsightsConfigProvider.get(any(), any())) .thenReturn( PageInsightsConfig.newBuilder() .setShouldAutoTrigger(true) .setShouldXsurfaceLog(true) - .setShouldAttachGaiaToRequest(true) .build()); when(mInMotionSupplier.get()).thenReturn(false); ChromeAccessibilityUtil.get().setAccessibilityEnabledForTesting(false); @@ -344,7 +342,7 @@ @Test @MediumTest public void testAutoTrigger_shouldNotAutoTrigger_doesNotTrigger() { - when(mPageInsightsConfigProvider.apply(mNavigationHandle)) + when(mPageInsightsConfigProvider.get(mNavigationHandle, mLastCommittedNavigationEntry)) .thenReturn(PageInsightsConfig.newBuilder().setShouldAutoTrigger(false).build()); createMediator(SHORT_TRIGGER_DELAY_MS); View feedView = new View(ContextUtils.getApplicationContext()); @@ -478,14 +476,14 @@ @Test @MediumTest public void testAutoTrigger_sendsCorrectMetadata() { - when(mPageInsightsConfigProvider.apply(mNavigationHandle)) + when(mPageInsightsConfigProvider.get(mNavigationHandle, mLastCommittedNavigationEntry)) .thenReturn( PageInsightsConfig.newBuilder() .setShouldAutoTrigger(true) .setServerShouldNotLogOrPersonalize(true) .setIsInitialPage(true) + .setNavigationTimestampMs(1234L) .build()); - when(mLastCommittedNavigationEntry.getTimestamp()).thenReturn(1234L); TestValues testValues = new TestValues(); testValues.addFieldTrialParamOverride( ChromeFeatureList.CCT_PAGE_INSIGHTS_HUB, @@ -653,13 +651,13 @@ @Test @MediumTest public void testLaunch_sendsCorrectMetadata() throws Exception { - when(mPageInsightsConfigProvider.apply(mNavigationHandle)) + when(mPageInsightsConfigProvider.get(mNavigationHandle, mLastCommittedNavigationEntry)) .thenReturn( PageInsightsConfig.newBuilder() .setServerShouldNotLogOrPersonalize(true) .setIsInitialPage(true) + .setNavigationTimestampMs(1234L) .build()); - when(mLastCommittedNavigationEntry.getTimestamp()).thenReturn(1234L); TestValues testValues = new TestValues(); testValues.addFieldTrialParamOverride( ChromeFeatureList.CCT_PAGE_INSIGHTS_HUB, @@ -760,7 +758,7 @@ @MediumTest public void testLaunch_signedIn_shouldNotXSurfaceLog_doesNotCallOnSurfaceCreated() throws Exception { - when(mPageInsightsConfigProvider.apply(mNavigationHandle)) + when(mPageInsightsConfigProvider.get(mNavigationHandle, mLastCommittedNavigationEntry)) .thenReturn(PageInsightsConfig.newBuilder().setShouldXsurfaceLog(false).build()); createMediator(); mMediator.onDidFinishNavigationInPrimaryMainFrame(mTab, mNavigationHandle);
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/proto/config.proto b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/proto/config.proto index a216013..b5740bd0 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/proto/config.proto +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/proto/config.proto
@@ -15,9 +15,6 @@ optional bool should_auto_trigger = 1; // True if XSurface logging should be done. optional bool should_xsurface_log = 2; - // DEPRECATED. Was: true if Gaia should be attached to the Page Insights - // request. - optional bool should_attach_gaia_to_request = 3 [deprecated = true]; // True if logging of URL by server, and personalisation of response, is // forbidden. optional bool server_should_not_log_or_personalize = 4; @@ -26,4 +23,6 @@ optional bool is_initial_page = 5; // Timestamp for the navigation that reached the URL, in milliseconds. optional int64 navigation_timestamp_ms = 6; + + reserved 3; }
diff --git a/chrome/browser/ui/android/signin/BUILD.gn b/chrome/browser/ui/android/signin/BUILD.gn index 931b65d6..9257836 100644 --- a/chrome/browser/ui/android/signin/BUILD.gn +++ b/chrome/browser/ui/android/signin/BUILD.gn
@@ -12,6 +12,7 @@ "//chrome/browser/consent_auditor/android:java", "//chrome/browser/first_run/android:java", "//chrome/browser/flags:java", + "//chrome/browser/password_manager/android:java", "//chrome/browser/preferences:java", "//chrome/browser/privacy:java", "//chrome/browser/profiles/android:java", @@ -249,6 +250,7 @@ "//base:base_java", "//base:base_java_test_support", "//chrome/browser/flags:java", + "//chrome/browser/password_manager/android:java", "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", "//chrome/browser/signin/services/android:java",
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java index 868641c..877e087 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java
@@ -16,6 +16,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; @@ -127,7 +128,10 @@ if (managedDomain != null) { return context.getString(R.string.signout_managed_account_message, managedDomain); } - return context.getString(R.string.turn_off_sync_and_signout_message); + return context.getString( + PasswordManagerUtilBridge.usesSplitStoresAndUPMForLocal(UserPrefs.get(profile)) + ? R.string.turn_off_sync_and_signout_message_without_passwords + : R.string.turn_off_sync_and_signout_message); } private static int getCheckBoxVisibility(Profile profile, String managedDomain) {
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java index 5a67e83..71d19b3 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java
@@ -28,6 +28,8 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge; +import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridgeJni; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; @@ -71,6 +73,8 @@ @Mock private SigninMetricsUtils.Natives mSigninMetricsUtilsNativeMock; + @Mock private PasswordManagerUtilBridge.Natives mPasswordManagerUtilBridgeNativeMock; + @Mock private SigninManager mSigninManagerMock; @Mock private IdentityManager mIdentityManagerMock; @@ -88,6 +92,7 @@ @Before public void setUp() { mocker.mock(SigninMetricsUtilsJni.TEST_HOOKS, mSigninMetricsUtilsNativeMock); + mocker.mock(PasswordManagerUtilBridgeJni.TEST_HOOKS, mPasswordManagerUtilBridgeNativeMock); IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class)); when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock); when(IdentityServicesProvider.get().getIdentityManager(any()))
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogTest.java index e10778c2..a417d43 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogTest.java
@@ -37,6 +37,8 @@ import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge; +import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridgeJni; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; @@ -71,6 +73,8 @@ @Mock private SigninMetricsUtils.Natives mSigninMetricsUtilsNativeMock; + @Mock private PasswordManagerUtilBridge.Natives mPasswordManagerUtilBridgeNativeMock; + @Mock private SigninManager mSigninManagerMock; @Mock private IdentityManager mIdentityManagerMock; @@ -86,6 +90,7 @@ @Before public void setUp() { mocker.mock(SigninMetricsUtilsJni.TEST_HOOKS, mSigninMetricsUtilsNativeMock); + mocker.mock(PasswordManagerUtilBridgeJni.TEST_HOOKS, mPasswordManagerUtilBridgeNativeMock); mocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsNatives); IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class)); when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock); @@ -208,6 +213,34 @@ @Test @MediumTest + public void testFooterWhenAccountIsNotManaged_UPMDisabled() { + mockAllowDeletingBrowserHistoryPref(true); + when(mPasswordManagerUtilBridgeNativeMock.usesSplitStoresAndUPMForLocal(mPrefService)) + .thenReturn(false); + + showSignOutDialog(); + + onView(withText(R.string.turn_off_sync_and_signout_message)) + .inRoot(isDialog()) + .check(matches(isDisplayed())); + } + + @Test + @MediumTest + public void testFooterWhenAccountIsNotManaged_UPMEnabled() { + mockAllowDeletingBrowserHistoryPref(true); + when(mPasswordManagerUtilBridgeNativeMock.usesSplitStoresAndUPMForLocal(mPrefService)) + .thenReturn(true); + + showSignOutDialog(); + + onView(withText(R.string.turn_off_sync_and_signout_message_without_passwords)) + .inRoot(isDialog()) + .check(matches(isDisplayed())); + } + + @Test + @MediumTest public void testPositiveButtonWhenAccountIsNotManagedAndRemoveLocalDataNotChecked() { mockAllowDeletingBrowserHistoryPref(true); var histogramWatcher =
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index c6101ee56..28ada2a 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2076,6 +2076,9 @@ <message name="IDS_TURN_OFF_SYNC_AND_SIGNOUT_MESSAGE" desc="Message to display in 'Sign out and turn off sync?' dialog"> Your bookmarks, history, passwords, and other Chrome data will no longer be synced to your Google Account </message> + <message name="IDS_TURN_OFF_SYNC_AND_SIGNOUT_MESSAGE_WITHOUT_PASSWORDS" desc="Message to display in 'Sign out and turn off sync?' dialog, without explicitly mentioning passwords. Similar to IDS_TURN_OFF_SYNC_AND_SIGNOUT_MESSAGE"> + Your bookmarks, history, and other Chrome data will no longer be synced to your Google Account + </message> <message name="IDS_REMOVE_LOCAL_DATA" desc="Checkbox to delete all existing data in local device storage"> Also clear your Chrome data from this device </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TURN_OFF_SYNC_AND_SIGNOUT_MESSAGE_WITHOUT_PASSWORDS.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TURN_OFF_SYNC_AND_SIGNOUT_MESSAGE_WITHOUT_PASSWORDS.png.sha1 new file mode 100644 index 0000000..2de7ed36 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TURN_OFF_SYNC_AND_SIGNOUT_MESSAGE_WITHOUT_PASSWORDS.png.sha1
@@ -0,0 +1 @@ +ffd90f985cd427b89f41a8b253248af926c4c532 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb index 2ce449a0..bbdd9787 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb
@@ -911,7 +911,7 @@ <translation id="5860033963881614850">Aus</translation> <translation id="5860491529813859533">Aktivieren</translation> <translation id="5864419784173784555">Warten auf weiteren Download…</translation> -<translation id="5865733239029070421">Nutzungsstatistiken und Absturzberichte automatisch an Google senden</translation> +<translation id="5865733239029070421">Nutzungsstatistiken und Absturzberichte werden automatisch an Google gesendet</translation> <translation id="5869522115854928033">Gespeicherte Passwörter</translation> <translation id="587735546353481577">Wenn du einer Website folgen möchtest, rufe die Website auf, öffne das Chrome-Menü und tippe auf „Folgen“.</translation> <translation id="5879072387416556377">Bessere Vorschläge erhalten</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb index c9446be..058b852 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb
@@ -335,7 +335,7 @@ <translation id="2870560284913253234">साइट</translation> <translation id="2871733351037274014">पेज प्रीलोड करा</translation> <translation id="2876136027428473467"><ph name="CHILD_NAME" /> याला तुमच्याकडून या वेबसाइटची मंजुरी हवी आहे:</translation> -<translation id="2876194821763651818">पासवर्ड <ph name="USERNAME" /> वर सेव्ह केले आहेत.</translation> +<translation id="2876194821763651818"><ph name="USERNAME" /> वर सेव्ह केलेले पासवर्ड.</translation> <translation id="2876628302275096482"><ph name="BEGIN_LINK" />Chrome तुमचा डेटा खाजगी कसा ठेवते<ph name="END_LINK" /> याविषयी अधिक जाणून घ्या</translation> <translation id="2888126860611144412">Chrome बद्दल</translation> <translation id="2891154217021530873">पेज लोड करणे थांबवा</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb index 422f9e2..2f6468e 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb
@@ -49,7 +49,7 @@ <translation id="1239792311949352652">Deel deze pagina snel. Je kunt deze snelkoppeling bewerken via Instellingen.</translation> <translation id="1240190568154816272">Chrome-tips</translation> <translation id="1240288207750131269"><ph name="LANG" /> laden</translation> -<translation id="1240903469550363138"><ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> deelt je naam, e-mailadres, adres en profielfoto met deze site om door te gaan. Bekijk het <ph name="BEGIN_LINK1" />privacybeleid<ph name="END_LINK1" /> en de <ph name="BEGIN_LINK2" />servicevoorwaarden<ph name="END_LINK2" /> van deze site.</translation> +<translation id="1240903469550363138"><ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> deelt je naam, e-mailadres en profielfoto met deze site om door te gaan. Bekijk het <ph name="BEGIN_LINK1" />privacybeleid<ph name="END_LINK1" /> en de <ph name="BEGIN_LINK2" />servicevoorwaarden<ph name="END_LINK2" /> van deze site.</translation> <translation id="124116460088058876">Meer talen</translation> <translation id="1241792820757384812">Je wachtwoorden worden verwijderd uit Google Wachtwoordmanager voor <ph name="CHROME_CHANNEL" />. Je houdt het wachtwoordbestand dat je net hebt gedownload.</translation> <translation id="1242883863226959074">apparaat</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb index 17042c5d..acd851b4 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb
@@ -610,7 +610,7 @@ <translation id="4351244548802238354">Zamknij okno</translation> <translation id="4355272626458588338">Utwórz zakładkę, jeśli chcesz wrócić do interesującej Cię strony</translation> <translation id="4378154925671717803">Telefon</translation> -<translation id="4380055775103003110">Jeśli problem będzie się powtarzał, możesz wypróbować inne sposoby logowania w domenie <ph name="SITE_ETLD_PLUS_ONE" />.</translation> +<translation id="4380055775103003110">Jeśli problem będzie się powtarzał, możesz wypróbować inne sposoby logowania w witrynie <ph name="SITE_ETLD_PLUS_ONE" />.</translation> <translation id="4384468725000734951">Korzystam z wyszukiwarki Sogou</translation> <translation id="4387647248986092471">Utwórz blokadę profilu samochodu</translation> <translation id="4402611456429872546"><ph name="LANG" /> – pobieram…</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb index b515b8ad..4e4c95f 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb
@@ -1221,7 +1221,7 @@ <translation id="7411224099004328643">Usuário da Conta do Google</translation> <translation id="741204030948306876">Sim</translation> <translation id="7419565702166471774">Sempre usar conexões seguras</translation> -<translation id="7431991332293347422">Controla como o histórico de navegação é usado para personalizar a Pesquisa e muito mais</translation> +<translation id="7431991332293347422">Controlar como o histórico de navegação é usado para personalizar a Pesquisa e muito mais</translation> <translation id="7435356471928173109">Desativado pelo administrador</translation> <translation id="7437998757836447326">Sair do Google Chrome</translation> <translation id="7450926666485653189">Envia apenas uma parte ofuscada do URL ao Google por um servidor de privacidade que oculta seu endereço IP</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb index 1ba03cf..35c34c7 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb
@@ -669,7 +669,7 @@ <translation id="4668279686271488041">系统会定期从您的设备中删除广告衡量数据</translation> <translation id="4668347365065281350">网站存储的所有数据,包括 Cookie 及其他本地存储的数据</translation> <translation id="4678082183394354975">Chrome 中已为网站开启深色主题</translation> -<translation id="4684427112815847243">同步所有数据类型</translation> +<translation id="4684427112815847243">同步所有数据</translation> <translation id="4685741273709472646">从下拉列表中选择</translation> <translation id="4687718960473379118">网站建议的广告</translation> <translation id="4695891336199304370">{SHIPPING_OPTIONS,plural, =1{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026以及另外 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 种送货方式}other{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026以及另外 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 种送货方式}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb index ec07522..2cf2632 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb
@@ -335,7 +335,7 @@ <translation id="2870560284913253234">網站</translation> <translation id="2871733351037274014">預先載入網頁</translation> <translation id="2876136027428473467"><ph name="CHILD_NAME" />希望您核准此網站:</translation> -<translation id="2876194821763651818">密碼已儲存至「<ph name="USERNAME" />」。</translation> +<translation id="2876194821763651818"><ph name="USERNAME" /> 中所儲存的密碼。</translation> <translation id="2876628302275096482">進一步瞭解 <ph name="BEGIN_LINK" />Chrome 如何確保你的資料保密<ph name="END_LINK" /></translation> <translation id="2888126860611144412">關於 Chrome</translation> <translation id="2891154217021530873">停止載入網頁</translation> @@ -1458,7 +1458,7 @@ <translation id="8503813439785031346">用戶名稱</translation> <translation id="8505766168025405649">查看下載狀態的通知</translation> <translation id="8506357771923193001">這裡會顯示您的下載檔案</translation> -<translation id="8512053371384421952">你不會再收到「<ph name="DOMAIN" />」的通知。</translation> +<translation id="8512053371384421952">你不會再收到 <ph name="DOMAIN" /> 的通知。</translation> <translation id="8514477925623180633">匯出儲存在 Chrome 中的密碼</translation> <translation id="8516012719330875537">圖片編輯器</translation> <translation id="8523928698583292556">刪除已儲存的密碼</translation>
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc index 5a55110..1fe7185f 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -494,8 +494,7 @@ suggestion, AutofillPopupDelegate::SuggestionPosition{ .row = index, .sub_popup_level = GetPopupLevel()}); #if BUILDFLAG(IS_ANDROID) - if ((suggestion.popup_item_id == PopupItemId::kPasswordEntry || - suggestion.popup_item_id == PopupItemId::kUsernameEntry) && + if ((suggestion.popup_item_id == PopupItemId::kPasswordEntry) && base::FeatureList::IsEnabled( password_manager::features:: kUnifiedPasswordManagerLocalPasswordsMigrationWarning)) {
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc index 305e60fc..b6a7fa6 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc
@@ -1200,7 +1200,7 @@ base::test::ScopedFeatureList scoped_feature_list( password_manager::features:: kUnifiedPasswordManagerLocalPasswordsMigrationWarning); - ShowSuggestions(manager(), {PopupItemId::kUsernameEntry}); + ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); // Calls are accepted immediately. EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1);
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc b/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc index 6cd5ad8..e6ca23c 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc
@@ -41,6 +41,7 @@ #include "components/autofill/core/browser/payments/autofill_save_card_ui_info.h" #else #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h" +#include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h" #include "chrome/browser/ui/hats/hats_service_factory.h" #include "chrome/browser/ui/hats/mock_hats_service.h" #endif @@ -425,5 +426,56 @@ base::DoNothing())); } #endif + +#if !BUILDFLAG(IS_ANDROID) +class MockVirtualCardEnrollBubbleController + : public VirtualCardEnrollBubbleControllerImpl { + public: + explicit MockVirtualCardEnrollBubbleController( + content::WebContents* web_contents) + : VirtualCardEnrollBubbleControllerImpl(web_contents) {} + ~MockVirtualCardEnrollBubbleController() override = default; + + MOCK_METHOD(void, HideIconAndBubble, (), (override)); + MOCK_METHOD(bool, IsIconVisible, (), (const override)); +}; + +class ChromeAutofillClientTestWithVcnEnrollLoadingAndConfirmation + : public ChromeAutofillClientTest { + public: + ChromeAutofillClientTestWithVcnEnrollLoadingAndConfirmation() { + feature_list_.InitAndEnableFeature( + features::kAutofillEnableVcnEnrollLoadingAndConfirmation); + } + + void SetUp() override { + ChromeAutofillClientTest::SetUp(); + + SecurityStateTabHelper::CreateForWebContents(web_contents()); + + auto mock_virtual_card_bubble_controller = + std::make_unique<MockVirtualCardEnrollBubbleController>(web_contents()); + web_contents()->SetUserData( + mock_virtual_card_bubble_controller->UserDataKey(), + std::move(mock_virtual_card_bubble_controller)); + } + + MockVirtualCardEnrollBubbleController& virtual_card_bubble_controller() { + return static_cast<MockVirtualCardEnrollBubbleController&>( + *VirtualCardEnrollBubbleController::GetOrCreate(web_contents())); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(ChromeAutofillClientTestWithVcnEnrollLoadingAndConfirmation, + VirtualCardEnrollCompleted_HidesVirtualCardBubbleAndIcon) { + ON_CALL(virtual_card_bubble_controller(), IsIconVisible()) + .WillByDefault(Return(true)); + EXPECT_CALL(virtual_card_bubble_controller(), HideIconAndBubble); + client()->GetPaymentsAutofillClient()->VirtualCardEnrollCompleted(true); +} +#endif } // namespace } // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc index 7cfc0f2..4bce5083 100644 --- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc +++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
@@ -11,7 +11,9 @@ #if !BUILDFLAG(IS_ANDROID) #include "chrome/browser/ui/autofill/payments/manage_migration_ui_controller.h" +#include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h" #include "components/autofill/core/browser/payments/local_card_migration_manager.h" +#include "components/autofill/core/common/autofill_payments_features.h" #endif // !BUILDFLAG(IS_ANDROID) namespace autofill::payments { @@ -71,6 +73,19 @@ migratable_credit_cards, delete_local_card_callback); } + +void ChromePaymentsAutofillClient::VirtualCardEnrollCompleted( + bool is_vcn_enrolled) { + if (base::FeatureList::IsEnabled( + features::kAutofillEnableVcnEnrollLoadingAndConfirmation)) { + VirtualCardEnrollBubbleControllerImpl::CreateForWebContents(web_contents()); + VirtualCardEnrollBubbleControllerImpl* controller = + VirtualCardEnrollBubbleControllerImpl::FromWebContents(web_contents()); + if (controller && controller->IsIconVisible()) { + controller->HideIconAndBubble(); + } + } +} #endif // BUILDFLAG(IS_ANDROID) } // namespace autofill::payments
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h index 9eedd0e..3dbf3e51 100644 --- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h +++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h
@@ -46,6 +46,7 @@ const std::u16string& tip_message, const std::vector<MigratableCreditCard>& migratable_credit_cards, MigrationDeleteCardCallback delete_local_card_callback) override; + void VirtualCardEnrollCompleted(bool is_vcn_enrolled) override; #endif // !BUILDFLAG(IS_ANDROID) };
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc index d4ed6ea5..5c6006d3 100644 --- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
@@ -102,16 +102,37 @@ void VirtualCardEnrollBubbleControllerImpl::HideIconAndBubble() { HideBubble(); bubble_state_ = BubbleState::kHidden; + is_enrollment_in_progress_ = false; UpdatePageActionIcon(); } + +bool VirtualCardEnrollBubbleControllerImpl::IsEnrollmentInProgress() const { + return is_enrollment_in_progress_; +} #endif -void VirtualCardEnrollBubbleControllerImpl::OnAcceptButton() { +void VirtualCardEnrollBubbleControllerImpl::OnAcceptButton( + bool did_switch_to_loading_state) { std::move(accept_virtual_card_callback_).Run(); decline_virtual_card_callback_.Reset(); #if !BUILDFLAG(IS_ANDROID) - bubble_state_ = BubbleState::kHidden; + if (did_switch_to_loading_state) { + // When user clicks "Accept", the bubble closing is delayed since we wait + // for the enrollment to finish on the server. + is_enrollment_in_progress_ = true; + } else { + bubble_state_ = BubbleState::kHidden; + } + // Log metrics here instead of when the bubble is closed. When + // "did_switch_to_loading_state == true" we don't immediately close the + // bubble, so this ensures we don't have to wait for a future closure to log + // the user's acceptance. + LogVirtualCardEnrollmentBubbleResultMetric( + VirtualCardEnrollmentBubbleResult:: + VIRTUAL_CARD_ENROLLMENT_BUBBLE_ACCEPTED, + GetVirtualCardEnrollmentBubbleSource(), is_user_gesture_, + ui_model_.enrollment_fields.previously_declined); #endif } @@ -152,6 +173,14 @@ set_bubble_view(nullptr); UpdatePageActionIcon(); +#if !BUILDFLAG(IS_ANDROID) + // If `closed_reason == PaymentsBubbleClosedReason::kAccepted`, the metrics + // have been logged by `OnAcceptButton()`. + if (closed_reason == PaymentsBubbleClosedReason::kAccepted) { + return; + } +#endif + VirtualCardEnrollmentBubbleResult result; switch (closed_reason) { case PaymentsBubbleClosedReason::kAccepted:
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h index 6a7254b..b0cd4d2 100644 --- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h +++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h
@@ -52,9 +52,11 @@ #if !BUILDFLAG(IS_ANDROID) void HideIconAndBubble() override; + + bool IsEnrollmentInProgress() const override; #endif - void OnAcceptButton() override; + void OnAcceptButton(bool did_switch_to_loading_state = false) override; void OnDeclineButton() override; void OnLinkClicked(VirtualCardEnrollmentLinkType link_type, const GURL& url) override; @@ -91,6 +93,10 @@ // Returns whether the web content associated with this controller is active. virtual bool IsWebContentsActive(); + // Denotes if the virtual card enrollment process is in progress. Is true + // after user has accepted virtual card enrollment. + bool is_enrollment_in_progress_ = false; + // Represents the current state of icon and bubble. BubbleState bubble_state_ = BubbleState::kHidden; #endif
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h index 42162cd..055d2fa 100644 --- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h +++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h
@@ -34,6 +34,10 @@ void SetFields(const VirtualCardEnrollmentFields& fields) { controller_->ui_model_.enrollment_fields = fields; } +#else + void SetIsEnrollmentInProgress(bool is_enrollment_in_progress) { + controller_->is_enrollment_in_progress_ = is_enrollment_in_progress; + } #endif // IS_ANDROID private:
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc index 9a7d3636..9b217383 100644 --- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc
@@ -4,8 +4,12 @@ #include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h" +#include "base/check_op.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/payments/test_legal_message_line.h" @@ -13,6 +17,7 @@ #include "components/autofill/core/browser/payments/virtual_card_enrollment_manager.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/infobars/content/content_infobar_manager.h" +#include "content/public/browser/web_contents_user_data.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_unittest_util.h" @@ -20,20 +25,29 @@ namespace autofill { namespace { +VirtualCardEnrollmentFields CreateVirtualCardEnrollmentFields() { + VirtualCardEnrollmentFields virtual_card_enrollment_fields; + virtual_card_enrollment_fields.credit_card = test::GetFullServerCard(); + gfx::ImageSkia card_art_image = gfx::test::CreateImage(100, 50).AsImageSkia(); + virtual_card_enrollment_fields.card_art_image = &card_art_image; + virtual_card_enrollment_fields.google_legal_message = { + TestLegalMessageLine("google_test_legal_message")}; + virtual_card_enrollment_fields.issuer_legal_message = { + TestLegalMessageLine("issuer_test_legal_message")}; + virtual_card_enrollment_fields.virtual_card_enrollment_source = + VirtualCardEnrollmentSource::kUpstream; + + return virtual_card_enrollment_fields; +} + +#if BUILDFLAG(IS_ANDROID) class ControllerTestSupport { public: explicit ControllerTestSupport(content::WebContents* web_contents) : card_art_image_(gfx::test::CreateImage(100, 50).AsImageSkia()), controller_(static_cast<VirtualCardEnrollBubbleControllerImpl*>( VirtualCardEnrollBubbleControllerImpl::GetOrCreate(web_contents))) { - virtual_card_enrollment_fields_.credit_card = test::GetFullServerCard(); - virtual_card_enrollment_fields_.card_art_image = &card_art_image_; - virtual_card_enrollment_fields_.google_legal_message = { - TestLegalMessageLine("google_test_legal_message")}; - virtual_card_enrollment_fields_.issuer_legal_message = { - TestLegalMessageLine("issuer_test_legal_message")}; - virtual_card_enrollment_fields_.virtual_card_enrollment_source = - VirtualCardEnrollmentSource::kUpstream; + virtual_card_enrollment_fields_ = CreateVirtualCardEnrollmentFields(); } ~ControllerTestSupport() = default; @@ -112,6 +126,102 @@ EXPECT_FALSE(test_api(test_support.controller()).DidShowBottomSheet()); } +#endif +class TestVirtualCardEnrollBubbleControllerImpl + : public VirtualCardEnrollBubbleControllerImpl { + public: + static void CreateForTesting(content::WebContents* web_contents) { + web_contents->SetUserData( + UserDataKey(), + std::make_unique<TestVirtualCardEnrollBubbleControllerImpl>( + web_contents)); + } + + explicit TestVirtualCardEnrollBubbleControllerImpl( + content::WebContents* web_contents) + : VirtualCardEnrollBubbleControllerImpl(web_contents) {} + + private: + bool IsWebContentsActive() override { return true; } +}; + +class VirtualCardEnrollBubbleControllerImplBubbleViewTest + : public BrowserWithTestWindowTest { + public: + VirtualCardEnrollBubbleControllerImplBubbleViewTest() = default; + VirtualCardEnrollBubbleControllerImplBubbleViewTest( + VirtualCardEnrollBubbleControllerImplBubbleViewTest&) = delete; + VirtualCardEnrollBubbleControllerImplBubbleViewTest& operator=( + VirtualCardEnrollBubbleControllerImplBubbleViewTest&) = delete; + + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + AddTab(browser(), GURL("about:blank")); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + TestVirtualCardEnrollBubbleControllerImpl::CreateForTesting(web_contents); + virtual_card_enrollment_fields_ = CreateVirtualCardEnrollmentFields(); + } + + void ShowBubble() { + controller()->ShowBubble( + virtual_card_enrollment_fields(), + /*accept_virtual_card_callback=*/base::DoNothing(), + /*decline_virtual_card_callback=*/base::DoNothing()); + } + + AutofillBubbleBase* GetBubbleViews() { + return controller()->GetVirtualCardEnrollBubbleView(); + } + + const VirtualCardEnrollmentFields& virtual_card_enrollment_fields() const { + return virtual_card_enrollment_fields_; + } + + protected: + TestVirtualCardEnrollBubbleControllerImpl* controller() { + return static_cast<TestVirtualCardEnrollBubbleControllerImpl*>( + TestVirtualCardEnrollBubbleControllerImpl::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents())); + } + gfx::ImageSkia card_art_image_; + base::test::ScopedFeatureList features_{ + features::kAutofillEnableVcnEnrollLoadingAndConfirmation}; + VirtualCardEnrollmentFields virtual_card_enrollment_fields_; +}; + +// Ensures that bubble acceptance is recorded after bubble is shown and +// accepted. +TEST_F(VirtualCardEnrollBubbleControllerImplBubbleViewTest, ShowBubble) { + base::HistogramTester histogram_tester; + ShowBubble(); + EXPECT_NE(GetBubbleViews(), nullptr); + controller()->OnAcceptButton(); + controller()->HideIconAndBubble(); + histogram_tester.ExpectUniqueSample( + "Autofill.VirtualCardEnrollBubble.Result.Upstream.FirstShow", + VirtualCardEnrollmentBubbleResult:: + VIRTUAL_CARD_ENROLLMENT_BUBBLE_ACCEPTED, + 1); +} + +// Ensures that bubble acceptance is recorded when bubble gets closed from the +// loading state. +TEST_F(VirtualCardEnrollBubbleControllerImplBubbleViewTest, + ShowBubbleInLoadingState) { + base::HistogramTester histogram_tester; + test_api(controller()) + .SetIsEnrollmentInProgress(/*is_enrollment_in_progress=*/true); + ShowBubble(); + EXPECT_TRUE(GetBubbleViews() != nullptr); + controller()->OnAcceptButton(); + controller()->HideIconAndBubble(); + histogram_tester.ExpectUniqueSample( + "Autofill.VirtualCardEnrollBubble.Result.Upstream.FirstShow", + VirtualCardEnrollmentBubbleResult:: + VIRTUAL_CARD_ENROLLMENT_BUBBLE_ACCEPTED, + 1); +} } // namespace } // namespace autofill
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index ac5e43d5..1a08ae88 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -242,44 +242,6 @@ int closing_count_ = 0; }; -class FullscreenOperationComplete { - public: - explicit FullscreenOperationComplete(Browser* browser) - : browser_(browser), last_state_(IsFullscreened(browser)) {} - - FullscreenOperationComplete(const FullscreenOperationComplete&) = delete; - FullscreenOperationComplete& operator=(const FullscreenOperationComplete&) = - delete; - ~FullscreenOperationComplete() = default; - - void Wait() { - base::RunLoop outer_loop; - auto wait_for_state = base::BindRepeating( - [](base::RunLoop* outer_loop, Browser* browser, bool* last_state) { - if (IsFullscreened(browser) != *last_state) { - outer_loop->Quit(); - *last_state = !(*last_state); - } - }, - &outer_loop, browser_, &last_state_); - - base::RepeatingTimer timer; - timer.Start(FROM_HERE, base::Milliseconds(1), std::move(wait_for_state)); - outer_loop.Run(); - } - - private: - static bool IsFullscreened(Browser* browser) { - FullscreenController* controller = - browser->exclusive_access_manager()->fullscreen_controller(); - return controller->IsFullscreenForBrowser() || - controller->IsTabFullscreen(); - } - - raw_ptr<Browser> browser_; - bool last_state_; -}; - // Used by CloseWithAppMenuOpen. Posts a CloseWindowCallback and shows the app // menu. void RunCloseWithAppMenuCallback(Browser* browser) { @@ -2755,16 +2717,22 @@ web_modal::WebContentsModalDialogManagerDelegate* browser_as_dialog_delegate = static_cast<web_modal::WebContentsModalDialogManagerDelegate*>(browser()); - FullscreenOperationComplete full_screen_complete_observer(browser()); // Simulate the tab requesting fullscreen. - browser_as_wc_delegate->EnterFullscreenModeForTab(tab->GetPrimaryMainFrame(), - {}); - full_screen_complete_observer.Wait(); + { + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); + browser_as_wc_delegate->EnterFullscreenModeForTab( + tab->GetPrimaryMainFrame(), {}); + waiter.Wait(); + } EXPECT_TRUE(browser_as_wc_delegate->IsFullscreenForTabOrPending(tab)); // The tab gets a modal dialog. - browser_as_dialog_delegate->SetWebContentsBlocked(tab, true); - full_screen_complete_observer.Wait(); + { + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); + browser_as_dialog_delegate->SetWebContentsBlocked(tab, true); + waiter.Wait(); + } // The dialog should drop fullscreen. EXPECT_FALSE(browser_as_wc_delegate->IsFullscreenForTabOrPending(tab));
diff --git a/chrome/browser/ui/browser_focus_uitest.cc b/chrome/browser/ui/browser_focus_uitest.cc index ff0af41..5944b7a 100644 --- a/chrome/browser/ui/browser_focus_uitest.cc +++ b/chrome/browser/ui/browser_focus_uitest.cc
@@ -107,8 +107,7 @@ namespace base { template <> -struct ::base::ScopedObservationTraits<views::FocusManager, - FocusChangeObserver> { +struct ScopedObservationTraits<views::FocusManager, FocusChangeObserver> { static void AddObserver(views::FocusManager* source, FocusChangeObserver* observer) { source->AddFocusChangeListener(observer);
diff --git a/chrome/browser/ui/download/download_bubble_contents_view_info.cc b/chrome/browser/ui/download/download_bubble_contents_view_info.cc index 0262139..4259e74 100644 --- a/chrome/browser/ui/download/download_bubble_contents_view_info.cc +++ b/chrome/browser/ui/download/download_bubble_contents_view_info.cc
@@ -4,8 +4,36 @@ #include "chrome/browser/ui/download/download_bubble_contents_view_info.h" +#include "chrome/browser/ui/download/download_bubble_row_view_info.h" + DownloadBubbleContentsViewInfo::DownloadBubbleContentsViewInfo( std::vector<DownloadUIModel::DownloadUIModelPtr> models) - : row_list_view_info_(std::move(models)) {} + : row_list_view_info_(std::move(models)), security_view_info_() {} DownloadBubbleContentsViewInfo::~DownloadBubbleContentsViewInfo() = default; + +DownloadUIModel* DownloadBubbleContentsViewInfo::GetDownloadModel( + const ContentId& id) const { + if (const DownloadBubbleRowViewInfo* row_info = + row_list_view_info_.GetRowInfo(id); + row_info) { + return row_info->model(); + } + + return nullptr; +} + +void DownloadBubbleContentsViewInfo::InitializeSecurityView( + const ContentId& id) { + CHECK(id != ContentId()); + if (security_view_info_.content_id() == id) { + return; + } + DownloadUIModel* model = GetDownloadModel(id); + CHECK(model); + security_view_info_.InitializeForDownload(*model); +} + +void DownloadBubbleContentsViewInfo::ResetSecurityView() { + security_view_info_.Reset(); +}
diff --git a/chrome/browser/ui/download/download_bubble_contents_view_info.h b/chrome/browser/ui/download/download_bubble_contents_view_info.h index d4b8664f..2ad48c41 100644 --- a/chrome/browser/ui/download/download_bubble_contents_view_info.h +++ b/chrome/browser/ui/download/download_bubble_contents_view_info.h
@@ -7,6 +7,7 @@ #include "chrome/browser/ui/download/download_bubble_info.h" #include "chrome/browser/ui/download/download_bubble_row_list_view_info.h" +#include "chrome/browser/ui/download/download_bubble_security_view_info.h" // Info class for DownloadBubbleContentsView class DownloadBubbleContentsViewInfo @@ -20,8 +21,20 @@ return row_list_view_info_; } + const DownloadBubbleSecurityViewInfo& security_view_info() const { + return security_view_info_; + } + + // Get the `DownloadUIModel` for any `id` among those listed within + // the row list view. + DownloadUIModel* GetDownloadModel(const ContentId& id) const; + + void InitializeSecurityView(const ContentId& id); + void ResetSecurityView(); + private: DownloadBubbleRowListViewInfo row_list_view_info_; + DownloadBubbleSecurityViewInfo security_view_info_; }; #endif // CHROME_BROWSER_UI_DOWNLOAD_DOWNLOAD_BUBBLE_CONTENTS_VIEW_INFO_H_
diff --git a/chrome/browser/ui/download/download_bubble_security_view_info.cc b/chrome/browser/ui/download/download_bubble_security_view_info.cc new file mode 100644 index 0000000..01e492c --- /dev/null +++ b/chrome/browser/ui/download/download_bubble_security_view_info.cc
@@ -0,0 +1,577 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/download/download_bubble_security_view_info.h" + +#include "base/metrics/histogram_functions.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/download/bubble/download_bubble_prefs.h" +#include "chrome/browser/download/download_item_model.h" +#include "chrome/browser/download/download_ui_safe_browsing_util.h" +#include "chrome/browser/download/offline_item_utils.h" +#include "chrome/browser/enterprise/connectors/common.h" +#include "chrome/browser/safe_browsing/advanced_protection_status_manager.h" +#include "chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/ui/color/chrome_color_id.h" +#include "chrome/grit/branded_strings.h" +#include "chrome/grit/generated_resources.h" +#include "components/offline_items_collection/core/fail_state.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/vector_icons/vector_icons.h" +#include "ui/base/l10n/l10n_util.h" + +using download::DownloadItem; +using TailoredWarningType = DownloadUIModel::TailoredWarningType; +using offline_items_collection::FailState; + +DownloadBubbleSecurityViewInfoObserver:: + DownloadBubbleSecurityViewInfoObserver() = default; +DownloadBubbleSecurityViewInfoObserver:: + ~DownloadBubbleSecurityViewInfoObserver() = default; + +DownloadBubbleSecurityViewInfo::SubpageButton::SubpageButton( + DownloadCommands::Command command, + std::u16string label, + bool is_prominent, + absl::optional<ui::ColorId> text_color) + : command(command), + label(label), + is_prominent(is_prominent), + text_color(text_color) {} + +DownloadBubbleSecurityViewInfo::DownloadBubbleSecurityViewInfo() = default; +DownloadBubbleSecurityViewInfo::~DownloadBubbleSecurityViewInfo() = default; + +void DownloadBubbleSecurityViewInfo::InitializeForDownload( + DownloadUIModel& model) { + if (model.GetContentId() != content_id_) { + Reset(); + download_item_observation_.Observe(model.GetDownloadItem()); + } + + OnDownloadUpdated(model.GetDownloadItem()); +} + +void DownloadBubbleSecurityViewInfo::SetSubpageButtonsForTesting( + std::vector<SubpageButton> buttons) { + subpage_buttons_ = std::move(buttons); +} + +bool DownloadBubbleSecurityViewInfo::HasSubpage() const { + return !warning_summary_.empty(); +} + +void DownloadBubbleSecurityViewInfo::OnDownloadUpdated( + download::DownloadItem* download) { + ContentId content_id = OfflineItemUtils::GetContentIdForDownload(download); + bool is_different_download = content_id != content_id_; + bool danger_type_changed = danger_type_ != download->GetDangerType(); + if (is_different_download) { + content_id_ = content_id; + title_text_ = download->GetFileNameToReportUser().LossyDisplayName(); + NotifyObservers( + &DownloadBubbleSecurityViewInfoObserver::OnContentIdChanged); + } + + if (is_different_download || danger_type_changed) { + danger_type_ = download->GetDangerType(); + PopulateForDownload(download); + NotifyObservers(&DownloadBubbleSecurityViewInfoObserver::OnInfoChanged); + } +} + +void DownloadBubbleSecurityViewInfo::OnDownloadRemoved( + download::DownloadItem* download) { + CHECK(content_id_ == OfflineItemUtils::GetContentIdForDownload(download)); + Reset(); +} + +void DownloadBubbleSecurityViewInfo::Reset() { + content_id_.reset(); + title_text_ = std::u16string(); + download_item_observation_.Reset(); +} + +void DownloadBubbleSecurityViewInfo::ClearForUpdate() { + // `title_text_` cannot change when a download is updated, so we do + // not need to clear it. + warning_summary_.clear(); + warning_secondary_text_.clear(); + warning_secondary_icon_ = nullptr; + learn_more_link_ = std::nullopt; + subpage_buttons_.clear(); + has_progress_bar_ = false; + is_progress_bar_looping_ = false; +} + +void DownloadBubbleSecurityViewInfo::PopulateForDownload( + download::DownloadItem* download) { + ClearForUpdate(); + + DownloadItemModel model( + download, std::make_unique<DownloadUIModel::BubbleStatusTextBuilder>()); + icon_and_color_ = IconAndColorForDownload(model); + + switch (model.GetState()) { + case download::DownloadItem::IN_PROGRESS: + case download::DownloadItem::COMPLETE: + PopulateForInProgressOrComplete(model); + break; + case download::DownloadItem::INTERRUPTED: + if (model.GetLastFailState() != + offline_items_collection::FailState::USER_CANCELED) { + PopulateForInterrupted(model); + } + break; + case download::DownloadItem::CANCELLED: + break; + case download::DownloadItem::MAX_DOWNLOAD_STATE: + NOTREACHED(); + } +} + +void DownloadBubbleSecurityViewInfo::PopulateForDangerousUi( + const std::u16string& subpage_summary) { + warning_summary_ = subpage_summary; + PopulateLearnMoreLink( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_BLOCKED_LEARN_MORE_LINK), + DownloadCommands::Command::LEARN_MORE_DOWNLOAD_BLOCKED); + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DELETE_FROM_HISTORY), + DownloadCommands::Command::DISCARD); +} + +void DownloadBubbleSecurityViewInfo::PopulateForSuspiciousUi( + const std::u16string& subpage_summary, + const std::u16string& secondary_subpage_button_label) { + warning_summary_ = subpage_summary; + PopulateLearnMoreLink( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_BLOCKED_LEARN_MORE_LINK), + DownloadCommands::Command::LEARN_MORE_DOWNLOAD_BLOCKED); + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DELETE_FROM_HISTORY), + DownloadCommands::Command::DISCARD); + PopulateSecondarySubpageButton(secondary_subpage_button_label, + DownloadCommands::Command::KEEP); +} + +void DownloadBubbleSecurityViewInfo::PopulateForInterrupted( + const DownloadUIModel& model) { + // Only handle danger types that are terminated in the interrupted state in + // this function. The other danger types are handled in + // `PopulateForInProgressOrComplete`. + switch (model.GetDangerType()) { + case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED: + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_ENCRYPTED); + return; + case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE: + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_TOO_BIG); + return; + case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK: { + if (!enterprise_connectors::ShouldPromptReviewForDownload( + model.profile(), model.GetDangerType())) { + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_SENSITIVE_CONTENT_BLOCK); + } + return; + } + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE: + case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: + case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: + case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING: + case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING: + case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_LOCAL_PASSWORD_SCANNING: + case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING: + case download::DOWNLOAD_DANGER_TYPE_ASYNC_LOCAL_PASSWORD_SCANNING: + case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE: + case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_FAILED: + case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE: + case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS: + case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: + case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: + case download::DOWNLOAD_DANGER_TYPE_ALLOWLISTED_BY_POLICY: + case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: + case download::DOWNLOAD_DANGER_TYPE_MAX: + // Fall through to the failed UX + // TODO(drubery): Not all of these danger types can occur with a + // fail state. Investigate which can and cannot, and fall + // through less frequently. + break; + } + + switch (model.GetLastFailState()) { + case FailState::FILE_BLOCKED: + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_INTERRUPTED_SUBPAGE_SUMMARY_BLOCKED_ORGANIZATION); + return; + case FailState::FILE_NAME_TOO_LONG: + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_INTERRUPTED_SUBPAGE_SUMMARY_PATH_TOO_LONG); + return; + case FailState::FILE_NO_SPACE: + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_INTERRUPTED_SUBPAGE_SUMMARY_DISK_FULL); + return; + case FailState::SERVER_UNAUTHORIZED: + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_INTERRUPTED_SUBPAGE_SUMMARY_FILE_UNAVAILABLE); + return; + // No Retry in these cases. + case FailState::FILE_TOO_LARGE: + case FailState::FILE_VIRUS_INFECTED: + case FailState::FILE_SECURITY_CHECK_FAILED: + case FailState::FILE_ACCESS_DENIED: + case FailState::SERVER_FORBIDDEN: + case FailState::FILE_SAME_AS_SOURCE: + case FailState::SERVER_BAD_CONTENT: + // Try resume if possible or retry if not in these cases, and in the default + // case. + case FailState::NETWORK_INVALID_REQUEST: + case FailState::NETWORK_FAILED: + case FailState::NETWORK_TIMEOUT: + case FailState::NETWORK_DISCONNECTED: + case FailState::NETWORK_SERVER_DOWN: + case FailState::FILE_TRANSIENT_ERROR: + case FailState::USER_SHUTDOWN: + case FailState::CRASH: + case FailState::SERVER_CONTENT_LENGTH_MISMATCH: + case FailState::SERVER_NO_RANGE: + case FailState::SERVER_CROSS_ORIGIN_REDIRECT: + case FailState::FILE_FAILED: + case FailState::FILE_HASH_MISMATCH: + case FailState::SERVER_FAILED: + case FailState::SERVER_CERT_PROBLEM: + case FailState::SERVER_UNREACHABLE: + case FailState::FILE_TOO_SHORT: + return; + // Not possible because the USER_CANCELED fail state does not allow a call + // into this function + case FailState::USER_CANCELED: + // Deprecated + case FailState::NETWORK_INSTABILITY: + case FailState::CANNOT_DOWNLOAD: + NOTREACHED(); + return; + case FailState::NO_FAILURE: + return; + } +} + +void DownloadBubbleSecurityViewInfo::PopulateForInProgressOrComplete( + const DownloadUIModel& model) { + switch (model.GetInsecureDownloadStatus()) { + case download::DownloadItem::InsecureDownloadStatus::BLOCK: + case download::DownloadItem::InsecureDownloadStatus::WARN: + PopulateForSuspiciousUi( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_INSECURE), + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_CONTINUE_INSECURE_FILE)); + return; + case download::DownloadItem::InsecureDownloadStatus::UNKNOWN: + case download::DownloadItem::InsecureDownloadStatus::SAFE: + case download::DownloadItem::InsecureDownloadStatus::VALIDATED: + case download::DownloadItem::InsecureDownloadStatus::SILENT_BLOCK: + break; + } + + if (enterprise_connectors::ShouldPromptReviewForDownload( + model.profile(), model.GetDangerType())) { + switch (model.GetDangerType()) { + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: + case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: + case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING: + return; + default: + break; + } + } + + if (TailoredWarningType type = model.GetTailoredWarningType(); + type != TailoredWarningType::kNoTailoredWarning) { + return PopulateForTailoredWarning(model); + } + + switch (model.GetDangerType()) { + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: + if (model.IsExtensionDownload()) { + PopulateForSuspiciousUi( + l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_UNKNOWN_SOURCE, + l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)), + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_CONTINUE_SUSPICIOUS_FILE)); + return; + } + if (WasSafeBrowsingVerdictObtained(model.GetDownloadItem())) { + PopulateForSuspiciousUi( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_DANGEROUS_FILE_TYPE), + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_CONTINUE_SUSPICIOUS_FILE)); + return; + } + if (ShouldShowWarningForNoSafeBrowsing(model.profile())) { + PopulateForFileTypeWarningNoSafeBrowsing(model); + return; + } + PopulateForSuspiciousUi( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_DANGEROUS_FILE_TYPE), + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_CONTINUE_UNVERIFIED_FILE)); + return; + + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE: + case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: + PopulateForDangerousUi(l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_DANGEROUS)); + return; + + case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: + PopulateForDangerousUi(l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_DECEPTIVE)); + return; + + case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: { + bool request_ap_verdicts = false; +#if BUILDFLAG(FULL_SAFE_BROWSING) + request_ap_verdicts = + safe_browsing::AdvancedProtectionStatusManagerFactory::GetForProfile( + model.profile()) + ->IsUnderAdvancedProtection(); +#endif + if (request_ap_verdicts) { + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_ADVANCED_PROTECTION); + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DELETE), + DownloadCommands::Command::DISCARD); + PopulateSecondarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CONTINUE), + DownloadCommands::Command::KEEP, kColorDownloadItemTextWarning); + return; + } + PopulateForSuspiciousUi( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_UNCOMMON_FILE), + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_CONTINUE_SUSPICIOUS_FILE)); + return; + } + case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING: + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_SENSITIVE_CONTENT_WARNING); + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DELETE), + DownloadCommands::Command::DISCARD); + PopulateSecondarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CONTINUE), + DownloadCommands::Command::KEEP, kColorDownloadItemTextWarning); + return; + case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING: { + warning_summary_ = l10n_util::GetStringFUTF16( + model.IsEncryptedArchive() + ? IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_DEEP_SCANNING_PROMPT_ENCRYPTED_ARCHIVE + : IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_DEEP_SCANNING_PROMPT_UPDATED, + u"\n\n"); + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_SCAN_UPDATED), + DownloadCommands::Command::DEEP_SCAN); + PopulateSecondarySubpageButton( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_OPEN_UPDATED), + DownloadCommands::Command::BYPASS_DEEP_SCANNING); + return; + } + case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_LOCAL_PASSWORD_SCANNING: { + warning_summary_ = l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_DEEP_SCANNING_PROMPT_LOCAL_DECRYPTION, + u"\n\n"); + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_ACCEPT_LOCAL_DECRYPTION), + // These download commands are not propagated + // to the DownloadItem. Instead they are handled specially in + // DownloadBubbleSecurityView::ProcessButtonClick. That makes it + // okay that the we aren't really prompting for a deep scan. + // TODO(crbug/1482901): Remove this by creating a dedicated View + // for the local decryption prompt which directly handles the + // button presses. + DownloadCommands::Command::DEEP_SCAN); + PopulateSecondarySubpageButton( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_BYPASS_LOCAL_DECRYPTION), + DownloadCommands::Command::KEEP); + return; + } + case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING: + has_progress_bar_ = true; + is_progress_bar_looping_ = true; + warning_summary_ = l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_ASYNC_SCANNING); + warning_secondary_icon_ = &vector_icons::kDocumentScannerIcon; + warning_secondary_text_ = + download::DoesDownloadConnectorBlock(model.profile(), model.GetURL()) + ? l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_ASYNC_SCANNING_ENTERPRISE_SECONDARY) + : l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_ASYNC_SCANNING_SECONDARY); + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_ASYNC_SCANNING_DISCARD), + DownloadCommands::Command::DISCARD, + /*is_prominent=*/false); + if (!download::DoesDownloadConnectorBlock(model.profile(), + model.GetURL())) { + PopulateSecondarySubpageButton( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_ASYNC_SCANNING_CANCEL), + DownloadCommands::Command::CANCEL_DEEP_SCAN); + } + return; + case download::DOWNLOAD_DANGER_TYPE_ASYNC_LOCAL_PASSWORD_SCANNING: { + warning_summary_ = l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_LOCAL_DECRYPTION_IN_PROGRESS, + u"\n\n"); + has_progress_bar_ = true; + is_progress_bar_looping_ = true; + // These download commands are not propagated + // to the DownloadItem. Instead they are handled specially + // in DownloadBubbleSecurityView::ProcessButtonClick. That + // means the semantics don't have to line up with the actual + // behavior of the download command. + // TODO(crbug/1482901): Remove this by creating a dedicated + // View for the local decryption prompt which directly + // handles the button presses. + PopulatePrimarySubpageButton( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_LOCAL_DECRYPTION_CANCEL), + DownloadCommands::Command::CANCEL); + PopulateSecondarySubpageButton( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_BYPASS_LOCAL_DECRYPTION), + DownloadCommands::Command::BYPASS_DEEP_SCANNING); + return; + } + case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_FAILED: + case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED: + case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE: + case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK: + case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE: + case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE: + case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS: + case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: + case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: + case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: + case download::DOWNLOAD_DANGER_TYPE_ALLOWLISTED_BY_POLICY: + case download::DOWNLOAD_DANGER_TYPE_MAX: + return; + } +} + +void DownloadBubbleSecurityViewInfo::PopulateForTailoredWarning( + const DownloadUIModel& model) { + switch (model.GetTailoredWarningType()) { + case TailoredWarningType::kSuspiciousArchive: + PopulateForSuspiciousUi( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_ARCHIVE_MALWARE), + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_CONTINUE_SUSPICIOUS_FILE)); + return; + case TailoredWarningType::kCookieTheft: + PopulateForDangerousUi(l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_COOKIE_THEFT)); + return; + case TailoredWarningType::kCookieTheftWithAccountInfo: { + std::string email; + if (auto* identity_manager = + IdentityManagerFactory::GetForProfile(model.profile()); + identity_manager) { + email = identity_manager + ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin) + .email; + } + base::UmaHistogramBoolean( + "SBClientDownload.TailoredWarning.HasVaidEmailForAccountInfo", + !email.empty()); + if (!email.empty()) { + PopulateForDangerousUi(l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_COOKIE_THEFT_AND_ACCOUNT, + base::ASCIIToUTF16(email))); + return; + } + PopulateForDangerousUi(l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_COOKIE_THEFT)); + return; + } + case TailoredWarningType::kNoTailoredWarning: { + NOTREACHED(); + } + } +} + +void DownloadBubbleSecurityViewInfo::PopulateForFileTypeWarningNoSafeBrowsing( + const DownloadUIModel& model) { + PopulateForSuspiciousUi( + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_NO_SAFE_BROWSING), + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CONTINUE_UNVERIFIED_FILE)); + // Clear the "Learn why Chrome..." link. If the user is not capable of turning + // on SB, do not show the default link and label. + learn_more_link_ = std::nullopt; + if (CanUserTurnOnSafeBrowsing(model.profile())) { + PopulateLearnMoreLink( + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_SAFE_BROWSING_SETTING_LABEL, + IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_SAFE_BROWSING_SETTING_LINK, + DownloadCommands::Command::OPEN_SAFE_BROWSING_SETTING); + } +} + +void DownloadBubbleSecurityViewInfo::PopulateLearnMoreLink( + const std::u16string& link_text, + DownloadCommands::Command command) { + learn_more_link_ = LabelWithLink{ + link_text, LabelWithLink::LinkedRange{0u, link_text.length(), command}}; +} + +void DownloadBubbleSecurityViewInfo::PopulateLearnMoreLink( + int label_text_id, + int link_text_id, + DownloadCommands::Command command) { + size_t link_start_offset = 0; + std::u16string link_text = l10n_util::GetStringUTF16(link_text_id); + std::u16string label_and_link_text = + l10n_util::GetStringFUTF16(label_text_id, link_text, &link_start_offset); + learn_more_link_ = LabelWithLink{ + label_and_link_text, LabelWithLink::LinkedRange{ + link_start_offset, link_text.length(), command}}; +} + +void DownloadBubbleSecurityViewInfo::PopulatePrimarySubpageButton( + const std::u16string& label, + DownloadCommands::Command command, + bool is_prominent) { + CHECK(subpage_buttons_.empty()); + subpage_buttons_.emplace_back(command, label, is_prominent); +} + +void DownloadBubbleSecurityViewInfo::PopulateSecondarySubpageButton( + const std::u16string& label, + DownloadCommands::Command command, + std::optional<ui::ColorId> color) { + CHECK(subpage_buttons_.size() == 1); + subpage_buttons_.emplace_back(command, label, /*is_prominent=*/false, color); +}
diff --git a/chrome/browser/ui/download/download_bubble_security_view_info.h b/chrome/browser/ui/download/download_bubble_security_view_info.h new file mode 100644 index 0000000..f97d3e6 --- /dev/null +++ b/chrome/browser/ui/download/download_bubble_security_view_info.h
@@ -0,0 +1,188 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_DOWNLOAD_DOWNLOAD_BUBBLE_SECURITY_VIEW_INFO_H_ +#define CHROME_BROWSER_UI_DOWNLOAD_DOWNLOAD_BUBBLE_SECURITY_VIEW_INFO_H_ + +#include "base/scoped_observation.h" +#include "chrome/browser/download/download_ui_model.h" +#include "chrome/browser/ui/download/download_bubble_info.h" +#include "chrome/browser/ui/download/download_bubble_info_utils.h" +#include "components/offline_items_collection/core/fail_state.h" + +class DownloadBubbleSecurityViewInfoObserver : public base::CheckedObserver { + public: + DownloadBubbleSecurityViewInfoObserver(); + ~DownloadBubbleSecurityViewInfoObserver() override; + + virtual void OnInfoChanged() {} + virtual void OnContentIdChanged() {} +}; + +class DownloadBubbleSecurityViewInfo + : public DownloadBubbleInfo<DownloadBubbleSecurityViewInfoObserver>, + public download::DownloadItem::Observer { + public: + struct LabelWithLink { + struct LinkedRange { + // The offset where the link text (i.e. "Chrome blocks some downloads") + // starts, with respect to the label string containing it. + size_t start_offset = 0; + // Link text length. + size_t length = 0; + // Action to perform when the link is clicked. + DownloadCommands::Command command; + }; + + // The entire label string with link, i.e. "Learn why Chrome blocks some + // downloads". + std::u16string label_and_link_text; + // The link info. Note this assumes that the text contains exactly one + // link. + LinkedRange linked_range; + }; + + struct SubpageButton { + DownloadCommands::Command command; + std::u16string label; + bool is_prominent = false; + + // Controls the text color of the button. Only applied for some secondary + // buttons. + absl::optional<ui::ColorId> text_color; + + SubpageButton(DownloadCommands::Command command, + std::u16string label, + bool is_prominent, + absl::optional<ui::ColorId> text_color = absl::nullopt); + }; + + DownloadBubbleSecurityViewInfo(); + ~DownloadBubbleSecurityViewInfo() override; + + // Update the security view when a subpage is opened for a particular + // download. Initializes this view, and associates it with `model`'s download. + // If it is already associated with the same download, this will update the + // view if the danger type has changed since the last time it was initialized. + // It is not an error to initialize this with a download when it is already + // initialized, either with the same download or a different download. + void InitializeForDownload(DownloadUIModel& model); + + void SetSubpageButtonsForTesting(std::vector<SubpageButton> buttons); + + // Accessors + const std::optional<offline_items_collection::ContentId>& content_id() const { + return content_id_; + } + download::DownloadDangerType danger_type() const { return danger_type_; } + const std::u16string& title_text() const { return title_text_; } + const gfx::VectorIcon* icon_model_override() const { + return icon_and_color_.icon; + } + ui::ColorId secondary_color() const { return icon_and_color_.color; } + const std::u16string& warning_summary() const { return warning_summary_; } + const std::u16string& warning_secondary_text() const { + return warning_secondary_text_; + } + const gfx::VectorIcon* warning_secondary_icon() const { + return warning_secondary_icon_; + } + const absl::optional<LabelWithLink>& learn_more_link() const { + return learn_more_link_; + } + bool has_primary_button() const { return subpage_buttons_.size() > 0; } + bool has_secondary_button() const { return subpage_buttons_.size() > 1; } + const SubpageButton& primary_button() const { return subpage_buttons_[0]; } + const SubpageButton& secondary_button() const { return subpage_buttons_[1]; } + bool has_progress_bar() const { return has_progress_bar_; } + bool is_progress_bar_looping() const { return is_progress_bar_looping_; } + bool HasSubpage() const; + + // Returns this to an uninitialized state, where this is not associated with + // a particular download. Called when navigating away from the security view. + void Reset(); + + private: + friend class DownloadBubbleSecurityViewInfoTest; + + // download::DownloadItem::Observer + void OnDownloadUpdated(download::DownloadItem* download) override; + void OnDownloadRemoved(download::DownloadItem* download) override; + + // Returns this to the default state, while maintaining the + // association with the download given by `content_id_`. This allows + // the PopulateFor* methods to only set fields that differ from + // default + void ClearForUpdate(); + + // Populate all the fields of this class based the current state of + // the download associated with `content_id_`. + void PopulateForDownload(download::DownloadItem* download); + void PopulateForDangerousUi(const std::u16string& subpage_summary); + void PopulateForSuspiciousUi( + const std::u16string& subpage_summary, + const std::u16string& secondary_subpage_button_label); + void PopulateForFileTypeWarningNoSafeBrowsing(const DownloadUIModel& model); + void PopulateForInterrupted(const DownloadUIModel& model); + void PopulateForInProgressOrComplete(const DownloadUIModel& model); + void PopulateForTailoredWarning(const DownloadUIModel& model); + + void PopulateLearnMoreLink(const std::u16string& link_text, + DownloadCommands::Command command); + void PopulateLearnMoreLink(int label_text_id, + int link_text_id, + DownloadCommands::Command command); + // The subpage of the bubble supports at most 2 buttons. The primary one must + // be populated first, then the secondary. + void PopulatePrimarySubpageButton(const std::u16string& label, + DownloadCommands::Command command, + bool is_prominent = true); + void PopulateSecondarySubpageButton( + const std::u16string& label, + DownloadCommands::Command command, + std::optional<ui::ColorId> color = std::nullopt); + + // ContentId of the download this refers to, if initialized. + std::optional<offline_items_collection::ContentId> content_id_; + + // The text for the title (i.e. filename) that this view was last + // created/updated with. + std::u16string title_text_; + + // Cached danger type for the current download + download::DownloadDangerType danger_type_ = + download::DOWNLOAD_DANGER_TYPE_MAX; + + // This is non-null if the view should display an icon other than the system + // icon for the filetype. + IconAndColor icon_and_color_{}; + + // Subpage summary of the download warning + std::u16string warning_summary_; + + // Secondary label for the subpage summary + std::u16string warning_secondary_text_; + + // Icon for the secondary text in the subpage + raw_ptr<const gfx::VectorIcon> warning_secondary_icon_ = nullptr; + + // Text with link to go at the bottom of the subpage summary, such as "Learn + // why Chrome blocks some downloads". + absl::optional<LabelWithLink> learn_more_link_; + + // Subpage buttons + std::vector<SubpageButton> subpage_buttons_; + + // Has a progress bar + bool has_progress_bar_ = false; + bool is_progress_bar_looping_ = false; + + // Observation of the download item this refers to. Only observes while this + // is associated with a download item. + base::ScopedObservation<download::DownloadItem, + download::DownloadItem::Observer> + download_item_observation_{this}; +}; + +#endif // CHROME_BROWSER_UI_DOWNLOAD_DOWNLOAD_BUBBLE_SECURITY_VIEW_INFO_H_
diff --git a/chrome/browser/ui/download/download_bubble_security_view_info_unittest.cc b/chrome/browser/ui/download/download_bubble_security_view_info_unittest.cc new file mode 100644 index 0000000..875a9f30 --- /dev/null +++ b/chrome/browser/ui/download/download_bubble_security_view_info_unittest.cc
@@ -0,0 +1,459 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/download/download_bubble_security_view_info.h" + +#include "base/strings/pattern.h" +#include "chrome/browser/download/bubble/download_bubble_prefs.h" +#include "chrome/browser/download/download_item_model.h" +#include "chrome/browser/download/download_ui_model.h" +#include "chrome/browser/safe_browsing/download_protection/download_protection_service.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/ui/color/chrome_color_id.h" +#include "chrome/test/base/testing_profile.h" +#include "components/download/public/common/mock_download_item.h" +#include "components/safe_browsing/core/common/features.h" +#include "components/safe_browsing/core/common/safe_browsing_prefs.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/identity_test_utils.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "components/vector_icons/vector_icons.h" +#include "content/public/browser/download_item_utils.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/vector_icons.h" + +using DownloadUIModelPtr = DownloadUIModel::DownloadUIModelPtr; +using TailoredVerdict = safe_browsing::ClientDownloadResponse::TailoredVerdict; +using download::DownloadItem; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::ReturnRefOfCopy; + +class DownloadBubbleSecurityViewInfoTest + : public ::testing::Test, + public DownloadBubbleSecurityViewInfoObserver { + public: + DownloadBubbleSecurityViewInfoTest() = default; + + void SetUp() override { + if (!download::IsDownloadBubbleEnabled()) { + GTEST_SKIP(); + } + item_ = std::make_unique<NiceMock<download::MockDownloadItem>>(); + ON_CALL(*item_, GetGuid()) + .WillByDefault(ReturnRefOfCopy(std::string("id"))); + ON_CALL(*item_, GetURL()) + .WillByDefault(ReturnRefOfCopy(GURL("http://example.com/foo.bar"))); + content::DownloadItemUtils::AttachInfoForTesting(item_.get(), &profile_, + nullptr); + info_ = std::make_unique<DownloadBubbleSecurityViewInfo>(); + } + + NiceMock<download::MockDownloadItem>& item() { return *item_; } + DownloadBubbleSecurityViewInfo& info() { return *info_; } + Profile* profile() { return &profile_; } + TestingProfile& testing_profile() { return profile_; } + + void RefreshInfo() { info_->PopulateForDownload(item_.get()); } + + private: + content::BrowserTaskEnvironment task_environment_; + TestingProfile profile_; + std::unique_ptr<NiceMock<download::MockDownloadItem>> item_; + DownloadUIModelPtr model_; + std::unique_ptr<DownloadBubbleSecurityViewInfo> info_; +}; + +TEST_F(DownloadBubbleSecurityViewInfoTest, DangerousWarningInfo) { + const struct DangerTypeTestCase { + download::DownloadDangerType danger_type; + std::optional<DownloadCommands::Command> primary_button_command; + std::vector<DownloadCommands::Command> subpage_button_commands; + } kDangerTypeTestCases[] = { + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, + std::nullopt, + {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, + std::nullopt, + {DownloadCommands::Command::DISCARD}}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST, + std::nullopt, + {DownloadCommands::Command::DISCARD}}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE, + std::nullopt, + {DownloadCommands::Command::DISCARD}}, + {download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, + std::nullopt, + {DownloadCommands::Command::DISCARD}}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, + std::nullopt, + {DownloadCommands::Command::DISCARD}}, + {download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING, + DownloadCommands::Command::DISCARD, + {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}}, + {download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT, + std::nullopt, + {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}}, + {download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING, + std::nullopt, + {DownloadCommands::Command::DEEP_SCAN, + DownloadCommands::Command::BYPASS_DEEP_SCANNING}}, + {download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING, + std::nullopt, + {DownloadCommands::Command::DISCARD, + DownloadCommands::Command::CANCEL_DEEP_SCAN}}, + }; + for (const auto& test_case : kDangerTypeTestCases) { + SCOPED_TRACE(testing::Message() + << "Failed for danger type " + << download::GetDownloadDangerTypeString(test_case.danger_type) + << std::endl); + ON_CALL(item(), GetDangerType()) + .WillByDefault(Return(test_case.danger_type)); + RefreshInfo(); + std::vector<DownloadCommands::Command> subpage_commands; + if (info().has_primary_button()) { + subpage_commands.push_back(info().primary_button().command); + } + if (info().has_secondary_button()) { + subpage_commands.push_back(info().secondary_button().command); + } + EXPECT_EQ(subpage_commands, test_case.subpage_button_commands); + } +} + +TEST_F(DownloadBubbleSecurityViewInfoTest, InterruptedInfo) { + std::vector<download::DownloadInterruptReason> no_retry_interrupt_reasons = { + download::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE, + download::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED, + download::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED, + download::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN, + download::DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT}; + std::vector<download::DownloadInterruptReason> retry_interrupt_reasons = { + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST, + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN, + download::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR, + download::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN, + download::DOWNLOAD_INTERRUPT_REASON_CRASH, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT, + download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, + download::DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE, + download::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT}; + + const struct TestCase { + std::vector<download::DownloadInterruptReason> interrupt_reasons; + bool can_resume; + + std::string expected_warning_summary; + raw_ptr<const gfx::VectorIcon> expected_icon_model_override; + std::optional<DownloadCommands::Command> expected_primary_button_command; + } kTestCases[] = { + {{download::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED}, + false, + "Your organization blocked this file because it didn't meet a security " + "policy", + &views::kInfoIcon, + std::optional<DownloadCommands::Command>()}, + {{download::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG}, + false, + "Try using a shorter file name or saving to a different folder", + &vector_icons::kFileDownloadOffIcon, + std::optional<DownloadCommands::Command>()}, + {{download::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE}, + false, + "Free up space on your device. Then, try to download again", + &vector_icons::kFileDownloadOffIcon, + std::optional<DownloadCommands::Command>()}, + {{download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED}, + false, + "Try to sign in to the site. Then, download again", + &vector_icons::kFileDownloadOffIcon, + std::optional<DownloadCommands::Command>()}, + {no_retry_interrupt_reasons, false, "", + &vector_icons::kFileDownloadOffIcon, + std::optional<DownloadCommands::Command>()}, + {retry_interrupt_reasons, false, "", &vector_icons::kFileDownloadOffIcon, + DownloadCommands::Command::RETRY}, + {retry_interrupt_reasons, true, "", &vector_icons::kFileDownloadOffIcon, + DownloadCommands::Command::RESUME}, + }; + + for (const auto& test_case : kTestCases) { + for (const auto& interrupt_reason : test_case.interrupt_reasons) { + EXPECT_CALL(item(), GetLastReason()) + .WillRepeatedly(Return(interrupt_reason)); + EXPECT_CALL(item(), GetState()) + .WillRepeatedly(Return( + (interrupt_reason == download::DOWNLOAD_INTERRUPT_REASON_NONE) + ? DownloadItem::IN_PROGRESS + : DownloadItem::INTERRUPTED)); + EXPECT_CALL(item(), CanResume()) + .WillRepeatedly(Return(test_case.can_resume)); + RefreshInfo(); + + EXPECT_EQ(test_case.expected_warning_summary, + base::UTF16ToUTF8(info().warning_summary())); + EXPECT_EQ(test_case.expected_icon_model_override, + info().icon_model_override()); + EXPECT_EQ(kColorDownloadItemIconDangerous, info().secondary_color()); + EXPECT_FALSE(info().has_progress_bar()); + } + } +} + +#if BUILDFLAG(FULL_SAFE_BROWSING) +// Test file type warning where verdict was obtained. +TEST_F(DownloadBubbleSecurityViewInfoTest, + FileTypeWarning_HasSafeBrowsingVerdict) { + EXPECT_CALL(item(), GetState()) + .WillRepeatedly(Return(DownloadItem::IN_PROGRESS)); + + for (auto sb_state : {safe_browsing::SafeBrowsingState::STANDARD_PROTECTION, + safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION, + // This can happen if the user subsequently turned off + // SB after verdict was obtained. + safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING}) { + SetSafeBrowsingState(profile()->GetPrefs(), sb_state); + EXPECT_CALL(item(), GetDangerType()) + .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE)); + safe_browsing::DownloadProtectionService::SetDownloadProtectionData( + &item(), "token", safe_browsing::ClientDownloadResponse::DANGEROUS, + safe_browsing::ClientDownloadResponse::TailoredVerdict()); + RefreshInfo(); + + // Subpage warning + EXPECT_TRUE(info().HasSubpage()); + EXPECT_TRUE(base::MatchPattern(info().warning_summary(), + u"*file type isn't commonly downloaded*")); + // Primary subpage button. + ASSERT_TRUE(info().has_primary_button()); + EXPECT_EQ(info().primary_button().command, DownloadCommands::DISCARD); + EXPECT_EQ(info().primary_button().label, u"Delete from history"); + // Secondary subpage button. File is described as "suspicious". + EXPECT_EQ(info().secondary_button().command, DownloadCommands::KEEP); + EXPECT_EQ(info().secondary_button().label, u"Download suspicious file"); + // Learn more link. + EXPECT_TRUE(info().learn_more_link().has_value()); + EXPECT_TRUE( + base::MatchPattern(info().learn_more_link()->label_and_link_text, + u"Learn why * blocks some downloads")); + } +} + +// Test file type warning where SB is on but no SB verdict was obtained. +TEST_F(DownloadBubbleSecurityViewInfoTest, + FileTypeWarning_SafeBrowsingOn_NoVerdict) { + EXPECT_CALL(item(), GetState()) + .WillRepeatedly(Return(DownloadItem::IN_PROGRESS)); + for (auto sb_state : + {safe_browsing::SafeBrowsingState::STANDARD_PROTECTION, + safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION}) { + SetSafeBrowsingState(profile()->GetPrefs(), sb_state); + EXPECT_CALL(item(), GetDangerType()) + .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE)); + + RefreshInfo(); + + // Subpage warning + EXPECT_TRUE(info().HasSubpage()); + EXPECT_TRUE(base::MatchPattern(info().warning_summary(), + u"*file type isn't commonly downloaded*")); + // Suspicious pattern has 2 buttons on the subpage. + // Primary subpage button. + ASSERT_TRUE(info().has_primary_button()); + EXPECT_EQ(info().primary_button().command, DownloadCommands::DISCARD); + EXPECT_EQ(info().primary_button().label, u"Delete from history"); + // Secondary subpage button. File is described as "unverified". + ASSERT_TRUE(info().has_secondary_button()); + EXPECT_EQ(info().secondary_button().command, DownloadCommands::KEEP); + EXPECT_EQ(info().secondary_button().label, u"Download unverified file"); + // Learn more link. + EXPECT_TRUE(info().learn_more_link().has_value()); + EXPECT_TRUE( + base::MatchPattern(info().learn_more_link()->label_and_link_text, + u"Learn why * blocks some downloads")); + } +} + +// Test file type warning where SB is disabled by pref and can be turned on. +TEST_F(DownloadBubbleSecurityViewInfoTest, + FileTypeWarning_NoSafeBrowsing_DisabledByPref) { + EXPECT_CALL(item(), GetState()) + .WillRepeatedly(Return(DownloadItem::IN_PROGRESS)); + SetSafeBrowsingState(profile()->GetPrefs(), + safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING); + EXPECT_CALL(item(), GetDangerType()) + .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE)); + + RefreshInfo(); + + // Subpage warning + EXPECT_TRUE(info().HasSubpage()); + EXPECT_TRUE(base::MatchPattern(info().warning_summary(), + u"*file can't be verified*")); + // Suspicious pattern has 2 buttons on the subpage. + // Primary subpage button. + ASSERT_TRUE(info().has_primary_button()); + EXPECT_EQ(info().primary_button().command, DownloadCommands::DISCARD); + EXPECT_EQ(info().primary_button().label, u"Delete from history"); + // Secondary subpage button. File is described as "unverified". + ASSERT_TRUE(info().has_secondary_button()); + EXPECT_EQ(info().secondary_button().command, DownloadCommands::KEEP); + EXPECT_EQ(info().secondary_button().label, u"Download unverified file"); + // Learn more link. + EXPECT_TRUE(info().learn_more_link().has_value()); + EXPECT_TRUE(base::MatchPattern(info().learn_more_link()->label_and_link_text, + u"Turn on Safe Browsing to *")); +} + +// Test file type warning where SB is disabled by enterprise controls and cannot +// be turned on. +TEST_F(DownloadBubbleSecurityViewInfoTest, + FileTypeWarning_NoSafeBrowsing_DisabledManaged) { + EXPECT_CALL(item(), GetState()) + .WillRepeatedly(Return(DownloadItem::IN_PROGRESS)); + SetSafeBrowsingState(profile()->GetPrefs(), + safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING); + testing_profile().GetTestingPrefService()->SetManagedPref( + prefs::kSafeBrowsingEnabled, std::make_unique<base::Value>(false)); + EXPECT_CALL(item(), GetDangerType()) + .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE)); + + RefreshInfo(); + + // Subpage warning + EXPECT_TRUE(info().HasSubpage()); + EXPECT_TRUE(base::MatchPattern(info().warning_summary(), + u"*file can't be verified*")); + // Suspicious pattern has 2 buttons on the subpage. + // Primary subpage button. + ASSERT_TRUE(info().has_primary_button()); + EXPECT_EQ(info().primary_button().command, DownloadCommands::DISCARD); + EXPECT_EQ(info().primary_button().label, u"Delete from history"); + // Secondary subpage button. File is described as "unverified". + ASSERT_TRUE(info().has_secondary_button()); + EXPECT_EQ(info().secondary_button().command, DownloadCommands::KEEP); + EXPECT_EQ(info().secondary_button().label, u"Download unverified file"); + // There is no learn more link because the user cannot turn on SB. + EXPECT_FALSE(info().learn_more_link().has_value()); +} +#endif // BUILDFLAG(FULL_SAFE_BROWSING) + +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) +class DownloadBubbleSecurityViewInfoTailoredWarningTest + : public DownloadBubbleSecurityViewInfoTest { + public: + DownloadBubbleSecurityViewInfoTailoredWarningTest() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + scoped_feature_list_.InitAndEnableFeature( + safe_browsing::kDownloadTailoredWarnings); + } + + ~DownloadBubbleSecurityViewInfoTailoredWarningTest() override = default; + + protected: + void SetupTailoredWarningForItem( + download::DownloadDangerType danger_type, + TailoredVerdict::TailoredVerdictType tailored_verdict_type, + std::vector<TailoredVerdict::ExperimentalWarningAdjustment> adjustments) { + ON_CALL(item(), GetDangerType()).WillByDefault(Return(danger_type)); + TailoredVerdict tailored_verdict; + tailored_verdict.set_tailored_verdict_type(tailored_verdict_type); + for (const auto& adjustment : adjustments) { + tailored_verdict.add_adjustments(adjustment); + } + safe_browsing::DownloadProtectionService::SetDownloadProtectionData( + &item(), "token", + safe_browsing::ClientDownloadResponse::SAFE, // placeholder + tailored_verdict); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(DownloadBubbleSecurityViewInfoTailoredWarningTest, + GetInfoForTailoredWarning_CookieTheft) { + SetupTailoredWarningForItem( + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE, + TailoredVerdict::COOKIE_THEFT, /*adjustments=*/{}); + RefreshInfo(); + + ASSERT_TRUE(info().has_primary_button()); + EXPECT_FALSE(info().has_secondary_button()); + EXPECT_EQ(info().primary_button().command, + DownloadCommands::Command::DISCARD); + EXPECT_TRUE(info().primary_button().is_prominent); + EXPECT_EQ(info().warning_summary(), + u"This file can harm your personal and social network accounts"); +} + +TEST_F(DownloadBubbleSecurityViewInfoTailoredWarningTest, + GetInfoForTailoredWarning_SuspiciousArchive) { + SetupTailoredWarningForItem(download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT, + TailoredVerdict::SUSPICIOUS_ARCHIVE, + /*adjustments=*/{}); + RefreshInfo(); + + ASSERT_TRUE(info().has_primary_button()); + EXPECT_EQ(info().primary_button().command, + DownloadCommands::Command::DISCARD); + EXPECT_TRUE(info().primary_button().is_prominent); + + ASSERT_TRUE(info().has_secondary_button()); + EXPECT_EQ(info().secondary_button().command, DownloadCommands::Command::KEEP); + EXPECT_FALSE(info().secondary_button().is_prominent); + EXPECT_EQ(info().warning_summary(), + u"This archive file includes other files that may hide malware"); +} + +TEST_F(DownloadBubbleSecurityViewInfoTailoredWarningTest, + GetInfoForTailoredWarning_AccountInfoStringWithAccount) { + SetupTailoredWarningForItem( + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE, + TailoredVerdict::COOKIE_THEFT, {TailoredVerdict::ACCOUNT_INFO_STRING}); + signin::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile()); + signin::SetPrimaryAccount(identity_manager, "test@example.com", + signin::ConsentLevel::kSignin); + RefreshInfo(); + + ASSERT_TRUE(info().has_primary_button()); + EXPECT_FALSE(info().has_secondary_button()); + EXPECT_EQ(info().primary_button().command, + DownloadCommands::Command::DISCARD); + EXPECT_TRUE(info().primary_button().is_prominent); + EXPECT_EQ(info().warning_summary(), + u"This file can harm your personal and social network accounts, " + u"including test@example.com"); +} + +TEST_F(DownloadBubbleSecurityViewInfoTailoredWarningTest, + GetInfoForTailoredWarning_AccountInfoStringWithoutAccount) { + SetupTailoredWarningForItem( + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE, + TailoredVerdict::COOKIE_THEFT, {TailoredVerdict::ACCOUNT_INFO_STRING}); + RefreshInfo(); + + ASSERT_TRUE(info().has_primary_button()); + EXPECT_FALSE(info().has_secondary_button()); + EXPECT_EQ(info().primary_button().command, + DownloadCommands::Command::DISCARD); + EXPECT_TRUE(info().primary_button().is_prominent); + EXPECT_EQ(info().warning_summary(), + u"This file can harm your personal and social network accounts"); +} +#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_test.cc b/chrome/browser/ui/exclusive_access/exclusive_access_test.cc index 808bf517..90d993eb 100644 --- a/chrome/browser/ui/exclusive_access/exclusive_access_test.cc +++ b/chrome/browser/ui/exclusive_access/exclusive_access_test.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/ui/exclusive_access/pointer_lock_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" #include "content/public/common/input/native_web_keyboard_event.h" @@ -37,72 +38,6 @@ using content::WebContents; -BrowserFullscreenModeWaiter::BrowserFullscreenModeWaiter( - Browser* browser, - bool wait_until_exit_fullscreen_mode) - : wait_until_exit_fullscreen_mode_(wait_until_exit_fullscreen_mode), - controller_( - browser->exclusive_access_manager()->fullscreen_controller()) { - CHECK(controller_); - CHECK_EQ(wait_until_exit_fullscreen_mode_, - controller_->IsFullscreenForBrowser()); - observation_.Observe(controller_); -} - -BrowserFullscreenModeWaiter::~BrowserFullscreenModeWaiter() = default; - -void BrowserFullscreenModeWaiter::OnFullscreenStateChanged() { - // Note: In Lacros, when full screen mode changes, FullscreenController - // triggers WindowFullscreenStateChanged twice for the same change - // asynchronously. If the test code toggles fullscreen mode on and off, there - // is a race between the second notification of fullscreen mode on and test - // code toggle fullscreen mode off. Wait until the fullscreen state changes to - // the expected mode. See details in crbug.com/1481727. - if (wait_until_exit_fullscreen_mode_ && - controller_->IsFullscreenForBrowser()) { - return; - } - if (!wait_until_exit_fullscreen_mode_ && - !controller_->IsFullscreenForBrowser()) { - return; - } - - observed_change_ = true; - if (run_loop_.running()) { - run_loop_.Quit(); - } -} - -void BrowserFullscreenModeWaiter::Wait() { - if (observed_change_) { - return; - } - - run_loop_.Run(); -} - -FullscreenNotificationObserver::FullscreenNotificationObserver( - Browser* browser) { - observation_.Observe( - browser->exclusive_access_manager()->fullscreen_controller()); -} - -FullscreenNotificationObserver::~FullscreenNotificationObserver() = default; - -void FullscreenNotificationObserver::OnFullscreenStateChanged() { - observed_change_ = true; - if (run_loop_.running()) { - run_loop_.Quit(); - } -} - -void FullscreenNotificationObserver::Wait() { - if (observed_change_) - return; - - run_loop_.Run(); -} - const char ExclusiveAccessTest::kFullscreenKeyboardLockHTML[] = "/fullscreen_keyboardlock/fullscreen_keyboardlock.html"; @@ -242,23 +177,18 @@ void ExclusiveAccessTest::EnterActiveTabFullscreen() { WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); browser()->EnterFullscreenModeForTab(tab->GetPrimaryMainFrame(), {}); - fullscreen_observer.Wait(); -} - -void ExclusiveAccessTest::ToggleBrowserFullscreen() { - FullscreenNotificationObserver fullscreen_observer(browser()); - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); + waiter.Wait(); } void ExclusiveAccessTest::EnterExtensionInitiatedFullscreen() { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.browser_fullscreen = true}); static const char kExtensionId[] = "extension-id"; browser()->ToggleFullscreenModeWithExtension( extensions::Extension::GetBaseURLFromExtensionId(kExtensionId)); - fullscreen_observer.Wait(); + waiter.Wait(); } void ExclusiveAccessTest::SetEscRepeatWindowLength(
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_test.h b/chrome/browser/ui/exclusive_access/exclusive_access_test.h index 76beec3..8ae4403 100644 --- a/chrome/browser/ui/exclusive_access/exclusive_access_test.h +++ b/chrome/browser/ui/exclusive_access/exclusive_access_test.h
@@ -9,15 +9,11 @@ #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" -#include "base/run_loop.h" -#include "base/scoped_observation.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_hide_callback.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" -#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" -#include "chrome/browser/ui/exclusive_access/fullscreen_observer.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/test/test_utils.h" @@ -25,67 +21,11 @@ #include "ui/base/test/scoped_fake_nswindow_fullscreen.h" #endif -class Browser; - namespace base { class TickClock; } // namespace base -// BrowserFullscreenModeWaiter can be used to wait for entering or exiting -// browser fullscreen mode. -class BrowserFullscreenModeWaiter : public FullscreenObserver { - public: - BrowserFullscreenModeWaiter(Browser* browser, - bool wait_until_exit_fullscreen_mode); - - BrowserFullscreenModeWaiter(const BrowserFullscreenModeWaiter&) = delete; - BrowserFullscreenModeWaiter& operator=(const BrowserFullscreenModeWaiter&) = - delete; - - ~BrowserFullscreenModeWaiter() override; - - // Runs a loop until it enters or exits the expected fullscreen mode. - void Wait(); - - // FullscreenObserver: - void OnFullscreenStateChanged() override; - - protected: - // If true, wait until browser fullscreen mode is off; otherwise wait until - // browser fullscreen mode is on. - const bool wait_until_exit_fullscreen_mode_; - bool observed_change_ = false; - raw_ptr<FullscreenController> controller_; // not owned - base::ScopedObservation<FullscreenController, FullscreenObserver> - observation_{this}; - base::RunLoop run_loop_; -}; - -// Observer for fullscreen state change notifications. -class FullscreenNotificationObserver : public FullscreenObserver { - public: - explicit FullscreenNotificationObserver(Browser* browser); - - FullscreenNotificationObserver(const FullscreenNotificationObserver&) = - delete; - FullscreenNotificationObserver& operator=( - const FullscreenNotificationObserver&) = delete; - - ~FullscreenNotificationObserver() override; - - // Runs a loop until a fullscreen change is seen (unless one has already been - // observed, in which case it returns immediately). - void Wait(); - - // FullscreenObserver: - void OnFullscreenStateChanged() override; - - protected: - bool observed_change_ = false; - base::ScopedObservation<FullscreenController, FullscreenObserver> - observation_{this}; - base::RunLoop run_loop_; -}; +class FullscreenController; // Test fixture with convenience functions for fullscreen, keyboard lock, and // pointer lock. @@ -116,7 +56,6 @@ void GoBack(); void Reload(); void EnterActiveTabFullscreen(); - void ToggleBrowserFullscreen(); void EnterExtensionInitiatedFullscreen(); static const char kFullscreenKeyboardLockHTML[]; @@ -145,9 +84,6 @@ keyboard_lock_bubble_hide_reason_recorder_; private: - void ToggleTabFullscreen_Internal(bool enter_fullscreen, - bool retry_until_success); - #if BUILDFLAG(IS_MAC) // On Mac, entering into the system fullscreen mode can tickle crashes in // the WindowServer (c.f. https://crbug.com/828031), so provide a fake for
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc index a543fb2..580de814 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -48,24 +48,11 @@ namespace { -int64_t GetDisplayId(const WebContents& web_contents) { - if (auto* screen = display::Screen::GetScreen()) { - // crbug.com/1347558 WebContents::GetNativeView is const-incorrect. - // const_cast is used to access GetNativeView(). Also GetDisplayNearestView - // should accept const gfx::NativeView, but there is other const - // incorrectness down the call chain in some implementations. - auto display = screen->GetDisplayNearestView( - const_cast<WebContents&>(web_contents).GetNativeView()); - return display.id(); - } - return display::kInvalidDisplayId; -} - bool IsAnotherScreen(const WebContents& web_contents, const int64_t display_id) { if (display_id == display::kInvalidDisplayId) return false; - return display_id != GetDisplayId(web_contents); + return display_id != FullscreenController::GetDisplayId(web_contents); } } // namespace @@ -83,6 +70,19 @@ observer_list_.RemoveObserver(observer); } +int64_t FullscreenController::GetDisplayId(const WebContents& web_contents) { + if (auto* screen = display::Screen::GetScreen()) { + // crbug.com/1347558 WebContents::GetNativeView is const-incorrect. + // const_cast is used to access GetNativeView(). Also GetDisplayNearestView + // should accept const gfx::NativeView, but there is other const + // incorrectness down the call chain in some implementations. + auto display = screen->GetDisplayNearestView( + const_cast<WebContents&>(web_contents).GetNativeView()); + return display.id(); + } + return display::kInvalidDisplayId; +} + bool FullscreenController::IsFullscreenForBrowser() const { return exclusive_access_manager()->context()->IsFullscreen() && !IsFullscreenCausedByTab();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h index c43ee319..439f0aa 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -66,6 +66,8 @@ void AddObserver(FullscreenObserver* observer); void RemoveObserver(FullscreenObserver* observer); + static int64_t GetDisplayId(const content::WebContents& web_contents); + // Browser/User Fullscreen /////////////////////////////////////////////////// // Returns true if the window is currently fullscreen and was initially
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc index 0ceacd8e..7150055 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc
@@ -466,7 +466,7 @@ EXPECT_TRUE(browser()->window()->IsToolbarVisible()); // Test Normal state <--> Browser fullscreen mode <--> Tab fullscreen mode. - ToggleBrowserFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(context->IsFullscreen()); #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH) bool should_show_top_ui = true; @@ -487,7 +487,7 @@ EXPECT_TRUE(context->IsFullscreen()); EXPECT_EQ(should_show_top_ui, browser()->window()->IsToolbarVisible()); - ToggleBrowserFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(context->IsFullscreen()); EXPECT_TRUE(browser()->window()->IsToolbarVisible()); @@ -500,11 +500,11 @@ EXPECT_TRUE(context->IsFullscreen()); EXPECT_FALSE(browser()->window()->IsToolbarVisible()); - ToggleBrowserFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(context->IsFullscreen()); EXPECT_TRUE(browser()->window()->IsToolbarVisible()); - ToggleBrowserFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(context->IsFullscreen()); EXPECT_EQ(should_show_top_ui, browser()->window()->IsToolbarVisible()); }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc index 50416f7..b60185c 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -40,6 +40,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/shell.h" +#include "ui/display/manager/display_manager.h" #include "ui/display/test/display_manager_test_api.h" // nogncheck #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -137,11 +138,9 @@ void FullscreenControllerInteractiveTest::ToggleBrowserFullscreen( bool enter_fullscreen) { ASSERT_EQ(browser()->window()->IsFullscreen(), !enter_fullscreen); - FullscreenNotificationObserver fullscreen_observer(browser()); - chrome::ToggleFullscreenMode(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); - fullscreen_observer.Wait(); ASSERT_EQ(browser()->window()->IsFullscreen(), enter_fullscreen); ASSERT_EQ(IsFullscreenForBrowser(), enter_fullscreen); } @@ -150,12 +149,14 @@ bool enter_fullscreen, bool retry_until_success) { WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); do { - FullscreenNotificationObserver fullscreen_observer(browser()); - if (enter_fullscreen) + ui_test_utils::FullscreenWaiter waiter( + browser(), {.tab_fullscreen = enter_fullscreen}); + if (enter_fullscreen) { browser()->EnterFullscreenModeForTab(tab->GetPrimaryMainFrame(), {}); - else + } else { browser()->ExitFullscreenModeForTab(tab); - fullscreen_observer.Wait(); + } + waiter.Wait(); // Repeat ToggleFullscreenModeForTab until the correct state is entered. // This addresses flakiness on test bots running many fullscreen // tests in parallel. @@ -186,10 +187,11 @@ ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(true)); { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); ASSERT_TRUE( AddTabAtIndex(1, GURL(url::kAboutBlankURL), PAGE_TRANSITION_TYPED)); - fullscreen_observer.Wait(); + waiter.Wait(); ASSERT_FALSE(browser()->window()->IsFullscreen()); } } @@ -360,18 +362,17 @@ } { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); + waiter.Wait(); EXPECT_FALSE(browser()->window()->IsFullscreen()); } { // Test that tab fullscreen mode doesn't make presentation mode the default // on Lion. - FullscreenNotificationObserver fullscreen_observer(browser()); - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser()->window()->IsFullscreen()); } } @@ -410,16 +411,17 @@ // Request to lock the pointer and enter fullscreen. { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); PressKeyAndWaitForPointerLockRequest(ui::VKEY_B); - fullscreen_observer.Wait(); + waiter.Wait(); } // Escape, no prompts should remain. { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); SendEscapeToExclusiveAccessManager(); - fullscreen_observer.Wait(); + waiter.Wait(); } ASSERT_FALSE(IsPointerLocked()); ASSERT_FALSE(IsWindowFullscreenForTabOrPending()); @@ -481,9 +483,9 @@ // Request to lock the pointer and enter fullscreen. { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); PressKeyAndWaitForPointerLockRequest(ui::VKEY_B); - fullscreen_observer.Wait(); + waiter.Wait(); } ASSERT_TRUE(IsExclusiveAccessBubbleDisplayed()); ASSERT_TRUE(IsPointerLocked()); @@ -642,9 +644,9 @@ // Request to lock the pointer and enter fullscreen. { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); PressKeyAndWaitForPointerLockRequest(ui::VKEY_B); - fullscreen_observer.Wait(); + waiter.Wait(); } // We are fullscreen. @@ -652,9 +654,10 @@ // Reload. Pointer should be unlocked and fullscreen exited. { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = false}); Reload(); - fullscreen_observer.Wait(); + waiter.Wait(); ASSERT_FALSE(IsPointerLocked()); ASSERT_FALSE(IsWindowFullscreenForTabOrPending()); } @@ -712,7 +715,7 @@ EXPECT_TRUE(tab->IsBeingVisiblyCaptured()); // The browser enters fullscreen-within-tab mode synchronously, but the window - // is not made fullscreen, and FullscreenNotificationObserver is not notified. + // is not made fullscreen, and FullscreenWaiter is not notified. content::WebContentsDelegate* delegate = tab->GetDelegate(); delegate->EnterFullscreenModeForTab(tab->GetPrimaryMainFrame(), {}); EXPECT_TRUE(delegate->IsFullscreenForTabOrPending(tab)); @@ -767,7 +770,7 @@ #if BUILDFLAG(IS_MAC) ns_window_faked_for_testing_ = ui::NSWindowFakedForTesting::IsEnabled(); // Disable `NSWindowFakedForTesting` to wait for actual async fullscreen on - // Mac via `FullscreenNotificationObserver`. + // Mac via `FullscreenWaiter`. ui::NSWindowFakedForTesting::SetEnabled(false); #else screen_.display_list().AddDisplay({1, gfx::Rect(100, 100, 801, 802)}, @@ -793,14 +796,17 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) .UpdateDisplay("100+100-801x802,901+0-802x803"); + secondary_display_id_ = + ash::Shell::Get()->display_manager()->GetConnectedDisplayIdList()[1]; #elif BUILDFLAG(IS_MAC) virtual_display_mac_util_ = std::make_unique<display::test::VirtualDisplayMacUtil>(); - display_id_ = virtual_display_mac_util_->AddDisplay( + secondary_display_id_ = virtual_display_mac_util_->AddDisplay( 1, display::test::VirtualDisplayMacUtil::k1680x1050); #else screen_.display_list().AddDisplay({2, gfx::Rect(901, 0, 802, 803)}, display::DisplayList::Type::NOT_PRIMARY); + secondary_display_id_ = 2; #endif // BUILDFLAG(IS_CHROMEOS_ASH) ASSERT_GE(display::Screen::GetScreen()->GetNumDisplays(), 2); } @@ -818,16 +824,18 @@ display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) .UpdateDisplay("100+100-801x802"); #elif BUILDFLAG(IS_MAC) - virtual_display_mac_util_->RemoveDisplay(display_id_); + virtual_display_mac_util_->RemoveDisplay(secondary_display_id_); #else screen_.display_list().RemoveDisplay(2); #endif // BUILDFLAG(IS_CHROMEOS_ASH) } + int64_t secondary_display_id() const { return secondary_display_id_; } + private: + int64_t secondary_display_id_ = display::kInvalidDisplayId; #if BUILDFLAG(IS_MAC) bool ns_window_faked_for_testing_ = false; - int64_t display_id_ = display::kInvalidDisplayId; std::unique_ptr<display::test::VirtualDisplayMacUtil> virtual_display_mac_util_; #elif !BUILDFLAG(IS_CHROMEOS_ASH) @@ -904,12 +912,16 @@ // Returns the script result. content::EvalJsResult RequestContentFullscreenFromScript( const std::string& eval_js_script, + bool expect_fullscreen, int eval_js_options = content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - bool expect_window_fullscreen = true) { - FullscreenNotificationObserver fullscreen_observer(browser()); + bool expect_window_fullscreen = true, + std::optional<int64_t> display_id = std::nullopt) { + ui_test_utils::FullscreenWaiter waiter( + browser(), + {.tab_fullscreen = expect_fullscreen, .display_id = display_id}); auto* tab = browser()->tab_strip_model()->GetActiveWebContents(); content::EvalJsResult result = EvalJs(tab, eval_js_script, eval_js_options); - fullscreen_observer.Wait(); + waiter.Wait(); EXPECT_EQ(expect_window_fullscreen, browser()->window()->IsFullscreen()); return result; } @@ -922,7 +934,7 @@ return !!document.fullscreenElement; })(); )JS"; - EXPECT_EQ(true, RequestContentFullscreenFromScript(script)); + EXPECT_EQ(true, RequestContentFullscreenFromScript(script, true)); } // Execute JS to request content fullscreen on a different screen from where @@ -939,7 +951,10 @@ return !!document.fullscreenElement; })(); )JS"; - EXPECT_EQ(true, RequestContentFullscreenFromScript(script)); + EXPECT_EQ(true, + RequestContentFullscreenFromScript( + script, true, content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, true, + test_screen_environment_->secondary_display_id())); } // Execute JS to exit content fullscreen. @@ -952,7 +967,7 @@ )JS"; // Exiting fullscreen does not require a user gesture; do not supply one. EXPECT_EQ(false, RequestContentFullscreenFromScript( - script, content::EXECUTE_SCRIPT_NO_USER_GESTURE, + script, false, content::EXECUTE_SCRIPT_NO_USER_GESTURE, expect_window_fullscreen)); } @@ -1321,7 +1336,7 @@ })(); )"; EXPECT_EQ(true, RequestContentFullscreenFromScript( - script, content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + script, true, content::EXECUTE_SCRIPT_NO_USER_GESTURE)); } // TODO(crbug.com/1034772): Disabled on Windows, where views::FullscreenHandler @@ -1447,7 +1462,7 @@ return !!document.fullscreenElement && !!w && !w.closed; })(); )"; - EXPECT_TRUE(RequestContentFullscreenFromScript(script).ExtractBool()); + EXPECT_TRUE(RequestContentFullscreenFromScript(script, true).ExtractBool()); EXPECT_TRUE(IsWindowFullscreenForTabOrPending()); EXPECT_EQ(0u, popup_blocker->GetBlockedPopupsCount()); EXPECT_EQ(2u, browser_list->size()); @@ -1516,10 +1531,10 @@ WaitForUserActivationExpiry(); // Update the display configuration to trigger screenDetails.onscreenschange. - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = GetParam()}); UpdateScreenEnvironment(); - if (GetParam()) // The request will only be honored with the flag enabled. - fullscreen_observer.Wait(); + waiter.Wait(); EXPECT_EQ(GetParam(), browser()->window()->IsFullscreen()); // Close all tabs to avoid assertions failing when their cached screen info
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc index e2dc8a8c..bb979ae 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/common/url_constants.h" #include "testing/gtest/include/gtest/gtest.h" @@ -178,26 +179,6 @@ #endif } -// static -bool FullscreenControllerStateTest::IsPersistentState(State state) { - switch (state) { - case STATE_NORMAL: - case STATE_BROWSER_FULLSCREEN: - case STATE_TAB_FULLSCREEN: - case STATE_TAB_BROWSER_FULLSCREEN: - return true; - - case STATE_TO_NORMAL: - case STATE_TO_BROWSER_FULLSCREEN: - case STATE_TO_TAB_FULLSCREEN: - return false; - - default: - NOTREACHED(); - return false; - } -} - void FullscreenControllerStateTest::TransitionToState(State final_state) { int max_steps = NUM_STATES; while (max_steps-- && TransitionAStepTowardState(final_state)) @@ -236,15 +217,6 @@ } bool FullscreenControllerStateTest::InvokeEvent(Event event) { - if (!fullscreen_notification_observer_.get()) { - // Start observing fullscreen changes. Construct the notification observer - // here instead of in - // FullscreenControllerStateTest::FullscreenControllerStateTest() so that we - // listen to notifications on the proper thread. - fullscreen_notification_observer_ = - std::make_unique<FullscreenNotificationObserver>(GetBrowser()); - } - State source_state = state_; State next_state = transition_table_[source_state][event]; @@ -256,6 +228,38 @@ if (IsWindowFullscreenStateChangedReentrant()) next_state = transition_table_[next_state][WINDOW_CHANGE]; + // Figure out the fullscreen mode expectation. + ui_test_utils::FullscreenWaiter::Expectation expectation; + content::WebContents* const active_tab = + GetBrowser()->tab_strip_model()->GetActiveWebContents(); + // If event is {ENTER,EXIT}_TAB_FULLSCREEN and `active_tab` is + // being captured, fullscreen mode won't be updated. + if ((event != ENTER_TAB_FULLSCREEN && event != EXIT_TAB_FULLSCREEN) || + !active_tab->IsBeingVisiblyCaptured()) { + switch (next_state) { + case STATE_NORMAL: + expectation.browser_fullscreen = false; + expectation.tab_fullscreen = false; + break; + case STATE_BROWSER_FULLSCREEN: + expectation.browser_fullscreen = true; + expectation.tab_fullscreen = false; + break; + case STATE_TAB_FULLSCREEN: + expectation.browser_fullscreen = false; + expectation.tab_fullscreen = true; + break; + case STATE_TAB_BROWSER_FULLSCREEN: + expectation.browser_fullscreen = true; + expectation.tab_fullscreen = true; + break; + default: + // Do nothing. + break; + } + } + ui_test_utils::FullscreenWaiter waiter(GetBrowser(), expectation); + debugging_log_ << " InvokeEvent(" << std::left << std::setw(kMaxStateNameLength) << GetEventString(event) << ") to " @@ -269,8 +273,6 @@ break; case ENTER_TAB_FULLSCREEN: case EXIT_TAB_FULLSCREEN: { - content::WebContents* const active_tab = - GetBrowser()->tab_strip_model()->GetActiveWebContents(); if (event == ENTER_TAB_FULLSCREEN) { if (GetFullscreenController()->CanEnterFullscreenModeForTab( active_tab->GetPrimaryMainFrame())) { @@ -307,7 +309,7 @@ else debugging_log_ << "\n"; - MaybeWaitForNotification(); + waiter.Wait(); VerifyWindowState(); return true; @@ -355,19 +357,6 @@ } } -void FullscreenControllerStateTest::MaybeWaitForNotification() { - // We should get a fullscreen notification each time we get to a new - // persistent state. If we don't get a notification, the test will - // fail by timing out. - if (state_ != last_notification_received_state_ && - IsPersistentState(state_)) { - fullscreen_notification_observer_->Wait(); - last_notification_received_state_ = state_; - fullscreen_notification_observer_ = - std::make_unique<FullscreenNotificationObserver>(GetBrowser()); - } -} - void FullscreenControllerStateTest::TestTransitionsForEachState() { for (int source_int = 0; source_int < NUM_STATES; ++source_int) { for (int event1_int = 0; event1_int < NUM_EVENTS; ++event1_int) { @@ -531,9 +520,7 @@ } } -void FullscreenControllerStateTest::TearDown() { - fullscreen_notification_observer_.reset(); -} +void FullscreenControllerStateTest::TearDown() {} FullscreenController* FullscreenControllerStateTest::GetFullscreenController() { return GetBrowser()->exclusive_access_manager()->fullscreen_controller();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h index 4b4602a..3e56d78e 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h
@@ -12,7 +12,6 @@ class Browser; class FullscreenController; -class FullscreenNotificationObserver; // Utility definition for mapping enum values to strings in switch statements. #define ENUM_TO_STRING(enum) case enum: return #enum @@ -77,10 +76,6 @@ // FullscreenController methods complete. static bool IsWindowFullscreenStateChangedReentrant(); - // Returns true if |state| can be persistent. This is true for all of the - // states without "_TO_" in their name. - static bool IsPersistentState(State state); - // Causes Fullscreen Controller to transition to an arbitrary state. void TransitionToState(State state); @@ -103,10 +98,6 @@ // Checks that window state matches the expected controller state. virtual void VerifyWindowState(); - // Wait for a fullscreen change if a notification should have been sent in - // transitioning to |state_| from the previous persistent state. - void MaybeWaitForNotification(); - // Tests all states with all permutations of multiple events to detect // lingering state issues that would bleed over to other states. // I.E. for each state test all combinations of events E1, E2, E3. @@ -180,14 +171,6 @@ // The state the FullscreenController is expected to be in. State state_ = STATE_NORMAL; - // The state when the previous NOTIFICATION_FULLSCREEN_CHANGED notification - // was received. - State last_notification_received_state_ = STATE_NORMAL; - - // Listens for the NOTIFICATION_FULLSCREEN_CHANGED notification. - std::unique_ptr<FullscreenNotificationObserver> - fullscreen_notification_observer_; - // Human defined |State| that results given each [state][event] pair. State transition_table_[NUM_STATES][NUM_EVENTS];
diff --git a/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc b/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc index 39f27e2..ca2e4e2 100644 --- a/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc +++ b/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc
@@ -14,8 +14,8 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" @@ -184,7 +184,13 @@ void FullscreenKeyboardBrowserTestBase::SendFullscreenShortcutAndWait() { // On MacOSX, entering and exiting fullscreen are not synchronous. So we wait // for the observer to notice the change of fullscreen state. - FullscreenNotificationObserver observer(GetActiveBrowser()); + bool current = + GetActiveBrowser()->exclusive_access_manager()->context()->IsFullscreen(); + ui_test_utils::FullscreenWaiter waiter( + GetActiveBrowser(), current + ? ui_test_utils::FullscreenWaiter::kNoFullscreen + : ui_test_utils::FullscreenWaiter::Expectation{ + .browser_fullscreen = true}); // Enter fullscreen. #if BUILDFLAG(IS_MAC) // On MACOSX, Command + Control + F is used. @@ -205,16 +211,17 @@ // TODO(crbug.com/837438): Remove this once ScopedFakeNSWindowFullscreen fires // OnFullscreenStateChanged. #if !BUILDFLAG(IS_MAC) - observer.Wait(); + waiter.Wait(); #endif } void FullscreenKeyboardBrowserTestBase::SendJsFullscreenShortcutAndWait() { - FullscreenNotificationObserver observer(GetActiveBrowser()); + ui_test_utils::FullscreenWaiter waiter(GetActiveBrowser(), + {.tab_fullscreen = true}); ASSERT_TRUE(ui_test_utils::SendKeyPressSync(GetActiveBrowser(), ui::VKEY_S, false, false, false, false)); expected_result_ += "KeyS ctrl:false shift:false alt:false meta:false\n"; - observer.Wait(); + waiter.Wait(); ASSERT_TRUE(IsActiveTabFullscreen()); } @@ -226,10 +233,11 @@ void FullscreenKeyboardBrowserTestBase:: SendEscapeAndWaitForExitingFullscreen() { - FullscreenNotificationObserver observer(GetActiveBrowser()); + ui_test_utils::FullscreenWaiter waiter(GetActiveBrowser(), + {.tab_fullscreen = false}); ASSERT_TRUE(ui_test_utils::SendKeyPressSync( GetActiveBrowser(), ui::VKEY_ESCAPE, false, false, false, false)); - observer.Wait(); + waiter.Wait(); ASSERT_FALSE(IsActiveTabFullscreen()); }
diff --git a/chrome/browser/ui/fullscreen_util_mac_browsertest.cc b/chrome/browser/ui/fullscreen_util_mac_browsertest.cc index 62045eac..f0b922b 100644 --- a/chrome/browser/ui/fullscreen_util_mac_browsertest.cc +++ b/chrome/browser/ui/fullscreen_util_mac_browsertest.cc
@@ -8,9 +8,9 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" @@ -35,13 +35,6 @@ contents_delegate->ExitFullscreenModeForTab(GetWebContents()); } - void ToggleBrowserFullscreen() { - { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } - } FullscreenController* GetFullscreenController() { return browser()->exclusive_access_manager()->fullscreen_controller(); } @@ -75,7 +68,7 @@ EXPECT_FALSE(fullscreen_utils::IsInContentFullscreen(browser())); // Browser fullscreen - ToggleBrowserFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(IsBrowserFullscreen()); EXPECT_FALSE(fullscreen_utils::IsInContentFullscreen(browser())); @@ -87,7 +80,7 @@ ASSERT_TRUE(IsBrowserFullscreen()); EXPECT_FALSE(fullscreen_utils::IsInContentFullscreen(browser())); - ToggleBrowserFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_FALSE(IsBrowserFullscreen()); EXPECT_FALSE(fullscreen_utils::IsInContentFullscreen(browser())); }
diff --git a/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc b/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc index 352e271..dac7956 100644 --- a/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc +++ b/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc
@@ -2094,13 +2094,13 @@ // platform is different from other desktop platforms. add(new OmniboxPedalShareThisPage()); add(new OmniboxPedalManageChromeAccessibility()); + add(new OmniboxPedalSetChromeAsDefaultBrowser()); #else // !BUILDFLAG(IS_CHROMEOS) add(new OmniboxPedalManageChromeOSAccessibility()); #endif // !BUILDFLAG(IS_CHROMEOS) add(new OmniboxPedalCustomizeChromeFonts()); add(new OmniboxPedalManageChromeThemes()); add(new OmniboxPedalCustomizeSearchEngines()); - add(new OmniboxPedalSetChromeAsDefaultBrowser()); #endif // BUILDFLAG(IS_ANDROID) return pedals;
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_collector.cc b/chrome/browser/ui/performance_controls/tab_resource_usage_collector.cc new file mode 100644 index 0000000..c16c5f9 --- /dev/null +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_collector.cc
@@ -0,0 +1,99 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/performance_controls/tab_resource_usage_collector.h" + +#include "base/no_destructor.h" +#include "base/time/time.h" +#include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h" +#include "components/performance_manager/public/resource_attribution/page_context.h" +#include "components/performance_manager/public/resource_attribution/resource_types.h" +#include "content/public/browser/web_contents.h" + +namespace { +constexpr base::TimeDelta kTabResourceUsageRefreshInterval = base::Minutes(2); + +using performance_manager::resource_attribution::MemorySummaryResult; +using performance_manager::resource_attribution::PageContext; +using performance_manager::resource_attribution::QueryBuilder; +using performance_manager::resource_attribution::QueryResultMap; +using performance_manager::resource_attribution::ResourceType; +} // namespace + +TabResourceUsageCollector::TabResourceUsageCollector() + : scoped_query_(QueryBuilder() + .AddAllContextsOfType<PageContext>() + .AddResourceType(ResourceType::kMemorySummary) + .CreateScopedQuery()) { + query_observer_.Observe(&scoped_query_); + scoped_query_.Start(kTabResourceUsageRefreshInterval); +} + +TabResourceUsageCollector::~TabResourceUsageCollector() = default; + +TabResourceUsageCollector* TabResourceUsageCollector::Get() { + static base::NoDestructor<TabResourceUsageCollector> collector; + return collector.get(); +} + +void TabResourceUsageCollector::AddObserver(Observer* o) { + observers_.AddObserver(o); +} + +void TabResourceUsageCollector::RemoveObserver(Observer* o) { + observers_.RemoveObserver(o); +} + +void TabResourceUsageCollector::ImmediatelyRefreshMetrics( + content::WebContents* web_contents) { + absl::optional<PageContext> page_context = + PageContext::FromWebContents(web_contents); + if (page_context.has_value()) { + QueryBuilder() + .AddResourceType(ResourceType::kMemorySummary) + .AddResourceContext(page_context.value()) + .QueryOnce( + base::BindOnce(&TabResourceUsageCollector::OnResourceUsageUpdated, + base::Unretained(Get()))); + } +} + +void TabResourceUsageCollector::ImmediatelyRefreshMetricsForAllTabs() { + QueryBuilder() + .AddResourceType(ResourceType::kMemorySummary) + .AddAllContextsOfType<PageContext>() + .QueryOnce( + base::BindOnce(&TabResourceUsageCollector::OnResourceUsageUpdated, + base::Unretained(Get()))); +} + +void TabResourceUsageCollector::OnResourceUsageUpdated( + const QueryResultMap& results) { + bool did_resource_update = false; + for (const auto& [page_context, result] : results) { + std::optional<MemorySummaryResult> memory_result = + result.memory_summary_result; + if (memory_result.has_value()) { + content::WebContents* const web_contents = + performance_manager::resource_attribution::AsContext<PageContext>( + page_context) + .GetWebContents(); + if (web_contents) { + auto* const tab_resource_usage_tab_helper = + TabResourceUsageTabHelper::FromWebContents(web_contents); + if (tab_resource_usage_tab_helper) { + tab_resource_usage_tab_helper->SetMemoryUsageInBytes( + memory_result->private_footprint_kb * 1024); + did_resource_update = true; + } + } + } + } + + if (did_resource_update) { + for (auto& obs : observers_) { + obs.OnTabResourceMetricsRefreshed(); + } + } +}
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_collector.h b/chrome/browser/ui/performance_controls/tab_resource_usage_collector.h new file mode 100644 index 0000000..fc715366 --- /dev/null +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_collector.h
@@ -0,0 +1,58 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_RESOURCE_USAGE_COLLECTOR_H_ +#define CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_RESOURCE_USAGE_COLLECTOR_H_ + +#include "base/observer_list.h" +#include "base/observer_list_types.h" +#include "components/performance_manager/public/resource_attribution/queries.h" + +namespace base { +template <typename T> +class NoDestructor; +} + +namespace content { +class WebContents; +} + +class TabResourceUsageCollector + : public performance_manager::resource_attribution::QueryResultObserver { + public: + class Observer : public base::CheckedObserver { + public: + // Raised after the tab resource metrics have refreshed through an immediate + // or periodic query made by the TabResourceUsageCollector + virtual void OnTabResourceMetricsRefreshed() = 0; + }; + + ~TabResourceUsageCollector() override; + + static TabResourceUsageCollector* Get(); + + void AddObserver(Observer* o); + void RemoveObserver(Observer* o); + + void ImmediatelyRefreshMetrics(content::WebContents* web_contents); + void ImmediatelyRefreshMetricsForAllTabs(); + + // performance_manager::resource_attribution::QueryResultObserver: + void OnResourceUsageUpdated( + const performance_manager::resource_attribution::QueryResultMap& results) + override; + + private: + friend base::NoDestructor<TabResourceUsageCollector>; + + TabResourceUsageCollector(); + + performance_manager::resource_attribution::ScopedResourceUsageQuery + scoped_query_; + performance_manager::resource_attribution::ScopedQueryObservation + query_observer_{this}; + base::ObserverList<Observer> observers_; +}; + +#endif // CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_RESOURCE_USAGE_COLLECTOR_H_
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_collector_browsertest.cc b/chrome/browser/ui/performance_controls/tab_resource_usage_collector_browsertest.cc new file mode 100644 index 0000000..d02a6ff --- /dev/null +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_collector_browsertest.cc
@@ -0,0 +1,84 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "chrome/browser/ui/performance_controls/tab_resource_usage_collector.h" + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h" +#include "chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "net/dns/mock_host_resolver.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +class TabResourceUsageCollectorBrowserTest : public InProcessBrowserTest { + public: + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(embedded_test_server()->Start()); + } + + // Adds a new tab and waits for that tab to finish receiving memory usage + // to prevent test from flaking + void AddAndWaitForTabReady() { + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + ResourceUsageCollectorObserver observer(run_loop.QuitClosure()); + ASSERT_TRUE(AddTabAtIndex( + 0, embedded_test_server()->GetURL("example.com", "/title1.html"), + ui::PAGE_TRANSITION_TYPED)); + run_loop.Run(); + } + + TabStripModel* GetTabStripModel() { return browser()->tab_strip_model(); } +}; + +IN_PROC_BROWSER_TEST_F(TabResourceUsageCollectorBrowserTest, + RefreshAllTabMemory) { + AddAndWaitForTabReady(); + AddAndWaitForTabReady(); + TabStripModel* const model = GetTabStripModel(); + uint64_t bytes_used = 100; + TabResourceUsageTabHelper* const first_tab_helper = + TabResourceUsageTabHelper::FromWebContents(model->GetWebContentsAt(0)); + first_tab_helper->SetMemoryUsageInBytes(bytes_used); + TabResourceUsageTabHelper* const second_tab_helper = + TabResourceUsageTabHelper::FromWebContents(model->GetWebContentsAt(0)); + second_tab_helper->SetMemoryUsageInBytes(bytes_used); + + // Collector refresh memory usage data for all tabs + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + ResourceUsageCollectorObserver observer(run_loop.QuitClosure()); + TabResourceUsageCollector::Get()->ImmediatelyRefreshMetricsForAllTabs(); + run_loop.Run(); + + EXPECT_NE(bytes_used, first_tab_helper->GetMemoryUsageInBytes()); + EXPECT_NE(bytes_used, second_tab_helper->GetMemoryUsageInBytes()); +} + +IN_PROC_BROWSER_TEST_F(TabResourceUsageCollectorBrowserTest, + RefreshMemoryForOneWebContents) { + AddAndWaitForTabReady(); + AddAndWaitForTabReady(); + TabStripModel* const model = GetTabStripModel(); + uint64_t bytes_used = 100; + content::WebContents* const first_tab_contents = model->GetWebContentsAt(0); + TabResourceUsageTabHelper* const first_tab_helper = + TabResourceUsageTabHelper::FromWebContents(first_tab_contents); + first_tab_helper->SetMemoryUsageInBytes(bytes_used); + TabResourceUsageTabHelper* const second_tab_helper = + TabResourceUsageTabHelper::FromWebContents(model->GetWebContentsAt(1)); + second_tab_helper->SetMemoryUsageInBytes(bytes_used); + + // Collector refresh memory usage data for the first web contents + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + ResourceUsageCollectorObserver observer(run_loop.QuitClosure()); + TabResourceUsageCollector::Get()->ImmediatelyRefreshMetrics( + first_tab_contents); + run_loop.Run(); + + EXPECT_NE(bytes_used, first_tab_helper->GetMemoryUsageInBytes()); + EXPECT_EQ(bytes_used, second_tab_helper->GetMemoryUsageInBytes()); +}
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc index a4df379..d71ee16 100644 --- a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc
@@ -4,6 +4,10 @@ #include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h" +#include "chrome/browser/ui/performance_controls/tab_resource_usage_collector.h" +#include "components/performance_manager/public/features.h" +#include "content/public/browser/navigation_handle.h" + WEB_CONTENTS_USER_DATA_KEY_IMPL(TabResourceUsageTabHelper); TabResourceUsageTabHelper::~TabResourceUsageTabHelper() = default; @@ -20,6 +24,17 @@ resource_usage_->set_memory_usage_in_bytes(0); } +void TabResourceUsageTabHelper::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (performance_manager::features::kMemoryUsageInHovercardsUpdateTrigger + .Get() == performance_manager::features:: + MemoryUsageInHovercardsUpdateTrigger::kNavigation && + navigation_handle->IsInPrimaryMainFrame() && + !navigation_handle->IsSameDocument()) { + TabResourceUsageCollector::Get()->ImmediatelyRefreshMetrics(web_contents()); + } +} + uint64_t TabResourceUsageTabHelper::GetMemoryUsageInBytes() { return resource_usage_->memory_usage_in_bytes(); }
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h index 2a7de84..b3ad596 100644 --- a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h
@@ -8,6 +8,10 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" +namespace content { +class NavigationHandle; +} + class TabResourceUsage : public base::RefCounted<TabResourceUsage> { public: TabResourceUsage() = default; @@ -38,6 +42,8 @@ // content::WebContentsObserver void PrimaryPageChanged(content::Page& page) override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; uint64_t GetMemoryUsageInBytes(); void SetMemoryUsageInBytes(uint64_t memory_usage_bytes);
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_interactive_uitest.cc b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_interactive_uitest.cc index 46648aa..ddf6b42 100644 --- a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_interactive_uitest.cc +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_interactive_uitest.cc
@@ -5,6 +5,8 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h" #include "chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h" +#include "chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.h" +#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/interaction/interactive_browser_test.h" #include "components/performance_manager/public/features.h" #include "content/public/browser/web_contents.h" @@ -35,7 +37,7 @@ auto ForceRefreshMemoryMetrics() { return Do([]() { - MemoryMetricsRefreshWaiter waiter; + TabResourceUsageRefreshWaiter waiter; waiter.Wait(); }); } @@ -57,3 +59,23 @@ return resource_usage && resource_usage->GetMemoryUsageInBytes() != 0; })); } + +IN_PROC_BROWSER_TEST_F(TabResourceUsageTabHelperTest, + MemoryUsageUpdatesAfterNavigation) { + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(url::kAboutBlankURL), WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + content::WebContents* const web_contents = + browser()->tab_strip_model()->GetWebContentsAt(0); + auto* const resource_usage = + TabResourceUsageTabHelper::FromWebContents(web_contents); + const uint64_t bytes_used = std::numeric_limits<uint64_t>::max(); + resource_usage->SetMemoryUsageInBytes(bytes_used); + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + ResourceUsageCollectorObserver observer(run_loop.QuitClosure()); + ui_test_utils::NavigateToURLWithDisposition( + browser(), GetURL(), WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_NO_WAIT); + run_loop.Run(); + EXPECT_NE(bytes_used, resource_usage->GetMemoryUsageInBytes()); +}
diff --git a/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.cc b/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.cc index dfd70935..ca78586 100644 --- a/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.cc +++ b/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.cc
@@ -5,33 +5,39 @@ #include "chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h" #include "base/run_loop.h" +#include "base/scoped_observation.h" #include "base/test/bind.h" +#include "chrome/browser/ui/performance_controls/tab_resource_usage_collector.h" +#include "components/performance_manager/public/decorators/process_metrics_decorator.h" +#include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/performance_manager.h" -MemoryMetricsRefreshWaiter::MemoryMetricsRefreshWaiter() = default; -MemoryMetricsRefreshWaiter::~MemoryMetricsRefreshWaiter() = default; - -void MemoryMetricsRefreshWaiter::OnMemoryMetricsRefreshed() { - std::move(quit_closure_).Run(); -} - // Forces and waits for the memory metrics to refresh void MemoryMetricsRefreshWaiter::Wait() { - auto* const manager = performance_manager::user_tuning:: - UserPerformanceTuningManager::GetInstance(); + // kNestableTasksAllowed is used to prevent kombucha interactive tests from + // hanging base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); - quit_closure_ = run_loop.QuitClosure(); - base::ScopedObservation< - performance_manager::user_tuning::UserPerformanceTuningManager, - MemoryMetricsRefreshWaiter> - memory_metrics_observer(this); - memory_metrics_observer.Observe(manager); + base::OnceClosure quit_closure = run_loop.QuitClosure(); performance_manager::PerformanceManager::CallOnGraph( FROM_HERE, - base::BindLambdaForTesting([](performance_manager::Graph* graph) { - auto* metrics_decorator = graph->GetRegisteredObjectAs< + base::BindLambdaForTesting([&](performance_manager::Graph* graph) { + auto* const metrics_decorator = graph->GetRegisteredObjectAs< performance_manager::ProcessMetricsDecorator>(); - metrics_decorator->RequestImmediateMetrics(); + metrics_decorator->RequestImmediateMetrics(std::move(quit_closure)); })); run_loop.Run(); } + +TabResourceUsageRefreshWaiter::TabResourceUsageRefreshWaiter() + : ResourceUsageCollectorObserver(base::DoNothing()) {} +TabResourceUsageRefreshWaiter::~TabResourceUsageRefreshWaiter() = default; + +// Forces and waits for the memory metrics to refresh +void TabResourceUsageRefreshWaiter::Wait() { + // kNestableTasksAllowed is used to prevent kombucha interactive tests from + // hanging + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + metrics_refresh_callback_ = run_loop.QuitClosure(); + TabResourceUsageCollector::Get()->ImmediatelyRefreshMetricsForAllTabs(); + run_loop.Run(); +}
diff --git a/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h b/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h index 899bf60..6ce1ed7 100644 --- a/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h +++ b/chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h
@@ -6,21 +6,28 @@ #define CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TEST_SUPPORT_MEMORY_METRICS_REFRESH_WAITER_H_ #include "base/functional/callback_forward.h" -#include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h" +#include "chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.h" -class MemoryMetricsRefreshWaiter : public performance_manager::user_tuning:: - UserPerformanceTuningManager::Observer { +// Requests and waits for memory usage data to update so tabs can report memory +// savings through discard +class MemoryMetricsRefreshWaiter { public: - MemoryMetricsRefreshWaiter(); - ~MemoryMetricsRefreshWaiter() override; - - void OnMemoryMetricsRefreshed() override; + MemoryMetricsRefreshWaiter() = default; + ~MemoryMetricsRefreshWaiter() = default; // Forces and waits for the memory metrics to refresh void Wait(); +}; - private: - base::OnceClosure quit_closure_; +// Requests and waits for memory usage data to updates resource usage data for +// active tabs +class TabResourceUsageRefreshWaiter : public ResourceUsageCollectorObserver { + public: + TabResourceUsageRefreshWaiter(); + ~TabResourceUsageRefreshWaiter() override; + + // Forces and waits for the memory metrics to refresh + void Wait(); }; #endif // CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TEST_SUPPORT_MEMORY_METRICS_REFRESH_WAITER_H_
diff --git a/chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.cc b/chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.cc new file mode 100644 index 0000000..59eea30c --- /dev/null +++ b/chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.cc
@@ -0,0 +1,17 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.h" + +ResourceUsageCollectorObserver::ResourceUsageCollectorObserver( + base::OnceClosure metrics_refresh_callback) { + resource_collector_observeration_.Observe(TabResourceUsageCollector::Get()); + metrics_refresh_callback_ = std::move(metrics_refresh_callback); +} + +ResourceUsageCollectorObserver::~ResourceUsageCollectorObserver() = default; + +void ResourceUsageCollectorObserver::OnTabResourceMetricsRefreshed() { + std::move(metrics_refresh_callback_).Run(); +}
diff --git a/chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.h b/chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.h new file mode 100644 index 0000000..d76cb9cc --- /dev/null +++ b/chrome/browser/ui/performance_controls/test_support/resource_usage_collector_observer.h
@@ -0,0 +1,30 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TEST_SUPPORT_RESOURCE_USAGE_COLLECTOR_OBSERVER_H_ +#define CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TEST_SUPPORT_RESOURCE_USAGE_COLLECTOR_OBSERVER_H_ + +#include "base/scoped_observation.h" +#include "chrome/browser/ui/performance_controls/tab_resource_usage_collector.h" + +// Automatically observes the TabResourceUsageCollector and runs the given +// OnceClosure when OnTabResourcemetricsRefreshed() is called +class ResourceUsageCollectorObserver + : public TabResourceUsageCollector::Observer { + public: + explicit ResourceUsageCollectorObserver( + base::OnceClosure metrics_refresh_callback); + ~ResourceUsageCollectorObserver() override; + + // TabResourceUsageCollector::Observer: + void OnTabResourceMetricsRefreshed() override; + + protected: + base::OnceClosure metrics_refresh_callback_; + base::ScopedObservation<TabResourceUsageCollector, + ResourceUsageCollectorObserver> + resource_collector_observeration_{this}; +}; + +#endif // CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TEST_SUPPORT_RESOURCE_USAGE_COLLECTOR_OBSERVER_H_
diff --git a/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc b/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc index 401cb297..b7e368f4 100644 --- a/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc +++ b/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/toolbar/app_menu_model.h" #include "chrome/test/base/ui_test_utils.h" @@ -80,11 +79,27 @@ ui::Accelerator fullscreen_accelerator_; ui::Accelerator close_tab_accelerator_; - auto CheckFullscreenForBrowser(bool is_fullscreen) { + auto CreateFullscreenWaiter( + std::unique_ptr<ui_test_utils::FullscreenWaiter>& out, + bool is_fullscreen) { + return Do(base::BindOnce( + [](std::unique_ptr<ui_test_utils::FullscreenWaiter>& out, + bool is_fullscreen, Browser* browser) { + out = std::make_unique<ui_test_utils::FullscreenWaiter>( + browser, ui_test_utils::FullscreenWaiter::Expectation{ + .browser_fullscreen = is_fullscreen}); + }, + std::ref(out), is_fullscreen, browser())); + } + + auto CheckFullscreenForBrowser( + std::unique_ptr<ui_test_utils::FullscreenWaiter>& waiter, + bool is_fullscreen) { return CheckView( kBrowserViewElementId, base::BindOnce( - [](bool is_fullscreen, Browser* browser, + [](std::unique_ptr<ui_test_utils::FullscreenWaiter>& waiter, + bool is_fullscreen, Browser* browser, views::View* browser_view) { auto* fullscreen_controller = browser->exclusive_access_manager()->fullscreen_controller(); @@ -93,9 +108,11 @@ // Fullscreen transition is an async process on Mac, which // browser_window->IsFullscreen() might changed before transition // completed. + // TODO(hidehiko): investigate a way to simplify the async + // fullscreen handling. if (fullscreen_controller->IsControllerInitiatedFullscreen() != is_fullscreen) { - FullscreenNotificationObserver(browser).Wait(); + waiter->Wait(); } if (fullscreen_controller->IsControllerInitiatedFullscreen() != is_fullscreen) { @@ -129,49 +146,58 @@ return true; }, - is_fullscreen, browser())); + std::ref(waiter), is_fullscreen, browser())); } }; // Check Toggle Fullscreen IN_PROC_BROWSER_TEST_F(AppMenuFullscreenInteractiveTest, ToggleFullscreen) { + std::unique_ptr<ui_test_utils::FullscreenWaiter> waiter1, waiter2; + RunTestSequence( // P1. Launch Chrome // P2. Hit F11/⌘-Ctrl-F/Full screen button + CreateFullscreenWaiter(waiter1, true), SendAccelerator(kBrowserViewElementId, fullscreen_accelerator_), // V2. Make sure chrome is in full screen mode - CheckFullscreenForBrowser(true), + CheckFullscreenForBrowser(waiter1, true), // P3. Hit F11/⌘-Ctrl-F/Full screen button again + CreateFullscreenWaiter(waiter2, false), SendAccelerator(kBrowserViewElementId, fullscreen_accelerator_), // V3. Chrome should exit the full screen upon hitting F11 again when in // the full screen mode. - CheckFullscreenForBrowser(false)); + CheckFullscreenForBrowser(waiter2, false)); } // Check Full screen Notification // The original manual test doesn't work on ChromeOS. #if !BUILDFLAG(IS_CHROMEOS) IN_PROC_BROWSER_TEST_F(AppMenuFullscreenInteractiveTest, Notification) { + std::unique_ptr<ui_test_utils::FullscreenWaiter> waiter1; + RunTestSequence( // 1. Launch Chrome // 2. Hit F11/⌘-Ctrl-F/Full screen button + CreateFullscreenWaiter(waiter1, true), SendAccelerator(kBrowserViewElementId, fullscreen_accelerator_), // 3. Verify the notification shown on the top in the full screen mode. - CheckFullscreenForBrowser(true), + CheckFullscreenForBrowser(waiter1, true), InAnyContext(WaitForShow(kExclusiveAccessBubbleViewElementId))); } #endif // Check Context menu in full screen mode IN_PROC_BROWSER_TEST_F(AppMenuFullscreenInteractiveTest, ContextMenu) { + std::unique_ptr<ui_test_utils::FullscreenWaiter> waiter1, waiter2; DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kPrimaryTabId); RunTestSequence( // 1. Wait for the default page to load. InstrumentTab(kPrimaryTabId), // 2. Hit F11/⌘-Ctrl-F/Full screen button + CreateFullscreenWaiter(waiter1, true), SendAccelerator(kBrowserViewElementId, fullscreen_accelerator_), // 3. Make sure the chrome window is in full screen mode - CheckFullscreenForBrowser(true), + CheckFullscreenForBrowser(waiter1, true), // 4. Right click anywhere on the page to open the context menu. This // chooses the center of the browser window, which is fine. MoveMouseTo(kBrowserViewElementId), ClickMouse(ui_controls::RIGHT), @@ -181,24 +207,27 @@ // views::MenuController::OpenMenu from the same call stack during the // NotifyElementShown. InAnyContext(WaitForShow(RenderViewContextMenu::kExitFullscreenMenuItem)), - FlushEvents(), + FlushEvents(), CreateFullscreenWaiter(waiter2, false), InAnyContext( SelectMenuItem(RenderViewContextMenu::kExitFullscreenMenuItem)), - CheckFullscreenForBrowser(false)); + CheckFullscreenForBrowser(waiter2, false)); } // Check Closing the tab in full screen mode IN_PROC_BROWSER_TEST_F(AppMenuFullscreenInteractiveTest, ClosingTab) { + std::unique_ptr<ui_test_utils::FullscreenWaiter> waiter1, waiter2; RunTestSequence( // 1. Launch Chrome and navigate to few web pages. PressButton(kNewTabButtonElementId), // 2. Hit F11/⌘-Ctrl-F/Full screen button + CreateFullscreenWaiter(waiter1, true), SendAccelerator(kBrowserViewElementId, fullscreen_accelerator_), - CheckFullscreenForBrowser(true), + CheckFullscreenForBrowser(waiter1, true), // 3. Hit Ctrl+W / Ctrl+F4 [Windows & Linux], ⌘-W [Mac], Ctrl+W [CrOS] // when chrome is in the full screen mode. Current tab should be closed + CreateFullscreenWaiter(waiter2, true), SendAccelerator(kBrowserViewElementId, close_tab_accelerator_), // Chrome should not exit full screen mode when you close a tab in full // screen mode. - CheckFullscreenForBrowser(true)); + CheckFullscreenForBrowser(waiter2, true)); }
diff --git a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc index e28248cc..2fe2361f 100644 --- a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc +++ b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc
@@ -37,6 +37,7 @@ #include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/payments/virtual_card_enrollment_manager.h" +#include "components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/constrained_window/constrained_window_views.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" @@ -46,12 +47,7 @@ AutofillBubbleHandlerImpl::AutofillBubbleHandlerImpl( Browser* browser, ToolbarButtonProvider* toolbar_button_provider) - : browser_(browser), toolbar_button_provider_(toolbar_button_provider) { - if (toolbar_button_provider_->GetAvatarToolbarButton()) { - avatar_toolbar_button_observation_.Observe( - toolbar_button_provider_->GetAvatarToolbarButton()); - } -} + : browser_(browser), toolbar_button_provider_(toolbar_button_provider) {} AutofillBubbleHandlerImpl::~AutofillBubbleHandlerImpl() = default; @@ -243,8 +239,9 @@ PageActionIconView* icon_view = toolbar_button_provider_->GetPageActionIconView( PageActionIconType::kVirtualCardManualFallback); - if (icon_view) + if (icon_view) { bubble->SetHighlightedButton(icon_view); + } return bubble; } @@ -259,14 +256,23 @@ web_contents, controller); views::BubbleDialogDelegateView::CreateBubble(bubble); + + // VirtualCardEnrollBubbleController::IsEnrollmentInProgress() == true when + // the bubble has been accepted and the enrollment is still in progress. In + // this case we do not want to offer enrollment again on reshow. + if (controller->IsEnrollmentInProgress()) { + bubble->SwitchToLoadingState(); + } + bubble->ShowForReason(is_user_gesture ? VirtualCardEnrollBubbleViews::USER_GESTURE : VirtualCardEnrollBubbleViews::AUTOMATIC); PageActionIconView* icon_view = toolbar_button_provider_->GetPageActionIconView( PageActionIconType::kVirtualCardEnroll); - if (icon_view) + if (icon_view) { bubble->SetHighlightedButton(icon_view); + } return bubble; } @@ -324,40 +330,6 @@ anchor_view, web_contents, std::move(callback), icon_view); } -void AutofillBubbleHandlerImpl::OnAvatarHighlightAnimationFinished() { - if (should_show_sign_in_promo_if_applicable_) { - should_show_sign_in_promo_if_applicable_ = false; - chrome::ExecuteCommand( - browser_, IDC_SHOW_SAVE_LOCAL_CARD_SIGN_IN_PROMO_IF_APPLICABLE); - } - - // Notify the virtual card enrollment manager that the avatar highlight - // animation has completed in case we are offering VCN enrollment. - content::WebContents* web_contents = - browser_->tab_strip_model()->GetActiveWebContents(); - if (!web_contents) - return; - - autofill::ContentAutofillDriverFactory* driver = - autofill::ContentAutofillDriverFactory::FromWebContents(web_contents); - if (!driver) - return; - - raw_ptr<autofill::VirtualCardEnrollmentManager> - virtual_card_enrollment_manager = - driver->client().GetVirtualCardEnrollmentManager(); - - if (virtual_card_enrollment_manager) - virtual_card_enrollment_manager->OnCardSavedAnimationComplete(); -} - -void AutofillBubbleHandlerImpl::ShowAvatarHighlightAnimation() { - AvatarToolbarButton* avatar = - toolbar_button_provider_->GetAvatarToolbarButton(); - if (avatar) - avatar->ShowAvatarHighlightAnimation(); -} - AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowSaveCardAndVirtualCardEnrollConfirmationBubble( views::View* anchor_view,
diff --git a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h index 7a04f9e..504dd14 100644 --- a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h +++ b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h
@@ -5,10 +5,10 @@ #ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_BUBBLE_HANDLER_IMPL_H_ #define CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_BUBBLE_HANDLER_IMPL_H_ +#include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" #include "chrome/browser/ui/autofill/autofill_bubble_handler.h" -#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h" #include "components/autofill/core/browser/ui/payments/payments_bubble_closed_reasons.h" class Browser; @@ -19,6 +19,10 @@ class WebContents; } +namespace views { +class View; +} + namespace autofill { class AutofillBubbleBase; class LocalCardMigrationBubbleController; @@ -26,8 +30,7 @@ class IbanBubbleController; enum class IbanBubbleType; -class AutofillBubbleHandlerImpl : public AutofillBubbleHandler, - public AvatarToolbarButton::Observer { +class AutofillBubbleHandlerImpl : public AutofillBubbleHandler { public: AutofillBubbleHandlerImpl(Browser* browser, ToolbarButtonProvider* toolbar_button_provider); @@ -81,13 +84,7 @@ content::WebContents* web_contents, SaveCardBubbleController* controller) override; - // AvatarToolbarButton::Observer: - void OnAvatarHighlightAnimationFinished() override; - private: - // Executes highlight animation on toolbar's avatar icon. - void ShowAvatarHighlightAnimation(); - // Show the save card and virtual card enrollment confirmation bubble. AutofillBubbleBase* ShowSaveCardAndVirtualCardEnrollConfirmationBubble( views::View* anchor_view, @@ -99,13 +96,6 @@ raw_ptr<Browser> browser_ = nullptr; raw_ptr<ToolbarButtonProvider> toolbar_button_provider_ = nullptr; - - // Whether a save local card sign in promo bubble could pop up from the avatar - // button after the highlight animation finishes. - bool should_show_sign_in_promo_if_applicable_ = false; - - base::ScopedObservation<AvatarToolbarButton, AvatarToolbarButton::Observer> - avatar_toolbar_button_observation_{this}; }; } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/offer_notification_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/autofill/payments/offer_notification_bubble_views_interactive_uitest.cc index 8dd592e..7b0ccb0 100644 --- a/chrome/browser/ui/views/autofill/payments/offer_notification_bubble_views_interactive_uitest.cc +++ b/chrome/browser/ui/views/autofill/payments/offer_notification_bubble_views_interactive_uitest.cc
@@ -710,41 +710,6 @@ } } -IN_PROC_BROWSER_TEST_P( - OfferNotificationBubbleViewsInteractiveUiTest, - RecordPageLoadsWithPromoOfferIconShowingMetricForFreeListingOffer) { - // Applies to free listing coupons offers only, as we don't log this metric - // for other offers. - if (test_offer_type_ != - AutofillOfferData::OfferType::FREE_LISTING_COUPON_OFFER) { - return; - } - - base::HistogramTester histogram_tester; - - ShowBubbleForOfferAndVerify(); - ASSERT_TRUE(GetOfferNotificationBubbleViews()); - ASSERT_TRUE(IsIconVisible()); - histogram_tester.ExpectBucketCount( - "Autofill.PageLoadsWithOfferIconShowing.FreeListingCouponOffer", true, 1); - - test_clock_.Advance(kAutofillBubbleSurviveNavigationTime); - - // Navigates to another valid domain will not reshow the bubble. - NavigateToAndWaitForForm(GetUrl("www.merchantsite1.test", "/second")); - EXPECT_FALSE(GetOfferNotificationBubbleViews()); - EXPECT_TRUE(IsIconVisible()); - histogram_tester.ExpectBucketCount( - "Autofill.PageLoadsWithOfferIconShowing.FreeListingCouponOffer", true, 2); - - // Navigates to an invalid domain will dismiss the icon. - NavigateToAndWaitForForm(GetUrl("www.about.test", "/")); - EXPECT_FALSE(GetOfferNotificationBubbleViews()); - EXPECT_FALSE(IsIconVisible()); - histogram_tester.ExpectBucketCount( - "Autofill.PageLoadsWithOfferIconShowing.FreeListingCouponOffer", true, 2); -} - IN_PROC_BROWSER_TEST_P(OfferNotificationBubbleViewsInteractiveUiTest, IconViewAccessibleName) { EXPECT_EQ(GetOfferNotificationIconView()->GetAccessibleName(),
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc index cfdfa85..d8dcd661 100644 --- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc
@@ -25,6 +25,7 @@ #include "ui/views/bubble/tooltip_icon.h" #include "ui/views/controls/label.h" #include "ui/views/controls/styled_label.h" +#include "ui/views/controls/throbber.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout_view.h" #include "ui/views/style/typography.h" @@ -45,9 +46,8 @@ controller->GetUiModel().cancel_action_text); SetCancelCallback(base::BindOnce( &VirtualCardEnrollBubbleViews::OnDialogDeclined, base::Unretained(this))); - SetAcceptCallback(base::BindOnce( + SetAcceptCallbackWithClose(base::BindRepeating( &VirtualCardEnrollBubbleViews::OnDialogAccepted, base::Unretained(this))); - SetShowCloseButton(true); set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); @@ -68,9 +68,17 @@ controller_ = nullptr; } -void VirtualCardEnrollBubbleViews::OnDialogAccepted() { - if (controller_) - controller_->OnAcceptButton(); +bool VirtualCardEnrollBubbleViews::OnDialogAccepted() { + bool did_switch_to_loading_state = false; + if (controller_) { + if (base::FeatureList::IsEnabled( + features::kAutofillEnableVcnEnrollLoadingAndConfirmation)) { + SwitchToLoadingState(); + did_switch_to_loading_state = true; + } + controller_->OnAcceptButton(did_switch_to_loading_state); + } + return !did_switch_to_loading_state; } void VirtualCardEnrollBubbleViews::OnDialogDeclined() { @@ -199,6 +207,11 @@ AddChildView(CreateLegalMessageView()) ->SetID(DialogViewId::LEGAL_MESSAGE_VIEW); + + if (base::FeatureList::IsEnabled( + features::kAutofillEnableVcnEnrollLoadingAndConfirmation)) { + loading_progress_row_ = AddChildView(CreateLoadingProgressRow()); + } } std::unique_ptr<views::View> @@ -233,6 +246,39 @@ return legal_message_view; } +std::unique_ptr<views::View> +VirtualCardEnrollBubbleViews::CreateLoadingProgressRow() { + auto progress_loading_row = std::make_unique<views::BoxLayoutView>(); + + // Set `progress_loading_row` initially hidden because it should only be + // visible after the user accepts virtual card enrollment. + progress_loading_row->SetVisible(false); + + progress_loading_row->SetOrientation( + views::BoxLayout::Orientation::kHorizontal); + progress_loading_row->SetMainAxisAlignment( + views::BoxLayout::MainAxisAlignment::kEnd); + loading_throbber_ = + progress_loading_row->AddChildView(std::make_unique<views::Throbber>()); + loading_throbber_->SetID(DialogViewId::LOADING_THROBBER); + + return progress_loading_row; +} + +views::View* VirtualCardEnrollBubbleViews::GetLoadingProgressRowForTesting() { + return loading_progress_row_.get(); +} + +void VirtualCardEnrollBubbleViews::SwitchToLoadingState() { + if (loading_progress_row_ == nullptr) { + return; + } + loading_throbber_->Start(); + loading_progress_row_->SetVisible(true); + SetButtons(ui::DIALOG_BUTTON_NONE); + DialogModelChanged(); +} + void VirtualCardEnrollBubbleViews::LearnMoreLinkClicked() { if (controller()) { controller()->OnLinkClicked(
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h index 49b3a06..c7cd97a 100644 --- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h +++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h
@@ -46,19 +46,24 @@ std::u16string GetWindowTitle() const override; void WindowClosing() override; + views::View* GetLoadingProgressRowForTesting(); + + void SwitchToLoadingState(); + protected: VirtualCardEnrollBubbleController* controller() const { return controller_; } // LocationBarBubbleDelegateView: void Init() override; - void OnDialogAccepted(); + bool OnDialogAccepted(); void OnDialogDeclined(); private: friend class VirtualCardEnrollBubbleViewsInteractiveUiTest; std::unique_ptr<views::View> CreateLegalMessageView(); + std::unique_ptr<views::View> CreateLoadingProgressRow(); void LearnMoreLinkClicked(); void GoogleLegalMessageClicked(const GURL& url); @@ -66,6 +71,10 @@ raw_ptr<VirtualCardEnrollBubbleController> controller_; + // Container for the `loading_throbber_`. + raw_ptr<views::View> loading_progress_row_ = nullptr; + raw_ptr<views::Throbber> loading_throbber_ = nullptr; + base::WeakPtrFactory<VirtualCardEnrollBubbleViews> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc index fc729be..a052365 100644 --- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc +++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc
@@ -5,11 +5,13 @@ #include <memory> #include <string> +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h" #include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h" #include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h" #include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -21,10 +23,12 @@ #include "components/autofill/core/browser/payments/payments_service_url.h" #include "components/autofill/core/browser/payments/test_legal_message_line.h" #include "components/autofill/core/browser/payments/virtual_card_enrollment_manager.h" +#include "components/autofill/core/common/autofill_payments_features.h" #include "components/strings/grit/components_strings.h" #include "content/public/test/browser_test.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/image/image_unittest_util.h" +#include "ui/views/controls/throbber.h" #include "ui/views/test/widget_test.h" #include "ui/views/view_observer.h" @@ -104,6 +108,12 @@ bool IsIconVisible() { return GetIconView() && GetIconView()->GetVisible(); } + bool IsLoadingProgressRowVisible() { + return GetBubbleViews() && + GetBubbleViews()->GetLoadingProgressRowForTesting() && + GetBubbleViews()->GetLoadingProgressRowForTesting()->GetVisible(); + } + VirtualCardEnrollBubbleControllerImpl* GetController() { if (!browser() || !browser()->tab_strip_model() || !browser()->tab_strip_model()->GetActiveWebContents()) { @@ -250,9 +260,15 @@ : public VirtualCardEnrollBubbleViewsInteractiveUiTest, public testing::WithParamInterface<VirtualCardEnrollmentSource> { public: - VirtualCardEnrollBubbleViewsInteractiveUiTestParameterized() = default; + VirtualCardEnrollBubbleViewsInteractiveUiTestParameterized() { + feature_list_.InitAndEnableFeature( + features::kAutofillEnableVcnEnrollLoadingAndConfirmation); + } ~VirtualCardEnrollBubbleViewsInteractiveUiTestParameterized() override = default; + + private: + base::test::ScopedFeatureList feature_list_; }; INSTANTIATE_TEST_SUITE_P( @@ -285,15 +301,6 @@ IN_PROC_BROWSER_TEST_P( VirtualCardEnrollBubbleViewsInteractiveUiTestParameterized, - Metrics_BubbleAccepted) { - TestCloseBubbleForExpectedResultFromSource( - VirtualCardEnrollmentBubbleResult:: - VIRTUAL_CARD_ENROLLMENT_BUBBLE_ACCEPTED, - GetParam()); -} - -IN_PROC_BROWSER_TEST_P( - VirtualCardEnrollBubbleViewsInteractiveUiTestParameterized, Metrics_BubbleCancelled) { TestCloseBubbleForExpectedResultFromSource( VirtualCardEnrollmentBubbleResult:: @@ -585,4 +592,92 @@ IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_FALLBACK_ICON_TOOLTIP)); } +IN_PROC_BROWSER_TEST_P( + VirtualCardEnrollBubbleViewsInteractiveUiTestParameterized, + ShowLoadingViewOnAccept) { + base::HistogramTester histogram_tester; + VirtualCardEnrollmentSource virtual_card_enrollment_source = GetParam(); + ShowBubbleAndWaitUntilShown( + GetFieldsForSource(virtual_card_enrollment_source), base::DoNothing(), + base::DoNothing()); + ASSERT_TRUE(GetBubbleViews()); + EXPECT_FALSE(IsLoadingProgressRowVisible()); + EXPECT_EQ(GetBubbleViews()->GetDialogButtons(), + (ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL)); + + GetBubbleViews()->AcceptDialog(); + + ASSERT_TRUE(GetBubbleViews()); + EXPECT_TRUE(IsLoadingProgressRowVisible()); + views::View* loading_throbber = + GetBubbleViews()->GetViewByID(DialogViewId::LOADING_THROBBER); + EXPECT_TRUE(loading_throbber->IsDrawn()); + EXPECT_EQ(GetBubbleViews()->GetDialogButtons(), ui::DIALOG_BUTTON_NONE); + + CloseBubbleForReasonAndWaitTillDestroyed( + views::Widget::ClosedReason::kAcceptButtonClicked); + + histogram_tester.ExpectBucketCount( + "Autofill.VirtualCardEnrollBubble.Result." + + VirtualCardEnrollmentSourceToMetricSuffix( + virtual_card_enrollment_source) + + ".FirstShow", + VirtualCardEnrollmentBubbleResult:: + VIRTUAL_CARD_ENROLLMENT_BUBBLE_ACCEPTED, + 1); +} + +class + VirtualCardEnrollBubbleViewsInteractiveUiTestDisabledLoadingAndConfirmation + : public VirtualCardEnrollBubbleViewsInteractiveUiTest, + public testing::WithParamInterface<VirtualCardEnrollmentSource> { + public: + VirtualCardEnrollBubbleViewsInteractiveUiTestDisabledLoadingAndConfirmation() { + feature_list_.InitAndDisableFeature( + features::kAutofillEnableVcnEnrollLoadingAndConfirmation); + } + ~VirtualCardEnrollBubbleViewsInteractiveUiTestDisabledLoadingAndConfirmation() + override = default; + + private: + base::test::ScopedFeatureList feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + , + VirtualCardEnrollBubbleViewsInteractiveUiTestDisabledLoadingAndConfirmation, + testing::Values(VirtualCardEnrollmentSource::kUpstream, + VirtualCardEnrollmentSource::kDownstream, + VirtualCardEnrollmentSource::kSettingsPage)); + +IN_PROC_BROWSER_TEST_P( + VirtualCardEnrollBubbleViewsInteractiveUiTestDisabledLoadingAndConfirmation, + CloseBubbleOnAcceptWhenLoadingAndConfirmationIsDisabled) { + base::HistogramTester histogram_tester; + VirtualCardEnrollmentSource virtual_card_enrollment_source = GetParam(); + ShowBubbleAndWaitUntilShown( + GetFieldsForSource(virtual_card_enrollment_source), base::DoNothing(), + base::DoNothing()); + ASSERT_TRUE(GetBubbleViews()); + EXPECT_FALSE(IsLoadingProgressRowVisible()); + EXPECT_EQ(GetBubbleViews()->GetDialogButtons(), + (ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL)); + + views::test::WidgetDestroyedWaiter destroyed_waiter( + GetBubbleViews()->GetWidget()); + GetBubbleViews()->AcceptDialog(); + destroyed_waiter.Wait(); + + EXPECT_FALSE(GetBubbleViews()); + EXPECT_FALSE(IsIconVisible()); + histogram_tester.ExpectBucketCount( + "Autofill.VirtualCardEnrollBubble.Result." + + VirtualCardEnrollmentSourceToMetricSuffix( + virtual_card_enrollment_source) + + ".FirstShow", + VirtualCardEnrollmentBubbleResult:: + VIRTUAL_CARD_ENROLLMENT_BUBBLE_ACCEPTED, + 1); +} + } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc index bc517bf..e6f02a5d 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc
@@ -326,9 +326,7 @@ case PopupItemId::kMixedFormMessage: case PopupItemId::kInsecureContextPaymentDisabledMessage: NOTREACHED_NORETURN(); - case PopupItemId::kUsernameEntry: case PopupItemId::kPasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kAccountStoragePasswordEntry: return std::make_unique<PopupRowView>( a11y_selection_delegate, selection_delegate, controller, line_number,
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils_browsertest.cc b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils_browsertest.cc index 7ee86f8..3488b7d 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils_browsertest.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils_browsertest.cc
@@ -79,7 +79,7 @@ }; const Suggestion kExpandableSuggestions[] = {CreateSuggestionWithChildren( u"Address_entry", - {Suggestion(u"Username", PopupItemId::kUsernameEntry)})}; + {Suggestion(u"Username", PopupItemId::kPasswordEntry)})}; } // namespace
diff --git a/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc b/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc index e0144fe..f7a2d1e 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc
@@ -554,7 +554,6 @@ case PopupItemId::kDeleteAddressProfile: return true; case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kAddressEntry: case PopupItemId::kAddressFieldByFieldFilling: case PopupItemId::kAutocompleteEntry: @@ -577,7 +576,6 @@ case PopupItemId::kMixedFormMessage: case PopupItemId::kPasswordEntry: case PopupItemId::kSeparator: - case PopupItemId::kUsernameEntry: case PopupItemId::kVirtualCreditCardEntry: case PopupItemId::kWebauthnCredential: case PopupItemId::kWebauthnSignInWithAnotherDevice: @@ -598,7 +596,6 @@ case PopupItemId::kCreditCardEntry: return true; case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kAllSavedPasswordsEntry: case PopupItemId::kAutocompleteEntry: case PopupItemId::kAutofillOptions: @@ -625,7 +622,6 @@ case PopupItemId::kSeePromoCodeDetails: case PopupItemId::kSeparator: case PopupItemId::kShowAccountCards: - case PopupItemId::kUsernameEntry: case PopupItemId::kVirtualCreditCardEntry: case PopupItemId::kWebauthnCredential: case PopupItemId::kWebauthnSignInWithAnotherDevice:
diff --git a/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc b/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc index 30058f9..e37f243 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc
@@ -81,7 +81,6 @@ PopupItemId::kAutofillOptions, PopupItemId::kDatalistEntry, PopupItemId::kScanCreditCard, - PopupItemId::kUsernameEntry, PopupItemId::kAllSavedPasswordsEntry, PopupItemId::kPasswordAccountStorageOptIn, PopupItemId::kPasswordAccountStorageReSignin, @@ -868,7 +867,7 @@ suggestion.labels = {{Suggestion::Text(u"example.com")}}; suggestion.voice_over = voice_over_value; suggestion.additional_label = u"\u2022\u2022\u2022\u2022"; - suggestion.popup_item_id = PopupItemId::kUsernameEntry; + suggestion.popup_item_id = PopupItemId::kPasswordEntry; // Create autofill menu. controller().set_suggestions({suggestion});
diff --git a/chrome/browser/ui/views/bubble/webui_bubble_manager.cc b/chrome/browser/ui/views/bubble/webui_bubble_manager.cc index ab2c93b8..841f3fa 100644 --- a/chrome/browser/ui/views/bubble/webui_bubble_manager.cc +++ b/chrome/browser/ui/views/bubble/webui_bubble_manager.cc
@@ -4,10 +4,14 @@ #include "chrome/browser/ui/views/bubble/webui_bubble_manager.h" +#include "base/notimplemented.h" #include "base/timer/timer.h" #include "chrome/browser/ui/browser_list.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "ui/base/interaction/element_identifier.h" #include "ui/gfx/geometry/rect.h" +#include "ui/views/controls/webview/webview.h" #include "ui/views/view_class_properties.h" #include "ui/views/widget/widget.h" @@ -44,8 +48,36 @@ bubble_init_start_time_ = base::TimeTicks::Now(); + const content::RenderProcessHost* spare_render_process_host = + content::RenderProcessHost::GetSpareRenderProcessHost(); + bubble_warmup_level_ = WebUIBubbleWarmUpLevel::kNoRenderer; + bubble_view_ = CreateWebUIBubbleDialog(anchor, arrow); + content::RenderProcessHost* render_process_host = bubble_view_->web_view() + ->GetWebContents() + ->GetPrimaryMainFrame() + ->GetProcess(); + const bool bubble_using_spare_render_process = + render_process_host == spare_render_process_host; + + size_t top_chrome_frames = 0; + render_process_host->ForEachRenderFrameHost( + [&top_chrome_frames](content::RenderFrameHost* rfh) { + top_chrome_frames += + base::EndsWith(rfh->GetSiteInstance()->GetSiteURL().host_piece(), + chrome::kChromeUITopChromeDomain); + }); + const bool bubble_reused_render_process = top_chrome_frames > 1; + + if (bubble_using_cached_web_contents_) { + bubble_warmup_level_ = WebUIBubbleWarmUpLevel::kNavigatedWebContents; + } else if (bubble_using_spare_render_process) { + bubble_warmup_level_ = WebUIBubbleWarmUpLevel::kSpareRenderer; + } else if (bubble_reused_render_process) { + bubble_warmup_level_ = WebUIBubbleWarmUpLevel::kDedicatedRenderer; + } + bubble_widget_observation_.Observe(bubble_view_->GetWidget()); // Some bubbles can be triggered when there is no active browser (e.g. emoji // picker in Chrome OS launcher). In that case, the close bubble helper isn't @@ -101,3 +133,21 @@ void WebUIBubbleManager::DisableCloseBubbleHelperForTesting() { disable_close_bubble_helper_ = true; } + +std::string ToString(WebUIBubbleWarmUpLevel warmup_level) { + switch (warmup_level) { + case WebUIBubbleWarmUpLevel::kNoRenderer: + return "NoRenderer"; + case WebUIBubbleWarmUpLevel::kSpareRenderer: + return "SpareRenderer"; + case WebUIBubbleWarmUpLevel::kDedicatedRenderer: + return "DedicatedRenderer"; + case WebUIBubbleWarmUpLevel::kRedirectedWebContents: + return "RedirectedWebContents"; + case WebUIBubbleWarmUpLevel::kNavigatedWebContents: + return "NavigatedWebContents"; + default: + NOTIMPLEMENTED(); + return ""; + } +}
diff --git a/chrome/browser/ui/views/bubble/webui_bubble_manager.h b/chrome/browser/ui/views/bubble/webui_bubble_manager.h index cb1eeda..dbc7e1f 100644 --- a/chrome/browser/ui/views/bubble/webui_bubble_manager.h +++ b/chrome/browser/ui/views/bubble/webui_bubble_manager.h
@@ -7,6 +7,7 @@ #include <memory> #include <optional> +#include <string> #include <utility> #include "base/memory/raw_ptr.h" @@ -18,6 +19,9 @@ #include "chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.h" #include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h" #include "chrome/browser/ui/views/close_bubble_on_tab_activation_helper.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" #include "ui/base/interaction/element_identifier.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/widget/widget.h" @@ -27,6 +31,25 @@ class Profile; class WebUIBubbleDialogView; +// The readiness levels of the browser prior to showing a new WebUI bubble, +// ordered by increasing readiness. Higher levels have lower latency at the cost +// of greater memory use. +enum class WebUIBubbleWarmUpLevel { + // No render process is available. No pre-existing process, including spare + // renderers, can be used or reused for this WebUI. + kNoRenderer, + // Uses a spare render process for this WebUI. + kSpareRenderer, + // Uses a render process that already hosts other WebUIs prior to this WebUI. + kDedicatedRenderer, + // Uses a WebContents that is initially on a different domain and requires + // redirection to this WebUI. + // Note: this is not currently used anywhere, but worth further investigation. + kRedirectedWebContents, + // Uses a WebContents that has already navigated to this WebUI. + kNavigatedWebContents, +}; + // WebUIBubbleManager handles the creation / destruction of the WebUI bubble. // This is needed to deal with the asynchronous presentation of WebUI. class WebUIBubbleManager : public views::WidgetObserver { @@ -45,6 +68,10 @@ bool bubble_using_cached_web_contents() const { return bubble_using_cached_web_contents_; } + WebUIBubbleWarmUpLevel bubble_warmup_level() const { + CHECK(bubble_warmup_level_.has_value()); + return *bubble_warmup_level_; + } // Creates the persistent renderer process if the feature is enabled. virtual void MaybeInitPersistentRenderer() = 0; @@ -87,6 +114,10 @@ // contents. bool bubble_using_cached_web_contents_ = false; + // The readiness of the browser when it is about to show this + // bubble. See WebUIBubbleWarmUpLevel. + std::optional<WebUIBubbleWarmUpLevel> bubble_warmup_level_; + // A timer controlling how long the |cached_web_view_| is cached for. std::unique_ptr<base::RetainingOneShotTimer> cache_timer_; @@ -138,7 +169,8 @@ BubbleContentsWrapperServiceFactory::GetForProfile(profile_, true); if (service && base::FeatureList::IsEnabled( features::kWebUIBubblePerProfilePersistence)) { - set_bubble_using_cached_web_contents(true); + set_bubble_using_cached_web_contents( + !!service->GetBubbleContentsWrapperFromURL(webui_url_)); // If using per-profile WebContents persistence get the associated // BubbleContentsWrapper from the BubbleContentsWrapperService. @@ -195,4 +227,6 @@ const int task_manager_string_id_; }; +std::string ToString(WebUIBubbleWarmUpLevel warmup_level); + #endif // CHROME_BROWSER_UI_VIEWS_BUBBLE_WEBUI_BUBBLE_MANAGER_H_
diff --git a/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc b/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc index 3786635..9bc09e3 100644 --- a/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc +++ b/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc
@@ -12,8 +12,39 @@ #include "chrome/grit/generated_resources.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" #include "ui/webui/mojo_bubble_web_ui_controller.h" +namespace { + +void DestroySpareRenderProcess() { + content::RenderProcessHost* spare_render_process_host = + content::RenderProcessHost::GetSpareRenderProcessHostForTesting(); + if (!spare_render_process_host) { + return; + } + + content::RenderProcessHostWatcher kill_observer( + spare_render_process_host, + content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + spare_render_process_host->FastShutdownIfPossible(0); + kill_observer.Wait(); +} + +// Close the bubble, clear any cached content wrapper, including the ones +// stored in the contents wrapper service. +void DestroyBubble(WebUIBubbleManager* bubble_manager, Profile* profile) { + bubble_manager->CloseBubble(); + bubble_manager->ResetContentsWrapperForTesting(); + if (auto* service = + BubbleContentsWrapperServiceFactory::GetForProfile(profile, true)) { + service->Shutdown(); + } + base::RunLoop().RunUntilIdle(); +} + +} // namespace + class TestWebUIController : public ui::MojoBubbleWebUIController { WEB_UI_CONTROLLER_TYPE_DECL(); }; @@ -53,10 +84,7 @@ // content::BrowserTestBase: void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); - bubble_manager_ = - std::make_unique<WebUIBubbleManagerT<TestWebUIController>>( - BrowserView::GetBrowserViewForBrowser(browser()), - browser()->profile(), GURL("chrome://test"), 1); + bubble_manager_ = MakeBubbleManager(); } void TearDownOnMainThread() override { bubble_manager_.reset(); @@ -65,6 +93,15 @@ WebUIBubbleManager* bubble_manager() { return bubble_manager_.get(); } + // WebContents under the ".top-chrome" pseudo-TLD will reuse the render + // process. + std::unique_ptr<WebUIBubbleManager> MakeBubbleManager( + GURL site_url = GURL("chrome://test.top-chrome")) { + return std::make_unique<WebUIBubbleManagerT<TestWebUIController>>( + BrowserView::GetBrowserViewForBrowser(browser()), browser()->profile(), + site_url, 1); + } + void DestroyBubbleManager() { bubble_manager_.reset(); } private: @@ -115,3 +152,38 @@ DestroyBubbleManager(); EXPECT_FALSE(bubble_view); } + +// Verifies that the warm-up levels are correctly recorded. +IN_PROC_BROWSER_TEST_F(WebUIBubbleManagerBrowserTest, WarmupLevel) { + // Use the spare renderer if there is one. + EXPECT_NE(content::RenderProcessHost::GetSpareRenderProcessHostForTesting(), + nullptr); + bubble_manager()->ShowBubble(); + EXPECT_EQ(bubble_manager()->bubble_warmup_level(), + WebUIBubbleWarmUpLevel::kSpareRenderer); + + // Create a new process if there is no spare renderer. + DestroySpareRenderProcess(); + DestroyBubble(bubble_manager(), browser()->profile()); + bubble_manager()->ShowBubble(); + EXPECT_EQ(bubble_manager()->bubble_warmup_level(), + WebUIBubbleWarmUpLevel::kNoRenderer); + + // Use the process dedicated to top chrome WebUIs if there is one. + DestroyBubble(bubble_manager(), browser()->profile()); + // Use a different domain under .top-chrome so that the WebContents + // is not reused if WebUIBubblePerProfilePersistence is enabled. + std::unique_ptr<WebUIBubbleManager> another_bubble_manager = + MakeBubbleManager(GURL("chrome://test2.top-chrome")); + another_bubble_manager->ShowBubble(); + bubble_manager()->ShowBubble(); + EXPECT_EQ(bubble_manager()->bubble_warmup_level(), + WebUIBubbleWarmUpLevel::kDedicatedRenderer); + + // Use the cached WebContents if there is one. + bubble_manager()->CloseBubble(); + base::RunLoop().RunUntilIdle(); + bubble_manager()->ShowBubble(); + EXPECT_EQ(bubble_manager()->bubble_warmup_level(), + WebUIBubbleWarmUpLevel::kNavigatedWebContents); +}
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc index 76a791d..51e2412 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc
@@ -66,7 +66,8 @@ primary_view_ = AddChildView(std::move(primary_view)); security_view_ = AddChildView(std::make_unique<DownloadBubbleSecurityView>( - /*delegate=*/this, navigation_handler, bubble_delegate)); + /*delegate=*/this, info_->security_view_info(), navigation_handler, + bubble_delegate)); // Starts on the primary page. ShowPrimaryPage(); @@ -97,6 +98,7 @@ CHECK(!id || *id != ContentId()); security_view_->SetVisible(false); security_view_->Reset(); + info_->ResetSecurityView(); // Reset fixed width, which could be previously set by the security // view. bubble_delegate_->set_fixed_width(0); @@ -126,15 +128,7 @@ } void DownloadBubbleContentsView::InitializeSecurityView(const ContentId& id) { - CHECK(id != ContentId()); - if (security_view_->content_id() == id) { - return; - } - if (DownloadUIModel* model = GetDownloadModel(id); model) { - security_view_->InitializeForDownload(*model); - return; - } - NOTREACHED(); + info_->InitializeSecurityView(id); } void DownloadBubbleContentsView::ProcessSecuritySubpageButtonPress( @@ -250,10 +244,7 @@ DownloadUIModel* DownloadBubbleContentsView::GetDownloadModel( const ContentId& id) { - if (DownloadBubbleRowView* row = primary_view_->GetRow(id); row) { - return row->model(); - } - return nullptr; + return info_->GetDownloadModel(id); } BEGIN_METADATA(DownloadBubbleContentsView)
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc b/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc index 3789f13..7c651b1 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc
@@ -272,11 +272,7 @@ ->controller()) .SetupForTest(); #endif // BUILDFLAG(IS_CHROMEOS_LACROS) - return [&]() { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - }; + return [&]() { ui_test_utils::ToggleFullscreenModeAndWait(browser()); }; } #if !BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc index aeb2b4d..1e5851a 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_ui_model.h" #include "chrome/browser/download/offline_item_utils.h" +#include "chrome/browser/ui/download/download_bubble_security_view_info.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/download/bubble/download_bubble_password_prompt_view.h" @@ -73,18 +74,19 @@ // Whether we should page away from the security view and return to the primary // view upon a download update. -bool ShouldReturnToPrimaryDialog(download::DownloadDangerType danger_type, - const DownloadUIModel::BubbleUIInfo& ui_info) { - return danger_type == download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED || +bool ShouldReturnToPrimaryDialog(const DownloadBubbleSecurityViewInfo& info) { + return info.danger_type() == download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED || // The only non-terminal danger types where the security subpage view // shows are `DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING` and // `DOWNLOAD_DANGER_TYPE_ASYNC_LOCAL_PASSWORD_SCANNING`. We should then // return to the row view when the deep scan completes and is in a // state that doesn't have a security subpage. Specifically, that's // both safe and failed deep scans, but not scans that find malware. - danger_type == download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE || - danger_type == download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_FAILED || - !ui_info.HasSubpage(); + info.danger_type() == + download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE || + info.danger_type() == + download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_FAILED || + !info.HasSubpage(); } bool HandleButtonClickWithDefaultClose( @@ -210,7 +212,7 @@ END_METADATA bool DownloadBubbleSecurityView::IsInitialized() const { - return content_id_ != ContentId(); + return info_->content_id().has_value(); } void DownloadBubbleSecurityView::AddHeader() { @@ -272,7 +274,7 @@ void DownloadBubbleSecurityView::BackButtonPressed() { if (IsInitialized()) { delegate_->AddSecuritySubpageWarningActionEvent( - content_id_, DownloadItemWarningData::WarningAction::BACK); + content_id(), DownloadItemWarningData::WarningAction::BACK); did_log_action_ = true; base::UmaHistogramEnumeration( kSubpageActionHistogram, @@ -283,7 +285,7 @@ } void DownloadBubbleSecurityView::UpdateHeader() { - title_->SetText(title_text_); + title_->SetText(info_->title_text()); title_->SizeToFit(GetMinimumTitleWidth()); title_->PreferredSizeChanged(); } @@ -291,7 +293,7 @@ void DownloadBubbleSecurityView::CloseBubble() { if (IsInitialized()) { delegate_->AddSecuritySubpageWarningActionEvent( - content_id_, DownloadItemWarningData::WarningAction::CLOSE); + content_id(), DownloadItemWarningData::WarningAction::CLOSE); did_log_action_ = true; } // CloseDialog will delete the object. Do not access any members below. @@ -303,10 +305,10 @@ void DownloadBubbleSecurityView::UpdateIconAndText() { icon_->SetImage(ui::ImageModel::FromVectorIcon( - *(ui_info_.icon_model_override), ui_info_.secondary_color, + *(info_->icon_model_override()), info_->secondary_color(), GetLayoutConstant(DOWNLOAD_ICON_SIZE))); - paragraphs_->SetText(ui_info_.warning_summary); + paragraphs_->SetText(info_->warning_summary()); // The label defaults to a single line, which would force the dialog wider; // instead give it a width that's the minimum we want it to have. Then the @@ -314,13 +316,13 @@ paragraphs_->SizeToFit(GetMinimumLabelWidth()); // TODO(chlily): Implement deep_scanning_link_ as a learn_more_link_. - if (danger_type_ == download::DownloadDangerType:: - DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING || - danger_type_ == + if (info_->danger_type() == download::DownloadDangerType:: + DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING || + info_->danger_type() == download::DownloadDangerType:: DOWNLOAD_DANGER_TYPE_PROMPT_FOR_LOCAL_PASSWORD_SCANNING) { std::u16string link_text = - danger_type_ == + info_->danger_type() == download::DownloadDangerType:: DOWNLOAD_DANGER_TYPE_PROMPT_FOR_LOCAL_PASSWORD_SCANNING ? l10n_util::GetStringUTF16( @@ -335,7 +337,7 @@ views::StyledLabel::RangeStyleInfo::CreateForLink( base::BindRepeating(&DownloadBubbleSecurityView::Delegate:: ProcessSecuritySubpageButtonPress, - base::Unretained(delegate_), content_id_, + base::Unretained(delegate_), content_id(), DownloadCommands::LEARN_MORE_SCANNING)); deep_scanning_link_->AddStyleRange(link_range, link_style); deep_scanning_link_->SetVisible(true); @@ -345,21 +347,21 @@ deep_scanning_link_->SetVisible(false); } - if (ui_info_.learn_more_link) { - learn_more_link_->SetText(ui_info_.learn_more_link->label_and_link_text); + if (info_->learn_more_link()) { + learn_more_link_->SetText(info_->learn_more_link()->label_and_link_text); size_t link_start_offset = - ui_info_.learn_more_link->linked_range.start_offset; + info_->learn_more_link()->linked_range.start_offset; gfx::Range link_range{ link_start_offset, - link_start_offset + ui_info_.learn_more_link->linked_range.length}; + link_start_offset + info_->learn_more_link()->linked_range.length}; // Unretained is safe because `delegate_` outlives this, which owns // `learn_more_link_`. views::StyledLabel::RangeStyleInfo link_style = views::StyledLabel::RangeStyleInfo::CreateForLink(base::BindRepeating( &DownloadBubbleSecurityView::Delegate:: ProcessSecuritySubpageButtonPress, - base::Unretained(delegate_), content_id_, - ui_info_.learn_more_link->linked_range.command)); + base::Unretained(delegate_), content_id(), + info_->learn_more_link()->linked_range.command)); learn_more_link_->AddStyleRange(link_range, link_style); learn_more_link_->SetVisible(true); learn_more_link_->SizeToFit(GetMinimumLabelWidth()); @@ -370,18 +372,18 @@ } void DownloadBubbleSecurityView::UpdateSecondaryIconAndText() { - secondary_icon_->SetVisible(!ui_info_.warning_secondary_text.empty()); - secondary_styled_label_->SetVisible(!ui_info_.warning_secondary_text.empty()); + secondary_icon_->SetVisible(!info_->warning_secondary_text().empty()); + secondary_styled_label_->SetVisible(!info_->warning_secondary_text().empty()); - if (ui_info_.warning_secondary_text.empty()) { + if (info_->warning_secondary_text().empty()) { return; } secondary_icon_->SetImage(ui::ImageModel::FromVectorIcon( - *ui_info_.warning_secondary_icon, ui::kColorSecondaryForeground, + *info_->warning_secondary_icon(), ui::kColorSecondaryForeground, GetLayoutConstant(DOWNLOAD_ICON_SIZE))); - secondary_styled_label_->SetText(ui_info_.warning_secondary_text); + secondary_styled_label_->SetText(info_->warning_secondary_text()); // The label defaults to a single line, which would force the dialog wider; // instead give it a width that's the minimum we want it to have. Then the // Layout will stretch it back out into any additional space available. @@ -581,7 +583,7 @@ // TODO(crbug/1482901): Remove the special-cased DownloadCommands by creating // a dedicated View for local decryption prompts and deep scanning. if (command == DownloadCommands::DEEP_SCAN) { - if (danger_type_ == + if (info_->danger_type() == download::DownloadDangerType:: DOWNLOAD_DANGER_TYPE_PROMPT_FOR_LOCAL_PASSWORD_SCANNING) { return ProcessLocalPasswordDecryptionClick(); @@ -590,9 +592,10 @@ } } - if (danger_type_ == download::DownloadDangerType:: - DOWNLOAD_DANGER_TYPE_ASYNC_LOCAL_PASSWORD_SCANNING) { - delegate_->ProcessLocalPasswordInProgressClick(content_id_, command); + if (info_->danger_type() == + download::DownloadDangerType:: + DOWNLOAD_DANGER_TYPE_ASYNC_LOCAL_PASSWORD_SCANNING) { + delegate_->ProcessLocalPasswordInProgressClick(content_id(), command); return false; } @@ -605,7 +608,7 @@ // Process the command first, since this may become uninitialized once the // navigation occurs. - delegate_->ProcessSecuritySubpageButtonPress(content_id_, command); + delegate_->ProcessSecuritySubpageButtonPress(content_id(), command); return true; } @@ -614,12 +617,18 @@ return; } delegate_->AddSecuritySubpageWarningActionEvent( - content_id_, DownloadItemWarningData::WarningAction::DISMISS); + content_id(), DownloadItemWarningData::WarningAction::DISMISS); did_log_action_ = true; } +const offline_items_collection::ContentId& +DownloadBubbleSecurityView::content_id() const { + CHECK(info_->content_id().has_value()); + return info_->content_id().value(); +} + void DownloadBubbleSecurityView::UpdateButton( - DownloadUIModel::BubbleUIInfo::SubpageButton button_info, + DownloadBubbleSecurityViewInfo::SubpageButton button_info, bool is_secondary_button) { ui::DialogButton button_type = is_secondary_button ? ui::DIALOG_BUTTON_CANCEL : ui::DIALOG_BUTTON_OK; @@ -632,8 +641,8 @@ bubble_delegate_->SetCancelCallbackWithClose(callback); bubble_delegate_->SetButtonEnabled(button_type, true); views::LabelButton* button = bubble_delegate_->GetCancelButton(); - if (button_info.color) { - button->SetEnabledTextColorIds(*button_info.color); + if (button_info.text_color) { + button->SetEnabledTextColorIds(*button_info.text_color); } } else { bubble_delegate_->SetAcceptCallbackWithClose(callback); @@ -654,15 +663,15 @@ bubble_delegate_->SetButtons(ui::DIALOG_BUTTON_NONE); bubble_delegate_->SetDefaultButton(ui::DIALOG_BUTTON_NONE); - if (ui_info_.subpage_buttons.size() > 0) { + if (info_->has_primary_button()) { bubble_delegate_->SetButtons(ui::DIALOG_BUTTON_OK); - UpdateButton(ui_info_.subpage_buttons[0], /*is_secondary_button=*/false); + UpdateButton(info_->primary_button(), /*is_secondary_button=*/false); } - if (ui_info_.subpage_buttons.size() > 1) { + if (info_->has_secondary_button()) { bubble_delegate_->SetButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL); - UpdateButton(ui_info_.subpage_buttons[1], /*is_secondary_button=*/true); + UpdateButton(info_->secondary_button(), /*is_secondary_button=*/true); } // After we have updated the buttons, set the minimum width to avoid the rest // of the contents stretching out the dialog unnecessarily. @@ -671,10 +680,10 @@ } void DownloadBubbleSecurityView::UpdateProgressBar() { - progress_bar_->SetVisible(ui_info_.has_progress_bar); + progress_bar_->SetVisible(info_->has_progress_bar()); // The progress bar is only supported for deep scanning currently, which // requires a looping progress bar. - if (!ui_info_.has_progress_bar || !ui_info_.is_progress_bar_looping) { + if (!info_->has_progress_bar() || !info_->is_progress_bar_looping()) { return; } @@ -690,15 +699,15 @@ return; } - bool should_show = - danger_type_ == download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING && - delegate_->IsEncryptedArchive(content_id_); + bool should_show = info_->danger_type() == + download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING && + delegate_->IsEncryptedArchive(content_id()); should_show |= - danger_type_ == + info_->danger_type() == download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_LOCAL_PASSWORD_SCANNING; DownloadBubblePasswordPromptView::State state = - delegate_->HasPreviousIncorrectPassword(content_id_) + delegate_->HasPreviousIncorrectPassword(content_id()) ? DownloadBubblePasswordPromptView::State::kInvalid : DownloadBubblePasswordPromptView::State::kValid; @@ -737,80 +746,19 @@ // Download.Bubble.Subpage.DangerousFile.SecondaryButtonActionTime std::string histogram = base::StrCat( {"Download.Bubble.Subpage.", - download::GetDownloadDangerTypeString(danger_type_), ".", + download::GetDownloadDangerTypeString(info_->danger_type()), ".", is_secondary_button ? "Secondary" : "Primary", "ButtonActionTime"}); base::UmaHistogramMediumTimes(histogram, base::Time::Now() - (*warning_time_)); } -void DownloadBubbleSecurityView::InitializeForDownload(DownloadUIModel& model) { - if (model.GetContentId() != content_id_) { - Reset(); - download_item_observation_.Observe(model.GetDownloadItem()); - base::UmaHistogramEnumeration(kSubpageActionHistogram, - DownloadBubbleSubpageAction::kShown); - } - OnDownloadUpdated(model.GetDownloadItem()); -} - void DownloadBubbleSecurityView::Reset() { - content_id_ = ContentId(); - ui_info_ = DownloadUIModel::BubbleUIInfo(); - title_text_ = std::u16string(); - download_item_observation_.Reset(); warning_time_ = std::nullopt; } -void DownloadBubbleSecurityView::OnDownloadUpdated( - download::DownloadItem* download) { - ContentId content_id = OfflineItemUtils::GetContentIdForDownload(download); - bool is_different_download = content_id != content_id_; - bool danger_type_changed = danger_type_ != download->GetDangerType(); - if (is_different_download) { - content_id_ = content_id; - title_text_ = download->GetFileNameToReportUser().LossyDisplayName(); - // Reset this to false because now this represents a different instance of - // the security dialog. This should not be reset anywhere else. We only want - // to consider it a different instance of the dialog (and potentially log a - // new action) when the action is performed by a user, not when the browser - // changes the danger type (when a scan is finished, for instance). - did_log_action_ = false; - } - if (is_different_download || danger_type_changed) { - warning_time_ = base::Time::Now(); - ui_info_ = DownloadItemModel(download).GetBubbleUIInfo(); - danger_type_ = download->GetDangerType(); - // If this represents a "terminal" state of a deep scan, or if the download - // is otherwise no longer dangerous, we return to the primary dialog. Note - // that we want this behavior even if `is_different_download` is true, e.g. - // user clicks on a different download via entry point external to the - // download bubble (e.g. notification on Lacros). - if (ShouldReturnToPrimaryDialog(danger_type_, ui_info_)) { - navigation_handler_->OpenPrimaryDialog(); - // No need to update views here because we're resetting and returning to - // the primary dialog anyway. - return; - } - UpdateViews(); - UpdateAccessibilityTextAndFocus(); - } -} - -void DownloadBubbleSecurityView::OnDownloadRemoved( - download::DownloadItem* download) { - CHECK(content_id_ == OfflineItemUtils::GetContentIdForDownload(download)); - Reset(); -} - -void DownloadBubbleSecurityView::SetUIInfoForTesting( - const DownloadUIModel::BubbleUIInfo& ui_info) { - ui_info_ = ui_info; - UpdateViews(); -} - void DownloadBubbleSecurityView::UpdateViews() { CHECK(IsInitialized()); - CHECK(ui_info_.HasSubpage()); + CHECK(info_->HasSubpage()); // Our multiline labels need to know the width of the bubble in order to size // themselves appropriately (see `GetMinimumLabelWidth`). This means that we @@ -835,7 +783,7 @@ } // Announce that the subpage was opened to inform the user about the changes // in the UI. - GetViewAccessibility().AnnounceText(ui_info_.warning_summary); + GetViewAccessibility().AnnounceText(info_->warning_summary()); // Focus the back button by default to ensure that focus is set when new // content is displayed. @@ -844,12 +792,15 @@ DownloadBubbleSecurityView::DownloadBubbleSecurityView( Delegate* delegate, + const DownloadBubbleSecurityViewInfo& info, base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler, views::BubbleDialogDelegate* bubble_delegate) : delegate_(delegate), + info_(info), navigation_handler_(std::move(navigation_handler)), bubble_delegate_(bubble_delegate) { CHECK(delegate_); + info_->AddObserver(this); SetLayoutManager(std::make_unique<views::FlexLayout>()) ->SetOrientation(views::LayoutOrientation::kVertical); if (features::IsChromeRefresh2023()) { @@ -894,7 +845,7 @@ if (base::FeatureList::IsEnabled( safe_browsing::kDeepScanningEncryptedArchives)) { password = base::UTF16ToUTF8(password_prompt_->GetText()); - if (delegate_->IsEncryptedArchive(content_id_) && password->empty()) { + if (delegate_->IsEncryptedArchive(content_id()) && password->empty()) { password_prompt_->SetState( DownloadBubblePasswordPromptView::State::kInvalidEmpty); bubble_delegate_->SizeToContents(); @@ -902,7 +853,7 @@ } } - delegate_->ProcessDeepScanPress(content_id_, password); + delegate_->ProcessDeepScanPress(content_id(), password); bubble_delegate_->SizeToContents(); return false; } @@ -920,10 +871,39 @@ return false; } - delegate_->ProcessLocalDecryptionPress(content_id_, password); + delegate_->ProcessLocalDecryptionPress(content_id(), password); bubble_delegate_->SizeToContents(); return false; } +void DownloadBubbleSecurityView::OnInfoChanged() { + warning_time_ = base::Time::Now(); + // If this represents a "terminal" state of a deep scan, or if the download + // is otherwise no longer dangerous, we return to the primary dialog. Note + // that we want this behavior even if this is a different download, e.g. + // user clicks on a different download via entry point external to the + // download bubble (e.g. notification on Lacros). + if (ShouldReturnToPrimaryDialog(info_.get())) { + navigation_handler_->OpenPrimaryDialog(); + // No need to update views here because we're resetting and returning to + // the primary dialog anyway. + return; + } + UpdateViews(); + UpdateAccessibilityTextAndFocus(); +} + +void DownloadBubbleSecurityView::OnContentIdChanged() { + Reset(); + // Reset this to false because now this represents a different instance of + // the security dialog. This should not be reset anywhere else. We only want + // to consider it a different instance of the dialog (and potentially log a + // new action) when the action is performed by a user, not when the browser + // changes the danger type (when a scan is finished, for instance). + did_log_action_ = false; + base::UmaHistogramEnumeration(kSubpageActionHistogram, + DownloadBubbleSubpageAction::kShown); +} + BEGIN_METADATA(DownloadBubbleSecurityView) END_METADATA
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h index a9b931a..bf6522e 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h +++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h
@@ -13,6 +13,7 @@ #include "base/types/optional_ref.h" #include "chrome/browser/download/download_item_warning_data.h" #include "chrome/browser/download/download_ui_model.h" +#include "chrome/browser/ui/download/download_bubble_security_view_info.h" #include "components/download/public/common/download_danger_type.h" #include "components/offline_items_collection/core/offline_item.h" #include "ui/base/metadata/metadata_header_macros.h" @@ -30,8 +31,9 @@ class ParagraphsView; class DownloadBubblePasswordPromptView; -class DownloadBubbleSecurityView : public views::View, - public download::DownloadItem::Observer { +class DownloadBubbleSecurityView + : public views::View, + public DownloadBubbleSecurityViewInfoObserver { METADATA_HEADER(DownloadBubbleSecurityView, views::View) public: @@ -78,6 +80,7 @@ DownloadBubbleSecurityView( Delegate* delegate, + const DownloadBubbleSecurityViewInfo& info, base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler, views::BubbleDialogDelegate* bubble_delegate); DownloadBubbleSecurityView(const DownloadBubbleSecurityView&) = delete; @@ -85,14 +88,6 @@ delete; ~DownloadBubbleSecurityView() override; - // Update the security view when a subpage is opened for a particular - // download. Initializes this view, and associates it with `model`'s download. - // If it is already associated with the same download, this will update the - // view if the danger type has changed since the last time it was initialized. - // It is not an error to initialize this with a download when it is already - // initialized, either with the same download or a different download. - void InitializeForDownload(DownloadUIModel& model); - // Returns this to an uninitialized state, where this is not associated with // a particular download. Called when navigating away from the security view. void Reset(); @@ -105,10 +100,6 @@ // announcing accessibility text. Must be initialized when called. void UpdateAccessibilityTextAndFocus(); - // download::DownloadItem::Observer implementation - void OnDownloadUpdated(download::DownloadItem* download) override; - void OnDownloadRemoved(download::DownloadItem* download) override; - // |is_secondary_button| checks if the command/action originated from the // secondary button. Returns whether the dialog should close due to this // command. @@ -119,13 +110,10 @@ // Should be called when the security view is about to be destroyed. void MaybeLogDismiss(); - const offline_items_collection::ContentId& content_id() const { - return content_id_; - } - - void SetUIInfoForTesting(const DownloadUIModel::BubbleUIInfo& ui_info); + const offline_items_collection::ContentId& content_id() const; private: + friend class DownloadBubbleSecurityViewTest; FRIEND_TEST_ALL_PREFIXES(DownloadBubbleSecurityViewTest, VerifyLogWarningActions); @@ -144,7 +132,7 @@ void UpdateSecondaryIconAndText(); // Updates the subpage button. Setting initial state and color for enabled // state, if it is a secondary button. - void UpdateButton(DownloadUIModel::BubbleUIInfo::SubpageButton button, + void UpdateButton(DownloadBubbleSecurityViewInfo::SubpageButton button, bool is_secondary_button); void UpdateButtons(); void UpdateProgressBar(); @@ -169,23 +157,16 @@ // these button presses is handled separately. bool ProcessLocalPasswordDecryptionClick(); + // DownloadBubbleSecurityViewInfoObserver: + void OnInfoChanged() override; + void OnContentIdChanged() override; + // Must outlive this. const raw_ptr<Delegate> delegate_; - // Following 4 fields are cached when the download/model is updated. - - // ContentId of the download this refers to, if initialized. - // TODO: This should be std::optional<offline_items_collection::ContentId>. - offline_items_collection::ContentId content_id_; - // UI info at the last time this was created/updated. - DownloadUIModel::BubbleUIInfo ui_info_; - // The text for the title (i.e. filename) that this view was last - // created/updated with. - std::u16string title_text_; - // Tracks the danger type of the model when it was last created/updated. Used - // to determine whether a given model update has changed the danger type. - download::DownloadDangerType danger_type_ = - download::DOWNLOAD_DANGER_TYPE_MAX; + // A reference to the info used to populate this class. `info_` will + // notify `this` about changes that require updates. + raw_ref<const DownloadBubbleSecurityViewInfo> info_; base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler_ = nullptr; raw_ptr<views::BubbleDialogDelegate, DanglingUntriaged> bubble_delegate_ = @@ -210,12 +191,6 @@ // double-logging. bool did_log_action_ = false; - // Observation of the download item this refers to. Only observes while this - // is associated with a download item. - base::ScopedObservation<download::DownloadItem, - download::DownloadItem::Observer> - download_item_observation_{this}; - base::WeakPtrFactory<DownloadBubbleSecurityView> weak_factory_{this}; };
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc b/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc index d570849..bfc075fc 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc
@@ -14,7 +14,9 @@ #include "chrome/browser/download/download_ui_model.h" #include "chrome/browser/download/offline_item_utils.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/download/download_bubble_contents_view_info.h" #include "chrome/browser/ui/download/download_bubble_info.h" +#include "chrome/browser/ui/download/download_bubble_security_view_info.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/download/bubble/download_bubble_contents_view.h" #include "chrome/browser/ui/views/download/bubble/download_bubble_row_view.h" @@ -42,6 +44,7 @@ using ::testing::Return; using ::testing::ReturnRefOfCopy; +using SubpageButton = DownloadBubbleSecurityViewInfo::SubpageButton; using WarningSurface = DownloadItemWarningData::WarningSurface; using WarningAction = DownloadItemWarningData::WarningAction; using WarningActionEvent = DownloadItemWarningData::WarningActionEvent; @@ -49,8 +52,12 @@ class MockDownloadBubbleNavigationHandler : public DownloadBubbleNavigationHandler { public: + explicit MockDownloadBubbleNavigationHandler( + DownloadBubbleSecurityViewInfo& security_view_info) + : security_view_info_(security_view_info) {} virtual ~MockDownloadBubbleNavigationHandler() = default; void OpenPrimaryDialog() override { + security_view_info_->Reset(); last_opened_page_ = DownloadBubbleContentsView::Page::kPrimary; } void OpenSecurityDialog(const offline_items_collection::ContentId&) override { @@ -76,6 +83,7 @@ } private: + raw_ref<DownloadBubbleSecurityViewInfo> security_view_info_; std::optional<DownloadBubbleContentsView::Page> last_opened_page_ = std::nullopt; bool was_closed_ = false; @@ -173,19 +181,21 @@ params.window = window_.get(); browser_ = std::unique_ptr<Browser>(Browser::Create(params)); + security_view_info_ = std::make_unique<DownloadBubbleSecurityViewInfo>(); anchor_widget_ = CreateTestWidget(views::Widget::InitParams::TYPE_WINDOW); auto bubble_delegate = std::make_unique<views::BubbleDialogDelegate>( anchor_widget_->GetContentsView(), views::BubbleBorder::TOP_RIGHT); bubble_delegate_ = bubble_delegate.get(); - bubble_navigator_ = std::make_unique<MockDownloadBubbleNavigationHandler>(); + bubble_navigator_ = std::make_unique<MockDownloadBubbleNavigationHandler>( + *security_view_info_); views::BubbleDialogDelegate::CreateBubble(std::move(bubble_delegate)); bubble_delegate_->GetWidget()->Show(); bubble_controller_ = std::make_unique<DownloadBubbleUIController>(browser_.get()); security_view_ = bubble_delegate_->SetContentsView( std::make_unique<DownloadBubbleSecurityView>( - security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(), - bubble_delegate_)); + security_view_delegate_.get(), *security_view_info_, + bubble_navigator_->GetWeakPtr(), bubble_delegate_)); DownloadCoreServiceFactory::GetInstance()->SetTestingFactory( browser_->profile(), @@ -247,6 +257,8 @@ DownloadBubbleSecurityViewTest& operator=( const DownloadBubbleSecurityViewTest&) = delete; + void UpdateView() { security_view_->UpdateViews(); } + std::unique_ptr<ChromeDownloadManagerDelegate> delegate_; testing::NiceMock<download::MockDownloadItem> download_item1_; testing::NiceMock<download::MockDownloadItem> download_item2_; @@ -255,10 +267,11 @@ raw_ptr<views::BubbleDialogDelegate, DanglingUntriaged> bubble_delegate_ = nullptr; std::unique_ptr<DownloadBubbleUIController> bubble_controller_; - std::unique_ptr<MockDownloadBubbleNavigationHandler> bubble_navigator_; raw_ptr<DownloadBubbleSecurityView, DanglingUntriaged> security_view_ = nullptr; std::unique_ptr<views::Widget> anchor_widget_; + std::unique_ptr<DownloadBubbleSecurityViewInfo> security_view_info_; + std::unique_ptr<MockDownloadBubbleNavigationHandler> bubble_navigator_; std::unique_ptr<DownloadBubbleRowListViewInfo> info_; std::unique_ptr<DownloadBubbleRowListView> row_list_view_; @@ -275,70 +288,48 @@ TEST_F(DownloadBubbleSecurityViewTest, UpdateSecurityView_WillHaveAppropriateDialogButtons) { // Two buttons, one prominent - security_view_->InitializeForDownload(*row1_model_); - security_view_->SetUIInfoForTesting( - DownloadUIModel::BubbleUIInfo() - .AddSubpageSummary(u"fake summary") - .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity) - .AddPrimaryButton(DownloadCommands::Command::KEEP) - // OK button - .AddPrimarySubpageButton(std::u16string(), - DownloadCommands::Command::DISCARD) - // Cancel button - .AddSecondarySubpageButton(std::u16string(), - DownloadCommands::Command::KEEP, - ui::kColorAlertHighSeverity)); + security_view_info_->InitializeForDownload(*row1_model_); + security_view_info_->SetSubpageButtonsForTesting( + {SubpageButton(DownloadCommands::Command::DISCARD, std::u16string(), + /*is_prominent=*/true), + SubpageButton(DownloadCommands::Command::KEEP, std::u16string(), + /*is_prominent=*/false, ui::kColorAlertHighSeverity)}); + EXPECT_EQ(bubble_delegate_->GetDialogButtons(), ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL); EXPECT_EQ(bubble_delegate_->GetDefaultDialogButton(), ui::DIALOG_BUTTON_OK); // Two buttons, none prominent security_view_->Reset(); - security_view_->InitializeForDownload(*row1_model_); - DownloadUIModel::BubbleUIInfo info = - DownloadUIModel::BubbleUIInfo() - .AddSubpageSummary(u"fake summary") - .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity) - .AddPrimaryButton(DownloadCommands::Command::KEEP) - // OK button - .AddPrimarySubpageButton(std::u16string(), - DownloadCommands::Command::DISCARD) - // Cancel button - .AddSecondarySubpageButton(std::u16string(), - DownloadCommands::Command::KEEP, - ui::kColorAlertHighSeverity); - info.subpage_buttons[0].is_prominent = false; // Primary buttons are - // prominent by default. - security_view_->SetUIInfoForTesting(std::move(info)); + security_view_info_->InitializeForDownload(*row1_model_); + security_view_info_->SetSubpageButtonsForTesting( + {SubpageButton(DownloadCommands::Command::DISCARD, std::u16string(), + /*is_prominent=*/false), + SubpageButton(DownloadCommands::Command::KEEP, std::u16string(), + /*is_prominent=*/false, ui::kColorAlertHighSeverity)}); + UpdateView(); + EXPECT_EQ(bubble_delegate_->GetDialogButtons(), ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL); EXPECT_EQ(bubble_delegate_->GetDefaultDialogButton(), ui::DIALOG_BUTTON_NONE); // One button, none prominent security_view_->Reset(); - security_view_->InitializeForDownload(*row1_model_); - info = DownloadUIModel::BubbleUIInfo() - .AddSubpageSummary(u"fake summary") - .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity) - .AddPrimaryButton(DownloadCommands::Command::KEEP) - // OK button - .AddPrimarySubpageButton(std::u16string(), - DownloadCommands::Command::DISCARD); - info.subpage_buttons[0].is_prominent = false; // Primary buttons are - // prominent by default. - security_view_->SetUIInfoForTesting(std::move(info)); + security_view_info_->InitializeForDownload(*row1_model_); + security_view_info_->SetSubpageButtonsForTesting( + {SubpageButton(DownloadCommands::Command::DISCARD, std::u16string(), + /*is_prominent=*/false)}); + UpdateView(); + EXPECT_EQ(bubble_delegate_->GetDialogButtons(), ui::DIALOG_BUTTON_OK); EXPECT_EQ(bubble_delegate_->GetDefaultDialogButton(), ui::DIALOG_BUTTON_NONE); // No buttons, none prominent security_view_->Reset(); - security_view_->InitializeForDownload(*row1_model_); - security_view_->SetUIInfoForTesting( - DownloadUIModel::BubbleUIInfo() - .AddSubpageSummary(u"fake summary") + security_view_info_->InitializeForDownload(*row1_model_); + security_view_info_->SetSubpageButtonsForTesting({}); + UpdateView(); - .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity) - .AddPrimaryButton(DownloadCommands::Command::KEEP)); EXPECT_EQ(bubble_delegate_->GetDialogButtons(), ui::DIALOG_BUTTON_NONE); EXPECT_EQ(bubble_delegate_->GetDefaultDialogButton(), ui::DIALOG_BUTTON_NONE); } @@ -351,10 +342,15 @@ // Back action logged. { + auto security_view_info = + std::make_unique<DownloadBubbleSecurityViewInfo>(); + auto bubble_navigator = + std::make_unique<MockDownloadBubbleNavigationHandler>( + *security_view_info); auto security_view = std::make_unique<DownloadBubbleSecurityView>( - security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(), - bubble_delegate_); - security_view->InitializeForDownload(*row1_model_); + security_view_delegate_.get(), *security_view_info, + bubble_navigator->GetWeakPtr(), bubble_delegate_); + security_view_info->InitializeForDownload(*row1_model_); security_view->BackButtonPressed(); ++item1_actions_expected; @@ -369,14 +365,19 @@ // Close action logged { + auto security_view_info = + std::make_unique<DownloadBubbleSecurityViewInfo>(); + auto bubble_navigator = + std::make_unique<MockDownloadBubbleNavigationHandler>( + *security_view_info); auto security_view = std::make_unique<DownloadBubbleSecurityView>( - security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(), - bubble_delegate_); - security_view->InitializeForDownload(*row1_model_); + security_view_delegate_.get(), *security_view_info, + bubble_navigator->GetWeakPtr(), bubble_delegate_); + security_view_info->InitializeForDownload(*row1_model_); security_view->CloseBubble(); ++item1_actions_expected; - EXPECT_TRUE(bubble_navigator_->was_closed()); + EXPECT_TRUE(bubble_navigator->was_closed()); security_view.reset(); std::vector<WarningActionEvent> events = @@ -387,10 +388,15 @@ // Dismiss action logged { + auto security_view_info = + std::make_unique<DownloadBubbleSecurityViewInfo>(); + auto bubble_navigator = + std::make_unique<MockDownloadBubbleNavigationHandler>( + *security_view_info); auto security_view = std::make_unique<DownloadBubbleSecurityView>( - security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(), - bubble_delegate_); - security_view->InitializeForDownload(*row1_model_); + security_view_delegate_.get(), *security_view_info, + bubble_navigator->GetWeakPtr(), bubble_delegate_); + security_view_info->InitializeForDownload(*row1_model_); security_view->MaybeLogDismiss(); ++item1_actions_expected; @@ -403,10 +409,15 @@ // Dismiss action logged after update { + auto security_view_info = + std::make_unique<DownloadBubbleSecurityViewInfo>(); + auto bubble_navigator = + std::make_unique<MockDownloadBubbleNavigationHandler>( + *security_view_info); auto security_view = std::make_unique<DownloadBubbleSecurityView>( - security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(), - bubble_delegate_); - security_view->InitializeForDownload(*row1_model_); + security_view_delegate_.get(), *security_view_info, + bubble_navigator->GetWeakPtr(), bubble_delegate_); + security_view_info->InitializeForDownload(*row1_model_); security_view->BackButtonPressed(); ++item1_actions_expected; @@ -417,7 +428,7 @@ EXPECT_EQ(events.back().action, WarningAction::BACK); // The security view can be re-opened after back button is pressed. - security_view->InitializeForDownload(*row1_model_); + security_view_info->InitializeForDownload(*row1_model_); security_view->MaybeLogDismiss(); ++item1_actions_expected; @@ -429,10 +440,15 @@ // Dismiss action not logged after update to a different download. { + auto security_view_info = + std::make_unique<DownloadBubbleSecurityViewInfo>(); + auto bubble_navigator = + std::make_unique<MockDownloadBubbleNavigationHandler>( + *security_view_info); auto security_view = std::make_unique<DownloadBubbleSecurityView>( - security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(), - bubble_delegate_); - security_view->InitializeForDownload(*row1_model_); + security_view_delegate_.get(), *security_view_info, + bubble_navigator->GetWeakPtr(), bubble_delegate_); + security_view_info->InitializeForDownload(*row1_model_); security_view->BackButtonPressed(); ++item1_actions_expected; @@ -447,7 +463,7 @@ DownloadItemWarningData::AddWarningActionEvent( &download_item2_, WarningSurface::BUBBLE_MAINPAGE, WarningAction::SHOWN); - security_view->InitializeForDownload(*row2_model_); + security_view_info->InitializeForDownload(*row2_model_); // Since the reset occurs while we are showing download2, we don't log // DISMISS for the first download. @@ -465,10 +481,15 @@ // Dismiss action not logged when download is removed. { + auto security_view_info = + std::make_unique<DownloadBubbleSecurityViewInfo>(); + auto bubble_navigator = + std::make_unique<MockDownloadBubbleNavigationHandler>( + *security_view_info); auto security_view = std::make_unique<DownloadBubbleSecurityView>( - security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(), - bubble_delegate_); - security_view->InitializeForDownload(*row1_model_); + security_view_delegate_.get(), *security_view_info, + bubble_navigator->GetWeakPtr(), bubble_delegate_); + security_view_info->InitializeForDownload(*row1_model_); // No action is logged upon removal of download. download_item1_.Remove(); @@ -487,75 +508,70 @@ // This test simulates the deep scanning flow. The prompt for scanning is // wider than the scan in progress view. The bubble should be able to scale up // and down in these transitions. - security_view_->InitializeForDownload(*row1_model_); - security_view_->SetUIInfoForTesting( - DownloadUIModel::BubbleUIInfo() - .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity) - .AddPrimarySubpageButton(std::u16string(), - DownloadCommands::Command::DISCARD) - .AddSubpageSummary(std::u16string(u"Subpage warning"))); + security_view_info_->InitializeForDownload(*row1_model_); + security_view_info_->SetSubpageButtonsForTesting( + {SubpageButton(DownloadCommands::Command::DISCARD, std::u16string(), + /*is_prominent=*/true)}); + UpdateView(); + int short_width = bubble_delegate_->GetDialogClientView()->GetMinimumSize().width(); security_view_->Reset(); - security_view_->InitializeForDownload(*row1_model_); - security_view_->SetUIInfoForTesting( - DownloadUIModel::BubbleUIInfo() - .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity) - .AddPrimarySubpageButton( - std::u16string(u"really really really really really really long " - u"button text"), - DownloadCommands::Command::DISCARD) - .AddSubpageSummary(std::u16string(u"Subpage warning"))); + security_view_info_->InitializeForDownload(*row1_model_); + security_view_info_->SetSubpageButtonsForTesting({SubpageButton( + DownloadCommands::Command::DISCARD, + std::u16string(u"really really really really really really long " + u"button text"), + /*is_prominent=*/true)}); + UpdateView(); int medium_width = bubble_delegate_->GetDialogClientView()->GetMinimumSize().width(); ASSERT_LT(short_width, medium_width); security_view_->Reset(); - security_view_->InitializeForDownload(*row1_model_); - security_view_->SetUIInfoForTesting( - DownloadUIModel::BubbleUIInfo() - .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity) - .AddPrimarySubpageButton(std::u16string(), - DownloadCommands::Command::DISCARD) - .AddSubpageSummary(std::u16string(u"Subpage warning"))); + security_view_info_->InitializeForDownload(*row1_model_); + security_view_info_->SetSubpageButtonsForTesting( + {SubpageButton(DownloadCommands::Command::DISCARD, std::u16string(), + /*is_prominent=*/true)}); + UpdateView(); EXPECT_EQ(short_width, bubble_delegate_->GetDialogClientView()->GetMinimumSize().width()); } TEST_F(DownloadBubbleSecurityViewTest, ProcessButtonClick) { - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); EXPECT_TRUE( security_view_->ProcessButtonClick(DownloadCommands::Command::DISCARD, /*is_secondary_button=*/false)); - EXPECT_FALSE( - security_view_->ProcessButtonClick(DownloadCommands::Command::DEEP_SCAN, - /*is_secondary_button=*/false)); + EXPECT_FALSE( + security_view_->ProcessButtonClick(DownloadCommands::Command::DEEP_SCAN, + /*is_secondary_button=*/false)); } TEST_F(DownloadBubbleSecurityViewTest, InitializeAndReset) { - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); // Reset and initialize with the other download. security_view_->Reset(); - security_view_->InitializeForDownload(*row2_model_); + security_view_info_->InitializeForDownload(*row2_model_); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item2_)); // Initialize directly to a different download without resetting. - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); // Initialize to the same download without resetting. - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); @@ -565,19 +581,18 @@ ON_CALL(download_item2_, GetDangerType()) .WillByDefault( Return(download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_FAILED)); - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); // Initialize to a different download without resetting. - security_view_->InitializeForDownload(*row2_model_); - EXPECT_TRUE(security_view_->IsInitialized()); - EXPECT_EQ(security_view_->content_id(), - OfflineItemUtils::GetContentIdForDownload(&download_item2_)); + security_view_info_->InitializeForDownload(*row2_model_); // Because the new item's danger type is a terminal state of a deep scan, - // we should return to the primary dialog. + // we should return to the primary dialog and reset the security view. + EXPECT_FALSE(security_view_->IsInitialized()); + EXPECT_FALSE(security_view_info_->content_id().has_value()); EXPECT_EQ(*bubble_navigator_->last_opened_page(), DownloadBubbleContentsView::Page::kPrimary); } @@ -585,8 +600,8 @@ // Test that an update with an insecure download status does not cause us to // return to the primary dialog. TEST_F(DownloadBubbleSecurityViewTest, InsecureDontReturnToPrimaryDialog) { - ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage()); - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); + ASSERT_TRUE(security_view_info_->HasSubpage()); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); @@ -602,7 +617,7 @@ .WillRepeatedly(ReturnRefOfCopy(GURL("http://insecure.com/a.exe"))); download_item1_.NotifyObserversDownloadUpdated(); - ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage()); + ASSERT_TRUE(security_view_info_->HasSubpage()); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); @@ -614,8 +629,8 @@ // Test that an update where the new state does not have a subpage causes us to // return to the primary dialog. TEST_F(DownloadBubbleSecurityViewTest, ReturnToPrimaryDialogNoSubpage) { - ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage()); - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); + ASSERT_TRUE(security_view_info_->HasSubpage()); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); @@ -626,10 +641,9 @@ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); download_item1_.NotifyObserversDownloadUpdated(); - ASSERT_FALSE(row1_model_->GetBubbleUIInfo().HasSubpage()); - EXPECT_TRUE(security_view_->IsInitialized()); - EXPECT_EQ(security_view_->content_id(), - OfflineItemUtils::GetContentIdForDownload(&download_item1_)); + ASSERT_FALSE(security_view_info_->HasSubpage()); + EXPECT_FALSE(security_view_->IsInitialized()); + EXPECT_FALSE(security_view_info_->content_id().has_value()); EXPECT_EQ(DownloadBubbleContentsView::Page::kPrimary, *bubble_navigator_->last_opened_page()); } @@ -637,8 +651,8 @@ // Test validating a dangerous download, such that it goes from having // a UI info subpage to not having one. See crbug.com/1478390. TEST_F(DownloadBubbleSecurityViewTest, ValidateDangerousDownload) { - ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage()); - security_view_->InitializeForDownload(*row1_model_); + security_view_info_->InitializeForDownload(*row1_model_); + ASSERT_TRUE(security_view_info_->HasSubpage()); EXPECT_TRUE(security_view_->IsInitialized()); EXPECT_EQ(security_view_->content_id(), OfflineItemUtils::GetContentIdForDownload(&download_item1_)); @@ -649,10 +663,9 @@ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_USER_VALIDATED)); download_item1_.NotifyObserversDownloadUpdated(); - ASSERT_FALSE(row1_model_->GetBubbleUIInfo().HasSubpage()); - EXPECT_TRUE(security_view_->IsInitialized()); - EXPECT_EQ(security_view_->content_id(), - OfflineItemUtils::GetContentIdForDownload(&download_item1_)); + ASSERT_FALSE(security_view_info_->HasSubpage()); + EXPECT_FALSE(security_view_->IsInitialized()); + EXPECT_FALSE(security_view_info_->content_id().has_value()); EXPECT_EQ(DownloadBubbleContentsView::Page::kPrimary, *bubble_navigator_->last_opened_page()); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc index da17868..74d4a90 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/web_applications/test/prevent_close_test_base.h" #include "chrome/browser/web_applications/web_app_id_constants.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/ui/base/window_properties.h" #include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h" @@ -512,7 +513,7 @@ // The frame should be painted again when fullscreen is exited and the caption // buttons should be visible. - ToggleFullscreenModeAndWait(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(browser_view->IsFullscreen()); EXPECT_TRUE(test_api.GetShouldPaint()); @@ -536,7 +537,7 @@ // The frame should be painted again when fullscreen is exited and the caption // buttons should be visible. - ToggleFullscreenModeAndWait(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(browser_view->IsFullscreen()); // Caption button container visible again. @@ -1192,7 +1193,7 @@ EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); // The kTopViewInset should be 0 when in immersive mode. - ToggleFullscreenModeAndWait(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(immersive_mode_controller->IsEnabled()); EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); @@ -1206,7 +1207,7 @@ // End the reveal and exit immersive mode. // The kTopViewInset should be 0 when immersive mode is exited. revealed_lock.reset(); - ToggleFullscreenModeAndWait(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(immersive_mode_controller->IsEnabled()); EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); } @@ -1419,7 +1420,7 @@ EXPECT_LT(0, window->GetProperty(aura::client::kTopViewInset)); // The kTopViewInset should be 0 when in immersive mode. - ToggleFullscreenModeAndWait(browser); + ui_test_utils::ToggleFullscreenModeAndWait(browser); EXPECT_TRUE(immersive_mode_controller->IsEnabled()); EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); @@ -1434,7 +1435,7 @@ // The kTopViewInset should be larger than 0 again when immersive mode is // exited. revealed_lock.reset(); - ToggleFullscreenModeAndWait(browser); + ui_test_utils::ToggleFullscreenModeAndWait(browser); EXPECT_FALSE(immersive_mode_controller->IsEnabled()); EXPECT_LT(0, window->GetProperty(aura::client::kTopViewInset)); @@ -1455,7 +1456,7 @@ ASSERT_FALSE(browser_view->IsFullscreen()); // Enter immersive mode. - ToggleFullscreenModeAndWait(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(immersive_mode_controller->IsEnabled()); ASSERT_TRUE(browser_view->IsFullscreen()); @@ -1481,7 +1482,7 @@ ash::ShellTestApi().SetTabletModeEnabledForTest(true)); // Enter immersive mode. - ToggleFullscreenModeAndWait(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); // Should be able to enter immersive mode even when the tablet mode is // enabled. ASSERT_TRUE(immersive_mode_controller->IsEnabled());
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc index 98b4d3b..fdeaaf6 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc
@@ -7,9 +7,9 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" @@ -22,17 +22,10 @@ #include "ash/wm/overview/overview_controller.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) -// Toggles fullscreen mode and waits for the notification. -void ToggleFullscreenModeAndWait(Browser* browser) { - FullscreenNotificationObserver waiter(browser); - chrome::ToggleFullscreenMode(browser); - waiter.Wait(); -} - // Enters fullscreen mode for tab and waits for the notification. void EnterFullscreenModeForTabAndWait(Browser* browser, content::WebContents* web_contents) { - FullscreenNotificationObserver waiter(browser); + ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = true}); static_cast<content::WebContentsDelegate*>(browser) ->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame(), {}); waiter.Wait(); @@ -41,7 +34,7 @@ // Exits fullscreen mode for tab and waits for the notification. void ExitFullscreenModeForTabAndWait(Browser* browser, content::WebContents* web_contents) { - FullscreenNotificationObserver waiter(browser); + ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = false}); browser->exclusive_access_manager() ->fullscreen_controller() ->ExitFullscreenModeForTab(web_contents);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h index 12d501f..58b83ce 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h
@@ -15,9 +15,6 @@ class WebContents; } -// Toggles fullscreen mode and waits for the notification. -void ToggleFullscreenModeAndWait(Browser* browser); - // Enters fullscreen mode for tab and waits for the notification. void EnterFullscreenModeForTabAndWait(Browser* browser, content::WebContents* web_contents);
diff --git a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc index 33e5b0f..9e6a1a9 100644 --- a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc
@@ -8,7 +8,6 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/tab_modal_confirm_dialog.h" #include "chrome/browser/ui/ui_features.h" @@ -78,10 +77,8 @@ // Focus starts in the location bar or one of its children. EXPECT_TRUE(location_bar_view->Contains(focus_manager->GetFocusedView())); - FullscreenNotificationObserver fullscreen_observer(browser()); // Enter into fullscreen mode. - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_view->IsFullscreen()); // Focus is released from the location bar. @@ -97,12 +94,8 @@ EXPECT_FALSE(browser_view->IsFullscreen()); EXPECT_TRUE(browser_view->GetTabStripVisible()); - { - FullscreenNotificationObserver fullscreen_observer(browser()); - // Enter into fullscreen mode. - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); - } + // Enter into fullscreen mode. + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_view->IsFullscreen()); bool top_view_in_browser_fullscreen = false; @@ -112,23 +105,15 @@ // The 'Always Show Bookmarks Bar' should be enabled. EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR)); - { - FullscreenNotificationObserver fullscreen_observer(browser()); - // Return back to normal mode and toggle to not show the top view in full - // screen mode. - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); - } + // Return back to normal mode and toggle to not show the top view in full + // screen mode. + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(browser_view->IsFullscreen()); // Disable 'Always Show Toolbar in Full Screen'. chrome::SetAlwaysShowToolbarInFullscreenForTesting(browser(), false); - { - FullscreenNotificationObserver fullscreen_observer(browser()); - // While back to fullscreen mode, the top view no longer shows up. - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); - } + // While back to fullscreen mode, the top view no longer shows up. + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_view->IsFullscreen()); EXPECT_FALSE(browser_view->GetTabStripVisible()); // In non-immersive mode, the bookmark visibility cannot be changed because @@ -194,18 +179,13 @@ EXPECT_EQ(top_view_in_browser_fullscreen, chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR)); -// Adding `FullscreenNotificationObserver` will make the TESTs on Lacros fail -// determinately, which should have been a no-op. -// TODO(crbug.com/1351971): Repair this defect. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) - { - FullscreenNotificationObserver fullscreen_observer(browser()); - // Return to regular mode. - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); - } -#else // Return to regular mode. +#if !BUILDFLAG(IS_CHROMEOS_LACROS) + ui_test_utils::ToggleFullscreenModeAndWait(browser()); +#else + // Adding `FullscreenWaiter` will make the TESTs on Lacros fail + // determinately, which should have been a no-op. + // TODO(crbug.com/1351971): Repair this defect. chrome::ToggleFullscreenMode(browser()); #endif // !BUILDFLAG(IS_CHROMEOS_LACROS) EXPECT_FALSE(browser_view->IsFullscreen()); @@ -266,12 +246,8 @@ EXPECT_FALSE(browser_view->IsFullscreen()); EXPECT_TRUE(browser_view->IsBookmarkBarVisible()); - { - FullscreenNotificationObserver fullscreen_observer(browser()); - // Enter into fullscreen mode. - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); - } + // Enter into fullscreen mode. + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_view->IsFullscreen()); // Move to the center of the window so that the toolbar becomes hidden in @@ -299,18 +275,13 @@ EXPECT_FALSE(browser_view->IsBookmarkBarVisible()); #endif -// Adding `FullscreenNotificationObserver` will make the TESTs on Lacros fail -// determinately, which should have been a no-op. -// TODO(crbug.com/1351971): Repair this defect. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) - { - FullscreenNotificationObserver fullscreen_observer(browser()); - // Exit from fullscreen mode. - chrome::ToggleFullscreenMode(browser()); - fullscreen_observer.Wait(); - } -#else // Exit from fullscreen mode. +#if !BUILDFLAG(IS_CHROMEOS_LACROS) + ui_test_utils::ToggleFullscreenModeAndWait(browser()); +#else + // Adding `FullscreenWaiter` will make the TESTs on Lacros fail + // determinately, which should have been a no-op. + // TODO(crbug.com/1351971): Repair this defect. chrome::ToggleFullscreenMode(browser()); #endif // !BUILDFLAG(IS_CHROMEOS_LACROS) EXPECT_FALSE(browser_view->IsFullscreen());
diff --git a/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc b/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc index bb57618..2313d2a 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/chromeos/window_pin_util.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -18,6 +17,7 @@ #include "chrome/browser/ui/views/frame/tab_strip_region_view.h" #include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_test_api.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" @@ -89,7 +89,7 @@ // Enter both browser fullscreen and tab fullscreen. Entering browser // fullscreen should enable immersive fullscreen. - ToggleFullscreenModeAndWait(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EnterFullscreenModeForTabAndWait(browser(), web_contents); EXPECT_TRUE(immersive_mode_controller->IsEnabled()); // Caption button container is hidden. @@ -142,7 +142,8 @@ // Exiting immersive fullscreen should make the caption buttons and the frame // visible again. { - FullscreenNotificationObserver waiter(browser()); + ui_test_utils::FullscreenWaiter waiter( + browser(), ui_test_utils::FullscreenWaiter::kNoFullscreen); browser_view->ExitFullscreen(); waiter.Wait(); }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc index 441f2d0d..89b495c0 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/profiles/profile_io_data.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" @@ -94,16 +93,6 @@ return view->ConvertRectToWidget(view->GetLocalBounds()); } - // Toggle the browser's fullscreen state. - void ToggleFullscreen() { - // The fullscreen change notification is sent asynchronously. The - // notification is used to trigger changes in whether the shelf is auto - // hidden. - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } - // Attempt revealing the top-of-window views. void AttemptReveal() { if (!revealed_lock_.get()) { @@ -162,7 +151,7 @@ // The window header should be above the web contents. int header_height = GetBoundsInWidget(contents_web_view).y(); - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen()); EXPECT_TRUE(controller()->IsEnabled()); EXPECT_FALSE(controller()->IsRevealed()); @@ -193,7 +182,7 @@ // Exit immersive fullscreen. The web contents should be back below the window // header. - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(browser_view()->GetWidget()->IsFullscreen()); EXPECT_FALSE(controller()->IsEnabled()); EXPECT_FALSE(tabstrip->GetVisible()); @@ -230,7 +219,7 @@ // Verify that immersive mode remains if fullscreen is toggled while in tablet // mode. - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(controller()->IsEnabled()); ASSERT_NO_FATAL_FAILURE( ash::ShellTestApi().SetTabletModeEnabledForTest(false)); @@ -245,7 +234,7 @@ // Verify that if the browser is not fullscreened, upon exiting tablet mode, // immersive mode is not enabled, and the associated window's top inset is // greater than 0 (the top of the window is visible). - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(controller()->IsEnabled()); ASSERT_NO_FATAL_FAILURE( ash::ShellTestApi().SetTabletModeEnabledForTest(false));
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_unittest.cc index ed95786b..e4f22e8 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_unittest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_unittest.cc
@@ -10,7 +10,6 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/chromeos/window_pin_util.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" @@ -22,6 +21,7 @@ #include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_test_api.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" @@ -61,28 +61,19 @@ return view->ConvertRectToWidget(view->GetLocalBounds()); } - // Toggle the browser's fullscreen state. - void ToggleFullscreen() { - // The fullscreen change notification is sent asynchronously. The - // notification is used to trigger changes in whether the shelf is auto - // hidden and whether a "light bar" version of the tab strip is used when - // the top-of-window views are hidden. - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } - // Set whether the browser is in tab fullscreen. void SetTabFullscreen(bool tab_fullscreen) { content::WebContents* web_contents = browser_view()->contents_web_view()->GetWebContents(); - FullscreenNotificationObserver waiter(browser()); auto* delegate = static_cast<content::WebContentsDelegate*>(browser()); - if (tab_fullscreen) + ui_test_utils::FullscreenWaiter waiter(browser(), + {.tab_fullscreen = tab_fullscreen}); + if (tab_fullscreen) { delegate->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame(), {}); - else + } else { delegate->ExitFullscreenModeForTab(web_contents); + } waiter.Wait(); } @@ -125,7 +116,7 @@ EXPECT_EQ( 0, browser_view()->contents_web_view()->holder()->GetHitTestTopInset()); - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen()); EXPECT_TRUE(controller()->IsEnabled()); EXPECT_FALSE(controller()->IsRevealed()); @@ -188,7 +179,7 @@ // Exiting both immersive and tab fullscreen should show the tab strip and // toolbar. - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_EQ( 0, browser_view()->contents_web_view()->holder()->GetHitTestTopInset()); EXPECT_FALSE(browser_view()->GetWidget()->IsFullscreen()); @@ -203,7 +194,7 @@ TEST_F(ImmersiveModeControllerChromeosTest, FullscreenToLockedTransition) { AddTab(browser(), GURL("about:blank")); // Start in fullscreen. - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); // ImmersiveController is enabled in fullscreen. EXPECT_TRUE(controller()->IsEnabled()); @@ -222,7 +213,7 @@ EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION)); - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(controller()->IsEnabled()); EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL)); EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); @@ -232,7 +223,7 @@ // Test that restoring a window properly exits immersive fullscreen. TEST_F(ImmersiveModeControllerChromeosTest, ExitUponRestore) { ASSERT_FALSE(controller()->IsEnabled()); - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); AttemptReveal(); ASSERT_TRUE(controller()->IsEnabled()); ASSERT_TRUE(controller()->IsRevealed()); @@ -255,12 +246,12 @@ EXPECT_FALSE(controller()->IsEnabled()); EXPECT_TRUE(tabstrip->CanPaintThrobberToLayer()); - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen()); EXPECT_TRUE(controller()->IsEnabled()); EXPECT_FALSE(tabstrip->CanPaintThrobberToLayer()); - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(tabstrip->CanPaintThrobberToLayer()); } @@ -288,7 +279,7 @@ ASSERT_TRUE(webui_tab_strip); EXPECT_FALSE(webui_tab_strip->GetVisible()); - ToggleFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(webui_tab_strip->GetVisible()); AttemptReveal();
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm b/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm index fec60ac1..e384ca2c 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm
@@ -13,13 +13,13 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/find_bar/find_bar_host_unittest_util.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" #import "ui/views/cocoa/native_widget_mac_ns_window_host.h" @@ -65,15 +65,6 @@ return browser()->window()->GetNativeWindow().GetNativeNSWindow(); } - void ToggleBrowserWindowFullscreen() { - // The fullscreen change notification is sent asynchronously. The - // notification is used to trigger changes in whether the shelf is auto - // hidden. - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } - // Creates a new widget as a child of the first browser window and brings it // onscreen. void CreateAndShowWidgetOnFirstBrowserWindow() { @@ -161,7 +152,7 @@ NSWindow* overlay_widget_window = [overlay_widget_content_view window]; EXPECT_EQ(GetMovedContentViewForWidget(overlay_widget), nullptr); - ToggleBrowserWindowFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); FullscreenController* fullscreen_controller = browser()->exclusive_access_manager()->fullscreen_controller(); @@ -176,7 +167,7 @@ EXPECT_NE([overlay_widget_window contentView], overlay_widget_content_view); } - ToggleBrowserWindowFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); EXPECT_EQ(GetMovedContentViewForWidget(overlay_widget), nullptr); @@ -265,7 +256,7 @@ CreateSecondBrowserWindow(); // Move the original browser window into its own fullscreen space. - ToggleBrowserWindowFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); // Add a widget to the original browser window. CreateAndShowWidgetOnFirstBrowserWindow(); @@ -380,7 +371,7 @@ chrome::DisableFindBarAnimationsDuringTesting(true); // Enter browser fullscreen. - ToggleBrowserWindowFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); // Open the find bar views::NamedWidgetShownWaiter shown_waiter(
diff --git a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc index 7b23ca49..3e4c80d 100644 --- a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc
@@ -14,7 +14,6 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/views/exclusive_access_bubble_views.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.h" @@ -120,11 +119,11 @@ bool IsPopupCreated() { return GetFullscreenControlHost()->IsPopupCreated(); } void EnterActiveTabFullscreen() { - FullscreenNotificationObserver fullscreen_observer(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); auto* delegate = static_cast<content::WebContentsDelegate*>(browser()); delegate->EnterFullscreenModeForTab( GetActiveWebContents()->GetPrimaryMainFrame(), {}); - fullscreen_observer.Wait(); + waiter.Wait(); ASSERT_TRUE(delegate->IsFullscreenForTabOrPending(GetActiveWebContents())); }
diff --git a/chrome/browser/ui/views/fullscreen_mac_browsertest.cc b/chrome/browser/ui/views/fullscreen_mac_browsertest.cc index 834eb39..4e424d1 100644 --- a/chrome/browser/ui/views/fullscreen_mac_browsertest.cc +++ b/chrome/browser/ui/views/fullscreen_mac_browsertest.cc
@@ -7,11 +7,11 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "ui/base/test/scoped_fake_nswindow_fullscreen.h" @@ -21,14 +21,6 @@ feature_list_.InitAndEnableFeature(features::kImmersiveFullscreen); } - void ToggleBrowserFullscreen() { - { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } - } - base::test::ScopedFeatureList feature_list_; }; @@ -36,7 +28,7 @@ // browser enters fullscreen. IN_PROC_BROWSER_TEST_F(FullscreenMacTest, ToolbarWidgetFullscreen) { ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen; - ToggleBrowserFullscreen(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_TRUE(BrowserView::GetBrowserViewForBrowser(browser()) ->top_container()
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc index ccfa42d9..5159291 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -8,7 +8,6 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/test/test_browser_dialog.h" @@ -16,6 +15,7 @@ #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "components/zoom/zoom_controller.h" #include "content/public/test/browser_test.h" #include "extensions/browser/extension_zoom_request_client.h" @@ -70,7 +70,7 @@ { // The fullscreen change notification is sent asynchronously. Wait for the // notification before testing the zoom bubble visibility. - FullscreenNotificationObserver waiter(browser()); + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); static_cast<content::WebContentsDelegate*>(browser()) ->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame(), {}); waiter.Wait(); @@ -89,11 +89,7 @@ EXPECT_FALSE(zoom_bubble->GetAnchorView()); // Exit fullscreen before ending the test for the sake of sanity. - { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); } // Immersive fullscreen is either/or on Mac. Base class for tests that only @@ -141,13 +137,7 @@ const views::View* org_anchor_view = zoom_bubble->GetAnchorView(); // Enter into a browser fullscreen mode. This would close the zoom bubble. - { - // The fullscreen change notification is sent asynchronously. Wait for the - // notification before testing the zoom bubble visibility. - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); EXPECT_FALSE(ZoomBubbleView::GetZoomBubble()); #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH) @@ -192,11 +182,7 @@ } // Don't leave the browser in fullscreen for subsequent tests. - { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); } #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -214,11 +200,7 @@ .SetupForTest(); // Enter immersive fullscreen. - { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_TRUE(immersive_controller->IsEnabled()); ASSERT_FALSE(immersive_controller->IsRevealed()); @@ -254,11 +236,7 @@ EXPECT_FALSE(immersive_controller->IsRevealed()); // Exit fullscreen before ending the test for the sake of sanity. - { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); - } + ui_test_utils::ToggleFullscreenModeAndWait(browser()); } #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/media_preview/mic_preview/audio_stream_view.cc b/chrome/browser/ui/views/media_preview/mic_preview/audio_stream_view.cc index 447608b..b65189d 100644 --- a/chrome/browser/ui/views/media_preview/mic_preview/audio_stream_view.cc +++ b/chrome/browser/ui/views/media_preview/mic_preview/audio_stream_view.cc
@@ -41,6 +41,7 @@ gfx::RectF base_rect(x, y, width(), rect_height); cc::PaintFlags base_rect_flags; base_rect_flags.setColor(GetColorProvider()->GetColor(ui::kColorSysSurface5)); + base_rect_flags.setAntiAlias(true); canvas->DrawRoundRect(base_rect, rounded_radius_, base_rect_flags); if (last_audio_level_ != 0) { @@ -52,6 +53,7 @@ cc::PaintFlags value_rect_flags; value_rect_flags.setColor( GetColorProvider()->GetColor(ui::kColorSysPrimary)); + value_rect_flags.setAntiAlias(true); canvas->DrawRoundRect(value_rect, rounded_radius_, value_rect_flags); } }
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc index 3e9d207c..e888b9b 100644 --- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc +++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -46,6 +46,7 @@ #include "ui/base/models/menu_model.h" #include "ui/base/theme_provider.h" #include "ui/base/ui_base_features.h" +#include "ui/color/color_provider.h" #include "ui/compositor/layer.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h" @@ -110,16 +111,20 @@ // to set colors. Defer updating until AddedToWidget(). This may get called as // a result of OnUserIdentityChanged() called from the constructor when the // button is not yet added to the ToolbarView's hierarchy. - if (!GetWidget()) + if (!GetWidget()) { return; + } - gfx::Image gaia_account_image = delegate_->GetGaiaAccountImage(); - for (auto state : kButtonStates) - SetImageModel(state, GetAvatarIcon(state, gaia_account_image)); + const int icon_size = GetIconSize(); + for (auto state : kButtonStates) { + SetImageModel( + state, delegate_->GetAvatarIcon(icon_size, GetForegroundColor(state))); + } // If `OnUserIdentityChanged()` has been called and the image is not empty, // show the animation. If the animation is shown, also resets the delegate's - // ButtonTextState so that the animation will not be triggered again. - delegate_->MaybeShowIdentityAnimation(gaia_account_image); + // `TextState` so that the animation will not be triggered again. + // TODO(b/324018028): This call should be moved within the delegate. + delegate_->MaybeShowIdentityAnimation(); SetInsets(); } @@ -147,74 +152,12 @@ } void AvatarToolbarButton::UpdateText() { - std::optional<SkColor> color; - std::u16string text; - const auto* const color_provider = GetColorProvider(); CHECK(color_provider); - if (features::IsChromeRefresh2023()) { - color = color_provider->GetColor(kColorAvatarButtonHighlightDefault); - } - switch (delegate_->GetState()) { - case State::kIncognitoProfile: { - const int incognito_window_count = delegate_->GetWindowCount(); - SetAccessibleName(l10n_util::GetPluralStringFUTF16( - IDS_INCOGNITO_BUBBLE_ACCESSIBLE_TITLE, incognito_window_count)); - text = l10n_util::GetPluralStringFUTF16(IDS_AVATAR_BUTTON_INCOGNITO, - incognito_window_count); - // TODO(shibalik): Remove this condition to make it generic by refactoring - // `ToolbarButton::HighlightColorAnimation`. - if (features::IsChromeRefresh2023()) { - color = color_provider->GetColor(kColorAvatarButtonHighlightIncognito); - } - break; - } - case State::kAnimatedUserIdentity: - text = delegate_->GetShortProfileName(); - break; - case State::kInterceptTextShowing: { -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_CHROMEOS_ASH) - // The signin text is not supported on Lacros. - NOTREACHED_NORETURN(); -#else - text = delegate_->GetInterceptText(); - break; -#endif - } - case State::kSyncError: - color = color_provider->GetColor(kColorAvatarButtonHighlightSyncError); - text = l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_SYNC_ERROR); - break; - case State::kSyncPaused: - color = color_provider->GetColor(kColorAvatarButtonHighlightSyncPaused); - text = l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_SYNC_PAUSED); - break; - case State::kGuestSession: { -#if BUILDFLAG(IS_CHROMEOS_ASH) - // On ChromeOS all windows are either Guest or not Guest and the Guest - // avatar button is not actionable. Showing the number of open windows is - // not as helpful as on other desktop platforms. Please see - // crbug.com/1178520. - const int guest_window_count = 1; -#else - const int guest_window_count = delegate_->GetWindowCount(); -#endif - SetAccessibleName(l10n_util::GetPluralStringFUTF16( - IDS_GUEST_BUBBLE_ACCESSIBLE_TITLE, guest_window_count)); - text = l10n_util::GetPluralStringFUTF16(IDS_AVATAR_BUTTON_GUEST, - guest_window_count); - break; - } - case State::kNormal: - if (delegate_->IsHighlightAnimationVisible()) { - color = color_provider->GetColor(kColorAvatarButtonHighlightNormal); - } - break; - } - SetInsets(); - SetTooltipText(GetAvatarTooltipText()); + SetTooltipText(delegate_->GetAvatarTooltipText()); + auto [text, color] = delegate_->GetTextAndColor(color_provider); SetHighlight(text, color); // Update the layout insets after `SetHighlight()` since // text might be updated by setting the highlight. @@ -223,9 +166,9 @@ if (features::IsChromeRefresh2023()) { UpdateInkdrop(); // Outset focus ring should be present for the chip but not when only - // the icon is visible. + // the icon is visible, when there is no text. views::FocusRing::Get(this)->SetOutsetFocusRingDisabled( - IsLabelPresentAndVisible() ? false : true); + !IsLabelPresentAndVisible()); } // TODO(crbug.com/1078221): this is a hack because toolbar buttons don't @@ -242,45 +185,13 @@ } std::optional<SkColor> AvatarToolbarButton::GetHighlightTextColor() const { - if (features::IsChromeRefresh2023()) { - std::optional<SkColor> color; - const auto* const color_provider = GetColorProvider(); - CHECK(color_provider); - - switch (delegate_->GetState()) { - case State::kIncognitoProfile: - color = color_provider->GetColor( - kColorAvatarButtonHighlightIncognitoForeground); - break; - case State::kSyncError: - color = color_provider->GetColor( - kColorAvatarButtonHighlightSyncErrorForeground); - break; - case State::kSyncPaused: - color = color_provider->GetColor( - kColorAvatarButtonHighlightNormalForeground); - break; - case State::kGuestSession: - case State::kInterceptTextShowing: - case State::kAnimatedUserIdentity: - color = color_provider->GetColor( - kColorAvatarButtonHighlightDefaultForeground); - break; - case State::kNormal: - if (delegate_->IsHighlightAnimationVisible()) { - color = color_provider->GetColor( - kColorAvatarButtonHighlightNormalForeground); - } else { - color = color_provider->GetColor( - kColorAvatarButtonHighlightDefaultForeground); - } - break; - } - - return color; + if (!features::IsChromeRefresh2023()) { + return std::nullopt; } - return std::nullopt; + const auto* const color_provider = GetColorProvider(); + CHECK(color_provider); + return delegate_->GetHighlightTextColor(color_provider); } std::optional<SkColor> AvatarToolbarButton::GetHighlightBorderColor() const { @@ -295,43 +206,14 @@ void AvatarToolbarButton::UpdateInkdrop() { CHECK(features::IsChromeRefresh2023()); - ChromeColorIds hover_color_id = kColorToolbarInkDropHover; - ChromeColorIds ripple_color_id = kColorToolbarInkDropRipple; - if (IsLabelPresentAndVisible()) { - switch (delegate_->GetState()) { - case State::kIncognitoProfile: - hover_color_id = kColorAvatarButtonIncognitoHover; - break; - case State::kSyncError: - case State::kGuestSession: - case State::kInterceptTextShowing: - case State::kAnimatedUserIdentity: - break; - case State::kSyncPaused: - ripple_color_id = kColorAvatarButtonNormalRipple; - break; - case State::kNormal: - if (delegate_->IsHighlightAnimationVisible()) { - ripple_color_id = kColorAvatarButtonNormalRipple; - } else { - ripple_color_id = kColorToolbarInkDropRipple; - } - break; - } - } - + auto [hover_color_id, ripple_color_id] = delegate_->GetInkdropColors(); ConfigureToolbarInkdropForRefresh2023(this, hover_color_id, ripple_color_id); } bool AvatarToolbarButton::ShouldPaintBorder() const { - AvatarToolbarButton::State state = delegate_->GetState(); return (!features::IsChromeRefresh2023()) || - (IsLabelPresentAndVisible() && - (state == State::kGuestSession || - state == State::kAnimatedUserIdentity || - (state == State::kNormal && - !delegate_->IsHighlightAnimationVisible()))); + (IsLabelPresentAndVisible() && delegate_->ShouldPaintBorder()); } bool AvatarToolbarButton::ShouldBlendHighlightColor() const { @@ -341,10 +223,6 @@ return !features::IsChromeRefresh2023() || has_custom_theme; } -void AvatarToolbarButton::ShowAvatarHighlightAnimation() { - delegate_->ShowHighlightAnimation(); -} - #if BUILDFLAG(ENABLE_DICE_SUPPORT) void AvatarToolbarButton::ShowInterceptText( WebSigninInterceptor::SigninInterceptionType interception_type) { @@ -364,19 +242,6 @@ return button_action_disabled_; } -void AvatarToolbarButton::AddObserver(Observer* observer) { - observer_list_.AddObserver(observer); -} - -void AvatarToolbarButton::RemoveObserver(Observer* observer) { - observer_list_.RemoveObserver(observer); -} - -void AvatarToolbarButton::NotifyHighlightAnimationFinished() { - for (AvatarToolbarButton::Observer& observer : observer_list_) - observer.OnAvatarHighlightAnimationFinished(); -} - void AvatarToolbarButton::MaybeShowProfileSwitchIPH() { // Prevent showing the promo right when the browser was created. Wait a small // delay for a smoother animation. @@ -441,38 +306,11 @@ void AvatarToolbarButton::AfterPropertyChange(const void* key, int64_t old_value) { - if (key == user_education::kHasInProductHelpPromoKey) + if (key == user_education::kHasInProductHelpPromoKey) { delegate_->SetHasInProductHelpPromo( GetProperty(user_education::kHasInProductHelpPromoKey)); - ToolbarButton::AfterPropertyChange(key, old_value); -} - -std::u16string AvatarToolbarButton::GetAvatarTooltipText() const { - switch (delegate_->GetState()) { - case State::kIncognitoProfile: - return l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_INCOGNITO_TOOLTIP); - case State::kGuestSession: - return l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_GUEST_TOOLTIP); - case State::kAnimatedUserIdentity: - return delegate_->GetShortProfileName(); - // kSyncPaused is just a type of sync error with different color, but should - // still use GetAvatarSyncErrorDescription() as tooltip. - case State::kSyncError: - case State::kSyncPaused: { - std::optional<AvatarSyncErrorType> error = - delegate_->GetAvatarSyncErrorType(); - DCHECK(error); - return l10n_util::GetStringFUTF16( - IDS_AVATAR_BUTTON_SYNC_ERROR_TOOLTIP, - delegate_->GetShortProfileName(), - GetAvatarSyncErrorDescription(*error, - delegate_->IsSyncFeatureEnabled())); - } - case State::kInterceptTextShowing: - case State::kNormal: - return delegate_->GetProfileName(); } - NOTREACHED_NORETURN(); + ToolbarButton::AfterPropertyChange(key, old_value); } SkColor AvatarToolbarButton::GetForegroundColor(ButtonState state) const { @@ -496,34 +334,6 @@ return ToolbarButton::GetForegroundColor(state); } -ui::ImageModel AvatarToolbarButton::GetAvatarIcon( - ButtonState state, - const gfx::Image& gaia_account_image) const { - const int icon_size = GetIconSize(); - SkColor icon_color = GetForegroundColor(state); - - switch (delegate_->GetState()) { - case State::kIncognitoProfile: - return ui::ImageModel::FromVectorIcon(features::IsChromeRefresh2023() - ? kIncognitoRefreshMenuIcon - : kIncognitoIcon, - icon_color, icon_size); - case State::kGuestSession: - return profiles::GetGuestAvatar(icon_size); - case State::kInterceptTextShowing: - case State::kAnimatedUserIdentity: - case State::kSyncError: - // TODO(crbug.com/1191411): If sync-the-feature is disabled, the icon should - // be different. - case State::kSyncPaused: - case State::kNormal: - return ui::ImageModel::FromImage(profiles::GetSizedAvatarIcon( - delegate_->GetProfileAvatarImage(gaia_account_image, icon_size), - icon_size, icon_size, profiles::SHAPE_CIRCLE)); - } - NOTREACHED_NORETURN(); -} - bool AvatarToolbarButton::IsLabelPresentAndVisible() const { if (!label()) { return false;
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h index 85c066d6..407682e 100644 --- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h +++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
@@ -20,41 +20,21 @@ class Browser; class BrowserView; +// This class takes care the Profile Avatar Button. +// Primarily applies UI configuration. +// It's data (text, icon, etc...) content are computed through the +// `AvatarToolbarButtonDelegate`, when relying on Chrome and Profile changes in +// order to adapt the expected content shown in the button. class AvatarToolbarButton : public ToolbarButton { METADATA_HEADER(AvatarToolbarButton, ToolbarButton) public: - // States of the button ordered in priority of getting displayed. - enum class State { - kIncognitoProfile, - kGuestSession, - kInterceptTextShowing, - kAnimatedUserIdentity, - kSyncPaused, - // An error in sync-the-feature or sync-the-transport. - kSyncError, - kNormal - }; - - class Observer { - public: - virtual ~Observer() = default; - - virtual void OnAvatarHighlightAnimationFinished() = 0; - }; - explicit AvatarToolbarButton(BrowserView* browser); AvatarToolbarButton(const AvatarToolbarButton&) = delete; AvatarToolbarButton& operator=(const AvatarToolbarButton&) = delete; ~AvatarToolbarButton() override; void UpdateText(); - std::optional<SkColor> GetHighlightTextColor() const override; - std::optional<SkColor> GetHighlightBorderColor() const override; - bool ShouldPaintBorder() const override; - bool ShouldBlendHighlightColor() const override; - - void ShowAvatarHighlightAnimation(); #if BUILDFLAG(ENABLE_DICE_SUPPORT) // Expands the pill to show the intercept text. @@ -71,14 +51,12 @@ void SetButtonActionDisabled(bool disabled); bool IsButtonActionDisabled() const; - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - void NotifyHighlightAnimationFinished(); - // Attempts showing the In-Produce-Help for profile Switching. void MaybeShowProfileSwitchIPH(); + // Returns true if a text is set and is visible. + bool IsLabelPresentAndVisible() const; + // ToolbarButton: void OnMouseExited(const ui::MouseEvent& event) override; void OnBlur() override; @@ -87,14 +65,10 @@ void Layout(PassKey) override; int GetIconSize() const override; SkColor GetForegroundColor(ButtonState state) const override; - - // Returns true if a text is set and is visible. - bool IsLabelPresentAndVisible() const; - - // Updates the inkdrop highlight and ripple properties depending on the state - // and - // whether the chip is expanded. - void UpdateInkdrop(); + std::optional<SkColor> GetHighlightTextColor() const override; + std::optional<SkColor> GetHighlightBorderColor() const override; + bool ShouldPaintBorder() const override; + bool ShouldBlendHighlightColor() const override; // Can be used in tests to reduce or remove the delay before showing the IPH. static void SetIPHMinDelayAfterCreationForTesting(base::TimeDelta delay); @@ -108,15 +82,15 @@ void ButtonPressed(); - std::u16string GetAvatarTooltipText() const; - ui::ImageModel GetAvatarIcon(ButtonState state, - const gfx::Image& profile_identity_image) const; - void SetInsets(); // Updates the layout insets depending on whether it is a chip or a button. void UpdateLayoutInsets(); + // Updates the inkdrop highlight and ripple properties depending on the state + // and whether the chip is expanded. + void UpdateInkdrop(); + std::unique_ptr<AvatarToolbarButtonDelegate> delegate_; const raw_ptr<Browser> browser_; @@ -133,8 +107,6 @@ // remain in active state, not affecting it's UI in any way. bool button_action_disabled_ = false; - base::ObserverList<Observer>::Unchecked observer_list_; - base::WeakPtrFactory<AvatarToolbarButton> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc index 03a33fe..751dfc3 100644 --- a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc +++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc
@@ -8,6 +8,7 @@ #include "base/notreached.h" #include "base/task/single_thread_task_runner.h" #include "build/chromeos_buildflags.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_attributes_entry.h" @@ -25,7 +26,9 @@ #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/profiles/profile_colors_util.h" +#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" #include "chrome/grit/branded_strings.h" #include "chrome/grit/generated_resources.h" @@ -38,8 +41,6 @@ constexpr base::TimeDelta kIdentityAnimationDuration = base::Seconds(3); -constexpr base::TimeDelta kAvatarHighlightAnimationDuration = base::Seconds(2); - ProfileAttributesStorage& GetProfileAttributesStorage() { return g_browser_process->profile_manager()->GetProfileAttributesStorage(); } @@ -89,9 +90,8 @@ sync_service_observation_.Observe(sync_service); } - AvatarToolbarButton::State state = GetState(); - if (state == AvatarToolbarButton::State::kIncognitoProfile || - state == AvatarToolbarButton::State::kGuestSession) { + bool is_incognito = profile_->IsOffTheRecord(); + if (is_incognito || profile_->IsGuestSession()) { BrowserList::AddObserver(this); } else { signin::IdentityManager* identity_manager = @@ -107,13 +107,11 @@ // captivie portal signin. It's only enabled for non captive portal Incognito // where a menu is available for closing all Incognito windows. avatar_toolbar_button_->SetEnabled( - state == AvatarToolbarButton::State::kIncognitoProfile && - !profile_->GetOTRProfileID().IsCaptivePortal()); + is_incognito && !profile_->GetOTRProfileID().IsCaptivePortal()); #elif BUILDFLAG(IS_CHROMEOS_LACROS) // On Lacros we need to disable the button for captivie portal signin. avatar_toolbar_button_->SetEnabled( - state != AvatarToolbarButton::State::kIncognitoProfile || - !profile_->GetOTRProfileID().IsCaptivePortal()); + !is_incognito || !profile_->GetOTRProfileID().IsCaptivePortal()); #endif // !BUILDFLAG(IS_CHROMEOS) } @@ -122,7 +120,7 @@ } std::u16string AvatarToolbarButtonDelegate::GetProfileName() const { - DCHECK_NE(GetState(), AvatarToolbarButton::State::kIncognitoProfile); + DCHECK_NE(ComputeState(), ButtonState::kIncognitoProfile); return profiles::GetAvatarNameForProfile(profile_->GetPath()); } @@ -150,7 +148,6 @@ } gfx::Image AvatarToolbarButtonDelegate::GetProfileAvatarImage( - gfx::Image gaia_account_image, int preferred_size) const { ProfileAttributesEntry* entry = GetProfileAttributesEntry(profile_); if (!entry) { // This can happen if the user deletes the current profile. @@ -172,6 +169,7 @@ // - the profile icon wasn't explicitly changed signin::IdentityManager* identity_manager = IdentityManagerFactory::GetForProfile(profile_); + gfx::Image gaia_account_image = GetGaiaAccountImage(); if (!gaia_account_image.IsEmpty() && AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_) && !identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync) && @@ -189,26 +187,27 @@ return BrowserList::GetOffTheRecordBrowsersActiveForProfile(profile_); } -AvatarToolbarButton::State AvatarToolbarButtonDelegate::GetState() const { +AvatarToolbarButtonDelegate::ButtonState +AvatarToolbarButtonDelegate::ComputeState() const { if (profile_->IsGuestSession()) - return AvatarToolbarButton::State::kGuestSession; + return ButtonState::kGuestSession; // Return |kIncognitoProfile| state for all OffTheRecord profile types except // guest mode. if (profile_->IsOffTheRecord()) - return AvatarToolbarButton::State::kIncognitoProfile; + return ButtonState::kIncognitoProfile; - if (button_text_state_ == ButtonTextState::kShowingName) { - return AvatarToolbarButton::State::kAnimatedUserIdentity; + if (button_text_state_ == TextState::kShowingName) { + return ButtonState::kAnimatedUserIdentity; } - if (button_text_state_ == ButtonTextState::kShowingInterceptText) { - return AvatarToolbarButton::State::kInterceptTextShowing; + if (button_text_state_ == TextState::kShowingInterceptText) { + return ButtonState::kInterceptTextShowing; } // Web app has limited toolbar space, thus always show kNormal state. if (web_app::AppBrowserController::IsWebApp(browser_) || !SyncServiceFactory::IsSyncAllowed(profile_)) { - return AvatarToolbarButton::State::kNormal; + return ButtonState::kNormal; } // Show any existing sync errors (sync-the-feature or sync-the-transport). @@ -216,14 +215,14 @@ // ::GetAvatarSyncErrorType(), so the result agrees with // AvatarToolbarButtonDelegate::GetAvatarSyncErrorType(). if (!last_avatar_error_) - return AvatarToolbarButton::State::kNormal; + return ButtonState::kNormal; if (last_avatar_error_ == AvatarSyncErrorType::kSyncPaused && AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_)) { - return AvatarToolbarButton::State::kSyncPaused; + return ButtonState::kSyncPaused; } - return AvatarToolbarButton::State::kSyncError; + return ButtonState::kSyncError; } std::optional<AvatarSyncErrorType> @@ -231,32 +230,9 @@ return last_avatar_error_; } -bool AvatarToolbarButtonDelegate::IsSyncFeatureEnabled() const { - return IdentityManagerFactory::GetForProfile(profile_)->HasPrimaryAccount( - signin::ConsentLevel::kSync); -} - -void AvatarToolbarButtonDelegate::ShowHighlightAnimation() { - signin_ui_util::RecordAvatarIconHighlighted(profile_); - highlight_animation_visible_ = true; - DCHECK_NE(GetState(), AvatarToolbarButton::State::kIncognitoProfile); - DCHECK_NE(GetState(), AvatarToolbarButton::State::kGuestSession); - avatar_toolbar_button_->UpdateText(); - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&AvatarToolbarButtonDelegate::HideHighlightAnimation, - weak_ptr_factory_.GetWeakPtr()), - kAvatarHighlightAnimationDuration); -} - -bool AvatarToolbarButtonDelegate::IsHighlightAnimationVisible() const { - return highlight_animation_visible_; -} - -void AvatarToolbarButtonDelegate::MaybeShowIdentityAnimation( - const gfx::Image& gaia_account_image) { - if (button_text_state_ != ButtonTextState::kWaitingForImage || +void AvatarToolbarButtonDelegate::MaybeShowIdentityAnimation() { + const gfx::Image gaia_account_image = GetGaiaAccountImage(); + if (button_text_state_ != TextState::kWaitingForImage || gaia_account_image.IsEmpty()) { return; } @@ -264,7 +240,7 @@ // Check that the user is still signed in. See https://crbug.com/1025674 if (!IdentityManagerFactory::GetForProfile(profile_)->HasPrimaryAccount( signin::ConsentLevel::kSignin)) { - button_text_state_ = ButtonTextState::kNotShowing; + button_text_state_ = TextState::kNotShowing; return; } @@ -283,10 +259,6 @@ ShowIdentityAnimation(); } -void AvatarToolbarButtonDelegate::NotifyClick() { - MaybeHideIdentityAnimation(); -} - void AvatarToolbarButtonDelegate::OnMouseExited() { MaybeHideIdentityAnimation(); } @@ -421,10 +393,10 @@ void AvatarToolbarButtonDelegate::OnUserIdentityChanged() { signin_ui_util::RecordAnimatedIdentityTriggered(profile_); - button_text_state_ = ButtonTextState::kWaitingForImage; + button_text_state_ = TextState::kWaitingForImage; // If we already have a gaia image, the pill will be immediately displayed by // `UpdateIcon()`. If not, it can still be displayed later, since the button - // text state is now set to `ButtonTextState::kWaitingForImage`. This state + // text state is now set to `TextState::kWaitingForImage`. This state // will trigger the animation in `MaybeShowIdentityAnimation(...)`. avatar_toolbar_button_->UpdateIcon(); } @@ -435,17 +407,17 @@ // OnIdentityAnimationTimeout() that will hide it after the proper delay. // Also return if the button is showing the signin text rather than the name. if (identity_animation_timeout_count_ > 0 || - button_text_state_ == ButtonTextState::kShowingInterceptText) { + button_text_state_ == TextState::kShowingInterceptText) { return; } - DCHECK_EQ(button_text_state_, ButtonTextState::kShowingName); + DCHECK_EQ(button_text_state_, TextState::kShowingName); MaybeHideIdentityAnimation(); } void AvatarToolbarButtonDelegate::MaybeHideIdentityAnimation() { // No-op if not showing or if the timeout hasn't passed, yet. - if (button_text_state_ != ButtonTextState::kShowingName || + if (button_text_state_ != TextState::kShowingName || identity_animation_timeout_count_ > 0) { return; } @@ -458,22 +430,14 @@ return; } - button_text_state_ = ButtonTextState::kNotShowing; + button_text_state_ = TextState::kNotShowing; // Update the text to the pre-shown state. This also makes sure that we now // reflect changes that happened while the identity pill was shown. avatar_toolbar_button_->UpdateText(); } -void AvatarToolbarButtonDelegate::HideHighlightAnimation() { - DCHECK_NE(GetState(), AvatarToolbarButton::State::kIncognitoProfile); - DCHECK_NE(GetState(), AvatarToolbarButton::State::kGuestSession); - highlight_animation_visible_ = false; - avatar_toolbar_button_->UpdateText(); - avatar_toolbar_button_->NotifyHighlightAnimationFinished(); -} - void AvatarToolbarButtonDelegate::ShowIdentityAnimation() { - button_text_state_ = ButtonTextState::kShowingName; + button_text_state_ = TextState::kShowingName; avatar_toolbar_button_->UpdateText(); // Hide the pill after a while. @@ -489,23 +453,211 @@ void AvatarToolbarButtonDelegate::ShowInterceptText( WebSigninInterceptor::SigninInterceptionType interception_type) { current_interception_type_ = interception_type; - button_text_state_ = ButtonTextState::kShowingInterceptText; + button_text_state_ = TextState::kShowingInterceptText; avatar_toolbar_button_->UpdateText(); } void AvatarToolbarButtonDelegate::HideText() { - button_text_state_ = ButtonTextState::kNotShowing; + button_text_state_ = TextState::kNotShowing; Reset(); avatar_toolbar_button_->UpdateText(); } - -std::u16string AvatarToolbarButtonDelegate::GetInterceptText() { - CHECK(current_interception_type_.has_value()); - return InterceptionTypeToIdentityPillText(current_interception_type_.value()); -} #endif void AvatarToolbarButtonDelegate::Reset() { current_interception_type_.reset(); } + +std::pair<std::u16string, std::optional<SkColor>> +AvatarToolbarButtonDelegate::GetTextAndColor( + const ui::ColorProvider* const color_provider) const { + std::optional<SkColor> color; + std::u16string text; + + if (features::IsChromeRefresh2023()) { + color = color_provider->GetColor(kColorAvatarButtonHighlightDefault); + } + switch (ComputeState()) { + case ButtonState::kIncognitoProfile: { + const int incognito_window_count = GetWindowCount(); + avatar_toolbar_button_->SetAccessibleName( + l10n_util::GetPluralStringFUTF16( + IDS_INCOGNITO_BUBBLE_ACCESSIBLE_TITLE, incognito_window_count)); + text = l10n_util::GetPluralStringFUTF16(IDS_AVATAR_BUTTON_INCOGNITO, + incognito_window_count); + // TODO(shibalik): Remove this condition to make it generic by refactoring + // `ToolbarButton::HighlightColorAnimation`. + if (features::IsChromeRefresh2023()) { + color = color_provider->GetColor(kColorAvatarButtonHighlightIncognito); + } + break; + } + case ButtonState::kAnimatedUserIdentity: + text = GetShortProfileName(); + break; + case ButtonState::kInterceptTextShowing: { +#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_CHROMEOS_ASH) + // The signin text is not supported on Lacros. + NOTREACHED_NORETURN(); +#else + CHECK(current_interception_type_.has_value()); + text = InterceptionTypeToIdentityPillText( + current_interception_type_.value()); + break; +#endif + } + case ButtonState::kSyncError: + color = color_provider->GetColor(kColorAvatarButtonHighlightSyncError); + text = l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_SYNC_ERROR); + break; + case ButtonState::kSyncPaused: + color = color_provider->GetColor(kColorAvatarButtonHighlightSyncPaused); + text = l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_SYNC_PAUSED); + break; + case ButtonState::kGuestSession: { +#if BUILDFLAG(IS_CHROMEOS_ASH) + // On ChromeOS all windows are either Guest or not Guest and the Guest + // avatar button is not actionable. Showing the number of open windows is + // not as helpful as on other desktop platforms. Please see + // crbug.com/1178520. + const int guest_window_count = 1; +#else + const int guest_window_count = GetWindowCount(); +#endif + avatar_toolbar_button_->SetAccessibleName( + l10n_util::GetPluralStringFUTF16(IDS_GUEST_BUBBLE_ACCESSIBLE_TITLE, + guest_window_count)); + text = l10n_util::GetPluralStringFUTF16(IDS_AVATAR_BUTTON_GUEST, + guest_window_count); + break; + } + case ButtonState::kNormal: + break; + } + + return {text, color}; +} + +std::optional<SkColor> AvatarToolbarButtonDelegate::GetHighlightTextColor( + const ui::ColorProvider* const color_provider) const { + std::optional<SkColor> color; + switch (ComputeState()) { + case ButtonState::kIncognitoProfile: + color = color_provider->GetColor( + kColorAvatarButtonHighlightIncognitoForeground); + break; + case ButtonState::kSyncError: + color = color_provider->GetColor( + kColorAvatarButtonHighlightSyncErrorForeground); + break; + case ButtonState::kSyncPaused: + color = + color_provider->GetColor(kColorAvatarButtonHighlightNormalForeground); + break; + case ButtonState::kGuestSession: + case ButtonState::kInterceptTextShowing: + case ButtonState::kAnimatedUserIdentity: + color = color_provider->GetColor( + kColorAvatarButtonHighlightDefaultForeground); + break; + case ButtonState::kNormal: + color = color_provider->GetColor( + kColorAvatarButtonHighlightDefaultForeground); + break; + } + return color; +} + +std::u16string AvatarToolbarButtonDelegate::GetAvatarTooltipText() const { + switch (ComputeState()) { + case ButtonState::kIncognitoProfile: + return l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_INCOGNITO_TOOLTIP); + case ButtonState::kGuestSession: + return l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_GUEST_TOOLTIP); + case ButtonState::kAnimatedUserIdentity: + return GetShortProfileName(); + // kSyncPaused is just a type of sync error with different color, but should + // still use GetAvatarSyncErrorDescription() as tooltip. + case ButtonState::kSyncError: + case ButtonState::kSyncPaused: { + std::optional<AvatarSyncErrorType> error = GetAvatarSyncErrorType(); + DCHECK(error); + return l10n_util::GetStringFUTF16( + IDS_AVATAR_BUTTON_SYNC_ERROR_TOOLTIP, GetShortProfileName(), + GetAvatarSyncErrorDescription( + *error, IdentityManagerFactory::GetForProfile(profile_) + ->HasPrimaryAccount(signin::ConsentLevel::kSync))); + } + case ButtonState::kInterceptTextShowing: + case ButtonState::kNormal: + return GetProfileName(); + } +} + +std::pair<ChromeColorIds, ChromeColorIds> +AvatarToolbarButtonDelegate::GetInkdropColors() const { + CHECK(features::IsChromeRefresh2023()); + + ChromeColorIds hover_color_id = kColorToolbarInkDropHover; + ChromeColorIds ripple_color_id = kColorToolbarInkDropRipple; + + if (avatar_toolbar_button_->IsLabelPresentAndVisible()) { + switch (ComputeState()) { + case ButtonState::kIncognitoProfile: + hover_color_id = kColorAvatarButtonIncognitoHover; + break; + case ButtonState::kSyncError: + case ButtonState::kGuestSession: + case ButtonState::kInterceptTextShowing: + case ButtonState::kAnimatedUserIdentity: + break; + case ButtonState::kSyncPaused: + ripple_color_id = kColorAvatarButtonNormalRipple; + break; + case ButtonState::kNormal: + ripple_color_id = kColorToolbarInkDropRipple; + break; + } + } + + return {hover_color_id, ripple_color_id}; +} + +ui::ImageModel AvatarToolbarButtonDelegate::GetAvatarIcon( + int icon_size, + SkColor icon_color) const { + switch (ComputeState()) { + case ButtonState::kIncognitoProfile: + return ui::ImageModel::FromVectorIcon(features::IsChromeRefresh2023() + ? kIncognitoRefreshMenuIcon + : kIncognitoIcon, + icon_color, icon_size); + case ButtonState::kGuestSession: + return profiles::GetGuestAvatar(icon_size); + case ButtonState::kInterceptTextShowing: + case ButtonState::kAnimatedUserIdentity: + case ButtonState::kSyncError: + // TODO(crbug.com/1191411): If sync-the-feature is disabled, the icon + // should be different. + case ButtonState::kSyncPaused: + case ButtonState::kNormal: + return ui::ImageModel::FromImage(profiles::GetSizedAvatarIcon( + GetProfileAvatarImage(icon_size), icon_size, icon_size, + profiles::SHAPE_CIRCLE)); + } +} + +bool AvatarToolbarButtonDelegate::ShouldPaintBorder() const { + switch (ComputeState()) { + case ButtonState::kGuestSession: + case ButtonState::kAnimatedUserIdentity: + case ButtonState::kNormal: + return true; + case ButtonState::kIncognitoProfile: + case ButtonState::kInterceptTextShowing: + case ButtonState::kSyncPaused: + case ButtonState::kSyncError: + return false; + } +}
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.h b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.h index b9e80629..388bcb2 100644 --- a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.h +++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.h
@@ -17,6 +17,7 @@ #include "chrome/browser/signin/web_signin_interceptor.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/browser/ui/browser_list_observer.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/sync/service/sync_service.h" @@ -26,8 +27,19 @@ class Browser; class Profile; -// Handles the business logic for AvatarToolbarButton. This includes -// managing the highlight animation and the identity animation. +// Handles the business logic for AvatarToolbarButton. +// Listens to Chrome and Profile changes in order to compute the proper state of +// the button. This state is used to compute the information requested by +// the button to be shown, such as Text and color, Icon, tooltip text etc... +// The different states that can be reached: +// - Regular state: regular browsing session. +// - Private mode: Incognito or Guest browser sessions. +// - Identity name shown: the identity name is shown for a short period of time. +// This can be triggered by identity changes in Chrome or when an IPH is +// showing. +// - Explicit modifications override: such as displaying specific text when +// intercept bubbles are displayed. +// - Sync paused/error state. class AvatarToolbarButtonDelegate : public BrowserListObserver, public ProfileAttributesStorage::Observer, public signin::IdentityManager::Observer, @@ -41,56 +53,57 @@ ~AvatarToolbarButtonDelegate() override; - // Methods called by the AvatarToolbarButton to get profile information. - std::u16string GetProfileName() const; - std::u16string GetShortProfileName() const; - gfx::Image GetGaiaAccountImage() const; - // Must only be called in states which have an avatar image (i.e. not - // kGuestSession and not kIncognitoProfile). - gfx::Image GetProfileAvatarImage(gfx::Image gaia_account_image, - int preferred_size) const; - - // Returns the count of incognito or guest windows attached to the profile. - int GetWindowCount() const; - - AvatarToolbarButton::State GetState() const; - - std::optional<AvatarSyncErrorType> GetAvatarSyncErrorType() const; - - bool IsSyncFeatureEnabled() const; - - void ShowHighlightAnimation(); - bool IsHighlightAnimationVisible() const; + // These info are based on the `ButtonState`. + std::pair<std::u16string, std::optional<SkColor>> GetTextAndColor( + const ui::ColorProvider* const color_provider) const; + std::optional<SkColor> GetHighlightTextColor( + const ui::ColorProvider* const color_provider) const; + std::u16string GetAvatarTooltipText() const; + std::pair<ChromeColorIds, ChromeColorIds> GetInkdropColors() const; + ui::ImageModel GetAvatarIcon(int icon_size, SkColor icon_color) const; + bool ShouldPaintBorder() const; #if BUILDFLAG(ENABLE_DICE_SUPPORT) void ShowInterceptText( WebSigninInterceptor::SigninInterceptionType interception_type); void HideText(); - - std::u16string GetInterceptText(); #endif // Should be called when the icon is updated. This may trigger the identity // pill animation if the delegate is waiting for the image. - void MaybeShowIdentityAnimation(const gfx::Image& gaia_account_image); + void MaybeShowIdentityAnimation(); // Enables or disables the IPH highlight. void SetHasInProductHelpPromo(bool has_promo); // Called by the AvatarToolbarButton to notify the delegate about events. - void NotifyClick(); void OnMouseExited(); void OnBlur(); void OnThemeChanged(const ui::ColorProvider* color_provider); private: - enum class ButtonTextState { + // Internal text state + enum class TextState { kNotShowing, kWaitingForImage, kShowingName, kShowingInterceptText }; + // States of the button ordered in priority of getting displayed. + enum class ButtonState { + kIncognitoProfile, + kGuestSession, + kInterceptTextShowing, + kAnimatedUserIdentity, + kSyncPaused, + // An error in sync-the-feature or sync-the-transport. + kSyncError, + kNormal + }; + + ButtonState ComputeState() const; + // BrowserListObserver: void OnBrowserAdded(Browser* browser) override; void OnBrowserRemoved(Browser* browser) override; @@ -124,12 +137,21 @@ void OnIdentityAnimationTimeout(); // Called after the user interacted with the button or after some timeout. void MaybeHideIdentityAnimation(); - void HideHighlightAnimation(); // Shows the identity pill animation. If the animation is already showing, // this extends the duration of the current animation. void ShowIdentityAnimation(); + std::u16string GetProfileName() const; + std::u16string GetShortProfileName() const; + // Must only be called in states which have an avatar image (i.e. not + // kGuestSession and not kIncognitoProfile). + gfx::Image GetProfileAvatarImage(int preferred_size) const; + // Returns the count of incognito or guest windows attached to the profile. + int GetWindowCount() const; + std::optional<AvatarSyncErrorType> GetAvatarSyncErrorType() const; + gfx::Image GetGaiaAccountImage() const; + void Reset(); base::ScopedObservation<ProfileAttributesStorage, @@ -144,7 +166,7 @@ const raw_ptr<AvatarToolbarButton> avatar_toolbar_button_; const raw_ptr<Browser> browser_; const raw_ptr<Profile> profile_; - ButtonTextState button_text_state_ = ButtonTextState::kNotShowing; + TextState button_text_state_ = TextState::kNotShowing; // Count of identity pill animation timeouts that are currently scheduled. // Multiple timeouts are scheduled when multiple animation triggers happen in @@ -155,11 +177,6 @@ bool refresh_tokens_loaded_ = false; bool has_in_product_help_promo_ = false; - // Whether the avatar highlight animation is visible. The animation is shown - // when an Autofill datatype is saved. When this is true the avatar button - // sync paused/error state will be disabled. - bool highlight_animation_visible_ = false; - // Caches the value of the last error so the class can detect when it // changes and notify |avatar_toolbar_button_|. std::optional<AvatarSyncErrorType> last_avatar_error_;
diff --git a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc index c1766d3d..ffb3417 100644 --- a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc +++ b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc
@@ -13,17 +13,22 @@ #include "chrome/browser/signin/signin_features.h" #include "chrome/common/chrome_features.h" #include "components/signin/public/base/signin_buildflags.h" +#include "components/signin/public/identity_manager/account_capabilities_test_mutator.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/identity_test_utils.h" +#include "components/signin/public/identity_manager/tribool.h" #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_unittest_util.h" namespace { -AccountInfo FillAccountInfo(const CoreAccountInfo& core_info, - AccountManagementStatus management_status) { +AccountInfo FillAccountInfo( + const CoreAccountInfo& core_info, + AccountManagementStatus management_status, + signin::Tribool + can_show_history_sync_opt_ins_without_minor_mode_restrictions) { const char kHostedDomain[] = "example.com"; AccountInfo account_info; @@ -40,6 +45,15 @@ : kNoHostedDomainFound; account_info.locale = "en"; account_info.picture_url = "https://example.com"; + + if (can_show_history_sync_opt_ins_without_minor_mode_restrictions != + signin::Tribool::kUnknown) { + AccountCapabilitiesTestMutator mutator(&account_info.capabilities); + mutator.set_can_show_history_sync_opt_ins_without_minor_mode_restrictions( + signin::TriboolToBoolOrDie( + can_show_history_sync_opt_ins_without_minor_mode_restrictions)); + } + return account_info; } } // namespace @@ -47,7 +61,9 @@ AccountInfo SignInWithAccount( signin::IdentityTestEnvironment& identity_test_env, AccountManagementStatus management_status, - std::optional<signin::ConsentLevel> consent_level) { + std::optional<signin::ConsentLevel> consent_level, + signin::Tribool + can_show_history_sync_opt_ins_without_minor_mode_restrictions) { auto* identity_manager = identity_test_env.identity_manager(); const std::string email = @@ -59,8 +75,9 @@ email, {.primary_account_consent_level = consent_level, .set_cookie = true}); - identity_test_env.UpdateAccountInfoForAccount( - FillAccountInfo(base_account_info, management_status)); + identity_test_env.UpdateAccountInfoForAccount(FillAccountInfo( + base_account_info, management_status, + can_show_history_sync_opt_ins_without_minor_mode_restrictions)); // Set account image SimulateAccountImageFetch(identity_manager, base_account_info.account_id,
diff --git a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h index 97b3a41..c67e293 100644 --- a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h +++ b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h
@@ -10,6 +10,7 @@ #include "base/scoped_environment_variable_override.h" #include "chrome/browser/signin/signin_browser_test_base.h" +#include "components/signin/public/identity_manager/tribool.h" namespace base { class CommandLine; @@ -50,7 +51,10 @@ AccountManagementStatus management_status = AccountManagementStatus::kNonManaged, std::optional<signin::ConsentLevel> consent_level = - signin::ConsentLevel::kSignin); + signin::ConsentLevel::kSignin, + signin::Tribool + can_show_history_sync_opt_ins_without_minor_mode_restrictions = + signin::Tribool::kTrue); // Sets up the parameters that are passed to the command line. For example, // to enable dark mode, we need to pass `kForceDarkMode` to the command line. @@ -91,9 +95,13 @@ AccountManagementStatus management_status = AccountManagementStatus::kNonManaged, std::optional<signin::ConsentLevel> consent_level = - signin::ConsentLevel::kSignin) { - return ::SignInWithAccount(*this->identity_test_env(), management_status, - consent_level); + signin::ConsentLevel::kSignin, + signin::Tribool + can_show_history_sync_opt_ins_without_minor_mode_restrictions = + signin::Tribool::kTrue) { + return ::SignInWithAccount( + *this->identity_test_env(), management_status, consent_level, + can_show_history_sync_opt_ins_without_minor_mode_restrictions); } // SigninBrowserTestBaseT overrides:
diff --git a/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc b/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc index de9d3bb..8267068 100644 --- a/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc +++ b/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc
@@ -16,8 +16,10 @@ #include "chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h" #include "chrome/browser/ui/webui/signin/signin_url_utils.h" #include "chrome/common/webui_url_constants.h" +#include "components/signin/public/base/consent_level.h" #include "components/signin/public/base/signin_buildflags.h" #include "components/signin/public/base/signin_switches.h" +#include "components/signin/public/identity_manager/tribool.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_navigation_observer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" @@ -34,11 +36,49 @@ // Tests for the chrome://sync-confirmation WebUI page. They live here and not // in the webui directory because they manipulate views. namespace { + +// Configures the state of ::switches::kMinorModeRestrictionsForHistorySyncOptIn +// that relies on can_show_history_sync_opt_ins_without_minor_mode_restrictions +// capability. +struct MinorModeRestrictions { + // Enable or disable the Feature + bool enable_feature = false; + // Related capability value + signin::Tribool capability = signin::Tribool::kTrue; +}; + +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) +constexpr MinorModeRestrictions kWithMinorModeRestrictionsWithUnrestrictedUser{ + .enable_feature = true, + .capability = signin::Tribool::kTrue}; +constexpr MinorModeRestrictions kWithMinorModeRestrictionsWithRestrictedUser{ + .enable_feature = true, + .capability = signin::Tribool::kFalse}; +#endif + +void ConfigureMinorModeRestrictionFeature( + MinorModeRestrictions minor_mode_restrictions, + base::test::ScopedFeatureList& feature_flag_) { +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) + if (minor_mode_restrictions.enable_feature) { + feature_flag_.InitAndEnableFeature( + ::switches::kMinorModeRestrictionsForHistorySyncOptIn); + } else { + feature_flag_.InitAndDisableFeature( + ::switches::kMinorModeRestrictionsForHistorySyncOptIn); + } +#else + CHECK(!minor_mode_restrictions.enable_feature) + << "This feature can be only enabled for selected platforms."; +#endif +} + struct SyncConfirmationTestParam { PixelTestParam pixel_test_param; AccountManagementStatus account_management_status = AccountManagementStatus::kNonManaged; SyncConfirmationStyle sync_style = SyncConfirmationStyle::kWindow; + MinorModeRestrictions minor_mode_restrictions; }; // To be passed as 4th argument to `INSTANTIATE_TEST_SUITE_P()`, allows the test @@ -61,6 +101,17 @@ .account_management_status = AccountManagementStatus::kManaged}, {.pixel_test_param = {.test_suffix = "CR2023", .use_chrome_refresh_2023_style = true}}, + +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) + // Restricted mode is only implemented for these platforms. + {.pixel_test_param = {.test_suffix = + "RegularWithRestrictionsWithUnrestrictedUser"}, + .minor_mode_restrictions = kWithMinorModeRestrictionsWithUnrestrictedUser}, + {.pixel_test_param = {.test_suffix = + "RegularWithRestrictionsWithRestrictedUser"}, + .minor_mode_restrictions = kWithMinorModeRestrictionsWithRestrictedUser}, +#endif + }; const SyncConfirmationTestParam kDialogTestParams[] = { @@ -82,6 +133,19 @@ {.pixel_test_param = {.test_suffix = "CR2023", .use_chrome_refresh_2023_style = true}, .sync_style = SyncConfirmationStyle::kDefaultModal}, + +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) + // Restricted mode is only implemented for these platforms. + {.pixel_test_param = {.test_suffix = + "RegularWithRestrictionsWithUnrestrictedUser"}, + .sync_style = SyncConfirmationStyle::kDefaultModal, + .minor_mode_restrictions = kWithMinorModeRestrictionsWithUnrestrictedUser}, + {.pixel_test_param = {.test_suffix = + "RegularWithRestrictionsWithRestrictedUser"}, + .sync_style = SyncConfirmationStyle::kDefaultModal, + .minor_mode_restrictions = kWithMinorModeRestrictionsWithRestrictedUser}, +#endif + }; GURL BuildSyncConfirmationWindowURL() { @@ -139,6 +203,9 @@ SyncConfirmationUIWindowPixelTest() : ProfilesPixelTestBaseT<UiBrowserTest>(GetParam().pixel_test_param) { DCHECK(GetParam().sync_style == SyncConfirmationStyle::kWindow); + + ConfigureMinorModeRestrictionFeature(GetParam().minor_mode_restrictions, + scoped_feature_list); } void ShowUi(const std::string& name) override { @@ -146,7 +213,9 @@ ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); DCHECK(browser()); - SignInWithAccount(GetParam().account_management_status); + SignInWithAccount(GetParam().account_management_status, + signin::ConsentLevel::kSignin, + GetParam().minor_mode_restrictions.capability); profile_picker_view_ = new ProfileManagementStepTestView( ProfilePicker::Params::ForFirstRun(browser()->profile()->GetPath(), base::DoNothing()), @@ -185,6 +254,8 @@ raw_ptr<ProfileManagementStepTestView, DanglingUntriaged> profile_picker_view_; + + base::test::ScopedFeatureList scoped_feature_list; }; IN_PROC_BROWSER_TEST_P(SyncConfirmationUIWindowPixelTest, InvokeUi_default) { @@ -203,6 +274,9 @@ SyncConfirmationUIDialogPixelTest() : ProfilesPixelTestBaseT<DialogBrowserTest>(GetParam().pixel_test_param) { DCHECK(GetParam().sync_style != SyncConfirmationStyle::kWindow); + + ConfigureMinorModeRestrictionFeature(GetParam().minor_mode_restrictions, + scoped_feature_list); } ~SyncConfirmationUIDialogPixelTest() override = default; @@ -211,7 +285,9 @@ void ShowUi(const std::string& name) override { DCHECK(browser()); - SignInWithAccount(GetParam().account_management_status); + SignInWithAccount(GetParam().account_management_status, + signin::ConsentLevel::kSignin, + GetParam().minor_mode_restrictions.capability); auto url = GURL(chrome::kChromeUISyncConfirmationURL); if (GetParam().sync_style == SyncConfirmationStyle::kSigninInterceptModal) { url = AppendSyncConfirmationQueryParams(url, GetParam().sync_style); @@ -232,6 +308,9 @@ widget_waiter.WaitIfNeededAndGet(); observer.Wait(); } + + private: + base::test::ScopedFeatureList scoped_feature_list; }; IN_PROC_BROWSER_TEST_P(SyncConfirmationUIDialogPixelTest, InvokeUi_default) {
diff --git a/chrome/browser/ui/views/tab_search_bubble_host.cc b/chrome/browser/ui/views/tab_search_bubble_host.cc index 5c88d55..6698387 100644 --- a/chrome/browser/ui/views/tab_search_bubble_host.cc +++ b/chrome/browser/ui/views/tab_search_bubble_host.cc
@@ -7,9 +7,12 @@ #include "base/functional/bind.h" #include "base/i18n/rtl.h" #include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" #include "base/trace_event/trace_event.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/feature_engagement/tracker_factory.h" +#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h" +#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/browser_finder.h" @@ -59,7 +62,10 @@ TabSearchBubbleHost::TabSearchBubbleHost(views::Button* button, Profile* profile) - : button_(button), + : optimization_guide::SettingsEnabledObserver( + optimization_guide::proto::ModelExecutionFeature:: + MODEL_EXECUTION_FEATURE_TAB_ORGANIZATION), + button_(button), profile_(profile), webui_bubble_manager_(button, profile, @@ -76,6 +82,12 @@ tab_organization_service->AddObserver(this); } } + OptimizationGuideKeyedService* optimization_guide_keyed_service = + OptimizationGuideKeyedServiceFactory::GetForProfile(profile); + if (optimization_guide_keyed_service) { + optimization_guide_keyed_service->AddModelExecutionSettingsEnabledObserver( + this); + } auto menu_button_controller = std::make_unique<views::MenuButtonController>( button, base::BindRepeating(&TabSearchBubbleHost::ButtonPressed, @@ -93,6 +105,12 @@ tab_organization_service->RemoveObserver(this); } } + OptimizationGuideKeyedService* optimization_guide_keyed_service = + OptimizationGuideKeyedServiceFactory::GetForProfile(profile_); + if (optimization_guide_keyed_service) { + optimization_guide_keyed_service + ->RemoveModelExecutionSettingsEnabledObserver(this); + } } void TabSearchBubbleHost::OnWidgetVisibilityChanged(views::Widget* widget, @@ -103,15 +121,23 @@ base::BindOnce( [](base::TimeTicks bubble_created_time, bool bubble_using_cached_web_contents, + WebUIBubbleWarmUpLevel bubble_warmup_level, base::TimeTicks presentation_timestamp) { + base::TimeDelta time_to_show = + presentation_timestamp - bubble_created_time; base::UmaHistogramMediumTimes( bubble_using_cached_web_contents ? "Tabs.TabSearch.WindowTimeToShowCachedWebView2" : "Tabs.TabSearch.WindowTimeToShowUncachedWebView2", - presentation_timestamp - bubble_created_time); + time_to_show); + base::UmaHistogramMediumTimes( + base::StrCat({"Tabs.TabSearch.TimeToShow.", + ToString(bubble_warmup_level)}), + time_to_show); }, *bubble_created_time_, - webui_bubble_manager_.bubble_using_cached_web_contents())); + webui_bubble_manager_.bubble_using_cached_web_contents(), + webui_bubble_manager_.bubble_warmup_level())); bubble_created_time_.reset(); } } @@ -147,6 +173,21 @@ } } +void TabSearchBubbleHost::OnChangeInFeatureCurrentlyEnabledState( + bool is_now_enabled) { + auto* const tab_organization_service = + TabOrganizationServiceFactory::GetForProfile(profile_); + if (!tab_organization_service) { + return; + } + + if (is_now_enabled) { + tab_organization_service->AddObserver(this); + } else { + tab_organization_service->RemoveObserver(this); + } +} + bool TabSearchBubbleHost::ShowTabSearchBubble( bool triggered_by_keyboard_shortcut, int tab_index) {
diff --git a/chrome/browser/ui/views/tab_search_bubble_host.h b/chrome/browser/ui/views/tab_search_bubble_host.h index faf4820..cafdc07 100644 --- a/chrome/browser/ui/views/tab_search_bubble_host.h +++ b/chrome/browser/ui/views/tab_search_bubble_host.h
@@ -24,7 +24,8 @@ // TabSearchBubbleHost assumes responsibility for configuring its button, // showing / hiding the tab search bubble and handling metrics collection. class TabSearchBubbleHost : public views::WidgetObserver, - public TabOrganizationObserver { + public TabOrganizationObserver, + public optimization_guide::SettingsEnabledObserver { public: TabSearchBubbleHost(views::Button* button, Profile* profile); TabSearchBubbleHost(const TabSearchBubbleHost&) = delete; @@ -39,6 +40,9 @@ void OnOrganizationAccepted(const Browser* browser) override; void OnUserInvokedFeature(const Browser* browser) override; + // SettingsEnabledObserver + void OnChangeInFeatureCurrentlyEnabledState(bool is_now_enabled) override; + // When this is called the bubble may already be showing or be loading in. // This returns true if the method call results in the creation of a new Tab // Search bubble. Optionally use tab_index to force the bubble to open to the
diff --git a/chrome/browser/ui/views/tab_search_bubble_host_browsertest.cc b/chrome/browser/ui/views/tab_search_bubble_host_browsertest.cc index 351383fb..fe0271d 100644 --- a/chrome/browser/ui/views/tab_search_bubble_host_browsertest.cc +++ b/chrome/browser/ui/views/tab_search_bubble_host_browsertest.cc
@@ -9,11 +9,11 @@ #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/browser/ui/views/bubble/webui_bubble_manager.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "ui/base/accelerators/accelerator.h" #include "ui/gfx/geometry/rect.h" @@ -22,13 +22,6 @@ #include "chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h" #endif -void EnterFullscreen(Browser* browser) { - browser->exclusive_access_manager() - ->fullscreen_controller() - ->ToggleBrowserFullscreenMode(); - FullscreenNotificationObserver(browser).Wait(); -} - class TabSearchBubbleHostBrowserTest : public InProcessBrowserTest { public: BrowserView* browser_view() { @@ -74,7 +67,7 @@ IN_PROC_BROWSER_TEST_F(TabSearchBubbleHostBrowserTest, BubbleShowCorrectlyInFullscreen) { - EnterFullscreen(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); gfx::Rect rect(20, 4, 0, 0); bubble_manager()->ShowBubble(rect); @@ -124,7 +117,7 @@ const FullscreenTabSearchBubbleDialogTest&) = delete; void ShowUi(const std::string& name) override { - EnterFullscreen(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); BrowserView* view = BrowserView::GetBrowserViewForBrowser(browser()); view->CreateTabSearchBubble(); }
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc b/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc index e907b3c..3fffe66f 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc
@@ -500,9 +500,7 @@ void TabHoverCardController::OnViewIsDeleting(views::View* observed_view) { if (hover_card_ == observed_view) { if (hover_card_tab_memory_usage_enabled_) { - performance_manager::user_tuning::UserPerformanceTuningManager:: - GetInstance() - ->RemoveObserver(this); + TabResourceUsageCollector::Get()->RemoveObserver(this); } delayed_show_timer_.Stop(); hover_card_observation_.Reset(); @@ -543,7 +541,7 @@ } } -void TabHoverCardController::OnMemoryMetricsRefreshed() { +void TabHoverCardController::OnTabResourceMetricsRefreshed() { if (hover_card_ != nullptr && target_tab_ != nullptr) { UpdateHoverCard(target_tab_, TabSlotController::HoverCardUpdateType::kTabDataChanged); @@ -581,9 +579,7 @@ } if (hover_card_tab_memory_usage_enabled_) { - performance_manager::user_tuning::UserPerformanceTuningManager:: - GetInstance() - ->AddObserver(this); + TabResourceUsageCollector::Get()->AddObserver(this); } }
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller.h b/chrome/browser/ui/views/tabs/tab_hover_card_controller.h index 75e180f..79cb3e3 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_controller.h +++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller.h
@@ -15,7 +15,7 @@ #include "base/scoped_observation.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h" +#include "chrome/browser/ui/performance_controls/tab_resource_usage_collector.h" #include "chrome/browser/ui/views/tabs/tab_slot_controller.h" #include "components/prefs/pref_change_registrar.h" #include "ui/events/event.h" @@ -34,9 +34,8 @@ class TabStrip; // Controls how hover cards are shown and hidden for tabs. -class TabHoverCardController - : public views::ViewObserver, - performance_manager::user_tuning::UserPerformanceTuningManager::Observer { +class TabHoverCardController : public views::ViewObserver, + public TabResourceUsageCollector::Observer { public: explicit TabHoverCardController(TabStrip* tab_strip); ~TabHoverCardController() override; @@ -90,8 +89,8 @@ void OnViewVisibilityChanged(views::View* observed_view, views::View* starting_view) override; - // UserPerformanceTuningManager::Observer: - void OnMemoryMetricsRefreshed() override; + // TabResourceUsageCollector::Observer: + void OnTabResourceMetricsRefreshed() override; bool ArePreviewsEnabled() const;
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc index 096be8af..97dd1700 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/performance_controls/memory_saver_utils.h" #include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h" +#include "chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h" #include "chrome/browser/ui/performance_controls/test_support/memory_saver_browser_test_mixin.h" #include "chrome/browser/ui/tabs/tab_enums.h" #include "chrome/browser/ui/ui_features.h" @@ -514,7 +515,8 @@ auto ForceRefreshMemoryMetrics() { return Steps(FlushEvents(), Do(base::BindLambdaForTesting([=]() { - ForceRefreshMemoryMetricsAndWait(); + TabResourceUsageRefreshWaiter waiter; + waiter.Wait(); }))); } }; @@ -621,7 +623,7 @@ tab_resource_usage_tab_helper->SetMemoryUsageInBytes(bytes_used); GetTabStrip(browser()) ->hover_card_controller_for_testing() - ->OnMemoryMetricsRefreshed(); + ->OnTabResourceMetricsRefreshed(); EXPECT_EQ(l10n_util::FormatString( l10n_util::GetStringUTF16(IDS_HOVERCARD_TAB_HIGH_MEMORY_USAGE), {ui::FormatBytes(bytes_used)}, nullptr),
diff --git a/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc b/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc index dd1058b..f43d11c 100644 --- a/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc +++ b/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc
@@ -5,7 +5,6 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h" #include "chrome/browser/ui/views/frame/top_container_view.h" @@ -15,6 +14,7 @@ #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/test/base/interactive_test_utils.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_test_api.h" #include "content/public/test/browser_test.h" @@ -78,9 +78,7 @@ // Test that the web app menu button opens a menu on click in immersive mode. IN_PROC_BROWSER_TEST_F(WebAppAshInteractiveUITest, ImmersiveMenuButtonClickable) { - FullscreenNotificationObserver waiter(browser()); - chrome::ToggleFullscreenMode(browser()); - waiter.Wait(); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); std::unique_ptr<ImmersiveRevealedLock> revealed_lock = controller_->GetRevealedLock(
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index 056fcea7..b3cb3ba8 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -51,7 +51,6 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" #include "chrome/browser/ui/startup/web_app_startup_utils.h" @@ -1224,13 +1223,10 @@ if (!BeforeStateChangeAction(__FUNCTION__)) { return; } - BrowserFullscreenModeWaiter fullscreen_observer( - app_browser(), /*wait_until_exit_fullscreen_mode=*/false); FullscreenController* fullscreen_controller = app_browser()->exclusive_access_manager()->fullscreen_controller(); ASSERT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); - fullscreen_controller->ToggleBrowserFullscreenMode(); - fullscreen_observer.Wait(); + ui_test_utils::ToggleFullscreenModeAndWait(app_browser()); ASSERT_TRUE(fullscreen_controller->IsFullscreenForBrowser()); AfterStateChangeAction(); } @@ -1239,13 +1235,10 @@ if (!BeforeStateChangeAction(__FUNCTION__)) { return; } - BrowserFullscreenModeWaiter fullscreen_observer( - app_browser(), /*wait_until_exit_fullscreen_mode=*/true); FullscreenController* fullscreen_controller = app_browser()->exclusive_access_manager()->fullscreen_controller(); ASSERT_TRUE(fullscreen_controller->IsFullscreenForBrowser()); - fullscreen_controller->ToggleBrowserFullscreenMode(); - fullscreen_observer.Wait(); + ui_test_utils::ToggleFullscreenModeAndWait(app_browser()); ASSERT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); AfterStateChangeAction(); }
diff --git a/chrome/browser/ui/views/webauthn/authenticator_request_bubble.cc b/chrome/browser/ui/views/webauthn/authenticator_request_bubble.cc index b800437..f1911931 100644 --- a/chrome/browser/ui/views/webauthn/authenticator_request_bubble.cc +++ b/chrome/browser/ui/views/webauthn/authenticator_request_bubble.cc
@@ -25,6 +25,10 @@ #include "ui/views/style/typography.h" #include "ui/views/view_class_properties.h" +#if BUILDFLAG(IS_MAC) +#include "chrome/browser/ui/views/webauthn/mac_authentication_view.h" +#endif // BUILDFLAG(IS_MAC) + namespace { struct BubbleContents { @@ -39,6 +43,13 @@ &AuthenticatorRequestDialogModel::StartOver; }; +constexpr BubbleContents kGPMTouchID = { + .title = u"Touch ID to proceed (UNTRANSLATED)", + .body = nullptr, + .show_footer = false, + .on_ok = &AuthenticatorRequestDialogModel::OnGPMCreate, +}; + constexpr BubbleContents kGPMCreateContents = { .illustration_light_id = IDR_WEBAUTHN_GPM_FINGERPRINT_LIGHT, .title = u"Create passkey for example.com? (UNTRANSLATED)", @@ -110,6 +121,8 @@ return &kGPMCreateContents; case AuthenticatorRequestDialogModel::Step::kTrustThisComputer: return &kTrustThisComputerContents; + case AuthenticatorRequestDialogModel::Step::kGPMTouchID: + return &kGPMTouchID; default: NOTREACHED(); return nullptr; @@ -178,6 +191,14 @@ std::unique_ptr<views::View> view = CreateViewForContents(*bubble_contents_); primary_view_->AddChildView(std::move(view)); +#if BUILDFLAG(IS_MAC) + if (step == AuthenticatorRequestDialogModel::Step::kGPMTouchID) { + if (__builtin_available(macos 12, *)) { + primary_view_->AddChildView( + std::make_unique<MacAuthenticationView>(base::DoNothing())); + } + } +#endif // BUILDFLAG(IS_MAC) } bool OnOk() {
diff --git a/chrome/browser/ui/views/webauthn/mac_authentication_view.h b/chrome/browser/ui/views/webauthn/mac_authentication_view.h new file mode 100644 index 0000000..720becd --- /dev/null +++ b/chrome/browser/ui/views/webauthn/mac_authentication_view.h
@@ -0,0 +1,49 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_WEBAUTHN_MAC_AUTHENTICATION_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_MAC_AUTHENTICATION_VIEW_H_ + +#include <memory> + +#include "base/functional/callback_forward.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/view.h" + +// MacAuthenticationView wraps an `LAAuthenticationView` such that it can be +// used in Views. It shows a biometric UI on macOS that collects Touch ID, and +// then triggers a callback. +class API_AVAILABLE(macos(12)) MacAuthenticationView : public views::View { + METADATA_HEADER(MacAuthenticationView, views::View) + + public: + explicit MacAuthenticationView( + // This callback is called when Touch ID is complete with a boolean that + // indicates whether the operation was successful. + base::OnceCallback<void(bool)> callback); + ~MacAuthenticationView() override; + + // views::View: + gfx::Size CalculatePreferredSize() const override; + void Layout(PassKey) override; + void AddedToWidget() override; + void RemovedFromWidget() override; + void OnPaint(gfx::Canvas*) override; + void VisibilityChanged(views::View* from, bool is_visible) override; + + private: + struct ObjCStorage; + + void OnAuthenticationComplete(bool success); + + base::OnceCallback<void(bool)> callback_; + std::unique_ptr<ObjCStorage> storage_; + bool evaluation_requested_ = false; + + base::WeakPtrFactory<MacAuthenticationView> weak_factory_{this}; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_MAC_AUTHENTICATION_VIEW_H_
diff --git a/chrome/browser/ui/views/webauthn/mac_authentication_view.mm b/chrome/browser/ui/views/webauthn/mac_authentication_view.mm new file mode 100644 index 0000000..6a62340 --- /dev/null +++ b/chrome/browser/ui/views/webauthn/mac_authentication_view.mm
@@ -0,0 +1,133 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/webauthn/mac_authentication_view.h" + +#import <LocalAuthentication/LocalAuthentication.h> +#import <LocalAuthenticationEmbeddedUI/LocalAuthenticationEmbeddedUI.h> + +#include "base/logging.h" +#include "components/device_event_log/device_event_log.h" +#include "content/public/browser/browser_thread.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/gfx/canvas.h" +#include "ui/views/widget/widget.h" + +// kWidth is the width (and height, since it's square) of the NSView. This +// particular width matches Safari, but isn't any of the predefined sizes. +constexpr int kWidth = 40; + +struct API_AVAILABLE(macos(12.0)) MacAuthenticationView::ObjCStorage { + LAContext* __strong context; + LAAuthenticationView* __strong auth_view; +}; + +MacAuthenticationView::MacAuthenticationView( + base::OnceCallback<void(bool)> callback) + : callback_(std::move(callback)), + storage_(std::make_unique<ObjCStorage>()) { + storage_->context = [[LAContext alloc] init]; + storage_->auth_view = + [[LAAuthenticationView alloc] initWithContext:storage_->context]; + + // The size of the NSView is set as constraints on itself. But none of the + // standard sizes match the size used in Safari. Thus we erase them set our + // own. + [storage_->auth_view removeConstraints:storage_->auth_view.constraints]; + [storage_->auth_view.widthAnchor constraintEqualToConstant:kWidth].active = + YES; + [storage_->auth_view.heightAnchor constraintEqualToConstant:kWidth].active = + YES; + return; +} + +MacAuthenticationView::~MacAuthenticationView() = default; + +gfx::Size MacAuthenticationView::CalculatePreferredSize() const { + return gfx::Size(kWidth, kWidth); +} + +void MacAuthenticationView::AddedToWidget() { + // An `LAAuthenticationView` is an NSView, but Chromium uses the Views + // framework for its UI, which just renders pixels onto a backing surface + // (called a "widget"). Thus any NSViews have to be composited onto what + // Views renders and positioned in the right place. + // + // Here the `LAAuthenticationView` is added to the NSWindow for this View, and + // positioned above it so that it's painted on top. We assume that the first + // existing NSView in the NSWindow is the `ViewsCompositorSuperview` that + // Views renders onto. + NSWindow* window = GetWidget()->GetNativeWindow().GetNativeNSWindow(); + [window.contentView addSubview:storage_->auth_view + positioned:NSWindowAbove + relativeTo:window.contentView.subviews[0]]; +} + +void MacAuthenticationView::RemovedFromWidget() { + [storage_->auth_view removeFromSuperview]; +} + +void MacAuthenticationView::Layout(PassKey) { + gfx::Rect bounds = this->bounds(); + // The bounds of this View include the offset from its parent View. + // However, `ConvertPointToWidget` (below) already takes this offset into + // account so it must be zeroed here to avoid it being applied twice. + bounds.set_x(0); + bounds.set_y(0); + // The LAAuthenticationView is centered within this View. + bounds.ClampToCenteredSize(gfx::Size(kWidth, kWidth)); + // The Widget represents the backing surface onto which Views renders. We need + // to know the position of the LAAuthenticationView in relation to the widget + // because NSView doesn't know anything about Chromium's Views tree. + gfx::Point point = bounds.origin(); + View::ConvertPointToWidget(this, &point); + // Views puts (0, 0) at the top left and positive-y is downwards. But NSView + // puts (0,0) at the bottom-left and positive-y is up. So we need to know the + // height of the Widget to adjust things. + gfx::Rect widget_rect = this->GetWidget()->GetClientAreaBoundsInScreen(); + // Place the LAAuthenticationView after adjusting for the different coordinate + // system. + storage_->auth_view.frame = + NSMakeRect(point.x(), widget_rect.height() - point.y() - bounds.height(), + kWidth, kWidth); +} + +void MacAuthenticationView::OnPaint(gfx::Canvas* canvas) { + views::View::OnPaint(canvas); + if (GetVisible() && !evaluation_requested_) { + __block auto internal_callback = + base::BindOnce(&MacAuthenticationView::OnAuthenticationComplete, + weak_factory_.GetWeakPtr()); + [storage_->context + evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics + localizedReason:@"NOT USED" + reply:^(BOOL success, NSError* error) { + if (error) { + FIDO_LOG(ERROR) << "Touch ID failed with error: " + << error.localizedDescription.UTF8String; + } + content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::UI) + ->PostTask(FROM_HERE, + base::BindOnce(std::move(internal_callback), + success)); + }]; + evaluation_requested_ = true; + } +} + +void MacAuthenticationView::VisibilityChanged(views::View* from, + bool is_visible) { + views::View::VisibilityChanged(from, is_visible); + storage_->auth_view.hidden = !is_visible; +} + +void MacAuthenticationView::OnAuthenticationComplete(bool success) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + storage_->context = nil; + std::move(callback_).Run(success); +} + +BEGIN_METADATA(MacAuthenticationView) +END_METADATA
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc index 42c6108..20de85d8 100644 --- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc +++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -336,6 +336,7 @@ case Step::kTrustThisComputer: case Step::kWaitingForEnclave: case Step::kGPMCreate: + case Step::kGPMTouchID: sheet_view = std::make_unique<AuthenticatorRequestSheetView>( std::make_unique<PlaceholderSheetModel>(dialog_model)); break;
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc index a8e0d45..41110c5b 100644 --- a/chrome/browser/ui/web_applications/web_app_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -50,7 +50,6 @@ #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/page_info/page_info_dialog.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/toolbar/app_menu_model.h" @@ -2087,9 +2086,7 @@ EXPECT_TRUE( popup_browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)); - FullscreenNotificationObserver waiter(popup_browser); - chrome::ToggleFullscreenMode(popup_browser); - waiter.Wait(); + ui_test_utils::ToggleFullscreenModeAndWait(popup_browser); EXPECT_TRUE( popup_browser->CanSupportWindowFeature(Browser::FEATURE_LOCATIONBAR));
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc index 3e7513c..381c3ff 100644 --- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc +++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -700,6 +700,9 @@ } else if (name == "gpm_create") { model_->SetCurrentStepForTesting( AuthenticatorRequestDialogModel::Step::kGPMCreate); + } else if (name == "touchid") { + model_->SetCurrentStepForTesting( + AuthenticatorRequestDialogModel::Step::kGPMTouchID); } else { NOTREACHED(); } @@ -781,3 +784,9 @@ InvokeUi_gpm_create) { ShowAndVerifyUi(); } + +#if BUILDFLAG(IS_MAC) +IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest, InvokeUi_touchid) { + ShowAndVerifyUi(); +} +#endif // BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc index a37d79c9..47e3f99 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc +++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -9,6 +9,7 @@ #include "base/functional/bind.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" +#include "base/notreached.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/consent_auditor/consent_auditor_factory.h" #include "chrome/browser/profiles/profile.h" @@ -26,6 +27,7 @@ #include "components/signin/public/base/avatar_icon_util.h" #include "components/signin/public/base/consent_level.h" #include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/tribool.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "url/gurl.h" @@ -43,6 +45,20 @@ const int kProfileImageSize = 128; } // namespace +SyncConfirmationScreenMode GetScreenMode( + const AccountCapabilities& capabilities) { + switch ( + capabilities + .can_show_history_sync_opt_ins_without_minor_mode_restrictions()) { + case signin::Tribool::kUnknown: + return SyncConfirmationScreenMode::kPending; + case signin::Tribool::kFalse: + return SyncConfirmationScreenMode::kRestricted; + case signin::Tribool::kTrue: + return SyncConfirmationScreenMode::kUnrestricted; + } +} + SyncConfirmationHandler::SyncConfirmationHandler( Profile* profile, const std::unordered_map<std::string, int>& string_to_grd_id_map, @@ -57,7 +73,6 @@ SyncConfirmationHandler::~SyncConfirmationHandler() { BrowserList::RemoveObserver(this); - identity_manager_->RemoveObserver(this); // Abort signin and prevent sync from starting if none of the actions on the // sync confirmation dialog are taken by the user. @@ -188,11 +203,12 @@ GURL picture_gurl(info.picture_url); GURL picture_gurl_with_options = signin::GetAvatarImageURLWithOptions( - picture_gurl, kProfileImageSize, false /* no_silhouette */); + picture_gurl, kProfileImageSize, /*no_silhouette=*/false); base::Value::Dict value; value.Set("src", picture_gurl_with_options.spec()); value.Set("showEnterpriseBadge", info.IsManaged()); + value.Set("screenMode", static_cast<int>(GetScreenMode(info.capabilities))); AllowJavascript(); FireWebUIListener("account-info-changed", value); @@ -208,7 +224,14 @@ return; } - identity_manager_->RemoveObserver(this); + if (GetScreenMode(info.capabilities) != + SyncConfirmationScreenMode::kPending) { + // AccountCapabilities are fetched asynchronously, so stop observing changes + // only after the screen mode derived from the capability is not pending + // anymore. + identity_manager_observation_.Reset(); + } + SetAccountInfo(info); } @@ -246,8 +269,10 @@ return; } - if (!primary_account_info.IsValid()) { - identity_manager_->AddObserver(this); + if (!(primary_account_info.IsValid() && + GetScreenMode(primary_account_info.capabilities) != + SyncConfirmationScreenMode::kPending)) { + identity_manager_observation_.Observe(identity_manager_); } else { SetAccountInfo(primary_account_info); }
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h index ab5ed52..60f528da 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h +++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
@@ -9,9 +9,12 @@ #include <unordered_map> #include "base/memory/raw_ptr.h" +#include "base/memory/safety_checks.h" +#include "base/notreached.h" #include "base/values.h" #include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h" +#include "components/signin/public/identity_manager/account_capabilities.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "content/public/browser/web_ui_message_handler.h" @@ -19,6 +22,18 @@ class IdentityManager; } +// LINT.IfChange(screen_mode) +enum class SyncConfirmationScreenMode : int { + kUnsupported = 0, + kPending = 1, + kRestricted = 2, + kUnrestricted = 3, +}; + +SyncConfirmationScreenMode GetScreenMode( + const AccountCapabilities& capabilities); +// LINT.ThenChange(//chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts:screen_mode) + // WebUI message handler for the sync confirmation dialog. IdentityManager calls // in this class use signin::ConsentLevel::kSignin because the user hasn't // consented to sync yet. @@ -118,6 +133,10 @@ raw_ptr<Browser> browser_; raw_ptr<signin::IdentityManager> identity_manager_; + + base::ScopedObservation<signin::IdentityManager, + signin::IdentityManager::Observer> + identity_manager_observation_{this}; }; #endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_SYNC_CONFIRMATION_HANDLER_H_
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc index e63163a7..026b10b 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc +++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
@@ -34,6 +34,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/consent_auditor/fake_consent_auditor.h" #include "components/signin/public/base/avatar_icon_util.h" +#include "components/signin/public/identity_manager/account_capabilities_test_mutator.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_ui.h" @@ -223,7 +224,8 @@ const char SyncConfirmationHandlerTest::kConsentText4[] = "consentText4"; const char SyncConfirmationHandlerTest::kConsentText5[] = "consentText5"; -TEST_F(SyncConfirmationHandlerTest, TestSetAccountInfoIfPrimaryAccountReady) { +TEST_F(SyncConfirmationHandlerTest, + TestAccountInfoAloneIsNotEnoughToTriggerAccountInfoChange) { identity_test_env()->SimulateSuccessfulFetchOfAccountInfo( account_info_.account_id, account_info_.email, account_info_.gaia, "", "full_name", "given_name", "locale", @@ -233,6 +235,26 @@ args.Append(kDefaultDialogHeight); handler()->HandleInitializedWithSize(args); + EXPECT_EQ(0U, web_ui()->call_data().size()); +} + +TEST_F(SyncConfirmationHandlerTest, + TestSetAccountInfoIfPrimaryAccountAndCapabilitiesReady) { + identity_test_env()->SimulateSuccessfulFetchOfAccountInfo( + account_info_.account_id, account_info_.email, account_info_.gaia, "", + "full_name", "given_name", "locale", + "http://picture.example.com/picture.jpg"); + + // Both account info and capability are required to trigger SetAccountInfo. + AccountCapabilitiesTestMutator mutator(&account_info_.capabilities); + mutator.set_can_show_history_sync_opt_ins_without_minor_mode_restrictions( + true); + identity_test_env()->UpdateAccountInfoForAccount(account_info_); + + base::Value::List args; + args.Append(kDefaultDialogHeight); + handler()->HandleInitializedWithSize(args); + ASSERT_EQ(1U, web_ui()->call_data().size()); ExpectAccountInfoChanged(*web_ui()->call_data()[0]); } @@ -284,12 +306,19 @@ ExpectAccountInfoChanged(*web_ui()->call_data()[0]); } -TEST_F(SyncConfirmationHandlerTest, TestSetAccountInfoManaged) { +TEST_F(SyncConfirmationHandlerTest, + TestSetAccountInfoManagedIfPrimaryAccountAndCapabilitiesReady) { identity_test_env()->SimulateSuccessfulFetchOfAccountInfo( account_info_.account_id, account_info_.email, account_info_.gaia, "google.com", "full_name", "given_name", "locale", "http://picture.example.com/picture.jpg"); + // Both account info and capability are required to trigger SetAccountInfo. + AccountCapabilitiesTestMutator mutator(&account_info_.capabilities); + mutator.set_can_show_history_sync_opt_ins_without_minor_mode_restrictions( + false); + identity_test_env()->UpdateAccountInfoForAccount(account_info_); + base::Value::List args; args.Append(kDefaultDialogHeight); handler()->HandleInitializedWithSize(args);
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc index 89f6d5b8..98cd9943 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc +++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -34,6 +34,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/signin_resources.h" #include "components/signin/public/base/avatar_icon_util.h" +#include "components/signin/public/base/consent_level.h" #include "components/signin/public/base/signin_switches.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/strings/grit/components_strings.h" @@ -82,20 +83,23 @@ return false; } -// Implements static compliance with -// CanShowHistorySyncOptInsWithoutMinorModeRestrictions capability requirement, -// as if the capability was always set to the opposite of the feature flag. -// -// When kMinorModeRestrictionsForHistorySyncOptIn feature is enabled, the -// compliance is achieved for all users without reading -// CanShowHistorySyncOptInsWithoutMinorModeRestrictions value. -bool UnrestrictedMode() { +// Derives screen mode of sync opt in screen from the +// CanShowHistorySyncOptInsWithoutMinorModeRestrictions capability. +SyncConfirmationScreenMode GetInitialScreenMode( + signin::IdentityManager* identity_manager) { #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) // ChromeOs handles minor modes separately. - return true; + return SyncConfirmationScreenMode::kUnrestricted; #else - return !base::FeatureList::IsEnabled( - ::switches::kMinorModeRestrictionsForHistorySyncOptIn); + if (base::FeatureList::IsEnabled( + ::switches::kMinorModeRestrictionsForHistorySyncOptIn)) { + CoreAccountInfo account_info = + identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin); + AccountInfo account = + identity_manager->FindExtendedAccountInfo(account_info); + return GetScreenMode(account.capabilities); + } + return SyncConfirmationScreenMode::kUnrestricted; #endif } @@ -338,7 +342,10 @@ // Registering other variables that are computed above based on multiple // factors (e.g. platform). source->AddBoolean("useClickableSyncInfoDesc", use_clickable_sync_info_desc); - source->AddBoolean("unrestrictedMode", UnrestrictedMode()); + + source->AddInteger("screenMode", + static_cast<int>(GetInitialScreenMode( + IdentityManagerFactory::GetForProfile(profile_)))); } void SyncConfirmationUI::InitializeForSyncDisabled( @@ -368,6 +375,9 @@ : IDS_SYNC_DISABLED_CONFIRMATION_CONFIRM_BUTTON_LABEL); AddStringResource(source, "syncDisabledConfirmationUndoLabel", IDS_SYNC_DISABLED_CONFIRMATION_UNDO_BUTTON_LABEL); + + source->AddInteger( + "screenMode", static_cast<int>(SyncConfirmationScreenMode::kUnsupported)); } void SyncConfirmationUI::AddStringResource(content::WebUIDataSource* source,
diff --git a/chrome/browser/ui/webui/signin/turn_sync_on_helper_browsertest.cc b/chrome/browser/ui/webui/signin/turn_sync_on_helper_browsertest.cc index d920421..e9964d6 100644 --- a/chrome/browser/ui/webui/signin/turn_sync_on_helper_browsertest.cc +++ b/chrome/browser/ui/webui/signin/turn_sync_on_helper_browsertest.cc
@@ -379,8 +379,15 @@ // For the scenario in https://crbug.com/1404961, the reconcilor has to be // triggered by the account removal. +#if BUILDFLAG(IS_CHROMEOS_LACROS) ASSERT_EQ(reconcilor->GetState(), signin_metrics::AccountReconcilorState::kRunning); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + // On Dice platforms with `switches::kUnoDesktop` enabled and empty primary + // account, updating cookies is disabled. Therefore running the reconcilor + // doesn't require any network requests and might have been completed by now. + // The reconcilor will not remove the account from cookies but revoking + // refresh tokens should be sufficient to invalidate cookies. } #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc index ef5e666..4288205 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc +++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -179,7 +179,10 @@ content::WebUI* web_ui, ui::MojoBubbleWebUIController* webui_controller, MetricsReporter* metrics_reporter) - : receiver_(this, std::move(receiver)), + : optimization_guide::SettingsEnabledObserver( + optimization_guide::proto::ModelExecutionFeature:: + MODEL_EXECUTION_FEATURE_TAB_ORGANIZATION), + receiver_(this, std::move(receiver)), page_(std::move(page)), web_ui_(web_ui), webui_controller_(webui_controller), @@ -196,13 +199,6 @@ tab_search_prefs::kTabSearchTabIndex, base::BindRepeating(&TabSearchPageHandler::NotifyTabIndexPrefChanged, base::Unretained(this), profile)); - pref_change_registrar_.Add( - optimization_guide::prefs::GetSettingEnabledPrefName( - optimization_guide::proto::ModelExecutionFeature:: - MODEL_EXECUTION_FEATURE_TAB_ORGANIZATION), - base::BindRepeating( - &TabSearchPageHandler::NotifySettingEnabledPrefChanged, - base::Unretained(this), profile)); if (TabOrganizationUtils::GetInstance()->IsEnabled(profile)) { organization_service_ = TabOrganizationServiceFactory::GetForProfile(profile); @@ -210,6 +206,12 @@ organization_service_->AddObserver(this); } } + optimization_guide_keyed_service_ = + OptimizationGuideKeyedServiceFactory::GetForProfile(profile); + if (optimization_guide_keyed_service_) { + optimization_guide_keyed_service_->AddModelExecutionSettingsEnabledObserver( + this); + } } TabSearchPageHandler::~TabSearchPageHandler() { @@ -225,6 +227,10 @@ for (TabOrganizationSession* session : listened_sessions_) { session->RemoveObserver(this); } + if (optimization_guide_keyed_service_) { + optimization_guide_keyed_service_ + ->RemoveModelExecutionSettingsEnabledObserver(this); + } pref_change_registrar_.Reset(); } @@ -1024,22 +1030,6 @@ page_->TabSearchTabIndexChanged(index); } -void TabSearchPageHandler::NotifySettingEnabledPrefChanged(Profile* profile) { - bool enabled = false; - if (TabOrganizationUtils::GetInstance()->IsEnabled(profile)) { - organization_service_ = - TabOrganizationServiceFactory::GetForProfile(profile); - if (organization_service_) { - enabled = true; - organization_service_->AddObserver(this); - } - } else if (organization_service_) { - organization_service_->RemoveObserver(this); - organization_service_ = nullptr; - } - page_->TabOrganizationEnabledChanged(enabled); -} - bool TabSearchPageHandler::IsWebContentsVisible() { auto visibility = web_ui_->GetWebContents()->GetVisibility(); return visibility == content::Visibility::VISIBLE || @@ -1179,6 +1169,22 @@ OnTabOrganizationSessionUpdated(session); } +void TabSearchPageHandler::OnChangeInFeatureCurrentlyEnabledState( + bool is_now_enabled) { + Profile* const profile = Profile::FromWebUI(web_ui_); + if (is_now_enabled) { + organization_service_ = + TabOrganizationServiceFactory::GetForProfile(profile); + if (organization_service_) { + organization_service_->AddObserver(this); + } + } else if (organization_service_) { + organization_service_->RemoveObserver(this); + organization_service_ = nullptr; + } + page_->TabOrganizationEnabledChanged(is_now_enabled && organization_service_); +} + bool TabSearchPageHandler::ShouldTrackBrowser(Browser* browser) { return browser->profile() == Profile::FromWebUI(web_ui_) && browser->type() == Browser::Type::TYPE_NORMAL;
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h index 8c5a509a9..0708fb7 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h +++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
@@ -18,6 +18,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h" +#include "components/optimization_guide/core/model_execution/settings_enabled_observer.h" #include "components/prefs/pref_change_registrar.h" #include "components/sessions/core/tab_restore_service.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -30,6 +31,7 @@ class Browser; class MetricsReporter; class TabOrganizationService; +class OptimizationGuideKeyedService; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. @@ -47,11 +49,13 @@ kMaxValue = kCollapse, }; -class TabSearchPageHandler : public tab_search::mojom::PageHandler, - public TabStripModelObserver, - public BrowserTabStripTrackerDelegate, - public TabOrganizationSession::Observer, - public TabOrganizationObserver { +class TabSearchPageHandler + : public tab_search::mojom::PageHandler, + public TabStripModelObserver, + public BrowserTabStripTrackerDelegate, + public TabOrganizationSession::Observer, + public TabOrganizationObserver, + public optimization_guide::SettingsEnabledObserver { public: TabSearchPageHandler( mojo::PendingReceiver<tab_search::mojom::PageHandler> receiver, @@ -129,6 +133,9 @@ void OnSessionCreated(const Browser* browser, TabOrganizationSession* session) override; + // SettingsEnabledObserver + void OnChangeInFeatureCurrentlyEnabledState(bool is_now_enabled) override; + protected: void SetTimerForTesting(std::unique_ptr<base::RetainingOneShotTimer> timer); @@ -191,8 +198,6 @@ void NotifyTabIndexPrefChanged(const Profile* profile); - void NotifySettingEnabledPrefChanged(Profile* profile); - mojo::Receiver<tab_search::mojom::PageHandler> receiver_; mojo::Remote<tab_search::mojom::Page> page_; const raw_ptr<content::WebUI> web_ui_; @@ -203,6 +208,7 @@ std::unique_ptr<base::RetainingOneShotTimer> debounce_timer_; raw_ptr<TabOrganizationService> organization_service_; PrefChangeRegistrar pref_change_registrar_; + raw_ptr<OptimizationGuideKeyedService> optimization_guide_keyed_service_; // Tracks how many times |CloseTab()| has been evoked for the currently open // instance of Tab Search for logging in UMA.
diff --git a/chrome/browser/vr/chrome_xr_integration_client.cc b/chrome/browser/vr/chrome_xr_integration_client.cc index 225a54fd..6f44294c 100644 --- a/chrome/browser/vr/chrome_xr_integration_client.cc +++ b/chrome/browser/vr/chrome_xr_integration_client.cc
@@ -135,20 +135,16 @@ #if BUILDFLAG(IS_ANDROID) // May be unused if all runtimes are disabled. - [[maybe_unused]] bool preferred_vr_runtime_added = false; [[maybe_unused]] const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); #if BUILDFLAG(ENABLE_OPENXR) - if (!preferred_vr_runtime_added && - IsEnabled(command_line, switches::kWebXrRuntimeOpenXr, + if (IsEnabled(command_line, switches::kWebXrRuntimeOpenXr, &device::features::kOpenXR)) { providers.emplace_back(std::make_unique<webxr::OpenXrDeviceProvider>()); - preferred_vr_runtime_added = true; } #endif // BUILDFLAG(ENABLE_OPENXR) #if BUILDFLAG(ENABLE_CARDBOARD) - if (!preferred_vr_runtime_added && - IsEnabled(command_line, switches::kWebXrRuntimeCardboard)) { + if (IsEnabled(command_line, switches::kWebXrRuntimeCardboard)) { base::android::ScopedJavaLocalRef<jobject> j_vr_compositor_delegate_provider = vr::Java_VrCompositorDelegateProviderImpl_Constructor( @@ -156,7 +152,6 @@ providers.emplace_back(std::make_unique<webxr::CardboardDeviceProvider>( std::make_unique<webxr::VrCompositorDelegateProvider>( std::move(j_vr_compositor_delegate_provider)))); - preferred_vr_runtime_added = true; } #endif // BUILDFLAG(ENABLE_CARDBOARD) #if BUILDFLAG(ENABLE_ARCORE)
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc index 9d8a7f33..e461bd74 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -310,6 +310,7 @@ case webapps::WebappUninstallSource::kExternalLockScreen: case webapps::WebappUninstallSource::kInstallUrlDeduping: case webapps::WebappUninstallSource::kHealthcareUserInstallCleanup: + case webapps::WebappUninstallSource::kIwaEnterprisePolicy: return apps::Readiness::kUninstalledByNonUser; } }
diff --git a/chrome/browser/web_applications/externally_managed_app_manager.cc b/chrome/browser/web_applications/externally_managed_app_manager.cc index 508a1bca..a2db5c7 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager.cc
@@ -19,7 +19,6 @@ #include "base/strings/to_string.h" #include "base/task/sequenced_task_runner.h" #include "base/values.h" -#include "build/chromeos_buildflags.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/external_install_options.h" #include "chrome/browser/web_applications/externally_managed_app_install_task.h" @@ -40,10 +39,6 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/url_constants.h" -#if BUILDFLAG(IS_CHROMEOS) -#include "base/containers/cxx20_erase.h" -#endif - namespace web_app { ExternallyManagedAppManager::InstallResult::InstallResult() = default; @@ -560,24 +555,6 @@ urls_to_remove_debug->Append(url_to_remove.spec()); } -#if BUILDFLAG(IS_CHROMEOS) - // This check ensures that on Chrome OS, the messages app is not uninstalled - // automatically when SynchronizeInstalledApps() is called for preinstalled - // apps. - // TODO(crbug.com/1239801): Once Messages has been migrated to be a - // preinstalled app, this logic can be removed because the - // PreInstalledWebAppManager will take care of this. - if (!urls_to_remove.empty() && - ConvertExternalInstallSourceToSource(install_source) == - WebAppManagement::kDefault) { - base::EraseIf(urls_to_remove, [&](const GURL& url) { - return url.spec() == - "https://messages-web.sandbox.google.com/web/authentication" || - url.spec() == "https://messages.google.com/web/authentication"; - }); - } -#endif - // Run callback immediately if there's no work to be done. if (urls_to_remove.empty() && desired_apps_install_options.empty()) { base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc index 461208e..751a20e 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
@@ -19,7 +19,6 @@ #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/test_future.h" -#include "build/chromeos_buildflags.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/apps/app_service/publishers/app_publisher.h" @@ -264,50 +263,6 @@ Expect(0, 1, std::vector<GURL>{}); } -#if BUILDFLAG(IS_CHROMEOS) -using ExternallyManagedAppManagerTestAndroidSMS = - ExternallyManagedAppManagerTest; -// This test verifies that AndroidSMS is not uninstalled during the Syncing -// process. -TEST_F(ExternallyManagedAppManagerTestAndroidSMS, - SynchronizeAppsAndroidSMSTest) { - GURL android_sms_url1( - "https://messages-web.sandbox.google.com/web/authentication"); - GURL android_sms_url2("https://messages.google.com/web/authentication"); - GURL extra_url("https://extra.com/"); - - // Install all URLs first. - Sync(std::vector<GURL>{android_sms_url1, android_sms_url2, extra_url}); - Expect(/*deduped_install_count=*/3, /*deduped_uninstall_count=*/0, - std::vector<GURL>{extra_url, android_sms_url1, android_sms_url2}); - - // Assume that extra_url is the only URL desired. - // install_count = 0 as no new installs happen. - // uninstall_count = 0 as android sms URLs does not get uninstalled. - // Both android SMS URLs remain. - Sync(std::vector<GURL>{extra_url}); - Expect(/*deduped_install_count=*/0, /*deduped_uninstall_count=*/0, - std::vector<GURL>{extra_url, android_sms_url1, android_sms_url2}); - - // Assume that android_sms_url1 is only required. - // install_count = 0 as no new installs happen. - // uninstall_count = 1 as extra.com gets uninstalled. - // Both android SMS URLs remain. - Sync(std::vector<GURL>{android_sms_url1}); - Expect(/*deduped_install_count=*/0, /*deduped_uninstall_count=*/1, - std::vector<GURL>{android_sms_url1, android_sms_url2}); - - // Assume that no URL is required. - // install_count = 0 as no new installs happen. - // uninstall_count = 0 as android sms URLs does not get uninstalled. - // Both android SMS URLs remain. - Sync(std::vector<GURL>{}); - Expect(/*deduped_install_count=*/0, /*deduped_uninstall_count=*/0, - std::vector<GURL>{android_sms_url1, android_sms_url2}); -} - -#endif - namespace { using ::testing::ElementsAre;
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc index cfe8facd2..8d6ec87 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc
@@ -103,6 +103,19 @@ return installed_ids; } +bool IsWebBundleIdInPolicy( + const std::vector<web_app::IsolatedWebAppExternalInstallOptions>& + apps_in_policy, + const web_package::SignedWebBundleId& web_bundle_id) { + auto are_ids_equal = + [web_bundle_id]( + const web_app::IsolatedWebAppExternalInstallOptions& app_in_policy) { + return web_bundle_id == app_in_policy.web_bundle_id(); + }; + return std::find_if(apps_in_policy.begin(), apps_in_policy.end(), + are_ids_equal) != apps_in_policy.end(); +} + } // namespace namespace web_app { @@ -223,19 +236,14 @@ DownloadUpdateManifest(); } -void BulkIwaInstaller::SetResultAndContinue(EphemeralAppInstallResult result) { +void BulkIwaInstaller::FinishWithResult(EphemeralAppInstallResult result) { const auto index = std::distance(ephemeral_iwa_install_options_.begin(), current_app_); result_vector_.at(index) = result; - // If the error occurs after the directory for an app had been created, - // then we should wipe the directory. - if (result != EphemeralAppInstallResult::kSuccess) { - WipeCurrentIwaDirectory(); - return; - } - - ContinueWithTheNextApp(); + // We always copy the downloaded files into the profile during installation. + // So we don't need the downloaded file any more. + WipeIwaDownloadDirectory(); } void BulkIwaInstaller::SetResultForAllAndFinish( @@ -251,16 +259,16 @@ if (!update_manifest.has_value()) { switch (update_manifest.error()) { case UpdateManifestFetcher::Error::kDownloadFailed: - SetResultAndContinue( + FinishWithResult( EphemeralAppInstallResult::kErrorUpdateManifestDownloadFailed); break; case UpdateManifestFetcher::Error::kInvalidJson: case UpdateManifestFetcher::Error::kInvalidManifest: - SetResultAndContinue( + FinishWithResult( EphemeralAppInstallResult::kErrorUpdateManifestParsingFailed); break; case UpdateManifestFetcher::Error::kNoApplicableVersion: - SetResultAndContinue( + FinishWithResult( EphemeralAppInstallResult::kErrorWebBundleUrlCantBeDetermined); break; } @@ -288,8 +296,7 @@ void BulkIwaInstaller::OnIwaDirectoryCreated(const base::FilePath& iwa_dir, base::File::Error error) { if (error != base::File::FILE_OK) { - SetResultAndContinue( - EphemeralAppInstallResult::kErrorCantCreateIwaDirectory); + FinishWithResult(EphemeralAppInstallResult::kErrorCantCreateIwaDirectory); return; } @@ -340,8 +347,7 @@ current_bundle_downloader_.reset(); if (net_error != net::OK) { - SetResultAndContinue( - EphemeralAppInstallResult::kErrorCantDownloadWebBundle); + FinishWithResult(EphemeralAppInstallResult::kErrorCantDownloadWebBundle); return; } @@ -362,30 +368,74 @@ LOG(ERROR) << "Could not install the IWA " << current_app_->web_bundle_id().id(); } - SetResultAndContinue( + FinishWithResult( result.has_value() ? EphemeralAppInstallResult::kSuccess : EphemeralAppInstallResult::kErrorCantInstallFromWebBundle); } -void BulkIwaInstaller::WipeCurrentIwaDirectory() { +void BulkIwaInstaller::WipeIwaDownloadDirectory() { const base::FilePath iwa_path_to_delete(current_app_->app_directory()); current_app_->reset_app_directory(); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, base::BindOnce(&base::DeletePathRecursively, iwa_path_to_delete), - base::BindOnce(&BulkIwaInstaller::OnCurrentIwaDirectoryWiped, + base::BindOnce(&BulkIwaInstaller::OnIwaDownloadDirectoryWiped, weak_factory_.GetWeakPtr())); } -void BulkIwaInstaller::OnCurrentIwaDirectoryWiped(bool wipe_result) { +void BulkIwaInstaller::OnIwaDownloadDirectoryWiped(bool wipe_result) { if (!wipe_result) { LOG(ERROR) << "Could not wipe an IWA directory"; } ContinueWithTheNextApp(); } + +BulkIwaUninstaller::BulkIwaUninstaller( + web_app::WebAppProvider* provider, + std::vector<web_package::SignedWebBundleId> to_be_removed, + base::OnceCallback<void(std::vector<webapps::UninstallResultCode>)> + uninstall_cb) + : to_be_removed_(std::move(to_be_removed)), + current_app_(to_be_removed_.begin()), + provider_(provider), + uninstall_cb_(std::move(uninstall_cb)) {} + +BulkIwaUninstaller::~BulkIwaUninstaller() = default; + +void BulkIwaUninstaller::UninstallApps() { + CHECK(!uninstall_cb_.is_null()); + CHECK(current_app_ == to_be_removed_.begin()); + + if (current_app_ == to_be_removed_.end()) { + std::move(uninstall_cb_).Run(std::vector<webapps::UninstallResultCode>()); + return; + } + + UninstallApp(*current_app_); +} + +void BulkIwaUninstaller::UninstallApp( + const web_package::SignedWebBundleId& id) { + IsolatedWebAppUrlInfo url_info = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(id); + provider_->scheduler().UninstallWebApp( + url_info.app_id(), webapps::WebappUninstallSource::kIwaEnterprisePolicy, + base::BindOnce(&BulkIwaUninstaller::OnAppUninstalled, + weak_factory_.GetWeakPtr())); +} + +void BulkIwaUninstaller::OnAppUninstalled(webapps::UninstallResultCode result) { + results_.push_back(result); + ++current_app_; + if (current_app_ == to_be_removed_.end()) { + std::move(uninstall_cb_).Run(std::move(results_)); + } else { + UninstallApp(*current_app_); + } +} } // namespace internal IsolatedWebAppPolicyManager::IsolatedWebAppPolicyManager(Profile* profile) @@ -422,6 +472,12 @@ policy_is_being_processed_ = true; + // So far we support only MGS. + if (!chromeos::IsManagedGuestSession()) { + OnPolicyProcessed(); + return; + } + provider_->scheduler().ScheduleCallback<AllAppsLock>( "IsolatedWebAppPolicyManager::ProcessPolicy", AllAppsLockDescription(), base::BindOnce(&IsolatedWebAppPolicyManager::DoProcessPolicy, @@ -433,6 +489,10 @@ AllAppsLock& lock, base::Value::Dict& debug_info) { CHECK(provider_); + CHECK(to_be_installed_.empty()); + CHECK(to_be_removed_.empty()); + CHECK(!bulk_installer_.get()); + CHECK(!bulk_uninstaller_.get()); const base::Value::List& iwa_policy_values = profile_->GetPrefs()->GetList(prefs::kIsolatedWebAppInstallForceList); @@ -446,24 +506,53 @@ debug_info.Set("installed_apps", base::ToString(installed_apps)); // This currently only installs apps that aren't already installed. - // TODO (peletskyi@): Implement removal in the app in not in the policy. // TODO (peletskyi@): As soon as we support version pinning // implement force update. - std::vector<IsolatedWebAppExternalInstallOptions> to_be_installed; for (const IsolatedWebAppExternalInstallOptions& app : apps_in_policy) { if (!base::Contains(installed_apps, app.web_bundle_id())) { - to_be_installed.push_back(app); + to_be_installed_.push_back(app); } } - debug_info.Set("to_be_installed", base::ToString(to_be_installed)); + debug_info.Set("to_be_installed", base::ToString(to_be_installed_)); - if (to_be_installed.empty()) { - OnPolicyProcessed( - std::vector< - web_app::internal::BulkIwaInstaller::EphemeralAppInstallResult>()); - return; + for (const web_package::SignedWebBundleId& installed_app : installed_apps) { + if (!IsWebBundleIdInPolicy(apps_in_policy, installed_app)) { + to_be_removed_.push_back(installed_app); + } + } + debug_info.Set("to_be_removed", base::ToString(to_be_removed_)); + + // Let's start with uninstalling because: + // - we free up space for the potential installs; + // - usually there is a strong reason why an admin whats to uninstall an app + // (e.g. security vulnerability). So it is better to uninstall it ASAP. + Uninstall(); +} + +void IsolatedWebAppPolicyManager::Uninstall() { + bulk_uninstaller_ = std::make_unique<internal::BulkIwaUninstaller>( + provider_, to_be_removed_, + base::BindOnce(&IsolatedWebAppPolicyManager::OnUninstalled, + weak_ptr_factory_.GetWeakPtr())); + bulk_uninstaller_->UninstallApps(); +} + +void IsolatedWebAppPolicyManager::OnUninstalled( + std::vector<webapps::UninstallResultCode> uninstall_results) { + for (size_t i = 0; i < uninstall_results.size(); ++i) { + if (uninstall_results[i] != webapps::UninstallResultCode::kSuccess) { + DLOG(WARNING) << "Could not uninstall IWA " << to_be_removed_[i].id() + << " Error: " << static_cast<int>(uninstall_results[i]); + } } + bulk_uninstaller_.reset(); + to_be_removed_.clear(); + + Install(); +} + +void IsolatedWebAppPolicyManager::Install() { std::unique_ptr<internal::BulkIwaInstaller::IwaInstallCommandWrapper> installer = std::make_unique< internal::BulkIwaInstaller::IwaInstallCommandWrapperImpl>(provider_); @@ -471,21 +560,29 @@ auto url_loader_factory = profile_->GetURLLoaderFactory(); auto install_complete_callback = - base::BindOnce(&IsolatedWebAppPolicyManager::OnPolicyProcessed, + base::BindOnce(&IsolatedWebAppPolicyManager::OnInstalled, weak_ptr_factory_.GetWeakPtr()); bulk_installer_ = std::make_unique<internal::BulkIwaInstaller>( - profile_->GetPath(), to_be_installed, url_loader_factory, + profile_->GetPath(), to_be_installed_, url_loader_factory, std::move(installer), std::move(install_complete_callback)); bulk_installer_->InstallEphemeralApps(); } -void IsolatedWebAppPolicyManager::OnPolicyProcessed( +void IsolatedWebAppPolicyManager::OnInstalled( std::vector<web_app::internal::BulkIwaInstaller::EphemeralAppInstallResult> result) { - policy_is_being_processed_ = false; - bulk_installer_.reset(); LogIsolatedWebAppInstallResult(std::move(result)); + + bulk_installer_.reset(); + to_be_installed_.clear(); + + OnPolicyProcessed(); +} + +void IsolatedWebAppPolicyManager::OnPolicyProcessed() { + policy_is_being_processed_ = false; + if (!on_started_callback_.is_null()) { std::move(on_started_callback_).Run(); }
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h index 3731726..db3ce75 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h
@@ -127,11 +127,11 @@ void OnIwaInstalled(base::expected<InstallIsolatedWebAppCommandSuccess, InstallIsolatedWebAppCommandError> result); - // Completely removes IWA directory. - void WipeCurrentIwaDirectory(); - void OnCurrentIwaDirectoryWiped(bool wipe_result); + // Removes the directory where the IWA has been downloaded. + void WipeIwaDownloadDirectory(); + void OnIwaDownloadDirectoryWiped(bool wipe_result); - void SetResultAndContinue(EphemeralAppInstallResult result); + void FinishWithResult(EphemeralAppInstallResult result); void SetResultForAllAndFinish(EphemeralAppInstallResult result); void ContinueWithTheNextApp(); @@ -157,6 +157,27 @@ base::WeakPtrFactory<BulkIwaInstaller> weak_factory_{this}; }; +class BulkIwaUninstaller { + public: + BulkIwaUninstaller( + web_app::WebAppProvider* provider, + std::vector<web_package::SignedWebBundleId> to_be_removed, + base::OnceCallback<void(std::vector<webapps::UninstallResultCode>)>); + ~BulkIwaUninstaller(); + void UninstallApps(); + + private: + void UninstallApp(const web_package::SignedWebBundleId& id); + void OnAppUninstalled(webapps::UninstallResultCode result); + std::vector<web_package::SignedWebBundleId> to_be_removed_; + std::vector<web_package::SignedWebBundleId>::iterator current_app_; + const raw_ptr<web_app::WebAppProvider> provider_; + base::OnceCallback<void(std::vector<webapps::UninstallResultCode>)> + uninstall_cb_; + std::vector<webapps::UninstallResultCode> results_; + base::WeakPtrFactory<BulkIwaUninstaller> weak_factory_{this}; +}; + } // namespace internal // This class is responsible for installing, uninstalling, updating etc. @@ -176,7 +197,13 @@ private: void ProcessPolicy(); void DoProcessPolicy(AllAppsLock& lock, base::Value::Dict& debug_info); - void OnPolicyProcessed( + void OnPolicyProcessed(); + + void Uninstall(); + void OnUninstalled( + std::vector<webapps::UninstallResultCode> uninstall_results); + void Install(); + void OnInstalled( std::vector< web_app::internal::BulkIwaInstaller::EphemeralAppInstallResult> result); @@ -185,10 +212,14 @@ raw_ptr<WebAppProvider> provider_ = nullptr; PrefChangeRegistrar pref_change_registrar_; std::unique_ptr<internal::BulkIwaInstaller> bulk_installer_; + std::unique_ptr<internal::BulkIwaUninstaller> bulk_uninstaller_; base::OnceClosure on_started_callback_; bool reprocess_policy_needed_ = false; bool policy_is_being_processed_ = false; + std::vector<IsolatedWebAppExternalInstallOptions> to_be_installed_; + std::vector<web_package::SignedWebBundleId> to_be_removed_; + base::WeakPtrFactory<IsolatedWebAppPolicyManager> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc index b61fe5ca..92bd86b 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc
@@ -13,6 +13,8 @@ #include "base/files/file_util.h" #include "base/strings/strcat.h" #include "base/strings/string_piece.h" +#include "base/test/bind.h" +#include "base/test/test_future.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/ash/login/existing_user_controller.h" @@ -39,6 +41,7 @@ #include "components/policy/core/common/policy_namespace.h" #include "components/policy/policy_constants.h" #include "components/policy/proto/chrome_device_policy.pb.h" +#include "content/public/browser/browsing_data_remover.h" #include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" @@ -311,4 +314,58 @@ .app_id()); } +IN_PROC_BROWSER_TEST_F(IsolatedWebAppPolicyManagerAshBrowserTest, + PolicyDelete) { + SetupServer(); + + AddManagedGuestSessionToDevicePolicy(); + + UploadAndInstallDeviceLocalAccountPolicy(); + WaitForPolicy(); + + // Log in in the managed guest session. + // There no IWA policy set at the moment of login. + ASSERT_NO_FATAL_FAILURE(StartLogin()); + WaitForSessionStart(); + + // Set the policy with 2 IWA and wait for the IWAs to be installed. + const webapps::AppId id1 = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(iwa_bundle_2_.id) + .app_id(); + const webapps::AppId id2 = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(iwa_bundle_2_.id) + .app_id(); + WebAppTestInstallObserver install_observer(GetProfileForTest()); + install_observer.BeginListening({id1, id2}); + + SetPolicyWithTwoApps(); + install_observer.Wait(); + + const WebAppProvider* provider = + WebAppProvider::GetForTest(GetProfileForTest()); + ASSERT_TRUE(provider->registrar_unsafe().IsInstalled(id1)); + ASSERT_TRUE(provider->registrar_unsafe().IsInstalled(id2)); + + // Prepare testing environment for uninstalling. + base::RunLoop run_loop; + auto* browsing_data_remover = GetProfileForTest()->GetBrowsingDataRemover(); + browsing_data_remover->SetWouldCompleteCallbackForTesting( + base::BindLambdaForTesting([&](base::OnceClosure callback) { + if (browsing_data_remover->GetPendingTaskCountForTesting() == 1) { + run_loop.Quit(); + } + std::move(callback).Run(); + })); + + // Set the policy with 1 IWA and wait for the unnecessary IWA to be + // uninstalled. + WebAppTestUninstallObserver uninstall_observer(GetProfileForTest()); + uninstall_observer.BeginListening({id2}); + SetPolicyWithOneApp(); + + run_loop.Run(); + + ASSERT_EQ(uninstall_observer.Wait(), id2); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc index 97886da..c55f771 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc
@@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "base/containers/contains.h" +#include "base/containers/flat_set.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -58,8 +60,6 @@ "https://example.com/6/update-manifest-6.json"; constexpr char kUpdateManifestUrl7[] = "https://example.com/7/update-manifest-7.json"; -constexpr char kUpdateManifestUrl8[] = - "https://example.com/8/update-manifest-8.json"; constexpr char kUpdateManifestValue1[] = R"( {"versions":[ @@ -78,13 +78,10 @@ [{"version": "1.0.0", "src": "chrome-extension://app5.wbn"}]})"; constexpr char kUpdateManifestValue6[] = R"( {"versions": - [{"version": "1.0.0", "src": "https://example.com/app6.swbn"}]})"; + [{"version": "1.0.0","src": "https://example.com/app6.swbn"}]})"; constexpr char kUpdateManifestValue7[] = R"( {"versions": [{"version": "1.0.0", "src": "https://example.com/app7.swbn"}]})"; -constexpr char kUpdateManifestValue8[] = R"( - {"versions": - [{"version": "1.0.0","src": "https://example.com/app8.swbn"}]})"; constexpr char kWebBundleId1[] = "aerugqztij5biqquuk3mfwpsaibuegaqcitgfchwuosuofdjabzqaaic"; @@ -96,11 +93,10 @@ "derugqztij5biqquuk3mfwpsaibuegaqcitgfchwuosuofdjabzqaaic"; constexpr char kWebBundleId5[] = "eerugqztij5biqquuk3mfwpsaibuegaqcitgfchwuosuofdjabzqaaic"; -constexpr base::StringPiece kWebBundleId6 = kWebBundleId1; +constexpr char kWebBundleId6[] = + "herugqztij5biqquuk3mfwpsaibuegaqcitgfchwuosuofdjabzqaaic"; constexpr char kWebBundleId7[] = "gerugqztij5biqquuk3mfwpsaibuegaqcitgfchwuosuofdjabzqaaic"; -constexpr char kWebBundleId8[] = - "herugqztij5biqquuk3mfwpsaibuegaqcitgfchwuosuofdjabzqaaic"; base::Value CreatePolicyEntry(base::StringPiece web_bundle_id, base::StringPiece update_manifest_url) { @@ -144,7 +140,7 @@ IsolatedWebAppExternalInstallOptions app_options_5 = IsolatedWebAppExternalInstallOptions::FromPolicyPrefValue(policy_value_5) .value(); - // ID of the App 6 is the same as ID of the App 1. + // The Web Bundle of the App 6 can't be installed. const base::Value policy_value_6 = CreatePolicyEntry(kWebBundleId6, kUpdateManifestUrl6); IsolatedWebAppExternalInstallOptions app_options_6 = @@ -156,12 +152,6 @@ IsolatedWebAppExternalInstallOptions app_options_7 = IsolatedWebAppExternalInstallOptions::FromPolicyPrefValue(policy_value_7) .value(); - // The Web Bundle of the App 8 can't be installed. - const base::Value policy_value_8 = - CreatePolicyEntry(kWebBundleId8, kUpdateManifestUrl8); - IsolatedWebAppExternalInstallOptions app_options_8 = - IsolatedWebAppExternalInstallOptions::FromPolicyPrefValue(policy_value_8) - .value(); std::vector<IsolatedWebAppExternalInstallOptions> options; options.push_back(std::move(app_options_1)); @@ -171,7 +161,7 @@ options.push_back(std::move(app_options_5)); options.push_back(std::move(app_options_6)); options.push_back(std::move(app_options_7)); - options.push_back(std::move(app_options_8)); + return options; } @@ -226,15 +216,15 @@ AddJsonResponse(kUpdateManifestUrl5, kUpdateManifestValue5); AddJsonResponse(kUpdateManifestUrl6, kUpdateManifestValue6); AddJsonResponse(kUpdateManifestUrl7, kUpdateManifestValue7); - AddJsonResponse(kUpdateManifestUrl8, kUpdateManifestValue8); test_factory_.AddResponse("https://example.com/app1.swbn", "Content of app1"); test_factory_.AddResponse("https://example.com/app2.swbn", "Content of app2"); + test_factory_.AddResponse("https://example.com/app6.swbn", + "Content of app6"); test_factory_.AddResponse("https://example.com/app7.swbn", "", net::HttpStatusCode::HTTP_NOT_FOUND); - test_factory_.AddResponse("https://example.com/app8.swbn", - "Content of app8"); + test_managed_guest_session_ = std::make_unique<profiles::testing::ScopedTestManagedGuestSession>(); } @@ -279,11 +269,10 @@ expected_results.at(4) = internal::BulkIwaInstaller:: EphemeralAppInstallResult::kErrorWebBundleUrlCantBeDetermined; expected_results.at(5) = internal::BulkIwaInstaller:: - EphemeralAppInstallResult::kErrorCantCreateIwaDirectory; + EphemeralAppInstallResult::kErrorCantInstallFromWebBundle; expected_results.at(6) = internal::BulkIwaInstaller:: EphemeralAppInstallResult::kErrorCantDownloadWebBundle; - expected_results.at(7) = internal::BulkIwaInstaller:: - EphemeralAppInstallResult::kErrorCantInstallFromWebBundle; + base::test::TestFuture< std::vector<internal::BulkIwaInstaller::EphemeralAppInstallResult>> future; @@ -296,25 +285,7 @@ const base::FilePath iwa_root_dir = dir_.GetPath().Append( internal::BulkIwaInstaller::kEphemeralIwaRootDirectory); - ASSERT_TRUE(base::DirectoryExists(iwa_root_dir)); - - // There should be 2 directories that represent successfully installed apps. - base::FileEnumerator iter( - iwa_root_dir, /*recursive=*/false, - base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); - int counter = 0; - while (!iter.Next().empty()) { - EXPECT_TRUE(iter.GetInfo().IsDirectory()); - ++counter; - } - EXPECT_EQ(counter, 2); - - EXPECT_TRUE(base::PathExists( - iwa_root_dir.Append(kWebBundleId1) - .Append(internal::BulkIwaInstaller::kMainSignedWebBundleFileName))); - EXPECT_TRUE(base::PathExists( - iwa_root_dir.Append(kWebBundleId2) - .Append(internal::BulkIwaInstaller::kMainSignedWebBundleFileName))); + ASSERT_TRUE(base::IsDirectoryEmpty(iwa_root_dir)); } // If there is no MGS we don't create root directory for the IWAs. @@ -419,6 +390,12 @@ provider().web_contents_manager()); } + void AssertAppInstalled(const web_package::SignedWebBundleId& swbn_id) { + const WebApp* web_app = fake_provider().registrar_unsafe().GetAppById( + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(swbn_id).app_id()); + ASSERT_THAT(web_app, testing::NotNull()) << "The app in not installed :("; + } + web_package::SignedWebBundleId get_app1_id() { return lazy_app1_id_.value(); } web_package::SignedWebBundleId get_app2_id() { return lazy_app2_id_.value(); } @@ -449,10 +426,7 @@ task_environment()->RunUntilIdle(); - const WebApp* web_app = fake_provider().registrar_unsafe().GetAppById( - IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(get_app1_id()) - .app_id()); - ASSERT_THAT(web_app, testing::NotNull()); + AssertAppInstalled(get_app1_id()); } // This implementation of the command scheduler can't install an IWA. Instead @@ -488,14 +462,14 @@ absl::optional<web_package::SignedWebBundleId> id_; }; -class IsolatedWebAppPolicyManagerPolicyRaceTest +template <typename T> +class IsolatedWebAppPolicyManagerCustomSchedulerTest : public IsolatedWebAppPolicyManagerTestBase { public: - TestWebAppCommandScheduler* get_command_scheduler() { return scheduler_; } + T* get_command_scheduler() { return scheduler_; } void SetCommandScheduler() override { - std::unique_ptr<TestWebAppCommandScheduler> scheduler = - std::make_unique<TestWebAppCommandScheduler>(*profile()); + std::unique_ptr<T> scheduler = std::make_unique<T>(*profile()); scheduler_ = scheduler.get(); fake_provider().SetScheduler(std::move(scheduler)); } @@ -506,9 +480,12 @@ } private: - raw_ptr<TestWebAppCommandScheduler> scheduler_; + raw_ptr<T> scheduler_; }; +using IsolatedWebAppPolicyManagerPolicyRaceTest = + IsolatedWebAppPolicyManagerCustomSchedulerTest<TestWebAppCommandScheduler>; + // Verifies that the updating of policy during previous policy processing // is handled correctly. TEST_F(IsolatedWebAppPolicyManagerPolicyRaceTest, @@ -566,4 +543,154 @@ task_environment()->RunUntilIdle(); } +// This scheduler is intercepting scheduling of the uninstall command, +// verifying if the App ID is expected for removal and returns the +// uninstall error. +class UninstallWebAppCommandScheduler : public WebAppCommandScheduler { + public: + using WebAppCommandScheduler::WebAppCommandScheduler; + + void UninstallWebApp(const webapps::AppId& app_id, + webapps::WebappUninstallSource uninstall_source, + UninstallJob::Callback callback, + const base::Location& location) override { + tried_to_uninstall_ = true; + EXPECT_TRUE(base::Contains(expected_apps_to_remove_, app_id)); + EXPECT_EQ(uninstall_source, + webapps::WebappUninstallSource::kIwaEnterprisePolicy); + auto app = expected_apps_to_remove_.find(app_id); + expected_apps_to_remove_.erase(app); + std::move(callback).Run(webapps::UninstallResultCode ::kError); + } + + void AddExpectedToUninstallApp(const webapps::AppId& app_id) { + expected_apps_to_remove_.insert(app_id); + } + + size_t GetNumberOfAppsRemainingToUninstall() const { + return expected_apps_to_remove_.size(); + } + + bool TriedToUninstall() { return tried_to_uninstall_; } + + private: + base::flat_set<webapps::AppId> expected_apps_to_remove_; + bool tried_to_uninstall_ = false; +}; + +using IsolatedWebAppPolicyManagerUninstallTest = + IsolatedWebAppPolicyManagerCustomSchedulerTest< + UninstallWebAppCommandScheduler>; + +// Remove the app from policy and check if there will be attempt to uninstall +// that app. +TEST_F(IsolatedWebAppPolicyManagerUninstallTest, OneAppUninstalled) { + // Force install 2 apps. + { + PolicyGenerator policy_generator_2_apps; + policy_generator_2_apps.AddForceInstalledIwa(get_app1_id(), + GURL(kUpdateManifestUrlApp1)); + policy_generator_2_apps.AddForceInstalledIwa(get_app2_id(), + GURL(kUpdateManifestUrlApp2)); + + profile()->GetPrefs()->Set(prefs::kIsolatedWebAppInstallForceList, + policy_generator_2_apps.Generate()); + + task_environment()->RunUntilIdle(); + + AssertAppInstalled(get_app1_id()); + AssertAppInstalled(get_app2_id()); + } + + // Now generate a policy with 1 app and expect an attempt to + // remove the other app. + { + PolicyGenerator policy_generator_1_app; + policy_generator_1_app.AddForceInstalledIwa(get_app1_id(), + GURL(kUpdateManifestUrlApp1)); + + const webapps::AppId app2_id = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(get_app2_id()) + .app_id(); + get_command_scheduler()->AddExpectedToUninstallApp(app2_id); + EXPECT_EQ(get_command_scheduler()->GetNumberOfAppsRemainingToUninstall(), + 1U); + + profile()->GetPrefs()->Set(prefs::kIsolatedWebAppInstallForceList, + policy_generator_1_app.Generate()); + + task_environment()->RunUntilIdle(); + + EXPECT_EQ(get_command_scheduler()->GetNumberOfAppsRemainingToUninstall(), + 0U); + } +} + +TEST_F(IsolatedWebAppPolicyManagerUninstallTest, BothAppUninstalled) { + // Force install 2 apps. + { + PolicyGenerator policy_generator; + policy_generator.AddForceInstalledIwa(get_app1_id(), + GURL(kUpdateManifestUrlApp1)); + policy_generator.AddForceInstalledIwa(get_app2_id(), + GURL(kUpdateManifestUrlApp2)); + + profile()->GetPrefs()->Set(prefs::kIsolatedWebAppInstallForceList, + policy_generator.Generate()); + + task_environment()->RunUntilIdle(); + + AssertAppInstalled(get_app1_id()); + AssertAppInstalled(get_app2_id()); + } + + // Set the policy without any app and expect an attempt to uninstall + // both previously installed apps. + { + PolicyGenerator empty_policy; + + const webapps::AppId app1_id = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(get_app1_id()) + .app_id(); + const webapps::AppId app2_id = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(get_app2_id()) + .app_id(); + get_command_scheduler()->AddExpectedToUninstallApp(app1_id); + get_command_scheduler()->AddExpectedToUninstallApp(app2_id); + EXPECT_EQ(get_command_scheduler()->GetNumberOfAppsRemainingToUninstall(), + 2U); + + profile()->GetPrefs()->Set(prefs::kIsolatedWebAppInstallForceList, + empty_policy.Generate()); + + task_environment()->RunUntilIdle(); + + EXPECT_EQ(get_command_scheduler()->GetNumberOfAppsRemainingToUninstall(), + 0U); + } +} + +// There should not be any attempt to uninstall an app if no apps have been +// removed from the apps. +TEST_F(IsolatedWebAppPolicyManagerUninstallTest, NoAppsUninstalled) { + PolicyGenerator policy_generator; + policy_generator.AddForceInstalledIwa(get_app1_id(), + GURL(kUpdateManifestUrlApp1)); + profile()->GetPrefs()->Set(prefs::kIsolatedWebAppInstallForceList, + policy_generator.Generate()); + task_environment()->RunUntilIdle(); + + AssertAppInstalled(get_app1_id()); + + policy_generator.AddForceInstalledIwa(get_app2_id(), + GURL(kUpdateManifestUrlApp2)); + profile()->GetPrefs()->Set(prefs::kIsolatedWebAppInstallForceList, + policy_generator.Generate()); + task_environment()->RunUntilIdle(); + + AssertAppInstalled(get_app1_id()); + AssertAppInstalled(get_app2_id()); + EXPECT_FALSE(get_command_scheduler()->TriedToUninstall()); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc b/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc index e7694766..eda2011 100644 --- a/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc +++ b/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc
@@ -49,7 +49,9 @@ uninstall_source == webapps::WebappUninstallSource::kStartupCleanup || uninstall_source == webapps::WebappUninstallSource::kTestCleanup || uninstall_source == - webapps::WebappUninstallSource::kHealthcareUserInstallCleanup; + webapps::WebappUninstallSource::kHealthcareUserInstallCleanup || + uninstall_source == + webapps::WebappUninstallSource::kIwaEnterprisePolicy; } } // namespace
diff --git a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc index e5b3cda..06268680 100644 --- a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc +++ b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.h" #include "base/command_line.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/hash/md5.h" #include "base/path_service.h" @@ -39,7 +40,7 @@ std::wstring key = base::StrCat({profile_path.value(), base::ASCIIToWide(app_id)}); base::MD5Digest digest; - base::MD5Sum(key.c_str(), key.size() * sizeof(wchar_t), &digest); + base::MD5Sum(base::as_byte_span(key), &digest); return base::ASCIIToWide(base::MD5DigestToBase16(digest)); }
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h index cdbce72..ee01b14 100644 --- a/chrome/browser/web_applications/web_app_command_scheduler.h +++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -287,10 +287,10 @@ // uninstalls them too if they have no other install sources. Adds the // uninstall web app to `UserUninstalledPreinstalledWebAppPrefs` if it was // default installed. - void UninstallWebApp(const webapps::AppId& app_id, - webapps::WebappUninstallSource uninstall_source, - UninstallJob::Callback callback, - const base::Location& location = FROM_HERE); + virtual void UninstallWebApp(const webapps::AppId& app_id, + webapps::WebappUninstallSource uninstall_source, + UninstallJob::Callback callback, + const base::Location& location = FROM_HERE); // Schedules a command that uninstalls all user-installed web apps. void UninstallAllUserInstalledWebApps(
diff --git a/chrome/browser/web_applications/web_app_constants.cc b/chrome/browser/web_applications/web_app_constants.cc index 5bca800..436cab7 100644 --- a/chrome/browser/web_applications/web_app_constants.cc +++ b/chrome/browser/web_applications/web_app_constants.cc
@@ -125,6 +125,8 @@ return "Install URL deduping"; case webapps::WebappUninstallSource::kHealthcareUserInstallCleanup: return "Healthcare User Install Cleanup"; + case webapps::WebappUninstallSource::kIwaEnterprisePolicy: + return "Isolated Web Apps Enterprise Policy"; } }
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index 228fca7..1237cfc 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -389,6 +389,7 @@ case AuthenticatorRequestDialogModel::Step::kGPMCreate: case AuthenticatorRequestDialogModel::Step::kTrustThisComputer: + case AuthenticatorRequestDialogModel::Step::kGPMTouchID: return StepUIType::BUBBLE; default:
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index 6b3ad3e7..a559457b 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -162,6 +162,10 @@ kTrustThisComputer, kGPMCreate, kWaitingForEnclave, + + // User verification prompt for GPM for demo purposes. + // TODO(nsatragno): integrate with create / get passkey instead. + kGPMTouchID, }; // Implemented by the dialog to observe this model and show the UI panels
diff --git a/chrome/browser/win/conflicts/inspection_results_cache.cc b/chrome/browser/win/conflicts/inspection_results_cache.cc index 4851c82e..4f24c70e 100644 --- a/chrome/browser/win/conflicts/inspection_results_cache.cc +++ b/chrome/browser/win/conflicts/inspection_results_cache.cc
@@ -7,6 +7,7 @@ #include <string> #include <utility> +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/important_file_writer.h" @@ -119,7 +120,7 @@ // Append the md5 digest of the data to detect serializations errors. base::MD5Digest md5_digest; - base::MD5Sum(pickle.payload(), pickle.payload_size(), &md5_digest); + base::MD5Sum(pickle.payload_bytes(), &md5_digest); pickle.WriteBytes(&md5_digest, sizeof(md5_digest)); return pickle; @@ -167,8 +168,8 @@ // Check if the md5 checksum matches. base::MD5Digest md5_digest; - base::MD5Sum(pickle.payload(), pickle.payload_size() - sizeof(md5_digest), - &md5_digest); + base::span<const uint8_t> payload = pickle.payload_bytes(); + base::MD5Sum(payload.first(payload.size() - sizeof(md5_digest)), &md5_digest); if (!base::ranges::equal(read_md5_digest->a, md5_digest.a)) return ReadCacheResult::kFailInvalidMD5;
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index 781fe50f..a7943c9 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1707177813-6d45c8b00f3860366b239f4c6b0e164f714e7766.profdata +chrome-chromeos-amd64-generic-main-1707220559-c81f8dd1478ee53193a3dc74228eb01f11a330ae.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index cbb15bc..3179ddd 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1707199177-3ffa5f2d59e628fc0e0050b3b530cf388455642e.profdata +chrome-linux-main-1707220559-52ccf6234e66a2ae6c814c5893632b7ee269087e.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 4e5657c7..5abb1b0 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1707206165-2cec8cfd5acfe2ba02e30042d0698539b7073f21.profdata +chrome-mac-arm-main-1707235122-971efa270f0dca8a5b38cb05caf7f7dac1a7adde.profdata
diff --git a/chrome/services/sharing/webrtc/ipc_network_manager.cc b/chrome/services/sharing/webrtc/ipc_network_manager.cc index a0ebb6b..17fa3ca 100644 --- a/chrome/services/sharing/webrtc/ipc_network_manager.cc +++ b/chrome/services/sharing/webrtc/ipc_network_manager.cc
@@ -119,11 +119,11 @@ DCHECK(it->address.IsIPv6()); iface_addr = rtc::InterfaceAddress(ip_address, it->ip_address_attributes); - // Only allow non-private, non-deprecated IPv6 addresses which don't - // contain MAC. + // Only allow non-link-local, non-loopback, non-deprecated IPv6 addresses + // which don't contain MAC. if (rtc::IPIsMacBased(iface_addr) || (it->ip_address_attributes & net::IP_ADDRESS_ATTRIBUTE_DEPRECATED) || - rtc::IPIsPrivate(iface_addr)) { + rtc::IPIsLinkLocal(iface_addr) || rtc::IPIsLoopback(iface_addr)) { continue; }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b7065f0..e590b64 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -618,6 +618,8 @@ "../browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h", "../browser/ui/performance_controls/test_support/memory_saver_browser_test_mixin.h", "../browser/ui/performance_controls/test_support/memory_saver_interactive_test_mixin.h", + "../browser/ui/performance_controls/test_support/resource_usage_collector_observer.cc", + "../browser/ui/performance_controls/test_support/resource_usage_collector_observer.h", "../browser/ui/performance_controls/test_support/user_education_browser_test_mixin.h", "../browser/ui/performance_controls/test_support/webui_interactive_test_mixin.h", "../browser/ui/profiles/profile_ui_test_utils.h", @@ -2666,6 +2668,7 @@ "../browser/ui/passwords/password_generation_popup_view_browsertest.cc", "../browser/ui/passwords/password_generation_popup_view_tester.h", "../browser/ui/passwords/well_known_change_password_navigation_throttle_browsertest.cc", + "../browser/ui/performance_controls/tab_resource_usage_collector_browsertest.cc", "../browser/ui/permission_bubble/permission_bubble_browser_test_util.cc", "../browser/ui/permission_bubble/permission_bubble_browser_test_util.h", "../browser/ui/prefs/prefs_tab_helper_browsertest.cc", @@ -6418,6 +6421,7 @@ "../browser/ssl/generated_https_first_mode_pref_unittest.cc", "../browser/ui/download/download_bubble_row_list_view_info_unittest.cc", "../browser/ui/download/download_bubble_row_view_info_unittest.cc", + "../browser/ui/download/download_bubble_security_view_info_unittest.cc", "../browser/ui/plus_addresses/plus_address_creation_controller_desktop_unittest.cc", "../browser/ui/safety_hub/menu_notification_service_unittest.cc", "../browser/ui/safety_hub/menu_notification_unittest.cc", @@ -7388,7 +7392,6 @@ "../browser/ui/android/toolbar/location_bar_model_android_unittest.cc", "../browser/ui/autofill/autofill_keyboard_accessory_adapter_unittest.cc", "../browser/ui/autofill/payments/autofill_snackbar_controller_impl_unittest.cc", - "../browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc", "../browser/ui/fast_checkout/fast_checkout_controller_impl_unittest.cc", "../browser/wallet/android/boarding_pass_detector_unittest.cc", "../browser/webauthn/android/cable_module_android_unittest.cc", @@ -7681,6 +7684,7 @@ "../browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl_unittest.cc", "../browser/ui/autofill/payments/offer_notification_bubble_controller_impl_unittest.cc", "../browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc", + "../browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc", "../browser/ui/autofill/save_update_address_profile_bubble_controller_impl_unittest.cc", "../browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc", "../browser/ui/bookmarks/bookmark_drag_drop_unittest.cc", @@ -8231,6 +8235,7 @@ "../browser/media/platform_verification_chromeos_unittest.cc", "../browser/performance_manager/policies/oom_score_policy_chromeos_unittest.cc", "../browser/performance_manager/policies/report_page_processes_policy_unittest.cc", + "../browser/policy/screen_capture_location_policy_handler_unittest.cc", "../browser/policy/system_features_disable_list_policy_handler_unittest.cc", "../browser/speech/tts_crosapi_util_unittest.cc", "../browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc",
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc index ce97adf..3740e0d 100644 --- a/chrome/test/base/ui_test_utils.cc +++ b/chrome/test/base/ui_test_utils.cc
@@ -37,6 +37,9 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" @@ -481,6 +484,83 @@ return minimize_waiter.Wait(); } +FullscreenWaiter::FullscreenWaiter(Browser* browser, + FullscreenWaiter::Expectation expectation) + : expectation_(std::move(expectation)), + controller_(browser->exclusive_access_manager()->fullscreen_controller()), + // Sometimes, the wait is called on a sequeunce, e.g. + // as a part of interactive_ui_tests's RunTestSequence. + // To handle that case, we can process pending task posted to the sequence + // in nested RunLoop. + run_loop_(base::RunLoop::Type::kNestableTasksAllowed), + satisfied_(IsSatisfied()) { + observation_.Observe(controller_); +} + +FullscreenWaiter::~FullscreenWaiter() = default; + +void FullscreenWaiter::Wait() { + if (satisfied_) { + return; + } + run_loop_.Run(); +} + +void FullscreenWaiter::OnFullscreenStateChanged() { + // Note: In Lacros, when full screen mode changes, FullscreenController + // triggers WindowFullscreenStateChanged twice for the same change + // asynchronously. If the test code toggles fullscreen mode on and off, there + // is a race between the second notification of fullscreen mode on and test + // code toggle fullscreen mode off. Wait until the fullscreen state changes to + // the expected mode. See details in crbug.com/1481727. + if (!IsSatisfied()) { + return; + } + satisfied_ = true; + if (run_loop_.running()) { + run_loop_.Quit(); + } +} + +bool FullscreenWaiter::IsSatisfied() const { + if (expectation_.browser_fullscreen.has_value() && + expectation_.browser_fullscreen.value() != + controller_->IsFullscreenForBrowser()) { + return false; + } + + if (expectation_.tab_fullscreen.has_value() && + expectation_.tab_fullscreen.value() != controller_->IsTabFullscreen()) { + return false; + } + + if (expectation_.display_id.has_value()) { + // Display ID is valid iff the tab fullscreen mode is active. + if (!controller_->IsTabFullscreen()) { + return false; + } + if (expectation_.display_id.value() != + FullscreenController::GetDisplayId( + *controller_->exclusive_access_tab())) { + return false; + } + } + + return true; +} + +void ToggleFullscreenModeAndWait(Browser* browser) { + // The waiting condition is following the current implementation. + // If the mode is either browser/tab fullscreen, it will be existed. + // Otherwise, entering into browser fullscreen. + bool current = browser->exclusive_access_manager()->context()->IsFullscreen(); + FullscreenWaiter waiter(browser, current ? FullscreenWaiter::kNoFullscreen + : FullscreenWaiter::Expectation{ + .browser_fullscreen = true}); + chrome::ToggleFullscreenMode(browser); + waiter.Wait(); +} + void SendToOmniboxAndSubmit(Browser* browser, const std::string& input, base::TimeTicks match_selection_timestamp) {
diff --git a/chrome/test/base/ui_test_utils.h b/chrome/test/base/ui_test_utils.h index 7c6caddcc..df278fc 100644 --- a/chrome/test/base/ui_test_utils.h +++ b/chrome/test/base/ui_test_utils.h
@@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/ui/browser_list_observer.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_observer.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/view_ids.h" @@ -27,6 +28,7 @@ #include "url/gurl.h" class Browser; +class FullscreenController; class Profile; namespace javascript_dialogs { @@ -199,6 +201,65 @@ // Returns success or not. bool WaitForMinimized(Browser* browser); +// Waits for fullscreen state to be updated. +// There're two variation of fullscreen concepts, browser fullscreen and +// tab fullscreen. Due to fullscreen implementation, fullscreen state may +// be updated synchronously, while observer invocations and some other +// following tasks are done asynchronously. +// This class checks the condition on instance creation, then every +// OnFullscreenStateChanged invocation to deal with the situation. +// Once the condition is met, this class remembers the state, so following +// Wait() will do nothing, even if the condition is changed once again. +class FullscreenWaiter : public FullscreenObserver { + public: + // The conditions to be satisfied. std::nullopt means to ignore the + // value. + struct Expectation { + // Condition for IsFullscreenForBrowser() to satisfy. + std::optional<bool> browser_fullscreen; + // Condition for IsTabFullscreen() to satisfy. + std::optional<bool> tab_fullscreen; + // ID of the display to be used for the fullscreen. + std::optional<int64_t> display_id; + }; + // Shortcut constant representing no fullscreen is enabled. + inline static constexpr Expectation kNoFullscreen = { + .browser_fullscreen = false, + .tab_fullscreen = false, + }; + + FullscreenWaiter(Browser* browser, Expectation expecation); + + FullscreenWaiter(const FullscreenWaiter&) = delete; + FullscreenWaiter& operator=(const FullscreenWaiter&) = delete; + ~FullscreenWaiter() override; + + // Waits for the fullscreen state(s) to be satisfied. + // Once it is satisfied after creation, this will do nothing, + // even if the state is changed once again, and does not satisfy + // the condition on calling Wait(). + void Wait(); + + // FullscreenObserver: + void OnFullscreenStateChanged() override; + + private: + // Checks whether the condition is satisfied now. + bool IsSatisfied() const; + + const Expectation expectation_; + const raw_ptr<FullscreenController> controller_; + base::ScopedObservation<FullscreenController, FullscreenObserver> + observation_{this}; + base::RunLoop run_loop_; + + // Caches if the condition is satisfied even once. + bool satisfied_; +}; + +// Toggles browser fullscreen mode, then wait for its completion. +void ToggleFullscreenModeAndWait(Browser* browser); + // Send the given text to the omnibox and wait until it's updated. void SendToOmniboxAndSubmit( Browser* browser,
diff --git a/chrome/test/data/extensions/api_test/preference/lacros/manifest.json b/chrome/test/data/extensions/api_test/preference/lacros/manifest.json index 6e2b833..a234369 100644 --- a/chrome/test/data/extensions/api_test/preference/lacros/manifest.json +++ b/chrome/test/data/extensions/api_test/preference/lacros/manifest.json
@@ -4,7 +4,7 @@ "manifest_version": 2, "description" : "Lacros extension controlled pref API Test Extension", "permissions": [ "accessibilityFeatures.read", "accessibilityFeatures.modify", - "privacy", "proxy"], + "proxy"], "background": { "scripts": ["test.js"], "persistent": false
diff --git a/chrome/test/data/extensions/api_test/preference/lacros/test.js b/chrome/test/data/extensions/api_test/preference/lacros/test.js index 083cb28..80e0ee8 100644 --- a/chrome/test/data/extensions/api_test/preference/lacros/test.js +++ b/chrome/test/data/extensions/api_test/preference/lacros/test.js
@@ -20,12 +20,6 @@ } }, { - root: chrome.privacy.websites, - preferences: { - protectedContentEnabled: true, - } - }, - { root: chrome.proxy, preferences: { settings: {mode: 'system'},
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js index 7dad647..8c568e9 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js +++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
@@ -124,6 +124,24 @@ }); } +// Promisify webview.getZoom. +function getZoomP(webview) { + return new Promise((resolve) => { + webview.getZoom((zoomFactor) => { + resolve(zoomFactor); + }); + }); +} + +// Promisify webview.setZoom. +function setZoomP(webview, zoomFactor) { + return new Promise((resolve) => { + webview.setZoom(zoomFactor, () => { + resolve(); + }); + }); +} + // Executes `fn` in the context of the `webview` with the given `args`. `fn` // must be written in a way that it can be serialized as a string. So anything // it references from this context must be passed explicitly via `args`. @@ -2661,78 +2679,64 @@ document.body.appendChild(webview); } +function getWebviewInnerWidth(webview) { + // Double rAF to help avoid flakiness if an update that affects layout hasn't + // happened yet. + let getInnerWidthAfterLifecycleUpdate = () => { + return new Promise((resolve) => { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + resolve(window.innerWidth); + }); + }); + }); + }; + return evalInWebView(webview, getInnerWidthAfterLifecycleUpdate, []); +} + function testZoomAPI() { var webview = new WebView(); webview.src = 'about:blank'; - webview.addEventListener('loadstop', function(e) { + webview.addEventListener('loadstop', async function(e) { // getZoom() should work initially. - webview.getZoom(function(zoomFactor) { - embedder.test.assertEq(zoomFactor, 1); - }); + embedder.test.assertEq(await getZoomP(webview), 1); // Two consecutive calls to getZoom() should return the same result. - var zoomFactor1; - webview.getZoom(function(zoomFactor) { - zoomFactor1 = zoomFactor; - }); - webview.getZoom(function(zoomFactor) { - embedder.test.assertEq(zoomFactor1, zoomFactor); - }); + let results = await Promise.all([getZoomP(webview), getZoomP(webview)]); + embedder.test.assertEq(results[0], results[1]); // Test setZoom()'s callback. - var callbackTest = false; - webview.setZoom(0.95, function() { - callbackTest = true; - }); + await setZoomP(webview, 0.95); // getZoom() should return the same zoom factor as is set in setZoom(). webview.setZoom(1.53); - webview.getZoom(function(zoomFactor) { - embedder.test.assertEq(zoomFactor, 1.53); - }); + embedder.test.assertEq(await getZoomP(webview), 1.53); webview.setZoom(0.835847); - webview.getZoom(function(zoomFactor) { - embedder.test.assertEq(zoomFactor, 0.835847); - }); + embedder.test.assertEq(await getZoomP(webview), 0.835847); webview.setZoom(0.3795); - webview.getZoom(function(zoomFactor) { - embedder.test.assertEq(zoomFactor, 0.3795); - }); + embedder.test.assertEq(await getZoomP(webview), 0.3795); // setZoom() should really zoom the page (thus changing window.innerWidth). - webview.setZoom(0.45, function() { - webview.executeScript({code: 'window.innerWidth'}, - function(result) { - var width1 = result[0]; - webview.setZoom(1.836); - webview.executeScript({code: 'window.innerWidth'}, - function(result) { - var width2 = result[0]; - embedder.test.assertTrue(width2 < width1); - webview.setZoom(0.73); - webview.executeScript({code: 'window.innerWidth'}, - function(result) { - var width3 = result[0]; - embedder.test.assertTrue(width3 < width1); - embedder.test.assertTrue(width2 < width3); + await setZoomP(webview, 0.45); + let width1 = await getWebviewInnerWidth(webview); - // Test the onzoomchange event. - webview.addEventListener('zoomchange', function(e) { - embedder.test.assertEq(event.oldZoomFactor, 0.73); - embedder.test.assertEq(event.newZoomFactor, 0.25325); + await setZoomP(webview, 1.836); + let width2 = await getWebviewInnerWidth(webview); + embedder.test.assertTrue(width2 < width1); - embedder.test.assertTrue(callbackTest); + await setZoomP(webview, 0.73); + let width3 = await getWebviewInnerWidth(webview); + embedder.test.assertTrue(width3 < width1); + embedder.test.assertTrue(width2 < width3); - embedder.test.succeed(); - }); - webview.setZoom(0.25325); - } - ); - } - ); - } - ); + // Test the onzoomchange event. + webview.addEventListener('zoomchange', (event) => { + embedder.test.assertEq(event.oldZoomFactor, 0.73); + embedder.test.assertEq(event.newZoomFactor, 0.25325); + + embedder.test.succeed(); }); + webview.setZoom(0.25325); }); document.body.appendChild(webview); }; @@ -3040,19 +3044,25 @@ document.body.appendChild(webview2); }); webview2.addEventListener('loadstop', function(e) { - webview1.getZoomMode(function(zoomMode) { + webview1.getZoomMode(async function(zoomMode) { // Check that |webview1| is in 'per-origin' mode and zoom it. Check that // both webviews zoomed. embedder.test.assertEq(zoomMode, 'per-origin'); - webview1.setZoom(3.14, function() { - webview1.getZoom(function(zoom) { - embedder.test.assertEq(zoom, 3.14); - webview2.getZoom(function(zoom) { - embedder.test.assertEq(zoom, 3.14); - embedder.test.succeed(); - }); - }); - }); + + let width1Before = await getWebviewInnerWidth(webview1); + let width2Before = await getWebviewInnerWidth(webview2); + + await setZoomP(webview1, 3.14); + embedder.test.assertEq(await getZoomP(webview1), 3.14); + embedder.test.assertEq(await getZoomP(webview2), 3.14); + + let width1After = await getWebviewInnerWidth(webview1); + let width2After = await getWebviewInnerWidth(webview2); + + embedder.test.assertTrue(width1After < width1Before); + embedder.test.assertTrue(width2After < width2Before); + + embedder.test.succeed(); }); }); @@ -3068,46 +3078,33 @@ webview1.addEventListener('loadstop', function(e) { document.body.appendChild(webview2); }); - webview2.addEventListener('loadstop', function(e) { + webview2.addEventListener('loadstop', async function(e) { // Set |webview2| to 'per-view' mode and zoom it. Make sure that the // zoom did not affect |webview1|. // We need to verify that the page actually is zooming by comparing // |window.innerWidth| before and after the zoom to prevent regressions like // https://crbug.com/860511. - webview1.executeScript({code: 'window.innerWidth'}, function(result) { - var webview1_original_width = result[0]; - webview2.executeScript({code: 'window.innerWidth'}, function(result) { - var webview2_original_width = result[0]; - webview2.setZoomMode('per-view', function() { - webview2.getZoomMode(function(zoomMode) { - embedder.test.assertEq(zoomMode, 'per-view'); - webview2.setZoom(0.45, function() { - webview1.getZoom(function(zoom) { - embedder.test.assertFalse(zoom == 0.45); - webview1.executeScript( - {code: 'window.innerWidth'}, function(result) { - var webview1_new_width = result[0]; - // Verify that inner width has not been changed for - // for this WebView. - embedder.test.assertEq( - webview1_new_width, webview1_original_width); - webview2.getZoom(function(zoom) { - embedder.test.assertEq(zoom, 0.45); - webview2.executeScript( - {code: 'window.innerWidth'}, function(result) { - var webview2_new_width = result[0]; - // Verify that inner width has been updated for - // the second WebView. - embedder.test.assertTrue( - webview2_original_width < webview2_new_width); - embedder.test.succeed(); - }); - }); - }); - }); - }); - }); - }); + let webview1_original_width = await getWebviewInnerWidth(webview1); + let webview2_original_width = await getWebviewInnerWidth(webview2); + + webview2.setZoomMode('per-view', function() { + webview2.getZoomMode(async function(zoomMode) { + embedder.test.assertEq(zoomMode, 'per-view'); + + await setZoomP(webview2, 0.45); + embedder.test.assertFalse((await getZoomP(webview1)) == 0.45); + embedder.test.assertEq(await getZoomP(webview2), 0.45); + + let webview1_new_width = await getWebviewInnerWidth(webview1); + // Verify that inner width has not been changed for + // for this WebView. + embedder.test.assertEq(webview1_new_width, webview1_original_width); + + let webview2_new_width = await getWebviewInnerWidth(webview2); + // Verify that inner width has been updated for + // the second WebView. + embedder.test.assertTrue(webview2_original_width < webview2_new_width); + embedder.test.succeed(); }); }); }); @@ -3152,10 +3149,18 @@ function testZoomBeforeNavigation() { var webview = new WebView(); - webview.addEventListener('loadstop', function(e) { + webview.addEventListener('loadstop', async function(e) { // Check that the zoom state persisted. - webview.getZoom(function(zoomFactor) { - embedder.test.assertEq(zoomFactor, 3.14); + embedder.test.assertEq(await getZoomP(webview), 3.14); + + // Disable zoom so that the webview reverts to the default zoom level. We + // then verify that there was a difference in layout when the zoom was + // applied. + let width1 = await getWebviewInnerWidth(webview); + webview.setZoomMode('disabled', async function() { + let width2 = await getWebviewInnerWidth(webview); + embedder.test.assertTrue(width2 > width1); + embedder.test.succeed(); }); });
diff --git a/chrome/test/supervised_user/supervision_mixin.cc b/chrome/test/supervised_user/supervision_mixin.cc index 1ecd7f4..5776d83 100644 --- a/chrome/test/supervised_user/supervision_mixin.cc +++ b/chrome/test/supervised_user/supervision_mixin.cc
@@ -158,10 +158,10 @@ // PRE_ tests intentionally leave accounts that are picked up by subsequent // test runs. AccountInfo account_info = - GetIdentityTestEnvironment()->MakeAccountAvailable(email_); + GetIdentityTestEnvironment()->MakePrimaryAccountAvailable( + email_, consent_level_); CHECK(!account_info.account_id.empty()); - GetIdentityTestEnvironment()->SetPrimaryAccount(email_, consent_level_); WaitForPrimaryAccount(GetIdentityTestEnvironment()->identity_manager(), consent_level_, account_info.account_id); } else {
diff --git a/chromecast/browser/service_manager_context.cc b/chromecast/browser/service_manager_context.cc index d3435c1..a9af3e8 100644 --- a/chromecast/browser/service_manager_context.cc +++ b/chromecast/browser/service_manager_context.cc
@@ -18,6 +18,7 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_pump_type.h" #include "base/no_destructor.h" +#include "base/notreached.h" #include "base/process/process_handle.h" #include "base/strings/utf_string_conversions.h" #include "base/task/deferred_sequenced_task_runner.h" @@ -98,38 +99,6 @@ g_io_thread_connector.Get().reset(); } -// A ServiceProcessHost implementation which delegates to Content-managed -// processes, either via a new UtilityProcessHost to launch new service -// processes, or the existing GpuProcessHost to run service instances in the GPU -// process. -class ContentChildServiceProcessHost - : public service_manager::ServiceProcessHost { - public: - ContentChildServiceProcessHost() = default; - - ContentChildServiceProcessHost(const ContentChildServiceProcessHost&) = - delete; - ContentChildServiceProcessHost& operator=( - const ContentChildServiceProcessHost&) = delete; - - ~ContentChildServiceProcessHost() override = default; - - // service_manager::ServiceProcessHost: - mojo::PendingRemote<service_manager::mojom::Service> Launch( - const service_manager::Identity& identity, - sandbox::mojom::Sandbox sandbox_type, - const std::u16string& display_name, - LaunchCallback callback) override { - // Start a new process for this service. - mojo::PendingRemote<service_manager::mojom::Service> remote; - content::LaunchUtilityProcessServiceDeprecated( - identity.name(), display_name, sandbox_type, - remote.InitWithNewPipeAndPassReceiver().PassPipe(), - std::move(callback)); - return remote; - } -}; - // A ServiceProcessHost implementation which uses the Service Manager's builtin // service executable launcher. Not yet intended for use in production Chrome, // hence availability is gated behind a flag. @@ -198,7 +167,9 @@ std::unique_ptr<service_manager::ServiceProcessHost> CreateProcessHostForBuiltinServiceInstance( const service_manager::Identity& identity) override { - return std::make_unique<ContentChildServiceProcessHost>(); + // Cast only uses the default kInProcessBuiltin mode. This function should + // only be called for kOutOfProcessBuiltin mode. + NOTREACHED_NORETURN(); } std::unique_ptr<service_manager::ServiceProcessHost>
diff --git a/chromecast/media/service/BUILD.gn b/chromecast/media/service/BUILD.gn index 5595668b..6b5fd743 100644 --- a/chromecast/media/service/BUILD.gn +++ b/chromecast/media/service/BUILD.gn
@@ -17,7 +17,6 @@ public_deps = [ "//media/mojo/mojom", "//media/mojo/services", - "//services/service_manager/public/cpp", ] deps = [
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc index a887749..48f301f9 100644 --- a/chromecast/media/service/cast_renderer.cc +++ b/chromecast/media/service/cast_renderer.cc
@@ -30,7 +30,6 @@ #include "media/base/media_log.h" #include "media/base/media_resource.h" #include "media/base/renderer_client.h" -#include "services/service_manager/public/mojom/interface_provider.mojom.h" namespace chromecast { namespace media {
diff --git a/chromeos/crosapi/mojom/app_service_types.mojom b/chromeos/crosapi/mojom/app_service_types.mojom index f86ba3d..93f065b 100644 --- a/chromeos/crosapi/mojom/app_service_types.mojom +++ b/chromeos/crosapi/mojom/app_service_types.mojom
@@ -478,6 +478,7 @@ [MinVersion=10] kFromUrlHandler, // Url handler. [MinVersion=11] kFromSysTrayCalendar, // System Tray Calendar. [MinVersion=12] kFromInstaller, // Installation UI. + [MinVersion=13] kFromFirstRun, // First Run. }; [Stable, Extensible]
diff --git a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc index 5b4da6b..50be59f 100644 --- a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc +++ b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
@@ -988,6 +988,8 @@ return crosapi::mojom::LaunchSource::kFromSysTrayCalendar; case apps::LaunchSource::kFromInstaller: return crosapi::mojom::LaunchSource::kFromInstaller; + case apps::LaunchSource::kFromFirstRun: + return crosapi::mojom::LaunchSource::kFromFirstRun; // TODO(crbug.com/1343692): Make lock screen apps use lacros browser. case apps::LaunchSource::kFromLockScreen: case apps::LaunchSource::kFromCommandLine: @@ -1101,6 +1103,9 @@ case crosapi::mojom::LaunchSource::kFromInstaller: *output = apps::LaunchSource::kFromInstaller; return true; + case crosapi::mojom::LaunchSource::kFromFirstRun: + *output = apps::LaunchSource::kFromFirstRun; + return true; } NOTREACHED();
diff --git a/chromeos/crosapi/mojom/prefs.mojom b/chromeos/crosapi/mojom/prefs.mojom index b5aeae8..696c9267 100644 --- a/chromeos/crosapi/mojom/prefs.mojom +++ b/chromeos/crosapi/mojom/prefs.mojom
@@ -96,8 +96,8 @@ [MinVersion=4] kApplicationLocale = 29, // M104: prefs::kSharedStorage (profile) [MinVersion=5] kSharedStorage = 30, - // M104: prefs::kProtectedContentDefault (extension) - [MinVersion=6] kProtectedContentDefault = 31, + // Deprecated in m123: No longer supported as ash-controlled pref. Do not use. + [MinVersion=6] kProtectedContentDefaultDeprecated = 31, // M109: prefs::kDnsOverHttpsTemplatesWithIdentifiers (local state) [MinVersion=7] kDnsOverHttpsTemplatesWithIdentifiers = 32, // M109: prefs::kDnsOverHttpsSalt (local state)
diff --git a/chromeos/strings/chromeos_strings_ar.xtb b/chromeos/strings/chromeos_strings_ar.xtb index a0b98b0..1eff0d9 100644 --- a/chromeos/strings/chromeos_strings_ar.xtb +++ b/chromeos/strings/chromeos_strings_ar.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">تعذَّر تحميل الصور. يُرجى التحقُّق من الاتصال بالشبكة أو إعادة محاولة تحميل الصور.</translation> <translation id="1751249301761991853">إعدادات التخصيص</translation> <translation id="1753496554272155572">إغلاق معاينة الخلفية</translation> +<translation id="1754578112426924640">زر تعديل <ph name="ACCELERATOR_INFO" /></translation> <translation id="1755556344721611131">تطبيق "بيانات التشخيص"</translation> <translation id="175763766237925754">إشارة جيدة (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android لا يعمل.</translation> <translation id="551689408806449779">انقطع اتصال الجهاز. يُرجى إعادة توصيل الجهاز لاختباره.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">مقفَل</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">التبديل تلقائيًا إلى المظهر الداكن عند الغروب</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">توسيط</translation> <translation id="5703716265115423771">صوت منخفض</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> من <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">زر تعديل الاختصار <ph name="SHORTCUT_DESCRIPTION" /></translation> <translation id="5733298426544876109">تحديث <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">متوسط</translation> <translation id="5757187557809630523">المقطع الصوتي التالي</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">محظورة</translation> <translation id="5916664084637901428">مفعّل</translation> <translation id="5921506667911082617">{COUNT,plural, =1{تم بنجاح مسح الملف ضوئيًا وحفظه في <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}zero{تم بنجاح مسح الملفات ضوئيًا وحفظها في <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}two{تم بنجاح مسح الملفين ضوئيًا وحفظهما في <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{تم بنجاح مسح الملفات ضوئيًا وحفظها في <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}many{تم بنجاح مسح الملفات ضوئيًا وحفظها في <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{تم بنجاح مسح الملفات ضوئيًا وحفظها في <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">زر حذف <ph name="ACCELERATOR_INFO" /></translation> <translation id="5931523347251946569">لم يتم العثور على الملف.</translation> <translation id="593880865674747800">إنشاء المزيد من الخلفيات على غرار هذا النمط</translation> <translation id="5939518447894949180">إعادة الضبط</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">تعذَّر التحويل باستخدام نظام أسماء النطاقات (DNS).</translation> <translation id="6768237774506518020">إن متوسط تعطُّل التحويل باستخدام نظام أسماء النطاقات (DNS) عالٍ.</translation> <translation id="6791471867139427246">لون إضاءة لوحة المفاتيح</translation> +<translation id="6796229976413584781">تم حذف الاختصار.</translation> <translation id="6798678288485555829">التنقّل بين أجزاء النص</translation> <translation id="680983167891198932">المفتاح</translation> <translation id="6816797338148849397">تتوفّر معلومات ذات صلة باختيارك. يمكنك استخدام مفتاح السهم المتجه للأعلى للوصول إلى هذه المعلومات.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">يمكنك إدارة إعدادات اسم نقطة الوصول للشبكة. وتُنشئ أسماء نقاط الوصول اتصالاً بين شبكة الجوّال والإنترنت. <ph name="BEGIN_LINK_LEARN_MORE" />مزيد من المعلومات<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">تحديثات البرامج الثابتة للأجهزة الخارجية</translation> <translation id="7216409898977639127">موفر شبكة الجوّال</translation> +<translation id="7233782086689993269">تمت استعادة الاختصار.</translation> <translation id="725133483556299729">اختيار عنوان البريد الإلكتروني</translation> <translation id="7271040990581020067">يتم حاليًا استخدام الماسح الضوئي. يُرجى إعادة المحاولة لاحقًا.</translation> <translation id="7271932918253517778">إنّ الاختصار المكوَّن من أحد مفاتيح الصف العلوي يجب أن يشتمل على مفتاح <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">وقت استجابة بروتوكول HTTPS طويل.</translation> <translation id="7656388927906093505">الجهاز هو ماوس.</translation> <translation id="7658239707568436148">إلغاء</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />، <ph name="ACCELERATOR_INFO" />، <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">تغيير الصورة الرمزية</translation> <translation id="7683228889864052081">التدرّج اللوني في إضاءة لوحة المفاتيح</translation> <translation id="7690294790491645610">تأكيد كلمة المرور الجديدة</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">إضاءة لوحة المفاتيح</translation> <translation id="7730077286107534951">قد يتم إرسال بعض المعلومات عن الحساب والنظام إلى Google. نستخدم هذه المعلومات للمساعدة في معالجة المشاكل الفنية وتحسين خدماتنا، بما يتوافق مع <ph name="BEGIN_LINK2" />سياسة الخصوصية<ph name="END_LINK2" /> و<ph name="BEGIN_LINK3" />بنود الخدمة<ph name="END_LINK3" />. لطلب إجراء تغييرات في المحتوى، يُرجى الانتقال إلى صفحة <ph name="BEGIN_LINK1" />المساعدة القانونية<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">عدد مرات تفريغ البطارية وشحنها</translation> +<translation id="7746357909584236306">قابل للتعديل</translation> <translation id="7747039790905080783">المفتاح المشترَك مسبقًا</translation> <translation id="7752963721013053477">صورة متحركة حصرية تعرض منظرًا من الفجر إلى الليل</translation> <translation id="7762130827864645708">تم تغيير كلمة المرور بنجاح. يُرجى استخدام كلمة المرور الجديدة من الآن فصاعدًا.</translation>
diff --git a/chromeos/strings/chromeos_strings_as.xtb b/chromeos/strings/chromeos_strings_as.xtb index a7b53b89..62764fd 100644 --- a/chromeos/strings/chromeos_strings_as.xtb +++ b/chromeos/strings/chromeos_strings_as.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">প্ৰতিচ্ছবি ল’ড কৰিব পৰা নগ’ল। আপোনাৰ নেটৱৰ্ক সংযোগ পৰীক্ষা কৰক অথবা প্ৰতিচ্ছবিসমূহ পুনৰ ল’ড কৰিবলৈ চেষ্টা কৰক।</translation> <translation id="1751249301761991853">ব্যক্তিগত</translation> <translation id="1753496554272155572">ৱালপেপাৰৰ পূৰ্বদৰ্শনৰ পৰা বাহিৰ হওক</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" />ৰ বাবে সম্পাদনা কৰাৰ বুটাম।</translation> <translation id="1755556344721611131">ডায়েগন’ষ্টিক্স এপ্</translation> <translation id="175763766237925754">ভাল (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android চলি থকা নাই</translation> <translation id="551689408806449779">ডিভাইচৰ সংযোগ বিচ্ছিন্ন হৈছে। পৰীক্ষাটোৰ সৈতে পুনৰ সংযোগ কৰিবলৈ চেষ্টা কৰক</translation> <translation id="5519195206574732858">এলটিই</translation> +<translation id="5543701552415191873">লক কৰা আছে</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">সূৰ্যাস্তৰ সময়ত স্বয়ংক্ৰিয়ভাৱে গাঢ় ৰঙৰ থীমলৈ সলনি কৰক</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">কেন্দ্ৰ</translation> <translation id="5703716265115423771">ভলিউম কমাওক</translation> <translation id="5707900041990977207"><ph name="TOTAL_PAGES" />ৰ <ph name="CURRENT_PAGE" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" />ৰ বাবে সম্পাদনা কৰাৰ বুটাম।</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> আপডে’ট কৰক</translation> <translation id="574392208103952083">মধ্যমীয়া</translation> <translation id="5757187557809630523">পৰৱৰ্তী ট্ৰেক</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">নিষিদ্ধ</translation> <translation id="5916664084637901428">অন আছে</translation> <translation id="5921506667911082617">{COUNT,plural, =1{আপোনাৰ ফাইলটো সফলভাৱে স্কেন আৰু <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />ত ছেভ কৰা হৈছে।}one{আপোনাৰ ফাইলসমূহ সফলভাৱে স্কেন আৰু <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />ত ছেভ কৰা হৈছে।}other{আপোনাৰ ফাইলসমূহ সফলভাৱে স্কেন আৰু <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />ত ছেভ কৰা হৈছে।}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" />ৰ বাবে মচাৰ বুটাম।</translation> <translation id="5931523347251946569">ফাইলটো পোৱা নগ’ল</translation> <translation id="593880865674747800">এই শৈলীত অধিক সৃষ্টি কৰক</translation> <translation id="5939518447894949180">ৰিছেট কৰক</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNSৰ সমাধান বিফল হৈছে</translation> <translation id="6768237774506518020">DNSৰ সমাধান বিফল হোৱাৰ হাৰ উচ্চ</translation> <translation id="6791471867139427246">কীব’ৰ্ডৰ পোহৰৰ ৰং</translation> +<translation id="6796229976413584781">শ্বৰ্টকাট মচা হ’ল</translation> <translation id="6798678288485555829">পাঠ নেভিগেশ্বন</translation> <translation id="680983167891198932">কী</translation> <translation id="6816797338148849397">আপুনি কৰা বাছনি সম্পৰ্কীয় তথ্য উপলব্ধ। এক্সেছ কৰিবলৈ উপৰমুৱা কাঁড়চিহ্নৰ কী ব্যৱহাৰ কৰক।</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">নেটৱৰ্ক এপিএনৰ ছেটিং পৰিচালনা কৰক। এপিএনে চেলুলাৰ নেটৱৰ্ক আৰু ইণ্টাৰনেটৰ মাজত এটা সংযোগ স্থাপন কৰে। <ph name="BEGIN_LINK_LEARN_MORE" />অধিক জানক<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">বাহ্যিক ডিভাইচৰ বাবে ফাৰ্মৱেৰৰ আপডে’ট</translation> <translation id="7216409898977639127">চেলুলাৰ প্ৰদানকাৰী</translation> +<translation id="7233782086689993269">শ্বৰ্টকাট পুনঃস্থাপন কৰা হ’ল</translation> <translation id="725133483556299729">ইমেইল বাছনি কৰক</translation> <translation id="7271040990581020067">বৰ্তমান স্কেনাৰটো ব্যৱহাৰ কৰি থকা হৈছে। পাছত পুনৰ চেষ্টা কৰক।</translation> <translation id="7271932918253517778">একেবাৰে ওপৰৰ শাৰীৰ কীসমূহ থকা শ্বৰ্টকাটত <ph name="META_KEY" /> কী অন্তৰ্ভুক্ত হ’ব লাগিব।</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPSৰ বেছি বিলম্বতা</translation> <translation id="7656388927906093505">ডিভাইচটো এটা মাউচ।</translation> <translation id="7658239707568436148">বাতিল কৰক</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />।</translation> <translation id="7665800271478495366">অৱতাৰ সলনি কৰক</translation> <translation id="7683228889864052081">কীব’ৰ্ডৰ বৰণ</translation> <translation id="7690294790491645610">নতুন পাছৱর্ড নিশ্চিত কৰক</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">কীব’ৰ্ডৰ পোহৰ</translation> <translation id="7730077286107534951">একাউণ্ট আৰু ছিষ্টেম সম্পৰ্কীয় কিছুমান তথ্য Googleলৈ পঠিওৱা হ’ব পাৰে। এই তথ্যখিনি আমি কাৰিকৰী সমস্যাসমূহ সমাধান কৰিবলৈ আৰু আমাৰ সেৱা উন্নত কৰিবলৈ <ph name="BEGIN_LINK2" />গোপনীয়তা নীতি<ph name="END_LINK2" /> আৰু <ph name="BEGIN_LINK3" />সেৱাৰ চৰ্তাৱলী<ph name="END_LINK3" /> অনুযায়ী ব্যৱহাৰ কৰিম। সমলৰ সালসলনিৰ অনুৰোধ জনাবলৈ <ph name="BEGIN_LINK1" />আইনী সহায়<ph name="END_LINK1" />লৈ যাওক।</translation> <translation id="773153675489693198">চক্ৰৰ গণনা</translation> +<translation id="7746357909584236306">সম্পাদনাযোগ্য</translation> <translation id="7747039790905080783">পূৰ্বতে শ্বেয়াৰ কৰা চাবি</translation> <translation id="7752963721013053477">কাহিলি পুৱাৰ পৰা আন্ধাৰ হোৱালৈকে - বিশেষ</translation> <translation id="7762130827864645708">আপোনাৰ পাছৱৰ্ড সলনি কৰাৰ প্ৰক্ৰিয়াটো সফল হৈছে। অনুগ্ৰহ কৰি এতিয়াৰ পৰা নতুন পাছৱৰ্ডটো ব্যৱহাৰ কৰক।</translation>
diff --git a/chromeos/strings/chromeos_strings_az.xtb b/chromeos/strings/chromeos_strings_az.xtb index 128d43c8..bfa035e 100644 --- a/chromeos/strings/chromeos_strings_az.xtb +++ b/chromeos/strings/chromeos_strings_az.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Şəkilləri yükləmək mümkün olmadı. Şəbəkə bağlantınızı yoxlayın və ya şəkilləri yenidən yükləməyə cəhd edin.</translation> <translation id="1751249301761991853">Şəxsi</translation> <translation id="1753496554272155572">Divar kağızı önizləməsindən çıxın</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> üçün redaktə düyməsi.</translation> <translation id="1755556344721611131">Diaqnostika tətbiqi</translation> <translation id="175763766237925754">Yaxşı (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android işləmir</translation> <translation id="551689408806449779">Cihaz ayrılıb. Test etmək üçün yenidən qoşmağa çalışın</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">kilidli</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Gün batımında avtomatik olaraq tünd temaya keçin</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Mərkəzi edin</translation> <translation id="5703716265115423771">həcmi azaldın</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />/<ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> üçün redaktə düyməsi.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> cihazını güncəlləyin</translation> <translation id="574392208103952083">Orta</translation> <translation id="5757187557809630523">növbəti trek</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Qadağan olunub</translation> <translation id="5916664084637901428">Aktiv</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Faylınız uğurla skanlandı və <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> qovluğunda saxlanıldı.}other{Fayllarınız uğurla skanlandı və <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> qovluğunda saxlanıldı.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> üçün silmə düyməsi.</translation> <translation id="5931523347251946569">Fayl tapılmadı</translation> <translation id="593880865674747800">Bu üslubda daha çoxunu yaradın</translation> <translation id="5939518447894949180">Sıfırlayın</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS həlləri alınmadı</translation> <translation id="6768237774506518020">DNS həllinin alınmama faizi yüksəkdir</translation> <translation id="6791471867139427246">klaviatura işıq rəngi</translation> +<translation id="6796229976413584781">Qısayol silindi</translation> <translation id="6798678288485555829">Mətn naviqasiyası</translation> <translation id="680983167891198932">Açar</translation> <translation id="6816797338148849397">Seçiminizlə əlaqəli məlumat əlçatandır. Giriş üçün Yuxarı ox düyməsini istifadə edin.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Şəbəkə APN ayarlarını idarə edin. APN mobil şəbəkə ilə internet arasında əlaqə yaradır. <ph name="BEGIN_LINK_LEARN_MORE" />Ətraflı məlumat<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Xarici cihazlar üçün proqram güncəlləmələri</translation> <translation id="7216409898977639127">Mobil provayder</translation> +<translation id="7233782086689993269">Qısayol bərpa edildi</translation> <translation id="725133483556299729">E-poçt seçin</translation> <translation id="7271040990581020067">Skaner hazırda istifadə olunur. Sonra cəhd edin.</translation> <translation id="7271932918253517778">Üst sıra düymələri olan qısayolda <ph name="META_KEY" /> düyməsi olmalıdır.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Yüksək HTTPS gecikməsi</translation> <translation id="7656388927906093505">Cihaz mausdur.</translation> <translation id="7658239707568436148">Ləğv edin</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Avatarı dəyişdirin</translation> <translation id="7683228889864052081">klaviatura çaları</translation> <translation id="7690294790491645610">Yeni parolu təsdiq edin</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">işıqlı klaviatura</translation> <translation id="7730077286107534951">Bəzi hesab və sistem məlumatları Google-a göndərilə bilər. <ph name="BEGIN_LINK2" />Məxfilik Siyasətinə<ph name="END_LINK2" /> və <ph name="BEGIN_LINK3" />Xidmət Şərtlərinə<ph name="END_LINK3" /> əsasən texniki problemləri həll etmək və xidmətləri təkmilləşdirmək üçün bu məlumatdan istifadə edirik. Kontent dəyişikliyi tələb etmək üçün <ph name="BEGIN_LINK1" />Hüquqi Kömək<ph name="END_LINK1" /> bölməsinə keçin.</translation> <translation id="773153675489693198">Dövrə sayı</translation> +<translation id="7746357909584236306">redaktə edilə bilən</translation> <translation id="7747039790905080783">Öncədən paylaşılan açar</translation> <translation id="7752963721013053477">Sübhdən axşama - eksklüziv</translation> <translation id="7762130827864645708">Parolunuz uğurla dəyişdirildi. Bundan sonra yeni paroldan istifadə edin.</translation>
diff --git a/chromeos/strings/chromeos_strings_bs.xtb b/chromeos/strings/chromeos_strings_bs.xtb index 26e2b4a..7d99b2d 100644 --- a/chromeos/strings/chromeos_strings_bs.xtb +++ b/chromeos/strings/chromeos_strings_bs.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Slike se nisu mogle učitati. Provjerite mrežnu vezu ili ponovo pokušajte učitati slike.</translation> <translation id="1751249301761991853">Lično</translation> <translation id="1753496554272155572">Izlaz iz pregleda pozadinske slike</translation> +<translation id="1754578112426924640">Uredite dugme za <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplikacija Diagnostics</translation> <translation id="175763766237925754">Dobro (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android nije pokrenut</translation> <translation id="551689408806449779">Prekinuta je veza s uređajem. Pokušajte ponovo povezati da testirate</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">zaključano</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Automatski prebacite na tamnu temu prilikom zalaska sunca</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Sredina</translation> <translation id="5703716265115423771">dugme za stišavanje zvuka</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> od <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Uredite dugme za prečicu <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Ažuriranje aplikacije <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Srednje</translation> <translation id="5757187557809630523">sljedeća numera</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Zabranjeno</translation> <translation id="5916664084637901428">Uključeno</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Vaš fajl je uspješno skeniran i sačuvan u folder <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Vaši fajlovi su uspješno skenirani i sačuvani u folder <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Vaši fajlovi su uspješno skenirani i sačuvani u folder <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Vaši fajlovi su uspješno skenirani i sačuvani u folder <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Izbrišite dugme za <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Fajl nije pronađen</translation> <translation id="593880865674747800">Kreiraj više u ovom stilu</translation> <translation id="5939518447894949180">Vrati na zadano</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS rezolucije nisu uspjele</translation> <translation id="6768237774506518020">Visoka stopa neuspjeha DNS rezolucije</translation> <translation id="6791471867139427246">boja osvjetljenja tastature</translation> +<translation id="6796229976413584781">Prečica je izbrisana</translation> <translation id="6798678288485555829">Kretanje kroz tekst</translation> <translation id="680983167891198932">Ključ</translation> <translation id="6816797338148849397">Dostupne su informacije u vezi s vašim odabirom. Pristupite tipkom strelice nagore.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Upravljajte mrežnim postavkama za APN. APN-ovi uspostavljaju vezu između mobilne mreže i interneta. <ph name="BEGIN_LINK_LEARN_MORE" />Saznajte više<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Ažuriranja firmvera za vanjske uređaje</translation> <translation id="7216409898977639127">Mobilni operater</translation> +<translation id="7233782086689993269">Prečica je vraćena</translation> <translation id="725133483556299729">Odabir e-poruke</translation> <translation id="7271040990581020067">Skener se trenutno koristi. Pokušajte ponovo kasnije.</translation> <translation id="7271932918253517778">Prečica s tipkama u gornjem redu mora uključivati tipku <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Visoka HTTPs latentnost</translation> <translation id="7656388927906093505">Uređaj je miš.</translation> <translation id="7658239707568436148">Otkaži</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Promjena avatara</translation> <translation id="7683228889864052081">nijansa tastature</translation> <translation id="7690294790491645610">Potvrdite novu lozinku</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">osvjetljenje tastature</translation> <translation id="7730077286107534951">Neke informacije o računu i sistemu mogu se slati Googleu. Koristimo te informacije da riješimo tehničke probleme i poboljšamo usluge podložno svojim <ph name="BEGIN_LINK2" />Pravilima privatnosti<ph name="END_LINK2" /> i <ph name="BEGIN_LINK3" />Uslovima korištenja usluge<ph name="END_LINK3" />. Da zatražite promjene sadržaja, posjetite <ph name="BEGIN_LINK1" />Pravnu pomoć<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Broj ciklusa</translation> +<translation id="7746357909584236306">može se urediti</translation> <translation id="7747039790905080783">Unaprijed dijeljeni ključ</translation> <translation id="7752963721013053477">Od svitanja do sumraka – ekskluzivna verzija</translation> <translation id="7762130827864645708">Uspješno ste promijenili lozinku. Od sada koristite novu lozinku.</translation>
diff --git a/chromeos/strings/chromeos_strings_ca.xtb b/chromeos/strings/chromeos_strings_ca.xtb index 4986cea..c255ca4 100644 --- a/chromeos/strings/chromeos_strings_ca.xtb +++ b/chromeos/strings/chromeos_strings_ca.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">No s'han pogut carregar les imatges. Comprova la teva connexió de xarxa o prova de carregar les imatges de nou.</translation> <translation id="1751249301761991853">Personal</translation> <translation id="1753496554272155572">Surt de la previsualització del fons de pantalla</translation> +<translation id="1754578112426924640">Botó d'edició per a <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplicació de diagnòstic</translation> <translation id="175763766237925754">Bo (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android no s'està executant</translation> <translation id="551689408806449779">El dispositiu s'ha desconnectat. Prova de connectar-te de nou per fer la prova.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">bloquejada</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Canvia automàticament al tema fosc al vespre</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centre</translation> <translation id="5703716265115423771">abaixa el volum</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> de <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Botó d'edició per a <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Actualitza <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Mitja</translation> <translation id="5757187557809630523">pista següent</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Prohibit</translation> <translation id="5916664084637901428">Activat</translation> <translation id="5921506667911082617">{COUNT,plural, =1{El fitxer s'ha escanejat correctament i s'ha desat a <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Els fitxers s'han escanejat correctament i s'han desat a <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Botó de supressió per a <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">No s'ha trobat el fitxer</translation> <translation id="593880865674747800">Crea'n més amb aquest estil</translation> <translation id="5939518447894949180">Restableix</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Algunes resolucions de DNS han fallat</translation> <translation id="6768237774506518020">El percentatge d'error de la resolució de DNS és alt</translation> <translation id="6791471867139427246">color de la llum del teclat</translation> +<translation id="6796229976413584781">La drecera s'ha suprimit</translation> <translation id="6798678288485555829">Navegació pel text</translation> <translation id="680983167891198932">Clau</translation> <translation id="6816797338148849397">Hi ha disponible informació relacionada amb la teva selecció. Utilitza la tecla de fletxa amunt per accedir-hi.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Gestiona la configuració de l'APN de la xarxa. Els APN estableixen una connexió entre una xarxa mòbil i Internet. <ph name="BEGIN_LINK_LEARN_MORE" />Més informació<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Actualitzacions de microprogramari per a dispositius externs</translation> <translation id="7216409898977639127">Proveïdor de dades mòbils</translation> +<translation id="7233782086689993269">La drecera s'ha restaurat</translation> <translation id="725133483556299729">Selecciona una adreça electrònica</translation> <translation id="7271040990581020067">L'escàner s'està utilitzant en aquests moments. Torna-ho a provar més tard.</translation> <translation id="7271932918253517778">La drecera amb tecles de la fila superior ha d'incloure la tecla de <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">La latència d'HTTPS és alta</translation> <translation id="7656388927906093505">El dispositiu és un ratolí.</translation> <translation id="7658239707568436148">Cancel·la</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Canvia l'avatar</translation> <translation id="7683228889864052081">to del teclat</translation> <translation id="7690294790491645610">Confirma la contrasenya nova</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">il·luminació del teclat</translation> <translation id="7730077286107534951">És possible que algunes dades del compte i del sistema s'enviïn a Google. Farem servir aquestes dades per ajudar a resoldre problemes tècnics i millorar els nostres serveis de conformitat amb la <ph name="BEGIN_LINK2" />política de privadesa<ph name="END_LINK2" /> i les <ph name="BEGIN_LINK3" />condicions del servei<ph name="END_LINK3" />. Per sol·licitar canvis en el contingut, ves a l'<ph name="BEGIN_LINK1" />ajuda legal<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Nombre de cicles</translation> +<translation id="7746357909584236306">editable</translation> <translation id="7747039790905080783">Clau precompartida</translation> <translation id="7752963721013053477">De l'alba a la foscor: exclusiu</translation> <translation id="7762130827864645708">La contrasenya s'ha canviat correctament. Utilitza la contrasenya nova a partir d'ara.</translation>
diff --git a/chromeos/strings/chromeos_strings_cy.xtb b/chromeos/strings/chromeos_strings_cy.xtb index 4136415f..047dde6 100644 --- a/chromeos/strings/chromeos_strings_cy.xtb +++ b/chromeos/strings/chromeos_strings_cy.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Methu â llwytho lluniau. Gwiriwch eich cysylltiad rhwydwaith neu rhowch gynnig arall ar lwytho'r lluniau.</translation> <translation id="1751249301761991853">Personal</translation> <translation id="1753496554272155572">Gadael rhagolwg papur wal</translation> +<translation id="1754578112426924640">Botwm golygu ar gyfer <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Ap diagnosteg</translation> <translation id="175763766237925754">Da (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Nid yw Android yn rhedeg</translation> <translation id="551689408806449779">Mae'r ddyfais wedi'i datgysylltu. Rhowch gynnig ar ailgysylltu i'r prawf</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">wedi'i gloi</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Newid yn awtomatig i thema dywyll ar fachlud haul</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Canoli</translation> <translation id="5703716265115423771">lleihau'r sain</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> o <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Botwm golygu ar gyfer <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Diweddaru <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Canolig</translation> <translation id="5757187557809630523">trac nesaf</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Gwaharddedig</translation> <translation id="5916664084637901428">Ymlaen</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Mae eich ffeil wedi'i sganio a'i chadw i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}zero{Mae eich ffeiliau wedi'u sganio a'u cadw i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}two{Mae eich ffeiliau wedi'u sganio a'u cadw i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Mae eich ffeiliau wedi'u sganio a'u cadw i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}many{Mae eich ffeiliau wedi'u sganio a'u cadw i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Mae eich ffeiliau wedi'u sganio a'u cadw i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Botwm dileu ar gyfer <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Ni chanfuwyd y ffeil</translation> <translation id="593880865674747800">Creu rhagor yn yr arddull hon</translation> <translation id="5939518447894949180">Ailosod</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Cydraniadau DNS wedi methu</translation> <translation id="6768237774506518020">Cyfradd fethiant cydraniad DNS uchel</translation> <translation id="6791471867139427246">lliw golau bysellfwrdd</translation> +<translation id="6796229976413584781">Llwybr byr wedi'i ddileu</translation> <translation id="6798678288485555829">Llywio testun</translation> <translation id="680983167891198932">Allwedd</translation> <translation id="6816797338148849397">Mae gwybodaeth sy'n ymwneud â'ch dewis ar gael. Defnyddiwch y fysell Saeth i fyny i gael mynediad.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Rheoli gosodiadau APN rhwydwaith. Mae APN yn sefydlu cysylltiad rhwng rhwydwaith cellog a'r rhyngrwyd. <ph name="BEGIN_LINK_LEARN_MORE" />Dysgu rhagor<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Diweddariadau cadarnwedd ar gyfer dyfeisiau allanol</translation> <translation id="7216409898977639127">Darparwr Rhwydwaith Symudol</translation> +<translation id="7233782086689993269">Llwybr byr wedi'i adfer</translation> <translation id="725133483556299729">Dewis e-bost</translation> <translation id="7271040990581020067">Mae'r sganiwr wrthi'n cael ei ddefnyddio. Rhowch gynnig arall arni'n nes ymlaen.</translation> <translation id="7271932918253517778">Mae angen i lwybr byr gyda bysellau rhes uchaf gynnwys y fysell <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Cuddni HTTPS uchel</translation> <translation id="7656388927906093505">Mae'r ddyfais yn llygoden.</translation> <translation id="7658239707568436148">Canslo</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Newid rhithffurf</translation> <translation id="7683228889864052081">arlliw bysellfwrdd</translation> <translation id="7690294790491645610">Cadarnhau cyfrinair newydd</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">golau bysellfwrdd</translation> <translation id="7730077286107534951">Mae'n bosib y byddwn yn anfon peth gwybodaeth system a chyfrif at Google. Rydym yn defnyddio'r wybodaeth hon i helpu i fynd i'r afael â materion technegol a gwella ein gwasanaethau, yn amodol ar ein <ph name="BEGIN_LINK2" />Polisi Preifatrwydd<ph name="END_LINK2" /> a'n <ph name="BEGIN_LINK3" />Telerau Gwasanaeth<ph name="END_LINK3" />. I ofyn am newidiadau cynnwys, ewch i <ph name="BEGIN_LINK1" />Gymorth Cyfreithiol<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Cyfrif cylch gwefru</translation> +<translation id="7746357909584236306">gellir ei olygu</translation> <translation id="7747039790905080783">Allwedd a rannwyd ymlaen llaw</translation> <translation id="7752963721013053477">O'r wawr i'r tywyllwch - unigryw</translation> <translation id="7762130827864645708">Gwnaethoch newid eich cyfrinair yn llwyddiannus. Defnyddiwch y cyfrinair newydd o hyn ymlaen.</translation>
diff --git a/chromeos/strings/chromeos_strings_en-GB.xtb b/chromeos/strings/chromeos_strings_en-GB.xtb index a9dbad6..b61122f 100644 --- a/chromeos/strings/chromeos_strings_en-GB.xtb +++ b/chromeos/strings/chromeos_strings_en-GB.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Couldn’t load images. Check your network connection or try loading the images again.</translation> <translation id="1751249301761991853">Personal</translation> <translation id="1753496554272155572">Exit wallpaper preview</translation> +<translation id="1754578112426924640">Edit button for <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Diagnostics app</translation> <translation id="175763766237925754">Good (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android not running</translation> <translation id="551689408806449779">Device has been disconnected. Try reconnecting to test</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">locked</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Automatically switch to Dark theme at sunset</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centre</translation> <translation id="5703716265115423771">volume down</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> of <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Edit button for <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Update <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Medium</translation> <translation id="5757187557809630523">next track</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Prohibited</translation> <translation id="5916664084637901428">On</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Your file has been successfully scanned and saved to <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Your files have been successfully scanned and saved to <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Delete button for <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">File not found</translation> <translation id="593880865674747800">Create more in this style</translation> <translation id="5939518447894949180">Reset</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Failed DNS resolutions</translation> <translation id="6768237774506518020">High DNS resolution failure rate</translation> <translation id="6791471867139427246">keyboard light colour</translation> +<translation id="6796229976413584781">Shortcut deleted</translation> <translation id="6798678288485555829">Text navigation</translation> <translation id="680983167891198932">Key</translation> <translation id="6816797338148849397">Info related to your selection available. Use the up arrow key to access.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Manage network APN settings. APNs establish a connection between a cellular network and the internet. <ph name="BEGIN_LINK_LEARN_MORE" />Learn more<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Firmware updates for external devices</translation> <translation id="7216409898977639127">Mobile provider</translation> +<translation id="7233782086689993269">Shortcut restored</translation> <translation id="725133483556299729">Select email</translation> <translation id="7271040990581020067">Scanner is currently in use. Try again later.</translation> <translation id="7271932918253517778">Shortcuts with top row keys need to include the <ph name="META_KEY" /> key.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">High HTTPS latency</translation> <translation id="7656388927906093505">Device is a mouse.</translation> <translation id="7658239707568436148">Cancel</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Change avatar</translation> <translation id="7683228889864052081">keyboard hue</translation> <translation id="7690294790491645610">Confirm new password</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">keyboard light</translation> <translation id="7730077286107534951">Some account and system information may be sent to Google. We use this information to help address technical issues and improve our services, subject to our <ph name="BEGIN_LINK2" />Privacy Policy<ph name="END_LINK2" /> and <ph name="BEGIN_LINK3" />Terms of Service<ph name="END_LINK3" />. To request content changes, go to <ph name="BEGIN_LINK1" />Legal Help<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Cycle count</translation> +<translation id="7746357909584236306">editable</translation> <translation id="7747039790905080783">Pre-shared key</translation> <translation id="7752963721013053477">Dawn to dark – exclusive</translation> <translation id="7762130827864645708">Your password change was successful. Please use the new password from now on.</translation>
diff --git a/chromeos/strings/chromeos_strings_et.xtb b/chromeos/strings/chromeos_strings_et.xtb index 8201ef7..74e9553f 100644 --- a/chromeos/strings/chromeos_strings_et.xtb +++ b/chromeos/strings/chromeos_strings_et.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Pilte ei õnnestunud laadida. Kontrollige võrguühendust või proovige pilte uuesti laadida.</translation> <translation id="1751249301761991853">Isiklik</translation> <translation id="1753496554272155572">Taustapildi eelvaatest väljumine</translation> +<translation id="1754578112426924640">Muutmisnupp funktsioonile <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Rakendus Diagnostika</translation> <translation id="175763766237925754">Hea (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android ei tööta</translation> <translation id="551689408806449779">Seadme ühendus on katkestatud. Proovige testimise jaoks ühendus uuesti luua.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">lukus</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Päikeseloojangul automaatselt tumedale teemale lülitumine</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Keskel</translation> <translation id="5703716265115423771">vähendab helitugevust</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />/<ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Muutmisnupp funktsioonile <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Värskenda seadet <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Keskmine</translation> <translation id="5757187557809630523">järgmine lugu</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Keelatud</translation> <translation id="5916664084637901428">Sees</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Teie faili skannimine õnnestus ja see salvestati kausta <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Teie failide skannimine õnnestus ja need salvestati kausta <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Kustutamisnupp funktsioonile <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Faili ei leitud</translation> <translation id="593880865674747800">Loo veel selles stiilis</translation> <translation id="5939518447894949180">Lähtesta</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Ebaõnnestunud DNS-lahendused</translation> <translation id="6768237774506518020">DNS-lahenduste ebaõnnestumiste kõrge määr</translation> <translation id="6791471867139427246">klaviatuurivalguse värv</translation> +<translation id="6796229976413584781">Otsetee kustutati</translation> <translation id="6798678288485555829">Tekstis navigeerimine</translation> <translation id="680983167891198932">Võti</translation> <translation id="6816797338148849397">Teie valikuga seotud teave on saadaval. Kasutage juurdepääsemiseks ülesnooleklahvi.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Hallake võrgu APN-ide seadeid. APN-id loovad ühenduse mobiilsidevõrgu ja interneti vahel. <ph name="BEGIN_LINK_LEARN_MORE" />Lisateave<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Välisseadmete püsivaravärskendused</translation> <translation id="7216409898977639127">Mobiilsideteenuse pakkuja</translation> +<translation id="7233782086689993269">Otsetee taastati</translation> <translation id="725133483556299729">Valige e-posti aadress</translation> <translation id="7271040990581020067">Skanner on kasutuses. Proovige hiljem uuesti.</translation> <translation id="7271932918253517778">Ülemise rea klahvidega otseteed peavad sisaldama klahvi <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Pikk HTTPS-i latentsusaeg</translation> <translation id="7656388927906093505">Seade on hiir.</translation> <translation id="7658239707568436148">Tühista</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Muuda avatari</translation> <translation id="7683228889864052081">klaviatuuri värvitoon</translation> <translation id="7690294790491645610">Kinnitage uus parool</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">klaviatuuri valgustus</translation> <translation id="7730077286107534951">Osa konto ja süsteemi teabest võidakse saata Google'ile. Kasutame seda teavet tehniliste probleemide lahendamiseks ja meie teenuste parandamiseks kooskõlas meie <ph name="BEGIN_LINK2" />privaatsuseeskirjade<ph name="END_LINK2" /> ja <ph name="BEGIN_LINK3" />teenusetingimustega<ph name="END_LINK3" />. Sisumuudatuste taotlemiseks minge lehele <ph name="BEGIN_LINK1" />Juriidiline abi<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Tsüklite arv</translation> +<translation id="7746357909584236306">muudetav</translation> <translation id="7747039790905080783">Eeljagatud võti</translation> <translation id="7752963721013053477">Päikesetõusust päikeseloojanguni – eksklusiivne</translation> <translation id="7762130827864645708">Parooli muutmine õnnestus. Edaspidi kasutage uut parooli.</translation>
diff --git a/chromeos/strings/chromeos_strings_eu.xtb b/chromeos/strings/chromeos_strings_eu.xtb index d9665b9..f9f8692 100644 --- a/chromeos/strings/chromeos_strings_eu.xtb +++ b/chromeos/strings/chromeos_strings_eu.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Ezin izan dira kargatu irudiak. Egiaztatu sarera konektatuta zaudela edo saiatu irudiak berriro kargatzen.</translation> <translation id="1751249301761991853">Pertsonalak</translation> <translation id="1753496554272155572">Irten horma-paperaren aurrebistatik</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> editatzeko botoia.</translation> <translation id="1755556344721611131">Diagnostikoen aplikazioa</translation> <translation id="175763766237925754">Ona (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android-ek ez du funtzionatzen</translation> <translation id="551689408806449779">Deskonektatu da gailua. Proba egiteko, konekta ezazu berriro.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">blokeatua</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Aldatu automatikoki gai ilunera ilunabarrean</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Erdiratu</translation> <translation id="5703716265115423771">jaitsi bolumena</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />/<ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> editatzeko botoia.</translation> <translation id="5733298426544876109">Eguneratu <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Ertaina</translation> <translation id="5757187557809630523">hurrengo pista</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Debekatuta</translation> <translation id="5916664084637901428">Aktibatuta</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Fitxategia eskaneatu da, eta <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> karpetan gorde.}other{Fitxategiak eskaneatu dira, eta <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> karpetan gorde.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> ezabatzeko botoia.</translation> <translation id="5931523347251946569">Ez da aurkitu fitxategia</translation> <translation id="593880865674747800">Sortu gehiago estilo honekin</translation> <translation id="5939518447894949180">Berrezarri</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">huts egin dute DNS bidezko ebazpenek</translation> <translation id="6768237774506518020">DNS bidezko ebazpenen hutsegite-tasa altua</translation> <translation id="6791471867139427246">teklatuaren argiaren kolorea</translation> +<translation id="6796229976413584781">Ezabatu da lasterbidea</translation> <translation id="6798678288485555829">Testuetako nabigazioa</translation> <translation id="680983167891198932">Gakoa</translation> <translation id="6816797338148849397">Eskuragarri dago zure hautapenari buruzko informazioa. Erabili gora egiteko gezi-tekla informazioa atzitzeko.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Kudeatu sarearen APNaren ezarpenak. Sare mugikorren eta Interneten arteko konexioak ezartzen dituzte APNek. <ph name="BEGIN_LINK_LEARN_MORE" />Lortu informazio gehiago<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Kanpoko gailuen firmware-eguneratzeak</translation> <translation id="7216409898977639127">Zerbitzu mugikorraren hornitzailea</translation> +<translation id="7233782086689993269">Leheneratu da lasterbidea</translation> <translation id="725133483556299729">Hautatu helbide elektroniko bat</translation> <translation id="7271040990581020067">Eskanerra erabiltzen ari zara. Saiatu berriro geroago.</translation> <translation id="7271932918253517778">Goiko errenkadako teklak darabiltzaten lasterbideetan <ph name="META_KEY" /> tekla ere erabili behar da.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPS eskaeren latentzia luzea</translation> <translation id="7656388927906093505">Gailua sagu bat da.</translation> <translation id="7658239707568436148">Utzi</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Aldatu abatarra</translation> <translation id="7683228889864052081">teklatuaren ñabardura</translation> <translation id="7690294790491645610">Berretsi pasahitz berria</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">teklatuaren argia</translation> <translation id="7730077286107534951">Baliteke kontuari eta sistemari buruzko zenbait datu bidaltzea Google-ri. Arazo teknikoak konpontzeko eta gure zerbitzuak hobetzeko erabiltzen dugu informazio hori, gure <ph name="BEGIN_LINK2" />Pribatutasun-gidalerroei<ph name="END_LINK2" /> eta <ph name="BEGIN_LINK3" />Zerbitzu-baldintzei<ph name="END_LINK3" /> jarraikiz. Edukian aldaketak eskatzeko, joan <ph name="BEGIN_LINK1" />legezko laguntzari buruzko orrira<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Ziklo kopurua</translation> +<translation id="7746357909584236306">editagarria</translation> <translation id="7747039790905080783">Aurrez partekatutako gakoa</translation> <translation id="7752963721013053477">Egunsentitik ilunabarrera: esklusiboa</translation> <translation id="7762130827864645708">Aldatu da pasahitza. Aurrerantzean, erabili pasahitz berria.</translation>
diff --git a/chromeos/strings/chromeos_strings_fa.xtb b/chromeos/strings/chromeos_strings_fa.xtb index 9e536ee..5c546eb 100644 --- a/chromeos/strings/chromeos_strings_fa.xtb +++ b/chromeos/strings/chromeos_strings_fa.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">تصویرها بار نشد. اتصال شبکه را بررسی کنید یا دوباره برای بار کردن تصویرها تلاش کنید.</translation> <translation id="1751249301761991853">شخصی</translation> <translation id="1753496554272155572">خروج از پیشنمای کاغذدیواری</translation> +<translation id="1754578112426924640">ویرایش دکمه <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">برنامه عیبیابی</translation> <translation id="175763766237925754">خوب (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android اجرا نمیشود</translation> <translation id="551689408806449779">ارتباط دستگاه قطع شده است. برای امتحان کردن، دوباره متصل شوید</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">قفلشده</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">رفتن خودکار به زمینه تیره هنگام غروب</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">مرکز</translation> <translation id="5703716265115423771">پایین آوردن صدا</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> از <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">ویرایش دکمه <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">بهروزرسانی <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">متوسط</translation> <translation id="5757187557809630523">آهنگ بعدی</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">ممنوع</translation> <translation id="5916664084637901428">روشن</translation> <translation id="5921506667911082617">{COUNT,plural, =1{فایل شما باموفقیت اسکن شد و در <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ذخیره شد.}one{فایل شما باموفقیت اسکن شد و در <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ذخیره شد.}other{فایلهای شما باموفقیت اسکن شد و در <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ذخیره شد.}}</translation> +<translation id="5928411637936685857">حذف دکمه <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">فایل پیدا نشد</translation> <translation id="593880865674747800">ایجاد کاغذدیواریهای بیشتر در این سبک</translation> <translation id="5939518447894949180">بازنشانی</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">تفکیک ساناد انجام نشد</translation> <translation id="6768237774506518020">میزان خطای تفکیک ساناد بالا است</translation> <translation id="6791471867139427246">رنگ نور صفحهکلید</translation> +<translation id="6796229976413584781">میانبر حذف شد</translation> <translation id="6798678288485555829">پیمایش نوشتار</translation> <translation id="680983167891198932">کلید</translation> <translation id="6816797338148849397">اطلاعات مرتبط با انتخاب شما دردسترس است. برای دسترسی، از کلید «پیکان روبه بالا» استفاده کنید.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">مدیریت تنظیمات APN شبکه. APN اتصالی میان شبکه تلفن همراه و اینترنت برقرار میکند. <ph name="BEGIN_LINK_LEARN_MORE" />بیشتر بدانید<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">بهروزرسانیهای سفتافزار برای دستگاههای خارجی</translation> <translation id="7216409898977639127">ارائهدهنده شبکه تلفن همراه</translation> +<translation id="7233782086689993269">میانبر بازیابی شد</translation> <translation id="725133483556299729">انتخاب ایمیل</translation> <translation id="7271040990581020067">اسکنر درحال استفاده است. بعداً دوباره امتحان کنید.</translation> <translation id="7271932918253517778">میانبرهای دارای کلیدهای ردیف بالا باید کلید <ph name="META_KEY" /> داشته باشند.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">تأخیر بالا در HTTPS</translation> <translation id="7656388927906093505">دستگاه موشواره است.</translation> <translation id="7658239707568436148">لغو</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />، <ph name="ACCELERATOR_INFO" />، <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">تغییر چهرک</translation> <translation id="7683228889864052081">رنگمایه صفحهکلید</translation> <translation id="7690294790491645610">تأیید گذرواژه جدید</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">میزان نور صفحهکلید</translation> <translation id="7730077286107534951">ممکن است برخیاز اطلاعات سیستم و حساب به Google ارسال شود. از این اطلاعات برای کمک به برطرف کردن مشکلات فنی و بهبود سرویسهایمان استفاده میکنیم، و این استفاده مطابق با <ph name="BEGIN_LINK2" />خطمشی رازداری<ph name="END_LINK2" /> و <ph name="BEGIN_LINK3" />شرایط خدمات<ph name="END_LINK3" /> ما خواهد بود. برای درخواست تغییر محتوا، به <ph name="BEGIN_LINK1" />راهنمای حقوقی<ph name="END_LINK1" /> بروید.</translation> <translation id="773153675489693198">تعداد چرخهها</translation> +<translation id="7746357909584236306">قابلویرایش</translation> <translation id="7747039790905080783">کلید ازپیش همرسانیشده</translation> <translation id="7752963721013053477">بامداد تا شامگاه - انحصاری</translation> <translation id="7762130827864645708">گذرواژهتان تغییر کرد. لطفاً ازاینپس، از گذرواژه جدید استفاده کنید.</translation>
diff --git a/chromeos/strings/chromeos_strings_fil.xtb b/chromeos/strings/chromeos_strings_fil.xtb index 305390d..a66d4efd 100644 --- a/chromeos/strings/chromeos_strings_fil.xtb +++ b/chromeos/strings/chromeos_strings_fil.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Hindi ma-load ang mga larawan. Suriin ang iyong koneksyon sa network o subukang i-load ulit ang mga larawan.</translation> <translation id="1751249301761991853">Personal</translation> <translation id="1753496554272155572">Lumabas sa preview ng wallpaper</translation> +<translation id="1754578112426924640">I-edit ang button para sa <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Diagnostics app</translation> <translation id="175763766237925754">Mabilis (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Hindi tumatakbo ang Android</translation> <translation id="551689408806449779">Na-disconnect ang device. Subukang kumonekta ulit para subukan</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">naka-lock</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Awtomatikong lumipat sa madilim na tema sa paglubog ng araw</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Gitna</translation> <translation id="5703716265115423771">hinaan ang volume</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> sa <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">I-edit ang button para sa <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">I-update ang <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Katamtaman</translation> <translation id="5757187557809630523">susunod na track</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Ipinagbabawal</translation> <translation id="5916664084637901428">Naka-on</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Na-scan at na-save na ang iyong file sa <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Na-scan at na-save na ang iyong mga file sa <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Na-scan at na-save na ang iyong mga file sa <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">I-delete ang button para sa <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Hindi nahanap ang file</translation> <translation id="593880865674747800">Gumawa pa gamit ang ganitong istilo</translation> <translation id="5939518447894949180">I-reset</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">May mga hindi naisagawang pagresolba sa DNS</translation> <translation id="6768237774506518020">Mataas na rate ng hindi naisagawang pagresolba sa DNS</translation> <translation id="6791471867139427246">kulay ng liwanag ng keyboard</translation> +<translation id="6796229976413584781">Na-delete ang shortcut</translation> <translation id="6798678288485555829">Pag-navigate sa text</translation> <translation id="680983167891198932">Key</translation> <translation id="6816797338148849397">Available ang impormasyong nauugnay sa iyong pinili. Gamitin ang Pataas na arrow key para ma-access.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Pamahalaan ang mga setting ng APN ng network. Bumubuo ang mga APN ng koneksyon sa pagitan ng cellular network at internet. <ph name="BEGIN_LINK_LEARN_MORE" />Matuto pa<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Mga update sa firmware para sa mga external na device</translation> <translation id="7216409898977639127">Cellular provider</translation> +<translation id="7233782086689993269">Na-restore ang shortcut</translation> <translation id="725133483556299729">Pumili ng email</translation> <translation id="7271040990581020067">Kasalukuyang ginagamit ang scanner. Subukan ulit sa ibang pagkakataon.</translation> <translation id="7271932918253517778">Kailangang kasama ang <ph name="META_KEY" /> key sa shortcut na may mga top row key.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Mataas na latency ng HTTPS</translation> <translation id="7656388927906093505">Mouse ang device.</translation> <translation id="7658239707568436148">Kanselahin</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Palitan ang avatar</translation> <translation id="7683228889864052081">hue ng keyboard</translation> <translation id="7690294790491645610">Kumpirmahin ang bagong password</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">liwanag ng keyboard</translation> <translation id="7730077286107534951">Puwedeng ipadala sa Google ang ilang impormasyon ng account at system. Ginagamit namin ang impormasyong ito para makatulong na lutasin ang mga teknikal na isyu at mapahusay ang aming mga serbisyo, na napapailalim sa aming <ph name="BEGIN_LINK2" />Patakaran sa Privacy<ph name="END_LINK2" /> at <ph name="BEGIN_LINK3" />Mga Tuntunin ng Serbisyo<ph name="END_LINK3" />. Para mag-request ng mga pagbabago sa content, pumunta sa <ph name="BEGIN_LINK1" />Legal na Tulong<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Bilang ng cycke</translation> +<translation id="7746357909584236306">nae-edit</translation> <translation id="7747039790905080783">Preshared key</translation> <translation id="7752963721013053477">Madaling araw hanggang pagdilim - eksklusibo</translation> <translation id="7762130827864645708">Matagumpay ang iyong pagpapalit ng password. Pakigamit ang bagong password mula ngayon.</translation>
diff --git a/chromeos/strings/chromeos_strings_gl.xtb b/chromeos/strings/chromeos_strings_gl.xtb index 7027fda..f443521f 100644 --- a/chromeos/strings/chromeos_strings_gl.xtb +++ b/chromeos/strings/chromeos_strings_gl.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Non se puideron cargar as imaxes. Comproba a túa conexión de rede ou tenta cargalas de novo.</translation> <translation id="1751249301761991853">Personalizar</translation> <translation id="1753496554272155572">Saír da vista previa do fondo de pantalla</translation> +<translation id="1754578112426924640">Botón para editar de <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplicación Diagnósticos</translation> <translation id="175763766237925754">Boa (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android non se está executando</translation> <translation id="551689408806449779">Desconectouse o dispositivo. Tenta conectalo de novo para facer a proba</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">con bloqueo</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Cambiar automaticamente ao tema escuro á hora do solpor</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centrar</translation> <translation id="5703716265115423771">baixa o volume</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> de <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Botón para editar de <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Actualizar <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Medio</translation> <translation id="5757187557809630523">pista seguinte</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Prohibida</translation> <translation id="5916664084637901428">Si</translation> <translation id="5921506667911082617">{COUNT,plural, =1{O teu ficheiro escaneouse e gardouse correctamente en <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Os teus ficheiros escaneáronse e gardáronse correctamente en <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Botón para eliminar de <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Non se encontrou o ficheiro</translation> <translation id="593880865674747800">Crear máis deste estilo</translation> <translation id="5939518447894949180">Restablecer</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Produciuse un erro coas resolucións de DNS</translation> <translation id="6768237774506518020">Hai un alto índice de erros relacionados coas resolucións de DNS</translation> <translation id="6791471867139427246">cor da luz do teclado</translation> +<translation id="6796229976413584781">Atallo eliminado</translation> <translation id="6798678288485555829">Navegación polo texto</translation> <translation id="680983167891198932">Clave</translation> <translation id="6816797338148849397">Hai dispoñible información sobre a túa selección. Utilizar frecha arriba para acceder.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Xestiona a configuración do APN da rede. Os APN establecen unha conexión entre unha rede de telefonía móbil e Internet. <ph name="BEGIN_LINK_LEARN_MORE" />Máis información<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Actualizacións de firmware para dispositivos externos</translation> <translation id="7216409898977639127">Provedor de rede móbil</translation> +<translation id="7233782086689993269">Atallo restaurado</translation> <translation id="725133483556299729">Seleccionar correo electrónico</translation> <translation id="7271040990581020067">Nestes momentos, o escáner está en uso. Téntao de novo máis tarde.</translation> <translation id="7271932918253517778">Os atallos con teclas da fila superior deben incluír a tecla <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Latencia de HTTPS alta</translation> <translation id="7656388927906093505">O dispositivo é un rato.</translation> <translation id="7658239707568436148">Cancelar</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Cambiar avatar</translation> <translation id="7683228889864052081">tonalidade do teclado</translation> <translation id="7690294790491645610">Confirmar contrasinal novo</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">luz do teclado</translation> <translation id="7730077286107534951">Pódese enviar parte da información da conta e do sistema a Google. Utilizaremos esta información para solucionar problemas técnicos e mellorar os nosos servizos, segundo o estipulado na nosa <ph name="BEGIN_LINK2" />Política de privacidade<ph name="END_LINK2" /> e nas <ph name="BEGIN_LINK3" />Condicións de servizo<ph name="END_LINK3" />. Para solicitar cambios no contido, vai a <ph name="BEGIN_LINK1" />Axuda legal<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Número de ciclos</translation> +<translation id="7746357909584236306">editable</translation> <translation id="7747039790905080783">Clave compartida previamente</translation> <translation id="7752963721013053477">Do amencer ao solpor (exclusivo)</translation> <translation id="7762130827864645708">Cambiaches o contrasinal correctamente. A partir de agora, utiliza o novo.</translation>
diff --git a/chromeos/strings/chromeos_strings_hr.xtb b/chromeos/strings/chromeos_strings_hr.xtb index 043ef40..6863371 100644 --- a/chromeos/strings/chromeos_strings_hr.xtb +++ b/chromeos/strings/chromeos_strings_hr.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Učitavanje slika nije uspjelo. Provjerite mrežnu vezu ili pokušajte ponovo učitati slike.</translation> <translation id="1751249301761991853">Osobno</translation> <translation id="1753496554272155572">Zatvaranje pregleda pozadina</translation> +<translation id="1754578112426924640">Gumb za uređivanje za stupac <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplikacija Dijagnostika</translation> <translation id="175763766237925754">Dobar (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android se ne pokreće</translation> <translation id="551689408806449779">Uređaj nije povezan. Pokušajte se povezati ponovo da biste testirali</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">zaključan</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Automatsko prebacivanje na tamnu temu kad zađe sunce</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centriraj</translation> <translation id="5703716265115423771">smanjivanje glasnoće</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> od <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Gumb za uređivanje za stupac <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Ažurirajte <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Srednje</translation> <translation id="5757187557809630523">sljedeća pjesma</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Zabranjeno</translation> <translation id="5916664084637901428">Uključi</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Vaša je datoteka skenirana i spremljena u mapu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Vaše su datoteke skenirane i spremljene u mapu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Vaše su datoteke skenirane i spremljene u mapu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Vaše su datoteke skenirane i spremljene u mapu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Gumb za brisanje za stupac <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Datoteka nije pronađena</translation> <translation id="593880865674747800">Izradite više u ovom stilu</translation> <translation id="5939518447894949180">Ponovno postavi</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Neuspješna razrješavanja DNS-a</translation> <translation id="6768237774506518020">Visoka stopa neuspješnih razrješavanja DNS-a</translation> <translation id="6791471867139427246">svijetla boja tipkovnice</translation> +<translation id="6796229976413584781">Prečac je izbrisan</translation> <translation id="6798678288485555829">Kretanje tekstom</translation> <translation id="680983167891198932">Ključ</translation> <translation id="6816797338148849397">Dostupne su informacije o vašem odabiru. Pristupite im pritiskom strelice prema gore.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Upravljajte postavkama APN-a mreže. APN-ovi uspostavljaju vezu između mobilne mreže i interneta. <ph name="BEGIN_LINK_LEARN_MORE" />Saznaj više<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Ažuriranja opreme za vanjske uređaje</translation> <translation id="7216409898977639127">Davatelj mobilnih usluga</translation> +<translation id="7233782086689993269">Prečac je vraćen</translation> <translation id="725133483556299729">Odaberite e-poštu</translation> <translation id="7271040990581020067">Skener se trenutačno upotrebljava. Pokušajte ponovo kasnije.</translation> <translation id="7271932918253517778">Prečac s tipkama iz gornjeg reda treba sadržavati tipku <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Visoka latencija HTTPS-a</translation> <translation id="7656388927906093505">Uređaj je miš.</translation> <translation id="7658239707568436148">Odustani</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Promjena avatara</translation> <translation id="7683228889864052081">nijansa tipkovnice</translation> <translation id="7690294790491645610">Potvrdite novu zaporku</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">svjetlo tipkovnice</translation> <translation id="7730077286107534951">Neki podaci o računu i sustavu možda će se poslati Googleu. Te podatke upotrebljavamo za rješavanje tehničkih problema i poboljšavanje usluga u skladu s našim <ph name="BEGIN_LINK2" />pravilima o privatnosti<ph name="END_LINK2" /> i <ph name="BEGIN_LINK3" />uvjetima pružanja usluge<ph name="END_LINK3" />. Da biste zatražili izmjene sadržaja, posjetite <ph name="BEGIN_LINK1" />pravnu pomoć<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Broj ciklusa</translation> +<translation id="7746357909584236306">uređivanje je moguće</translation> <translation id="7747039790905080783">Unaprijed podijeljen ključ</translation> <translation id="7752963721013053477">Od zore do mraka – ekskluzivno</translation> <translation id="7762130827864645708">Promjena zaporke je uspjela. Od sad upotrebljavajte novu zaporku.</translation>
diff --git a/chromeos/strings/chromeos_strings_id.xtb b/chromeos/strings/chromeos_strings_id.xtb index c9b0440..f9870448 100644 --- a/chromeos/strings/chromeos_strings_id.xtb +++ b/chromeos/strings/chromeos_strings_id.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Tidak dapat memuat foto. Periksa koneksi jaringan Anda atau coba muat foto lagi.</translation> <translation id="1751249301761991853">Pribadi</translation> <translation id="1753496554272155572">Keluar dari pratinjau wallpaper</translation> +<translation id="1754578112426924640">Tombol edit untuk <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplikasi Diagnostik</translation> <translation id="175763766237925754">Baik (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android tidak berjalan</translation> <translation id="551689408806449779">Perangkat telah terputus. Coba hubungkan kembali untuk melakukan pengujian</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">terkunci</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Otomatis beralih ke tema gelap saat matahari terbenam</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Tengah</translation> <translation id="5703716265115423771">menurunkan volume</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> dari <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Tombol edit untuk <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Update <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Sedang</translation> <translation id="5757187557809630523">lagu berikutnya</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Terlarang</translation> <translation id="5916664084637901428">Aktif</translation> <translation id="5921506667911082617">{COUNT,plural, =1{File Anda berhasil dipindai dan disimpan ke <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{File Anda berhasil dipindai dan disimpan ke <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Tombol hapus untuk <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">File tidak ditemukan</translation> <translation id="593880865674747800">Buat lebih banyak wallpaper dengan gaya ini</translation> <translation id="5939518447894949180">Reset</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Resolusi DNS gagal</translation> <translation id="6768237774506518020">Tingkat kegagalan resolusi DNS tinggi</translation> <translation id="6791471867139427246">warna lampu keyboard</translation> +<translation id="6796229976413584781">Pintasan dihapus</translation> <translation id="6798678288485555829">Navigasi teks</translation> <translation id="680983167891198932">Kunci</translation> <translation id="6816797338148849397">Info terkait pilihan Anda tersedia. Gunakan tombol Panah atas untuk mengakses.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Kelola setelan APN jaringan. APN membuat koneksi antara jaringan seluler dan internet. <ph name="BEGIN_LINK_LEARN_MORE" />Pelajari lebih lanjut<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Update firmware untuk perangkat eksternal</translation> <translation id="7216409898977639127">Operator seluler</translation> +<translation id="7233782086689993269">Pintasan dipulihkan</translation> <translation id="725133483556299729">Pilih email</translation> <translation id="7271040990581020067">Pemindai sedang digunakan. Coba lagi nanti.</translation> <translation id="7271932918253517778">Pintasan dengan tombol baris atas harus menyertakan tombol <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Latensi HTTPS tinggi</translation> <translation id="7656388927906093505">Perangkat adalah mouse.</translation> <translation id="7658239707568436148">Batal</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Ubah avatar</translation> <translation id="7683228889864052081">hue keyboard</translation> <translation id="7690294790491645610">Konfirmasi sandi baru</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">lampu keyboard</translation> <translation id="7730077286107534951">Beberapa informasi akun dan sistem dapat dikirimkan ke Google. Kami menggunakan informasi ini untuk membantu mengatasi masalah teknis dan meningkatkan kualitas layanan kami, sesuai dengan <ph name="BEGIN_LINK2" />Kebijakan Privasi<ph name="END_LINK2" /> dan <ph name="BEGIN_LINK3" />Persyaratan Layanan<ph name="END_LINK3" /> kami. Untuk meminta perubahan konten, buka <ph name="BEGIN_LINK1" />Bantuan Hukum<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Jumlah siklus</translation> +<translation id="7746357909584236306">dapat diedit</translation> <translation id="7747039790905080783">Kunci yang dibagikan sebelumnya</translation> <translation id="7752963721013053477">Dawn to dark - eksklusif</translation> <translation id="7762130827864645708">Perubahan sandi Anda berhasil. Gunakan sandi baru mulai sekarang.</translation>
diff --git a/chromeos/strings/chromeos_strings_is.xtb b/chromeos/strings/chromeos_strings_is.xtb index 3cb1976..ad6632d1 100644 --- a/chromeos/strings/chromeos_strings_is.xtb +++ b/chromeos/strings/chromeos_strings_is.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Ekki tókst að hlaða myndum. Athugaðu nettenginguna og reyndu að hlaða myndunum aftur.</translation> <translation id="1751249301761991853">Persónulegt</translation> <translation id="1753496554272155572">Loka forskoðun veggfóðurs</translation> +<translation id="1754578112426924640">Breyta hnappi fyrir <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Greiningarforrit</translation> <translation id="175763766237925754">Góður (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android er ekki í gangi</translation> <translation id="551689408806449779">Tækið aftengdist. Prófaðu að tengjast á ný til að prófa</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">læst</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Skipta sjálfkrafa yfir í dökkt þema við sólarlag</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Miðjujafna</translation> <translation id="5703716265115423771">lækka hljóð</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> af <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Breyta hnappi fyrir <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Uppfæra <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Miðlungs</translation> <translation id="5757187557809630523">næsta lag</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Bannað</translation> <translation id="5916664084637901428">Kveikt</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Skráin var skönnuð og vistuð í <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Skrárnar voru skannaðar og vistaðar í <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Skrárnar voru skannaðar og vistaðar í <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Eyða hnappi fyrir <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Skráin fannst ekki</translation> <translation id="593880865674747800">Búa til fleiri í þessum stíl</translation> <translation id="5939518447894949180">Endurstilla</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS-úrlausn mistókst</translation> <translation id="6768237774506518020">DNS-úrlausn mistekst oft</translation> <translation id="6791471867139427246">litur lyklaborðsljóss</translation> +<translation id="6796229976413584781">Flýtilykli eytt</translation> <translation id="6798678288485555829">Fletting í texta</translation> <translation id="680983167891198932">Lykill</translation> <translation id="6816797338148849397">Tiltækar upplýsingar sem tengjast vali þínu. Notaðu ör upp-lykilinn til að opna.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Stjórna stillingum aðgangsstaðar netkerfis. Aðgangsstaðir tengja saman farsímakerfi og internetið. <ph name="BEGIN_LINK_LEARN_MORE" />Nánar<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Fastbúnaðaruppfærslur fyrir ytri tæki</translation> <translation id="7216409898977639127">Farsímafyrirtæki</translation> +<translation id="7233782086689993269">Flýtilykill endurheimtur</translation> <translation id="725133483556299729">Velja netfang</translation> <translation id="7271040990581020067">Skanninn er í notkun núna. Reyndu aftur síðar.</translation> <translation id="7271932918253517778">Flýtilyklar sem innihalda lykla í efstu röð lyklaborðsins verða að innihalda <ph name="META_KEY" />-lykilinn.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Langur HTTPS-biðtími</translation> <translation id="7656388927906093505">Tækið er mús.</translation> <translation id="7658239707568436148">Hætta við</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Breyta notandamynd</translation> <translation id="7683228889864052081">litblær lyklaborðs</translation> <translation id="7690294790491645610">Staðfestu nýtt aðgangsorð</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">ljós lyklaborðs</translation> <translation id="7730077286107534951">Sumar reiknings- og kerfisupplýsingar gætu verið sendar til Google. Við notum þessar upplýsingar til að leysa tæknileg vandamál og bæta þjónustur okkar í samræmi við <ph name="BEGIN_LINK2" />persónuverndarstefnu<ph name="END_LINK2" /> okkar og <ph name="BEGIN_LINK3" />þjónustuskilmála<ph name="END_LINK3" />. Farðu í <ph name="BEGIN_LINK1" />lagalega aðstoð<ph name="END_LINK1" /> til að óska eftir efnislegum breytingum.</translation> <translation id="773153675489693198">Fjöldi endurhleðslna</translation> +<translation id="7746357909584236306">hægt að breyta</translation> <translation id="7747039790905080783">Samnotalykill</translation> <translation id="7752963721013053477">Frá dögun til rökkurs - sérstakt</translation> <translation id="7762130827864645708">Aðgangsorðinu þínu var breytt. Notaðu nýja aðgangsorðið framvegis.</translation>
diff --git a/chromeos/strings/chromeos_strings_iw.xtb b/chromeos/strings/chromeos_strings_iw.xtb index 1f6c2cd..e121830 100644 --- a/chromeos/strings/chromeos_strings_iw.xtb +++ b/chromeos/strings/chromeos_strings_iw.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">לא ניתן היה לטעון את התמונות. כדאי לבדוק את החיבור לרשת או לנסות לטעון את התמונות שוב.</translation> <translation id="1751249301761991853">התאמה אישית</translation> <translation id="1753496554272155572">יציאה מהתצוגה המקדימה של הטפט</translation> +<translation id="1754578112426924640">לחצן לעריכת מקש הקיצור <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">אפליקציית אבחון</translation> <translation id="175763766237925754">טוב (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">מערכת Android לא פועלת</translation> <translation id="551689408806449779">המכשיר נותק. כדי לבצע את הבדיקה, יש לחבר את המכשיר מחדש.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">נעולה</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">מעבר אוטומטי לעיצוב כהה בשקיעה</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">מרכז</translation> <translation id="5703716265115423771">הפחתת עוצמת הקול</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> מתוך <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">לחצן לעריכת מקש הקיצור <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">עדכון של <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">בינוני</translation> <translation id="5757187557809630523">הטראק הבא</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">אסור</translation> <translation id="5916664084637901428">פועל</translation> <translation id="5921506667911082617">{COUNT,plural, =1{הקובץ נסרק בהצלחה ונשמר בתיקייה <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{הקבצים נסרקו בהצלחה ונשמרו בתיקייה <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}two{הקבצים נסרקו בהצלחה ונשמרו בתיקייה <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{הקבצים נסרקו בהצלחה ונשמרו בתיקייה <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">לחצן למחיקת מקש הקיצור <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">הקובץ לא נמצא</translation> <translation id="593880865674747800">יצירת טפטים נוספים בסגנון הזה</translation> <translation id="5939518447894949180">איפוס</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">בקשות לזיהוי DNS שנכשלו</translation> <translation id="6768237774506518020">שיעור כישלון גבוה לנסיונות זיהוי DNS</translation> <translation id="6791471867139427246">צבע התאורה של המקלדת</translation> +<translation id="6796229976413584781">מקש הקיצור נמחק</translation> <translation id="6798678288485555829">ניווט בטקסט</translation> <translation id="680983167891198932">מקש</translation> <translation id="6816797338148849397">יש מידע בקשר לבחירה שלך. כדי לגשת אליו, יש להקיש על מקש החץ למעלה.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">ניהול הגדרות APN של הרשת. נקודות APN יוצרות חיבור בין רשת סלולרית לבין האינטרנט. <ph name="BEGIN_LINK_LEARN_MORE" />מידע נוסף<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">עדכוני קושחה למכשירים חיצוניים</translation> <translation id="7216409898977639127">ספק שירות סלולרי</translation> +<translation id="7233782086689993269">מקש הקיצור שוחזר</translation> <translation id="725133483556299729">בחירת אימייל</translation> <translation id="7271040990581020067">הסורק נמצא בשימוש כרגע. יש לנסות שוב מאוחר יותר.</translation> <translation id="7271932918253517778">מקש קיצור עם מקשים בשורה העליונה צריך לכלול את המקש '<ph name="META_KEY" />'.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">זמן רב של אחזור HTTPS</translation> <translation id="7656388927906093505">המכשיר הוא עכבר.</translation> <translation id="7658239707568436148">ביטול</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">החלפת הדמות</translation> <translation id="7683228889864052081">כוונון הגוון במקלדת</translation> <translation id="7690294790491645610">אישור הסיסמה החדשה</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">תאורה במקלדת</translation> <translation id="7730077286107534951">פרטים מסוימים על החשבון והמערכת עשויים להישלח ל-Google. אנחנו משתמשים בפרטים האלה כדי לפתור בעיות טכניות ולשפר את השירותים שלנו, בכפוף ל<ph name="BEGIN_LINK2" />מדיניות הפרטיות<ph name="END_LINK2" /> ו<ph name="BEGIN_LINK3" />לתנאים ולהגבלות<ph name="END_LINK3" /> שלנו. כדי לבקש שינויים בתוכן, צריך לעבור אל <ph name="BEGIN_LINK1" />העזרה המשפטית<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">מספר המחזורים</translation> +<translation id="7746357909584236306">ניתנת לעריכה</translation> <translation id="7747039790905080783">מפתח משותף מראש</translation> <translation id="7752963721013053477">מעלות השחר עד לרדת החושך – בלעדי</translation> <translation id="7762130827864645708">שינוי הסיסמה הסתיים בהצלחה. עליך להשתמש בסיסמה החדשה מעתה ואילך.</translation>
diff --git a/chromeos/strings/chromeos_strings_ja.xtb b/chromeos/strings/chromeos_strings_ja.xtb index 1f2f5e7..bb60c24 100644 --- a/chromeos/strings/chromeos_strings_ja.xtb +++ b/chromeos/strings/chromeos_strings_ja.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">画像を読み込めませんでした。ネットワーク接続を確認するか、画像をもう一度読み込んでみてください。</translation> <translation id="1751249301761991853">パーソナライズ</translation> <translation id="1753496554272155572">壁紙のプレビューを終了</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> の編集ボタン。</translation> <translation id="1755556344721611131">診断アプリ</translation> <translation id="175763766237925754">良好(<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android は実行されていません</translation> <translation id="551689408806449779">デバイスの接続が解除されました。テストするには再接続してください</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">ロック中</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">日の入り時にダークテーマへ自動的に切り替える</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">中央揃え</translation> <translation id="5703716265115423771">音量を下げる</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />/<ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> の編集ボタン。</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> を更新します。</translation> <translation id="574392208103952083">中</translation> <translation id="5757187557809630523">次のトラック</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">禁止</translation> <translation id="5916664084637901428">ON</translation> <translation id="5921506667911082617">{COUNT,plural, =1{ファイルは正常にスキャンされ、<ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> に保存されました。}other{ファイルは正常にスキャンされ、<ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> に保存されました。}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> の削除ボタン。</translation> <translation id="5931523347251946569">ファイルが見つかりません</translation> <translation id="593880865674747800">このスタイルでさらに作成</translation> <translation id="5939518447894949180">リセット</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS 解決に失敗しました</translation> <translation id="6768237774506518020">DNS 解決の失敗率が高くなっています</translation> <translation id="6791471867139427246">キーボード ライトの色</translation> +<translation id="6796229976413584781">ショートカットを削除しました</translation> <translation id="6798678288485555829">テキスト内の移動</translation> <translation id="680983167891198932">キー</translation> <translation id="6816797338148849397">選択した項目に関連する情報があります。上矢印キーでアクセスできます。</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">ネットワークの APN 設定を管理します。APN は、モバイル ネットワークとインターネットの間の接続を確立します。<ph name="BEGIN_LINK_LEARN_MORE" />詳細<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">外部デバイスのファームウェア アップデート</translation> <translation id="7216409898977639127">モバイル プロバイダ</translation> +<translation id="7233782086689993269">ショートカットを復元しました</translation> <translation id="725133483556299729">メールアドレスを選択</translation> <translation id="7271040990581020067">スキャナは現在使用中です。しばらくしてからもう一度お試しください。</translation> <translation id="7271932918253517778">最上段のキーを使用するショートカットには、<ph name="META_KEY" /> キーを含める必要があります。</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPS レイテンシが高くなっています</translation> <translation id="7656388927906093505">デバイスの種類はマウスです。</translation> <translation id="7658239707568436148">キャンセル</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />、<ph name="ACCELERATOR_INFO" />、<ph name="ROW_STATUS" />。</translation> <translation id="7665800271478495366">アバターを変更</translation> <translation id="7683228889864052081">キーボードの色調</translation> <translation id="7690294790491645610">新しいパスワードの確認入力</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">キーボード ライト</translation> <translation id="7730077286107534951">アカウント情報とシステム情報の一部が Google に送信されます。この情報は、Google の<ph name="BEGIN_LINK2" />プライバシー ポリシー<ph name="END_LINK2" />と<ph name="BEGIN_LINK3" />利用規約<ph name="END_LINK3" />に基づき、技術的な問題への対処やサービス改善のために使用されます。コンテンツの変更をリクエストするには、<ph name="BEGIN_LINK1" />法的事項に関するヘルプ<ph name="END_LINK1" />をご覧ください。</translation> <translation id="773153675489693198">サイクル回数</translation> +<translation id="7746357909584236306">編集可能</translation> <translation id="7747039790905080783">事前共有キー</translation> <translation id="7752963721013053477">夜明けから夜更けまで - 限定</translation> <translation id="7762130827864645708">パスワードを変更しました。今後は新しいパスワードを使用してください。</translation>
diff --git a/chromeos/strings/chromeos_strings_kk.xtb b/chromeos/strings/chromeos_strings_kk.xtb index 7dd2626..9f4d8c9 100644 --- a/chromeos/strings/chromeos_strings_kk.xtb +++ b/chromeos/strings/chromeos_strings_kk.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Суреттерді жүктеу мүмкін болмады. Желі байланысын тексеріңіз немесе суреттерді қайта жүктеп көріңіз.</translation> <translation id="1751249301761991853">Жеке</translation> <translation id="1753496554272155572">Тұсқағазды алдын ала көру режимінен шығу</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> бойынша өзгерту түймесі.</translation> <translation id="1755556344721611131">Diagnostics қолданбасы</translation> <translation id="175763766237925754">Жақсы (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android іске қосылмаған.</translation> <translation id="551689408806449779">Құрылғы ажыратылған. Сынау үшін қайта қосылып көріңіз.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">құлыпталған</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Күн батқанда, қараңғы режимге автоматты түрде ауысу</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Ортаға</translation> <translation id="5703716265115423771">дыбыс деңгейін төмендету</translation> <translation id="5707900041990977207"><ph name="TOTAL_PAGES" />/<ph name="CURRENT_PAGE" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> бойынша өзгерту түймесі.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> жаңарту</translation> <translation id="574392208103952083">Орташа</translation> <translation id="5757187557809630523">келесі трек</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Тыйым салынды</translation> <translation id="5916664084637901428">Қосулы</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Файлыңыз сканерленді және <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> қалтасына сақталды.}other{Файлдарыңыз сканерленді және <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> қалтасына сақталды.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> бойынша жою түймесі.</translation> <translation id="5931523347251946569">Файл табылмады.</translation> <translation id="593880865674747800">Осындай стильдегі көбірек тұсқағаз жасау</translation> <translation id="5939518447894949180">Қалпына келтіру</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS ажыратымдылықтары сәтсіз болды.</translation> <translation id="6768237774506518020">DNS ажыратымдылығының ақау көрсеткіші жоғары.</translation> <translation id="6791471867139427246">пернетақта жарығының түсі</translation> +<translation id="6796229976413584781">Пернелер тіркесімі жойылды</translation> <translation id="6798678288485555829">Мәтін навигациясы</translation> <translation id="680983167891198932">Кілт</translation> <translation id="6816797338148849397">Таңдауға қатысты ақпарат қолжетімді. Оны пайдалану үшін жоғарыға бағыттауыш пернені қолданыңыз.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Желінің APN параметрлерін басқаруға арналған. APN аттары ұялы желі мен интернет арасында байланыс орнатады. <ph name="BEGIN_LINK_LEARN_MORE" />Толық ақпарат<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Сыртқы құрылғыларға арналған микробағдарламаның жаңа нұсқалары</translation> <translation id="7216409898977639127">Ұялы байланыс провайдері</translation> +<translation id="7233782086689993269">Пернелер тіркесімі қалпына келді</translation> <translation id="725133483556299729">Электрондық поштаны таңдау</translation> <translation id="7271040990581020067">Сканер пайдаланылуда. Кейінірек қайталап көріңіз.</translation> <translation id="7271932918253517778">Жоғарғы жол пернелері бар пернелер тіркесімі <ph name="META_KEY" /> пернесін қамтуы керек.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPS кідірісі жоғары.</translation> <translation id="7656388927906093505">Бұл — тінтуір.</translation> <translation id="7658239707568436148">Бас тарту</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Аватарды өзгерту</translation> <translation id="7683228889864052081">пернетақта реңкі</translation> <translation id="7690294790491645610">Жаңа құпия сөзді қайталаңыз</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">пернетақта жарығы</translation> <translation id="7730077286107534951">Аккаунт және жүйе туралы кейбір ақпарат Google-ға жіберілуі мүмкін. Бұл ақпарат <ph name="BEGIN_LINK2" />Құпиялық саясаты<ph name="END_LINK2" /> мен <ph name="BEGIN_LINK3" />Қызмет көрсету шарттарына<ph name="END_LINK3" /> сәйкес техникалық мәселелерді шешу және қызметтерімізді жақсарту үшін пайдаланылады. Контентті өзгертуді сұрау үшін <ph name="BEGIN_LINK1" />Құқықтық анықтамаға<ph name="END_LINK1" /> өтіңіз.</translation> <translation id="773153675489693198">Цикл саны</translation> +<translation id="7746357909584236306">өзгертуге болады</translation> <translation id="7747039790905080783">Алдын ала бөлісілген код</translation> <translation id="7752963721013053477">Таң атқаннан қараңғыға дейін – эксклюзивті</translation> <translation id="7762130827864645708">Құпия сөзіңіз өзгерді. Бұдан былай жаңа құпия сөзді пайдаланыңыз.</translation>
diff --git a/chromeos/strings/chromeos_strings_kn.xtb b/chromeos/strings/chromeos_strings_kn.xtb index a03a2555..494ca15 100644 --- a/chromeos/strings/chromeos_strings_kn.xtb +++ b/chromeos/strings/chromeos_strings_kn.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">ಚಿತ್ರಗಳನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ನಿಮ್ಮ ನೆಟ್ವರ್ಕ್ ಕನೆಕ್ಷನ್ ಪರಿಶೀಲಿಸಿ ಅಥವಾ ಚಿತ್ರಗಳನ್ನು ಪುನಃ ಲೋಡ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ.</translation> <translation id="1751249301761991853">ವೈಯಕ್ತಿಕ</translation> <translation id="1753496554272155572">ವಾಲ್ಪೇಪರ್ ಪೂರ್ವವೀಕ್ಷಣೆಯಿಂದ ನಿರ್ಗಮಿಸಿ</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> ಗಾಗಿ ಎಡಿಟ್ ಮಾಡುವ ಬಟನ್.</translation> <translation id="1755556344721611131">ಡಯಾಗ್ನಾಸ್ಟಿಕ್ಸ್ ಆ್ಯಪ್</translation> <translation id="175763766237925754">ಉತ್ತಮ (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android ರನ್ ಆಗುತ್ತಿಲ್ಲ</translation> <translation id="551689408806449779">ಸಾಧನವು ಡಿಸ್ಕನೆಕ್ಟ್ ಆಗಿದೆ. ಪರೀಕ್ಷಿಸುವುದಕ್ಕಾಗಿ ಪುನಃ ಕನೆಕ್ಟ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">ಲಾಕ್ ಆಗಿದೆ</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">ಸೂರ್ಯಾಸ್ತದ ಸಮಯದಲ್ಲಿ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಡಾರ್ಕ್ ಥೀಮ್ಗೆ ಬದಲಿಸಿ</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">ಮಧ್ಯಕ್ಕೆ</translation> <translation id="5703716265115423771">ವಾಲ್ಯೂಮ್ ಕಡಿಮೆ ಮಾಡಿ</translation> <translation id="5707900041990977207"><ph name="TOTAL_PAGES" /> ರಲ್ಲಿ <ph name="CURRENT_PAGE" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> ಗಾಗಿ ಎಡಿಟ್ ಮಾಡುವ ಬಟನ್.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಿ</translation> <translation id="574392208103952083">ಮಧ್ಯಮ</translation> <translation id="5757187557809630523">ಮುಂದಿನ ಟ್ರ್ಯಾಕ್</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">ನಿಷೇಧಿಸಲಾಗಿದೆ</translation> <translation id="5916664084637901428">ಆನ್</translation> <translation id="5921506667911082617">{COUNT,plural, =1{ನಿಮ್ಮ ಫೈಲ್ ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ಗೆ ಸೇವ್ ಮಾಡಲಾಗಿದೆ.}one{ನಿಮ್ಮ ಫೈಲ್ಗಳನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ಗೆ ಸೇವ್ ಮಾಡಲಾಗಿದೆ.}other{ನಿಮ್ಮ ಫೈಲ್ಗಳನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ಗೆ ಸೇವ್ ಮಾಡಲಾಗಿದೆ.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> ಗಾಗಿ ಅಳಿಸುವ ಬಟನ್.</translation> <translation id="5931523347251946569">ಫೈಲ್ ಕಂಡುಬಂದಿಲ್ಲ</translation> <translation id="593880865674747800">ಈ ಶೈಲಿಯಲ್ಲಿ ಇನ್ನಷ್ಟು ರಚಿಸಿ</translation> <translation id="5939518447894949180">ಮರುಹೊಂದಿಸು</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS ರೆಸಲ್ಯೂಷನ್ಗಳು ವಿಫಲವಾಗಿವೆ</translation> <translation id="6768237774506518020">ಅಧಿಕ DNS ರೆಸಲ್ಯೂಷನ್ ವೈಫಲ್ಯ ದರ</translation> <translation id="6791471867139427246">ಕೀಬೋರ್ಡ್ ಲೈಟ್ ಬಣ್ಣ</translation> +<translation id="6796229976413584781">ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಅಳಿಸಲಾಗಿದೆ</translation> <translation id="6798678288485555829">ಪಠ್ಯದ ನ್ಯಾವಿಗೇಷನ್</translation> <translation id="680983167891198932">ಕೀ</translation> <translation id="6816797338148849397">ನಿಮ್ಮ ಆಯ್ಕೆಗೆ ಸಂಬಂಧಿಸಿದ ಮಾಹಿತಿ ಲಭ್ಯವಿದೆ. ಇದಕ್ಕೆ ಆ್ಯಕ್ಸೆಸ್ ಪಡೆಯಲು, ಅಪ್ ಆ್ಯರೋ ಬಳಸಿ.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">ನೆಟ್ವರ್ಕ್ APN ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ನಿರ್ವಹಿಸಿ. APN ಗಳು ಸೆಲ್ಯುಲಾರ್ ನೆಟ್ವರ್ಕ್ ಹಾಗೂ ಇಂಟರ್ನೆಟ್ ನಡುವೆ ಕನೆಕ್ಷನ್ ಅನ್ನು ಸ್ಥಾಪಿಸುತ್ತವೆ. <ph name="BEGIN_LINK_LEARN_MORE" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">ಬಾಹ್ಯ ಸಾಧನಗಳಿಗಾಗಿ ಫರ್ಮ್ವೇರ್ ಅಪ್ಡೇಟ್ಗಳು</translation> <translation id="7216409898977639127">ಸೆಲ್ಯುಲಾರ್ ಒದಗಿಸುವವರು</translation> +<translation id="7233782086689993269">ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲಾಗಿದೆ</translation> <translation id="725133483556299729">ಇಮೇಲ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ</translation> <translation id="7271040990581020067">ಸ್ಕ್ಯಾನರ್ ಅನ್ನು ಪ್ರಸ್ತುತವಾಗಿ ಬಳಸಲಾಗುತ್ತಿದೆ. ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.</translation> <translation id="7271932918253517778">ಮೇಲಿನ ಸಾಲಿನ ಕೀಗಳ ಶಾರ್ಟ್ಕಟ್ <ph name="META_KEY" /> ಕೀಯನ್ನು ಹೊಂದಿರಬೇಕಾದ ಅಗತ್ಯವಿದೆ.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">ಅಧಿಕ HTTPS ವಿಳಂಬ</translation> <translation id="7656388927906093505">ಸಾಧನವು ಮೌಸ್ ಆಗಿದೆ.</translation> <translation id="7658239707568436148">ರದ್ದುಮಾಡಿ</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">ಅವತಾರ್ ಬದಲಾಯಿಸಿ</translation> <translation id="7683228889864052081">ಕೀಬೋರ್ಡ್ ಹ್ಯೂ</translation> <translation id="7690294790491645610">ಹೊಸ ಪಾಸ್ವರ್ಡ್ ಖಚಿತಪಡಿಸಿ</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">ಕೀಬೋರ್ಡ್ ಲೈಟ್</translation> <translation id="7730077286107534951">ಕೆಲವು ಖಾತೆ ಮತ್ತು ಸಿಸ್ಟಂ ಮಾಹಿತಿಯನ್ನು Google ಗೆ ಕಳುಹಿಸಲಾಗುತ್ತದೆ. ತಾಂತ್ರಿಕ ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಹರಿಸುವುದಕ್ಕೆ ಮತ್ತು ನಮ್ಮ ಸೇವೆಗಳನ್ನು ಸುಧಾರಿಸುವುದಕ್ಕೆ ಸಹಾಯ ಮಾಡಲು ನಾವು ಈ ಮಾಹಿತಿಯನ್ನು ಬಳಸುತ್ತೇವೆ, ಇದು ನಮ್ಮ <ph name="BEGIN_LINK2" />ಗೌಪ್ಯತೆ ನೀತಿ<ph name="END_LINK2" /> ಮತ್ತು <ph name="BEGIN_LINK3" />ಸೇವಾ ನಿಯಮಗಳಿಗೆ<ph name="END_LINK3" /> ಒಳಪಟ್ಟಿರುತ್ತದೆ. ಕಂಟೆಂಟ್ ಬದಲಾವಣೆಗಳಿಗೆ ವಿನಂತಿಸುವುದಕ್ಕಾಗಿ, <ph name="BEGIN_LINK1" />ಕಾನೂನುಬದ್ಧ ಸಹಾಯ<ph name="END_LINK1" /> ಪುಟಕ್ಕೆ ಹೋಗಿ.</translation> <translation id="773153675489693198">ಆವರ್ತನ ಎಣಿಕೆ</translation> +<translation id="7746357909584236306">ಎಡಿಟ್ ಮಾಡಬಹುದು</translation> <translation id="7747039790905080783">ಪೂರ್ವ-ಹಂಚಿಕೆಯ ಕೀ</translation> <translation id="7752963721013053477">ಡಾನ್ ಟು ಡಾರ್ಕ್ - ಎಕ್ಸ್ಕ್ಲೂಸಿವ್</translation> <translation id="7762130827864645708">ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ ಬದಲಾವಣೆಯು ಯಶಸ್ವಿಯಾಗಿದೆ. ಈಗಿನಿಂದ ಹೊಸ ಪಾಸ್ವರ್ಡ್ ಬಳಸಿ.</translation>
diff --git a/chromeos/strings/chromeos_strings_ko.xtb b/chromeos/strings/chromeos_strings_ko.xtb index e75bef0..4ec7151 100644 --- a/chromeos/strings/chromeos_strings_ko.xtb +++ b/chromeos/strings/chromeos_strings_ko.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">이미지를 로드할 수 없습니다. 네트워크 연결을 확인하거나 이미지를 다시 로드해 보세요.</translation> <translation id="1751249301761991853">개인</translation> <translation id="1753496554272155572">배경화면 미리보기 종료</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" />의 수정 버튼입니다.</translation> <translation id="1755556344721611131">진단 앱</translation> <translation id="175763766237925754">양호(<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android 실행되고 있지 않음</translation> <translation id="551689408806449779">기기 연결이 해제되었습니다. 테스트하려면 다시 연결해 보세요.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">잠김</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">일몰 시 어두운 테마로 자동 전환</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">가운데</translation> <translation id="5703716265115423771">볼륨 작게</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />/<ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" />의 수정 버튼입니다.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> 업데이트</translation> <translation id="574392208103952083">보통</translation> <translation id="5757187557809630523">다음 트랙입니다</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">금지됨</translation> <translation id="5916664084637901428">사용</translation> <translation id="5921506667911082617">{COUNT,plural, =1{파일 스캔이 완료되어 <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />에 저장되었습니다.}other{파일 스캔이 완료되어 <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />에 저장되었습니다.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" />의 삭제 버튼입니다.</translation> <translation id="5931523347251946569">파일을 찾을 수 없음</translation> <translation id="593880865674747800">이 스타일로 더 만들기</translation> <translation id="5939518447894949180">초기화</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS 변환 실패함</translation> <translation id="6768237774506518020">DNS 변환 실패율 높음</translation> <translation id="6791471867139427246">키보드 조명 색상</translation> +<translation id="6796229976413584781">단축키가 삭제됨</translation> <translation id="6798678288485555829">텍스트 탐색</translation> <translation id="680983167891198932">키</translation> <translation id="6816797338148849397">선택 항목과 관련된 정보를 이용할 수 있습니다. 액세스하려면 위쪽 화살표 키를 사용하세요.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">네트워크 APN 설정을 관리하세요. APN은 셀룰러 네트워크와 인터넷 간의 연결을 설정합니다. <ph name="BEGIN_LINK_LEARN_MORE" />자세히 알아보기<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">외부 기기 펌웨어 업데이트</translation> <translation id="7216409898977639127">이동통신사</translation> +<translation id="7233782086689993269">단축키가 복원됨</translation> <translation id="725133483556299729">이메일 선택</translation> <translation id="7271040990581020067">현재 스캐너를 사용하고 있습니다. 나중에 다시 시도해 주세요.</translation> <translation id="7271932918253517778">맨 위 행의 단축키에는 <ph name="META_KEY" /> 키가 포함되어야 합니다.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPS 지연 시간 높음</translation> <translation id="7656388927906093505">마우스 기기입니다.</translation> <translation id="7658239707568436148">취소</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">아바타 변경</translation> <translation id="7683228889864052081">키보드 색조</translation> <translation id="7690294790491645610">새 비밀번호 확인</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">키보드 조명</translation> <translation id="7730077286107534951">일부 계정 및 시스템 정보가 Google로 전송될 수 있습니다. 이러한 정보는 Google <ph name="BEGIN_LINK2" />개인정보처리방침<ph name="END_LINK2" /> 및 <ph name="BEGIN_LINK3" />서비스 약관<ph name="END_LINK3" />에 따라 기술 문제를 해결하고 서비스를 개선하는 데 사용됩니다. 콘텐츠 변경을 요청하려면 <ph name="BEGIN_LINK1" />법률 도움말<ph name="END_LINK1" />로 이동하세요.</translation> <translation id="773153675489693198">사이클 수</translation> +<translation id="7746357909584236306">수정 가능</translation> <translation id="7747039790905080783">사전 공유 키</translation> <translation id="7752963721013053477">새벽부터 밤까지 - 전용</translation> <translation id="7762130827864645708">비밀번호가 변경되었습니다. 지금부터 새로운 비밀번호를 사용해 주세요.</translation>
diff --git a/chromeos/strings/chromeos_strings_ky.xtb b/chromeos/strings/chromeos_strings_ky.xtb index ba560ce0..71317b4 100644 --- a/chromeos/strings/chromeos_strings_ky.xtb +++ b/chromeos/strings/chromeos_strings_ky.xtb
@@ -475,7 +475,7 @@ <translation id="4469288414739283461">Жер көшөгөсү</translation> <translation id="4479639480957787382">Ethernet</translation> <translation id="4483049906298469269">Демейкиден башка тармактын шлюзуна ping сурамы жөнөтүлгөн жок</translation> -<translation id="4500722292849917410">Ыкчам баскыч жеткиликсиз. Өзгөртүү баскычы (ctrl, alt, shift же <ph name="META_KEY" />) бар жаңы ыкчам баскычты басыңыз.</translation> +<translation id="4500722292849917410">Ыкчам баскыч жеткиликсиз. Өзгөртүүчү баскыч (ctrl, alt, shift же <ph name="META_KEY" />) бар жаңы ыкчам баскычты басыңыз.</translation> <translation id="4500966230243561393">Интерфейстин түсү</translation> <translation id="4503223151711056411">Солго жебе</translation> <translation id="4507392511610824664">жарыктыгын көбөйтүү</translation> @@ -550,7 +550,7 @@ <translation id="4969079779290789265">Бөлүү</translation> <translation id="4972592110715526173">режимди өзгөртүү</translation> <translation id="498186245079027698">Сканерди текшерип, кайра аракет кылыңыз. Скандалган файлдарды сактоо үчүн орун жетиштүү экенин текшериңиз.</translation> -<translation id="4982627662315910959">Ыкчам баскыч жеткиликсиз. Shift жана дагы 1 өзгөртүү баскычы (ctrl, alt же <ph name="META_KEY" />) бар жаңы ыкчам баскычты басыңыз.</translation> +<translation id="4982627662315910959">Ыкчам баскыч жеткиликсиз. Shift жана дагы 1 өзгөртүүчү баскыч (ctrl, alt же <ph name="META_KEY" />) бар жаңы ыкчам баскычты басыңыз.</translation> <translation id="4985509611418653372">Иштетүү</translation> <translation id="4987769320337599931">Тармактык коргоо</translation> <translation id="4988526792673242964">Барактар</translation>
diff --git a/chromeos/strings/chromeos_strings_lt.xtb b/chromeos/strings/chromeos_strings_lt.xtb index fce4d7ce..6f205e53 100644 --- a/chromeos/strings/chromeos_strings_lt.xtb +++ b/chromeos/strings/chromeos_strings_lt.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Nepavyko įkelti vaizdų. Patikrinkite tinklo ryšį arba pabandykite dar kartą įkelti vaizdus.</translation> <translation id="1751249301761991853">Suasmeninimas</translation> <translation id="1753496554272155572">Išeiti iš ekrano fono peržiūros</translation> +<translation id="1754578112426924640">„<ph name="ACCELERATOR_INFO" />“ redagavimo mygtukas.</translation> <translation id="1755556344721611131">Diagnostikos programa</translation> <translation id="175763766237925754">Geras (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">„Android“ neveikia</translation> <translation id="551689408806449779">Įrenginys atjungtas. Bandykite prisijungti dar kartą ir išbandykite</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">užrakinta</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Automatiškai perjungti į tamsiąją temą saulei leidžiantis</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centre</translation> <translation id="5703716265115423771">garsumo mažinimas</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> iš <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">„<ph name="SHORTCUT_DESCRIPTION" />“ redagavimo mygtukas.</translation> <translation id="5733298426544876109">Atnaujinti „<ph name="DEVICE_NAME" />“</translation> <translation id="574392208103952083">Vidutinis</translation> <translation id="5757187557809630523">kitas takelis</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Draudžiama</translation> <translation id="5916664084637901428">Įjungta</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Failas sėkmingai nuskaitytas ir išsaugotas aplanke <ph name="LINK_BEGIN" />„<ph name="FOLDER_NAME" />“<ph name="LINK_END" />.}one{Failai sėkmingai nuskaityti ir išsaugoti aplanke <ph name="LINK_BEGIN" />„<ph name="FOLDER_NAME" />“<ph name="LINK_END" />.}few{Failai sėkmingai nuskaityti ir išsaugoti aplanke <ph name="LINK_BEGIN" />„<ph name="FOLDER_NAME" />“<ph name="LINK_END" />.}many{Failai sėkmingai nuskaityti ir išsaugoti aplanke <ph name="LINK_BEGIN" />„<ph name="FOLDER_NAME" />“<ph name="LINK_END" />.}other{Failai sėkmingai nuskaityti ir išsaugoti aplanke <ph name="LINK_BEGIN" />„<ph name="FOLDER_NAME" />“<ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">„<ph name="ACCELERATOR_INFO" />“ ištrynimo mygtukas.</translation> <translation id="5931523347251946569">Failas nerastas</translation> <translation id="593880865674747800">Kurkite daugiau šiuo stiliumi</translation> <translation id="5939518447894949180">Nustatyti iš naujo</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Nepavykę DNS nustatymo veiksmai</translation> <translation id="6768237774506518020">Aukštas DNS nustatymo trikčių rodiklis</translation> <translation id="6791471867139427246">klaviatūros šviesos spalva</translation> +<translation id="6796229976413584781">Spartusis klavišas ištrintas</translation> <translation id="6798678288485555829">Teksto naršymas</translation> <translation id="680983167891198932">Raktas</translation> <translation id="6816797338148849397">Pasiekiama su pasirinkimu susijusi informacija Norėdami pasiekti, spustelėkite rodyklės aukštyn klavišą.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Tvarkyti tinklo APN nustatymus. APN užmezga ryšį tarp mobiliojo ryšio tinklo ir interneto. <ph name="BEGIN_LINK_LEARN_MORE" />Sužinokite daugiau<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Išorinių įrenginių programinės aparatinės įrangos naujiniai</translation> <translation id="7216409898977639127">Mobiliojo ryšio teikėjas</translation> +<translation id="7233782086689993269">Spartusis klavišas atkurtas</translation> <translation id="725133483556299729">El. pašto adreso pasirinkimas</translation> <translation id="7271040990581020067">Skaitytuvas šiuo metu naudojamas. Vėliau bandykite dar kartą.</translation> <translation id="7271932918253517778">Į spartųjį klavišą su viršutinės eilutės klavišais turi būti įtrauktas klavišas „<ph name="META_KEY" />“.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Didelė HTTPS delsa</translation> <translation id="7656388927906093505">Įrenginys yra pelė.</translation> <translation id="7658239707568436148">Atšaukti</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Keisti pseudoportretą</translation> <translation id="7683228889864052081">klaviatūros atspalvis</translation> <translation id="7690294790491645610">Patvirtinkite naują slaptažodį</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">klaviatūros lemputė</translation> <translation id="7730077286107534951">Dalis informacijos apie paskyrą ir sistemą gali būti išsiųsta į sistemą „Google“. Šią informaciją naudojame spręsdami technines problemas ir tobulindami paslaugas pagal mūsų <ph name="BEGIN_LINK2" />privatumo politiką<ph name="END_LINK2" /> ir <ph name="BEGIN_LINK3" />paslaugų teikimo sąlygas<ph name="END_LINK3" />. Jei norite pateikti turinio pakeitimų užklausą, eikite į <ph name="BEGIN_LINK1" />teisinės pagalbos puslapį<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Ciklų skaičius</translation> +<translation id="7746357909584236306">redaguotina</translation> <translation id="7747039790905080783">Paruoštas bendrinti raktas</translation> <translation id="7752963721013053477">Nuo aušros iki sutemų – išskirtinis</translation> <translation id="7762130827864645708">Slaptažodis sėkmingai pakeistas. Nuo šiol naudokite naują slaptažodį.</translation>
diff --git a/chromeos/strings/chromeos_strings_lv.xtb b/chromeos/strings/chromeos_strings_lv.xtb index f399ae9..685c9d2 100644 --- a/chromeos/strings/chromeos_strings_lv.xtb +++ b/chromeos/strings/chromeos_strings_lv.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Nevarēja ielādēt attēlus. Pārbaudiet tīkla savienojumu vai vēlreiz mēģiniet ielādēt attēlus.</translation> <translation id="1751249301761991853">Personīgi</translation> <translation id="1753496554272155572">Aizvērt fona tapetes priekšskatījumu</translation> +<translation id="1754578112426924640">Rediģēšanas poga īsinājumtaustiņam <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Diagnostikas lietotne</translation> <translation id="175763766237925754">Labs (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android nedarbojas</translation> <translation id="551689408806449779">Savienojums ar ierīci ir pārtraukts. Lai veiktu testēšanu, izveidojiet savienojumu atkārtoti.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">bloķēta</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Saulrietā automātiski pāriet uz tumšo motīvu</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centrēt</translation> <translation id="5703716265115423771">samazināt skaļumu</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />. no <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Rediģēšanas poga darbībai <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Atjaunināt ierīci “<ph name="DEVICE_NAME" />”</translation> <translation id="574392208103952083">Vidējs</translation> <translation id="5757187557809630523">nākamais ieraksts</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Aizliegts</translation> <translation id="5916664084637901428">Iesl.</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Fails ir sekmīgi noskenēts un saglabāts mapē <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}zero{Faili ir sekmīgi noskenēti un saglabāti mapē <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Faili ir sekmīgi noskenēti un saglabāti mapē <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Faili ir sekmīgi noskenēti un saglabāti mapē <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Dzēšanas poga īsinājumtaustiņam <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Fails nav atrasts</translation> <translation id="593880865674747800">Izveidot vēl, izmantojot šo stilu</translation> <translation id="5939518447894949180">Atiestatīt</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS atrisināšanas kļūmes</translation> <translation id="6768237774506518020">Biežas DNS atrisināšanas kļūmes</translation> <translation id="6791471867139427246">tastatūras apgaismojuma krāsa</translation> +<translation id="6796229976413584781">Īsinājumtaustiņš ir izdzēsts</translation> <translation id="6798678288485555829">Navigācija tekstā</translation> <translation id="680983167891198932">Atslēga</translation> <translation id="6816797338148849397">Ir pieejama informācija, kas saistīta ar jūsu atlasīto saturu. Lai piekļūtu informācijai, nospiediet augšupvērsto bultiņu.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Pārvaldiet tīkla APN iestatījumus. APN izveido savienojumu starp mobilo tīklu un internetu. <ph name="BEGIN_LINK_LEARN_MORE" />Uzziniet vairāk<ph name="END_LINK_LEARN_MORE" />.</translation> <translation id="7212734716605298123">Aparātprogrammatūras atjauninājumi ārējām ierīcēm</translation> <translation id="7216409898977639127">Mobilo sakaru operators</translation> +<translation id="7233782086689993269">Īsinājumtaustiņš ir atjaunots</translation> <translation id="725133483556299729">Atlasiet e-pasta adresi</translation> <translation id="7271040990581020067">Skeneris pašlaik tiek izmantots. Vēlāk mēģiniet vēlreiz.</translation> <translation id="7271932918253517778">Īsinājumtaustiņiem, kuros tiek izmantots kāds no augšējās rindas taustiņiem, ir jāietver arī <ph name="META_KEY" /> taustiņš.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Liels HTTPS latentums</translation> <translation id="7656388927906093505">Ierīce ir pele.</translation> <translation id="7658239707568436148">Atcelt</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Mainīt iemiesojumu</translation> <translation id="7683228889864052081">tastatūras nokrāsa</translation> <translation id="7690294790491645610">Apstipriniet jauno paroli</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">tastatūras apgaismojums</translation> <translation id="7730077286107534951">Noteikta konta un sistēmas informācija var tikt nosūtīta uzņēmumam Google. Mēs izmantojam šo informāciju tehnisku problēmu novēršanai un savu pakalpojumu uzlabošanai saskaņā ar savu <ph name="BEGIN_LINK2" />konfidencialitātes politiku<ph name="END_LINK2" /> un <ph name="BEGIN_LINK3" />pakalpojumu sniegšanas noteikumiem<ph name="END_LINK3" />. Lai pieprasītu satura izmaiņas, pārejiet uz <ph name="BEGIN_LINK1" />juridiskās palīdzības lapu<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Ciklu laiks</translation> +<translation id="7746357909584236306">rediģējama</translation> <translation id="7747039790905080783">Iepriekš kopīgota atslēga</translation> <translation id="7752963721013053477">No ausmas līdz tumsai — ekskluzīvi attēli</translation> <translation id="7762130827864645708">Parole ir sekmīgi nomainīta. Lūdzu, turpmāk izmantojiet jauno paroli.</translation>
diff --git a/chromeos/strings/chromeos_strings_mn.xtb b/chromeos/strings/chromeos_strings_mn.xtb index 5cd36885..beb29cf 100644 --- a/chromeos/strings/chromeos_strings_mn.xtb +++ b/chromeos/strings/chromeos_strings_mn.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Зургийг ачаалж чадсангүй. Сүлжээний холболтоо шалгах эсвэл зургуудыг дахин ачаалж үзнэ үү</translation> <translation id="1751249301761991853">Хувийн</translation> <translation id="1753496554272155572">Дэлгэцийн зургийг урьдчилан үзэхээс гарах</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" />-н засах товчлуур.</translation> <translation id="1755556344721611131">Оношилгооны апп</translation> <translation id="175763766237925754">Сайн (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android ажиллахгүй байна</translation> <translation id="551689408806449779">Төхөөрөмж салсан байна. Туршихын тулд дахин холбогдохоор оролдоно уу</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">түгжсэн</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Нар жаргах үед бараан загвар луу автоматаар сэлгэх</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Төв</translation> <translation id="5703716265115423771">дууны түвшинг хасах</translation> <translation id="5707900041990977207"><ph name="TOTAL_PAGES" />-н <ph name="CURRENT_PAGE" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" />-н засах товчлуур.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" />-г шинэчлэх</translation> <translation id="574392208103952083">Дунд зэрэг</translation> <translation id="5757187557809630523">дараагийн бичлэг</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Хориглосон</translation> <translation id="5916664084637901428">Асаах</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Таны файлыг амжилттай скан хийсэн бөгөөд <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />-д хадгалсан.}other{Таны файлуудыг амжилттай скан хийсэн бөгөөд <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />-д хадгалсан.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" />-н устгах товчлуур.</translation> <translation id="5931523347251946569">Файл олдсонгүй</translation> <translation id="593880865674747800">Ийм загвартай илүү их дэлгэцийн зураг үүсгэх</translation> <translation id="5939518447894949180">Дахин сэргээх</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS-н тайлал амжилтгүй</translation> <translation id="6768237774506518020">DNS-н тайллын алдааны өндөр хувь</translation> <translation id="6791471867139427246">гарын гэрлийн өнгө</translation> +<translation id="6796229976413584781">Товчлолыг устгасан</translation> <translation id="6798678288485555829">Текстийн навигац</translation> <translation id="680983167891198932">Түлхүүр</translation> <translation id="6816797338148849397">Таны сонголттой холбоотой мэдээлэл боломжтой байна. Хандахын тулд Дээш суман товчийг ашиглана уу.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Сүлжээний APN-н тохиргоог удирдана уу. APN үүрэн холбооны сүлжээ болон интернэтийн хооронд холболт тогтоодог. <ph name="BEGIN_LINK_LEARN_MORE" />Нэмэлт мэдээлэл авах<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Гадаад төхөөрөмжүүдийн жижиг программын шинэчлэлтүүд</translation> <translation id="7216409898977639127">Үүрэн холбооны үйлчилгээ үзүүлэгч</translation> +<translation id="7233782086689993269">Товчлолыг сэргээсэн</translation> <translation id="725133483556299729">Имэйл сонгох</translation> <translation id="7271040990581020067">Сканнерыг одоогоор ашиглаж байна. Дараа дахин оролдоно уу.</translation> <translation id="7271932918253517778">Дээд талын мөрийн товчнуудтай товчлол нь <ph name="META_KEY" /> товчийг оруулах шаардлагатай.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Өндөр HTTPS хоцролт</translation> <translation id="7656388927906093505">Төхөөрөмж нь хулгана байна.</translation> <translation id="7658239707568436148">Болих</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Аватар өөрчлөх</translation> <translation id="7683228889864052081">гарын өнгө</translation> <translation id="7690294790491645610">Шинэ нууц үг баталгаажуулна уу</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">гарын гэрэл</translation> <translation id="7730077286107534951">Зарим бүртгэл болон системийн мэдээллийг Google рүү илгээж болзошгүй. Бид энэ мэдээллийг <ph name="BEGIN_LINK2" />нууцлалын бодлого<ph name="END_LINK2" /> ба <ph name="BEGIN_LINK3" />үйлчилгээний нөхцөлийн<ph name="END_LINK3" /> дагуу техникийн асуудлуудыг шийдвэрлэхэд туслах болон үйлчилгээнүүдээ сайжруулахад ашиглана. Контентын өөрчлөлтийн хүсэлт тавихын тулд <ph name="BEGIN_LINK1" />Хууль эрх зүйн тусламж<ph name="END_LINK1" /> руу очно уу.</translation> <translation id="773153675489693198">Мөчлөгийн тоо</translation> +<translation id="7746357909584236306">засах боломжтой</translation> <translation id="7747039790905080783">Урьдчилан хуваалцсан түлхүүр</translation> <translation id="7752963721013053477">Үүр цайхаас шөнө хүртэл - онцгой</translation> <translation id="7762130827864645708">Таны нууц үгийг амжилттай өөрчиллөө. Одооноос шинэ нууц үгийг ашиглана уу.</translation>
diff --git a/chromeos/strings/chromeos_strings_mr.xtb b/chromeos/strings/chromeos_strings_mr.xtb index 97176ca..d29de90 100644 --- a/chromeos/strings/chromeos_strings_mr.xtb +++ b/chromeos/strings/chromeos_strings_mr.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">इमेज लोड करता आल्या नाहीत. तुमचे नेटवर्क कनेक्शन तपासा किंवा इमेज पुन्हा लोड करून पहा.</translation> <translation id="1751249301761991853">वैयक्तिक</translation> <translation id="1753496554272155572">वॉलपेपर पूर्वावलोकनामधून बाहेर पडा</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> साठी संपादित करा बटण.</translation> <translation id="1755556344721611131">निदान करण्यासाठी अॅप</translation> <translation id="175763766237925754">चांगला (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android रन होत नाही</translation> <translation id="551689408806449779">डिव्हाइस डिस्कनेक्ट केले गेले आहे. चाचणीला पुन्हा कनेक्ट करण्याचा प्रयत्न करा</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">लॉक केले आहे</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">सूर्यास्ताच्या वेळी आपोआप गडद थीमवर स्विच करा</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">मध्यभागी</translation> <translation id="5703716265115423771">आवाज कमी करा</translation> <translation id="5707900041990977207"><ph name="TOTAL_PAGES" /> पैकी <ph name="CURRENT_PAGE" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> साठी संपादित करा बटण.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> अपडेट करा</translation> <translation id="574392208103952083">मध्यम</translation> <translation id="5757187557809630523">पुढील ट्रॅक</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">प्रतिबंधित</translation> <translation id="5916664084637901428">सुरू</translation> <translation id="5921506667911082617">{COUNT,plural, =1{तुमची फाइल यशस्वीरीत्या स्कॅन करण्यात आली आहे आणि <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> वर सेव्ह केली आहे.}other{तुमच्या फाइल यशस्वीरीत्या स्कॅन करण्यात आल्या आहेत आणि <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> वर सेव्ह केल्या आहेत.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> साठी हटवा बटण.</translation> <translation id="5931523347251946569">फाइल सापडली नाही</translation> <translation id="593880865674747800">या शैलीमध्ये आणखी तयार करा</translation> <translation id="5939518447894949180">रीसेट करा</translation> @@ -774,7 +778,7 @@ <translation id="6564646048574748301">अयशस्वी झाले - प्रिंटरशी कनेक्ट करता आले नाही</translation> <translation id="6566314079205407217">मल्टी-पेज स्कॅन</translation> <translation id="6574762126505704998">भरा</translation> -<translation id="6575134580692778371">कॉंफिगर केले नाही</translation> +<translation id="6575134580692778371">कॉन्फिगर केले नाही</translation> <translation id="6576005492601044801">डावीकडे</translation> <translation id="6579509898032828423">हा फोटो वापरा</translation> <translation id="6596816719288285829">IP पत्ता</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">अयशस्वी DNS रिझोल्युशन</translation> <translation id="6768237774506518020">उच्च DNS रिझोल्युशन अयशस्वी रेट</translation> <translation id="6791471867139427246">कीबोर्डच्या लाइटचा रंग</translation> +<translation id="6796229976413584781">शॉर्टकट हटवला आहे</translation> <translation id="6798678288485555829">मजकुरासंबंधी नेव्हिगेशन</translation> <translation id="680983167891198932">की</translation> <translation id="6816797338148849397">तुमच्या निवडीशी संबंधित माहिती उपलब्ध आहे. अॅक्सेस करण्यासाठी अप अॅरो की वापरा.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">नेटवर्क APN सेटिंग्ज व्यवस्थापित करा. APNs ही मोबाइल नेटवर्क आणि इंटरनेटदरम्यान कनेक्शन तयार करतात. <ph name="BEGIN_LINK_LEARN_MORE" />अधिक जाणून घ्या<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">बाह्य डिव्हाइससाठी फर्मवेअर अपडेट</translation> <translation id="7216409898977639127">सेल्युलर सेवा देणारा</translation> +<translation id="7233782086689993269">शॉर्टकट रिस्टोअर केला आहे</translation> <translation id="725133483556299729">ईमेल निवडा</translation> <translation id="7271040990581020067">स्कॅनर सध्या वापरात आहे. नंतर पुन्हा प्रयत्न करा.</translation> <translation id="7271932918253517778">वरील ओळीमधील की असलेल्या शॉर्टकटमध्ये <ph name="META_KEY" /> की समाविष्ट असणे आवश्यक आहे.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">उच्च HTTPS लेटन्सी</translation> <translation id="7656388927906093505">डिव्हाइस हे माउस आहे.</translation> <translation id="7658239707568436148">रद्द करा</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">अवतार बदला</translation> <translation id="7683228889864052081">कीबोर्ड रंग</translation> <translation id="7690294790491645610">नवीन पासवर्ड कन्फर्म करा</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">कीबोर्ड लाइट</translation> <translation id="7730077286107534951">काही खाते आणि सिस्टीम माहिती Google ला पाठवली जाऊ शकते. आम्ही आमचे <ph name="BEGIN_LINK2" />गोपनीयता धोरण<ph name="END_LINK2" /> आणि <ph name="BEGIN_LINK3" />सेवा अटी<ph name="END_LINK3" /> यांच्या अधीन राहून, ही माहिती तांत्रिक समस्या सोडवण्यात व आमच्या सेवा सुधारण्यात मदत करण्यासाठी वापरतो. आशय बदलांची विनंती करण्यासाठी, <ph name="BEGIN_LINK1" />कायदेशीर मदत<ph name="END_LINK1" /> वर जा.</translation> <translation id="773153675489693198">सायकलची संख्या</translation> +<translation id="7746357909584236306">संपादन करण्यायोग्य</translation> <translation id="7747039790905080783">आधीपासून शेअर केलेली की</translation> <translation id="7752963721013053477">डॉन टू डार्क - विशिष्ट</translation> <translation id="7762130827864645708">तुमचा पासवर्ड यशस्वीरीत्या बदलला होता. कृपया आतापासून नवीन पासवर्ड वापरा.</translation>
diff --git a/chromeos/strings/chromeos_strings_ne.xtb b/chromeos/strings/chromeos_strings_ne.xtb index 82e6f5c..6f71c08 100644 --- a/chromeos/strings/chromeos_strings_ne.xtb +++ b/chromeos/strings/chromeos_strings_ne.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">फोटोहरू लोड गर्न सकिएन। आफ्नो नेटवर्क कनेक्सन जाँच्नुहोस् वा ती फोटोहरू फेरि लोड गरी हेर्नुहोस्।</translation> <translation id="1751249301761991853">व्यक्तिगत</translation> <translation id="1753496554272155572">वालपेपरको प्रिभ्यूबाट बाहिरिनुहोस्</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> परिवर्तन गर्ने बटन।</translation> <translation id="1755556344721611131">डाइग्नोस्टिक्स एप</translation> <translation id="175763766237925754">राम्रो (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android चलिरहेको छैन</translation> <translation id="551689408806449779">डिभाइस डिस्कनेक्ट गरिएको छ। परीक्षण गर्न रिकनेक्ट गरी हेर्नुहोस्</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">लक गरिएको छ</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">सूर्यास्तपछि स्वतः अँध्यारो थिम लागू गरियोस्</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">केन्द्र</translation> <translation id="5703716265115423771">आवाज सानो</translation> <translation id="5707900041990977207"><ph name="TOTAL_PAGES" /> मध्ये <ph name="CURRENT_PAGE" /> पृष्ठ</translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> परिवर्तन गर्ने बटन।</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> अपडेट गर्नुहोस्</translation> <translation id="574392208103952083">मध्यम</translation> <translation id="5757187557809630523">"अर्को ट्र्याक" जनाउने आइकन</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">प्रतिबन्धित</translation> <translation id="5916664084637901428">अन</translation> <translation id="5921506667911082617">{COUNT,plural, =1{तपाईंको फाइल स्क्यान गर्ने काम पूरा भएको छ र उक्त फाइल <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> मा सुरक्षित गरिएको छ।}other{तपाईंका फाइलहरू स्क्यान गर्ने काम पूरा भएको छ र ती फाइलहरू <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> मा सुरक्षित गरिएका छन्।}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> मेटाउने बटन।</translation> <translation id="5931523347251946569">फाइल भेट्टिएन</translation> <translation id="593880865674747800">यो शैलीका थप वालपेपरहरू बनाउनुहोस्</translation> <translation id="5939518447894949180">रिसेट गर्नुहोस्</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS रिजोल्युसन पूरा हुन सकेनन्</translation> <translation id="6768237774506518020">DNS रिजोल्युसन पूरा हुन नसक्ने दर उच्च छ</translation> <translation id="6791471867139427246">किबोर्डको प्रकाशको रङ</translation> +<translation id="6796229976413584781">सर्टकट मेटाइयो</translation> <translation id="6798678288485555829">टेक्स्ट नेभिगेसन</translation> <translation id="680983167891198932">की</translation> <translation id="6816797338148849397">तपाईंले चयन गर्नुभएको पाठसँग सम्बन्धित जानकारी उपलब्ध छ। उक्त जानकारी प्राप्त गर्न अप एरो की प्रयोग गर्नुहोस्।</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">नेटवर्क APN सम्बन्धी सेटिङ मिलाउनुहोस्। APN ले मोबाइल नेटवर्क र इन्टरनेटबिचको कनेक्सन बनाउँछ। <ph name="BEGIN_LINK_LEARN_MORE" />थप जान्नुहोस्<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">बाह्य डिभाइसहरूका लागि फर्मवेयरसम्बन्धी अपडेटहरू</translation> <translation id="7216409898977639127">सेलुलर प्रदायक</translation> +<translation id="7233782086689993269">सर्टकट रिस्टोर गरियो</translation> <translation id="725133483556299729">इमेल चयन गर्नुहोस्</translation> <translation id="7271040990581020067">स्क्यानर हाल प्रयोग भइरहेको छ। पछि फेरि प्रयास गर्नुहोस्।</translation> <translation id="7271932918253517778">सिरानमा भएको रोका कीहरू भएको सर्टकटमा <ph name="META_KEY" /> की समावेश हुनु पर्छ।</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPS को विलम्बता धेरै छ</translation> <translation id="7656388927906093505">यो डिभाइस माउस हो।</translation> <translation id="7658239707568436148">रद्द गर्नुहोस्</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />।</translation> <translation id="7665800271478495366">अवतार बदल्नुहोस्</translation> <translation id="7683228889864052081">किबोर्डको ब्याकलाइटको रङ</translation> <translation id="7690294790491645610">नयाँ पासवर्ड पुष्टि गर्नुहोस्</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">किबोर्डको ब्याकलाइटको प्रकाश</translation> <translation id="7730077286107534951">खाता तथा सिस्टमसम्बन्धी केही जानकारी Google मा पठाइन सक्छ। हामी यो जानकारी प्राविधिक समस्याहरू समाधान गर्ने र हाम्रा सेवाहरूको गुणस्तर सुधार गर्ने प्रयोजनका लागि हाम्रो <ph name="BEGIN_LINK2" />गोपनीयता नीति<ph name="END_LINK2" /> तथा <ph name="BEGIN_LINK3" />सेवाका सर्तहरू<ph name="END_LINK3" />बमोजिम प्रयोग गर्छौँ। सामग्री परिवर्तन गरिदिन अनुरोध गर्न "<ph name="BEGIN_LINK1" />कानुनी सहायता<ph name="END_LINK1" />" मा जानुहोस्।</translation> <translation id="773153675489693198">साइकल काउन्ट</translation> +<translation id="7746357909584236306">सम्पादन गर्न मिल्छ</translation> <translation id="7747039790905080783">अग्रिम रूपमा सेयर गरिएको की</translation> <translation id="7752963721013053477">डन टु डार्क - विशेष</translation> <translation id="7762130827864645708">तपाईंको पासवर्ड परिवर्तन गरिएको छ। कृपया अबदेखि नयाँ पासवर्ड प्रयोग गर्नुहोस्।</translation>
diff --git a/chromeos/strings/chromeos_strings_nl.xtb b/chromeos/strings/chromeos_strings_nl.xtb index 6d432f2c..11dbdaa 100644 --- a/chromeos/strings/chromeos_strings_nl.xtb +++ b/chromeos/strings/chromeos_strings_nl.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Kan afbeeldingen niet laden. Check de netwerkverbinding of probeer de afbeeldingen opnieuw te laden.</translation> <translation id="1751249301761991853">Persoonlijk</translation> <translation id="1753496554272155572">Achtergrondvoorbeeld sluiten</translation> +<translation id="1754578112426924640">Knop Bewerken voor <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">App Diagnostische gegevens</translation> <translation id="175763766237925754">Goed (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android wordt niet uitgevoerd</translation> <translation id="551689408806449779">De verbinding met het apparaat is verbroken. Maak opnieuw verbinding om te testen.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">vergrendeld</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Automatisch overschakelen naar donker thema bij zonsondergang</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centreren</translation> <translation id="5703716265115423771">volume omlaag</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> van <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Knop Bewerken voor <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> updaten</translation> <translation id="574392208103952083">Gemiddeld</translation> <translation id="5757187557809630523">volgend nummer</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Verboden</translation> <translation id="5916664084637901428">Aan</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Je bestand is gescand en opgeslagen in <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Je bestanden zijn gescand en opgeslagen in <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Knop Verwijderen voor <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Bestand niet gevonden</translation> <translation id="593880865674747800">Meer maken in deze stijl</translation> <translation id="5939518447894949180">Resetten</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Mislukte DNS-omzettingen</translation> <translation id="6768237774506518020">Hoog percentage mislukte DNS-omzettingen</translation> <translation id="6791471867139427246">kleur van toetsenbordverlichting</translation> +<translation id="6796229976413584781">Sneltoets verwijderd</translation> <translation id="6798678288485555829">Tekstnavigatie</translation> <translation id="680983167891198932">Sleutel</translation> <translation id="6816797338148849397">Er is informatie met betrekking tot je selectie beschikbaar. Gebruik de pijl-omhoog om deze te openen.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Beheer de APN-instellingen voor het netwerk. APN's maken verbinding tussen een mobiel netwerk en internet. <ph name="BEGIN_LINK_LEARN_MORE" />Meer informatie<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Firmware-updates voor externe apparaten</translation> <translation id="7216409898977639127">Mobiele provider</translation> +<translation id="7233782086689993269">Sneltoets hersteld</translation> <translation id="725133483556299729">E-mailadres selecteren</translation> <translation id="7271040990581020067">De scanner wordt momenteel gebruikt. Probeer het later opnieuw.</translation> <translation id="7271932918253517778">Sneltoets met toetsen op de bovenste rij moet de <ph name="META_KEY" />-toets bevatten.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Lage HTTPS-latentie</translation> <translation id="7656388927906093505">Apparaat is een muis.</translation> <translation id="7658239707568436148">Annuleren</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Avatar wijzigen</translation> <translation id="7683228889864052081">tint toetsenbord</translation> <translation id="7690294790491645610">Nieuw wachtwoord bevestigen</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">toetsenbordlampje</translation> <translation id="7730077286107534951">Bepaalde account- en systeemgegevens worden misschien naar Google gestuurd. We gebruiken deze informatie om technische problemen op te lossen en onze services te verbeteren, in overeenstemming met ons <ph name="BEGIN_LINK2" />Privacybeleid<ph name="END_LINK2" /> en onze <ph name="BEGIN_LINK3" />Servicevoorwaarden<ph name="END_LINK3" />. Als je contentwijzigingen wilt aanvragen, ga je naar de <ph name="BEGIN_LINK1" />juridische Help-pagina<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Aantal oplaadbeurten</translation> +<translation id="7746357909584236306">bewerkbaar</translation> <translation id="7747039790905080783">Eerder gedeelde sleutel</translation> <translation id="7752963721013053477">Dageraad tot donker - exclusief</translation> <translation id="7762130827864645708">Je wachtwoord is gewijzigd. Gebruik vanaf nu je nieuwe wachtwoord.</translation>
diff --git a/chromeos/strings/chromeos_strings_no.xtb b/chromeos/strings/chromeos_strings_no.xtb index 35b7ee8..6f9292b 100644 --- a/chromeos/strings/chromeos_strings_no.xtb +++ b/chromeos/strings/chromeos_strings_no.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Kunne ikke laste inn bilder. Kontroller nettverkstilkoblingen din, eller prøv å laste inn bildene på nytt.</translation> <translation id="1751249301761991853">Personlig</translation> <translation id="1753496554272155572">Avslutt forhåndsvisning av bakgrunn</translation> +<translation id="1754578112426924640">Endreknapp for <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Diagnostikk-appen</translation> <translation id="175763766237925754">God (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android kjører ikke</translation> <translation id="551689408806449779">Enheten er koblet fra. Prøv å koble til på nytt for å teste</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">låst</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Bytt automatisk til mørkt tema ved solnedgang</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Midtstill</translation> <translation id="5703716265115423771">volum ned</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> av <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Endreknapp for <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Oppdater <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Medium</translation> <translation id="5757187557809630523">neste spor</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Forbudt</translation> <translation id="5916664084637901428">På</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Filen er skannet og lagret i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Filene er skannet og lagret i <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Sletteknapp for <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Fant ikke filen</translation> <translation id="593880865674747800">Lag flere med denne stilen</translation> <translation id="5939518447894949180">Tilbakestill</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Mislykkede DNS-oppslag</translation> <translation id="6768237774506518020">Høy feilfrekvens for DNS-oppslag</translation> <translation id="6791471867139427246">farge på tastaturlys</translation> +<translation id="6796229976413584781">Hurtigtasten er slettet</translation> <translation id="6798678288485555829">Tekstnavigasjon</translation> <translation id="680983167891198932">Nøkkel</translation> <translation id="6816797338148849397">Informasjon om det du har markert, er tilgjengelig. Bruk oppoverpilen for å se informasjonen.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Administrer APN-innstillingene for nettverket. APN oppretter en tilkobling mellom et mobilnettverk og internett. <ph name="BEGIN_LINK_LEARN_MORE" />Finn ut mer<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Fastvareoppdateringer for eksterne enheter</translation> <translation id="7216409898977639127">Mobiloperatør</translation> +<translation id="7233782086689993269">Hurtigtasten er gjenopprettet</translation> <translation id="725133483556299729">Velg en e-postadresse</translation> <translation id="7271040990581020067">Skanneren er i bruk for øyeblikket. Prøv på nytt senere.</translation> <translation id="7271932918253517778">En hurtigtast som bruker taster på øverste rad, må inneholde <ph name="META_KEY" />-tasten.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Høy HTTPS-tidsforsinkelse</translation> <translation id="7656388927906093505">Enheten er en mus.</translation> <translation id="7658239707568436148">Avbryt</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Bytt brukerbilde</translation> <translation id="7683228889864052081">tastaturfargetone</translation> <translation id="7690294790491645610">Bekreft det nye passordet</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">tastaturlys</translation> <translation id="7730077286107534951">Noe konto- og systeminformasjon kan bli sendt til Google. Vi bruker denne informasjonen til å løse tekniske problemer og forbedre tjenestene våre i henhold til <ph name="BEGIN_LINK2" />personvernreglene<ph name="END_LINK2" /> og <ph name="BEGIN_LINK3" />vilkårene for bruk<ph name="END_LINK3" />. For å be om innholdsendringer, gå til <ph name="BEGIN_LINK1" />Juridisk hjelp<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Syklusantall</translation> +<translation id="7746357909584236306">kan endres</translation> <translation id="7747039790905080783">Forhåndsdelt nøkkel</translation> <translation id="7752963721013053477">Fra morgen til kveld – eksklusiv</translation> <translation id="7762130827864645708">Passordendringen var vellykket. Bruk det nye passordet fra nå av.</translation>
diff --git a/chromeos/strings/chromeos_strings_pa.xtb b/chromeos/strings/chromeos_strings_pa.xtb index 9e0783b..256e970 100644 --- a/chromeos/strings/chromeos_strings_pa.xtb +++ b/chromeos/strings/chromeos_strings_pa.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">ਚਿੱਤਰ ਲੋਡ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕੇ। ਆਪਣੇ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੀ ਜਾਂਚ ਕਰੋ ਜਾਂ ਚਿੱਤਰਾਂ ਨੂੰ ਦੁਬਾਰਾ ਲੋਡ ਕਰ ਕੇ ਦੇਖੋ।</translation> <translation id="1751249301761991853">ਨਿੱਜੀ</translation> <translation id="1753496554272155572">ਵਾਲਪੇਪਰ ਦੀ ਪੂਰਵ-ਝਲਕ ਤੋਂ ਬਾਹਰ ਜਾਓ</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> ਲਈ 'ਸੰਪਾਦਨ ਕਰੋ' ਬਟਨ।</translation> <translation id="1755556344721611131">ਤਸ਼ਖੀਸੀ ਐਪ</translation> <translation id="175763766237925754">ਵਧੀਆ (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android ਨਹੀਂ ਚੱਲ ਰਿਹਾ ਹੈ</translation> <translation id="551689408806449779">ਡੀਵਾਈਸ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਜਾਂਚ ਕਰਨ ਲਈ ਮੁੜ-ਕਨੈਕਟ ਕਰ ਕੇ ਦੇਖੋ</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">ਲਾਕ ਹੈ</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">ਸੂਰਜ ਡੁੱਬਣ ਵੇਲੇ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਗੂੜ੍ਹੇ ਥੀਮ 'ਤੇ ਸਵਿੱਚ ਕਰੋ</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">ਕੇਂਦਰ</translation> <translation id="5703716265115423771">ਵੌਲਿਊਮ ਘਟਾਓ</translation> <translation id="5707900041990977207"><ph name="TOTAL_PAGES" /> ਵਿੱਚੋਂ <ph name="CURRENT_PAGE" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> ਲਈ 'ਸੰਪਾਦਨ ਕਰੋ' ਬਟਨ।</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> ਨੂੰ ਅੱਪਡੇਟ ਕਰੋ</translation> <translation id="574392208103952083">ਦਰਮਿਆਨਾ</translation> <translation id="5757187557809630523">ਅਗਲਾ ਟਰੈਕ</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">ਪਾਬੰਦੀ ਲਗਾਈ ਗਈ</translation> <translation id="5916664084637901428">ਚਾਲੂ</translation> <translation id="5921506667911082617">{COUNT,plural, =1{ਤੁਹਾਡੀ ਫ਼ਾਈਲ ਸਫਲਤਾਪੂਰਕ ਸਕੈਨ ਕੀਤੀ ਗਈ ਅਤੇ <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤੀ ਗਈ।}one{ਤੁਹਾਡੀ ਫ਼ਾਈਲ ਸਫਲਤਾਪੂਰਕ ਸਕੈਨ ਕੀਤੀ ਗਈ ਅਤੇ <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤੀ ਗਈ।}other{ਤੁਹਾਡੀਆਂ ਫ਼ਾਈਲਾਂ ਸਫਲਤਾਪੂਰਕ ਸਕੈਨ ਕੀਤੀਆਂ ਗਈਆਂ ਅਤੇ <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤੀਆਂ ਗਈਆਂ।}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> ਲਈ 'ਮਿਟਾਓ' ਬਟਨ।</translation> <translation id="5931523347251946569">ਫ਼ਾਈਲ ਨਹੀਂ ਮਿਲੀ</translation> <translation id="593880865674747800">ਇਸ ਸਟਾਈਲ ਵਿੱਚ ਹੋਰ ਬਣਾਓ</translation> <translation id="5939518447894949180">ਰੀਸੈਟ ਕਰੋ</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">ਅਸਫਲ DNS ਰੈਜ਼ੋਲਿਊਸ਼ਨ</translation> <translation id="6768237774506518020">DNS ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਦੀ ਉੱਚ ਅਸਫਲ ਦਰ</translation> <translation id="6791471867139427246">ਕੀ-ਬੋਰਡ ਦੀ ਰੌਸ਼ਨੀ ਦਾ ਰੰਗ</translation> +<translation id="6796229976413584781">ਸ਼ਾਰਟਕੱਟ ਮਿਟਾਇਆ ਗਿਆ</translation> <translation id="6798678288485555829">ਲਿਖਤ ਨੈਵੀਗੇਸ਼ਨ</translation> <translation id="680983167891198932">ਕੁੰਜੀ</translation> <translation id="6816797338148849397">ਤੁਹਾਡੀ ਚੋਣ ਨਾਲ ਸੰਬੰਧਿਤ ਜਾਣਕਾਰੀ ਉਪਲਬਧ ਹੈ। ਪਹੁੰਚ ਕਰਨ ਲਈ 'ਉੱਪਰ ਤੀਰ' ਕੁੰਜੀ ਵਰਤੋ।</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">ਨੈੱਟਵਰਕ APN ਸੈਟਿੰਗਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ। APN ਸੈਲਿਊਲਰ ਨੈੱਟਵਰਕ ਅਤੇ ਇੰਟਰਨੈੱਟ ਵਿਚਕਾਰ ਕਨੈਕਸ਼ਨ ਸਥਾਪਤ ਕਰਦੇ ਹਨ। <ph name="BEGIN_LINK_LEARN_MORE" />ਹੋਰ ਜਾਣੋ<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">ਬਾਹਰੀ ਡੀਵਾਈਸਾਂ ਲਈ ਫ਼ਰਮਵੇਅਰ ਅੱਪਡੇਟ</translation> <translation id="7216409898977639127">ਸੈਲਿਊਲਰ ਪ੍ਰਦਾਨਕ</translation> +<translation id="7233782086689993269">ਸ਼ਾਰਟਕੱਟ ਮੁੜ-ਬਹਾਲ ਕੀਤਾ ਗਿਆ</translation> <translation id="725133483556299729">ਈਮੇਲ ਚੁਣੋ</translation> <translation id="7271040990581020067">ਫ਼ਿਲਹਾਲ ਸਕੈਨਰ ਵਰਤੋਂ ਵਿੱਚ ਹੈ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation> <translation id="7271932918253517778">ਸਿਖਰਲੀ ਕਤਾਰ ਨਾਲ ਕੁੰਜੀਆਂ ਵਾਲੇ ਸ਼ਾਰਟਕੱਟ ਵਿੱਚ <ph name="META_KEY" /> ਕੁੰਜੀ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">ਜ਼ਿਆਦਾ HTTPS ਵਿਲੰਬਤਾ</translation> <translation id="7656388927906093505">ਡੀਵਾਈਸ ਇੱਕ ਮਾਊਸ ਹੈ।</translation> <translation id="7658239707568436148">ਰੱਦ ਕਰੋ</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />।</translation> <translation id="7665800271478495366">ਅਵਤਾਰ ਬਦਲੋ</translation> <translation id="7683228889864052081">ਕੀ-ਬੋਰਡ ਦੇ ਰੰਗ ਦੇ ਭਾਹ</translation> <translation id="7690294790491645610">ਨਵੇਂ ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">ਕੀ-ਬੋਰਡ ਲਾਈਟ</translation> <translation id="7730077286107534951">ਖਾਤੇ ਅਤੇ ਸਿਸਟਮ ਦੀ ਕੁਝ ਜਾਣਕਾਰੀ Google ਨੂੰ ਭੇਜੀ ਜਾ ਸਕਦੀ ਹੈ। ਅਸੀਂ ਇਸ ਜਾਣਕਾਰੀ ਦੀ ਵਰਤੋਂ ਸਾਡੀ <ph name="BEGIN_LINK3" />ਪਰਦੇਦਾਰੀ ਨੀਤੀ<ph name="END_LINK3" /> ਅਤੇ <ph name="BEGIN_LINK2" />ਸੇਵਾ ਦੇ ਨਿਯਮਾਂ<ph name="END_LINK2" /> ਦੇ ਅਧੀਨ, ਤਕਨੀਕੀ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਹੱਲ ਕਰਨ ਅਤੇ ਸਾਡੀਆਂ ਸੇਵਾਵਾਂ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ ਕਰਦੇ ਹਾਂ। ਸਮੱਗਰੀ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਦੀ ਬੇਨਤੀ ਕਰਨ ਲਈ, <ph name="BEGIN_LINK1" />ਕਨੂੰਨੀ ਮਦਦ<ph name="END_LINK1" /> 'ਤੇ ਜਾਓ।</translation> <translation id="773153675489693198">ਸਾਈਕਲ ਗਿਣਤੀ</translation> +<translation id="7746357909584236306">ਸੰਪਾਦਨਯੋਗ ਹੈ</translation> <translation id="7747039790905080783">ਪਹਿਲਾਂ ਤੋਂ ਸਾਂਝੀ ਕੀਤੀ ਗਈ ਕੁੰਜੀ</translation> <translation id="7752963721013053477">ਸਵੇਰ ਤੋਂ ਰਾਤ ਤੱਕ - ਵਿਸ਼ੇਸ਼</translation> <translation id="7762130827864645708">ਤੁਹਾਡੇ ਵੱਲੋਂ ਪਾਸਵਰਡ ਨੂੰ ਬਦਲਣਾ ਸਫਲ ਰਿਹਾ। ਕਿਰਪਾ ਕਰਕੇ ਹੁਣ ਤੋਂ ਨਵੇਂ ਪਾਸਵਰਡ ਦੀ ਵਰਤੋਂ ਕਰੋ।</translation>
diff --git a/chromeos/strings/chromeos_strings_pt-BR.xtb b/chromeos/strings/chromeos_strings_pt-BR.xtb index 13a1a6e5..1fd7048a 100644 --- a/chromeos/strings/chromeos_strings_pt-BR.xtb +++ b/chromeos/strings/chromeos_strings_pt-BR.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Não foi possível carregar as imagens. Verifique sua conexão de rede ou tente carregar novamente.</translation> <translation id="1751249301761991853">Pessoal</translation> <translation id="1753496554272155572">Sair da visualização do plano de fundo</translation> +<translation id="1754578112426924640">Botão "Editar" para o atalho <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">App Diagnóstico</translation> <translation id="175763766237925754">Bom (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">O Android não está funcionando</translation> <translation id="551689408806449779">O dispositivo foi desconectado. Reconecte-se para testar</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">bloqueada</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Mudar automaticamente para o tema escuro ao anoitecer</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centralizar</translation> <translation id="5703716265115423771">diminuir o volume</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> de <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Botão "Editar" para o atalho <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Atualizar o <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Médio</translation> <translation id="5757187557809630523">próxima faixa</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Proibido</translation> <translation id="5916664084637901428">Ativada</translation> <translation id="5921506667911082617">{COUNT,plural, =1{O arquivo foi digitalizado e salvo em <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{O arquivo foi digitalizado e salvo em <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Os arquivos foram digitalizados e salvos em <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Botão "Excluir" para o atalho <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Arquivo não encontrado</translation> <translation id="593880865674747800">Criar mais conteúdo nesse estilo</translation> <translation id="5939518447894949180">Redefinir</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Falha em resoluções de DNS</translation> <translation id="6768237774506518020">Taxa elevada de erro de resolução de DNS</translation> <translation id="6791471867139427246">cor da luz do teclado</translation> +<translation id="6796229976413584781">Atalho excluído</translation> <translation id="6798678288485555829">Navegação de texto</translation> <translation id="680983167891198932">Chave</translation> <translation id="6816797338148849397">Informações relacionadas à sua seleção disponíveis. Use a tecla de seta para cima para acessar.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Gerenciar configurações do APN de rede. Os APNs estabelecem uma conexão entre a rede celular e a Internet. <ph name="BEGIN_LINK_LEARN_MORE" />Saiba mais<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Atualizações de firmware para dispositivos externos</translation> <translation id="7216409898977639127">Operadora de celular</translation> +<translation id="7233782086689993269">Atalho restaurado</translation> <translation id="725133483556299729">Selecione um e-mail</translation> <translation id="7271040990581020067">O scanner está em uso. Tente novamente mais tarde.</translation> <translation id="7271932918253517778">O atalho com as teclas da primeira fileira precisa incluir a tecla <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Latência de HTTPS alta</translation> <translation id="7656388927906093505">Este dispositivo é um mouse.</translation> <translation id="7658239707568436148">Cancelar</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Mudar o avatar</translation> <translation id="7683228889864052081">matiz do teclado</translation> <translation id="7690294790491645610">Confirmar nova senha</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">luz do teclado</translation> <translation id="7730077286107534951">Talvez alguns dados sobre a conta e o sistema sejam enviados ao Google. Usamos essas informações para ajudar a solucionar problemas técnicos e aprimorar nossos serviços, conforme nossa <ph name="BEGIN_LINK2" />Política de Privacidade<ph name="END_LINK2" /> e nossos <ph name="BEGIN_LINK3" />Termos de Serviço<ph name="END_LINK3" />. Para pedir mudanças no conteúdo, acesse a página de <ph name="BEGIN_LINK1" />Ajuda jurídica<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Contagem de ciclos</translation> +<translation id="7746357909584236306">editável</translation> <translation id="7747039790905080783">Chave pré-compartilhada</translation> <translation id="7752963721013053477">Do amanhecer à escuridão (exclusivo)</translation> <translation id="7762130827864645708">Senha modificada. De agora em diante, use a nova senha.</translation>
diff --git a/chromeos/strings/chromeos_strings_ro.xtb b/chromeos/strings/chromeos_strings_ro.xtb index ddca1e2..377c445 100644 --- a/chromeos/strings/chromeos_strings_ro.xtb +++ b/chromeos/strings/chromeos_strings_ro.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Nu s-au putut încărca imagini. Verifică-ți conexiunea la rețea sau încearcă să încarci din nou imaginile.</translation> <translation id="1751249301761991853">Personal</translation> <translation id="1753496554272155572">Ieși din previzualizarea imaginii de fundal</translation> +<translation id="1754578112426924640">Buton de editare pentru <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplicația Diagnosticare</translation> <translation id="175763766237925754">Bună (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android nu rulează</translation> <translation id="551689408806449779">Dispozitivul a fost deconectat. Încearcă să-l reconectezi pentru a-l testa</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">blocat</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Comută automat la tema întunecată la apus</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Pe centru</translation> <translation id="5703716265115423771">reduce volumul</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> din <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Buton de editare pentru <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Actualizează <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Mediu</translation> <translation id="5757187557809630523">melodia următoare</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Interzis</translation> <translation id="5916664084637901428">Activat</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Fișierul a fost scanat și salvat în <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Fișierele au fost scanate și salvate în <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Fișierele au fost scanate și salvate în <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Buton de ștergere pentru <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Fișierul nu a fost găsit</translation> <translation id="593880865674747800">Creează mai multe în acest stil</translation> <translation id="5939518447894949180">Resetează</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Rezolvări DNS nereușite</translation> <translation id="6768237774506518020">Rată de eroare ridicată a rezolvărilor DNS</translation> <translation id="6791471867139427246">culoarea iluminării tastaturii</translation> +<translation id="6796229976413584781">Comanda rapidă a fost ștearsă</translation> <translation id="6798678288485555829">Navigare în text</translation> <translation id="680983167891198932">Cheie</translation> <translation id="6816797338148849397">Sunt disponibile informații despre selecția ta. Folosește tasta săgeată în sus pentru a le accesa.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Gestionează setările APN ale rețelei. APN-urile stabilesc o conexiune între o rețea de date mobile și internet. <ph name="BEGIN_LINK_LEARN_MORE" />Află mai multe<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Actualizări de firmware pentru dispozitive externe</translation> <translation id="7216409898977639127">Furnizor de date mobile</translation> +<translation id="7233782086689993269">Comanda rapidă a fost restabilită</translation> <translation id="725133483556299729">Selectează adresa de e-mail</translation> <translation id="7271040990581020067">Scanerul este în uz. Încearcă din nou mai târziu.</translation> <translation id="7271932918253517778">Comenzile rapide cu taste de pe rândul de sus trebuie să includă tasta <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Latență mare a solicitărilor HTTPS</translation> <translation id="7656388927906093505">Dispozitivul este un mouse.</translation> <translation id="7658239707568436148">Anulează</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Schimbă avatarul</translation> <translation id="7683228889864052081">nuanța tastaturii</translation> <translation id="7690294790491645610">Confirmă noua parolă</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">iluminarea tastaturii</translation> <translation id="7730077286107534951">Unele informații despre cont și sistem pot fi trimise la Google. Le folosim pentru a rezolva problemele tehnice și pentru a îmbunătăți serviciile, în conformitate cu <ph name="BEGIN_LINK2" />Politica de confidențialitate<ph name="END_LINK2" /> și cu <ph name="BEGIN_LINK3" />Termenii și condițiile<ph name="END_LINK3" />. Pentru a solicita modificări ale conținutului, accesează <ph name="BEGIN_LINK1" />Ajutor pentru probleme juridice<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Numărul de cicluri</translation> +<translation id="7746357909584236306">editabil</translation> <translation id="7747039790905080783">Cheie predistribuită</translation> <translation id="7752963721013053477">Din zori până seara – Exclusive</translation> <translation id="7762130827864645708">Parola a fost schimbată. Folosește noua parolă de acum înainte.</translation>
diff --git a/chromeos/strings/chromeos_strings_si.xtb b/chromeos/strings/chromeos_strings_si.xtb index 60c502c..51b65b0 100644 --- a/chromeos/strings/chromeos_strings_si.xtb +++ b/chromeos/strings/chromeos_strings_si.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">රූප පූරණය කළ නොහැකි විය. ඔබගේ ජාල සබැඳුම පරීක්ෂා කරන්න හෝ රූප නැවත පූරණය කිරීම උත්සාහ කරන්න.</translation> <translation id="1751249301761991853">පුද්ගලික</translation> <translation id="1753496554272155572">වෝල්පේපර පෙරදසුනෙන් පිටවන්න</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> සඳහා බොත්තම සංස්කරණය කරන්න.</translation> <translation id="1755556344721611131">Diagnostics යෙදුම</translation> <translation id="175763766237925754">හොඳයි (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android ධාවනය නොවේ</translation> <translation id="551689408806449779">උපාංගය විසන්ධි කර ඇත. පරීක්ෂා කිරීමට නැවත සම්බන්ධ වීමට උත්සාහ කරන්න</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">අඟුළුලන ලදී</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">ඉර බැස යන විට ස්වයංක්රීයව අඳුරු තේමාව වෙත මාරු වන්න</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">මධ්ය</translation> <translation id="5703716265115423771">හඩ පරිමාව අඩු කිරීම</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />න් <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> සඳහා බොත්තම සංස්කරණය කරන්න.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> යාවත්කාලීන කරන්න</translation> <translation id="574392208103952083">මධ්යම</translation> <translation id="5757187557809630523">මීළඟ ඛණ්ඩය</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">තහනම්</translation> <translation id="5916664084637901428">ක්රියාත්මකයි</translation> <translation id="5921506667911082617">{COUNT,plural, =1{ඔබගේ ගොනුව සාර්ථකව ස්කෑන් කර <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> වෙත සුරැක ඇත.}one{ඔබගේ ගොනු සාර්ථකව ස්කෑන් කර <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> වෙත සුරැක ඇත.}other{ඔබගේ ගොනු සාර්ථකව ස්කෑන් කර <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> වෙත සුරැක ඇත.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> සඳහා බොත්තම මකන්න.</translation> <translation id="5931523347251946569">ගොනුව හමු නොවිණි</translation> <translation id="593880865674747800">මෙම විලාසය තුළ තවත් තනන්න</translation> <translation id="5939518447894949180">නැවත සකසන්න</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">අසාර්ථක වූ DNS විභේදන</translation> <translation id="6768237774506518020">ඉහළ DNS විභේදන අසාර්ථක වීම් අනුපාතය</translation> <translation id="6791471867139427246">යතුරුපුවරුවේ ආලෝක වර්ණය</translation> +<translation id="6796229976413584781">කෙටිමඟ මැකුවා</translation> <translation id="6798678288485555829">පෙළ සංචාලනය</translation> <translation id="680983167891198932">යතුර</translation> <translation id="6816797338148849397">ඔබේ තේරීමට අදාළ තොරතුරු ලබා ගත නොහැකිය. ප්රවේශ වීමට ඉහළට ඊතල යතුර භාවිත කරන්න.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">ජාල APN සැකසීම් කළමනා කරන්න. APN සෙලියුලර් ජාලයක් සහ අන්තර්ජාලය අතර සම්බන්ධතාවක් ඇති කරයි. <ph name="BEGIN_LINK_LEARN_MORE" />තව දැන ගන්න<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">බාහිර උපාංග සඳහා නිත්ය මෘදුකාංග යාවත්කාලීන</translation> <translation id="7216409898977639127">සෙලියුලර් සපයන්නා</translation> +<translation id="7233782086689993269">කෙටිමඟ ප්රතිසාධන කළා</translation> <translation id="725133483556299729">ඉ-තැපෑල තෝරන්න</translation> <translation id="7271040990581020067">ස්කෑනරය දැනට භාවිතයේ ඇත. පසුව නැවත උත්සාහ කරන්න.</translation> <translation id="7271932918253517778"><ph name="META_KEY" /> යතුරට ඉහළ පේළියේ යතුරු සහිත කෙටිමඟ ඇතුළත් කිරීම අවශ්යයි.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">ඉහළ HTTPS පමාව</translation> <translation id="7656388927906093505">උපාංගය මූසිකයකි.</translation> <translation id="7658239707568436148">අවලංගු කරන්න</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">නියුරුව වෙනස් කරන්න</translation> <translation id="7683228889864052081">යතුරු පුවරුවේ පැහැය</translation> <translation id="7690294790491645610">නව මුරපදය තහවුරු කරන්න</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">යතුරු පුවරු ආලෝකය</translation> <translation id="7730077286107534951">සමහර ගිණුම් සහ පද්ධති තොරතුරු Google වෙත යැවිය හැක. අපගේ <ph name="BEGIN_LINK2" />පෞද්ගලිකත්ව ප්රතිපත්තියට<ph name="END_LINK2" /> සහ <ph name="BEGIN_LINK3" />සේවා නියමවලට<ph name="END_LINK3" /> යටත්ව, තාක්ෂණික ගැටලු විසඳීමට සහ අපගේ සේවා වැඩි දියුණු කිරීමට උදවු කිරීමට අපි මෙම තොරතුරු භාවිත කරමු. අන්තර්ගත වෙනස්කම් ඉල්ලා සිටීම සඳහා, <ph name="BEGIN_LINK1" />නීතිමය උදවු<ph name="END_LINK1" /> වෙත යන්න.</translation> <translation id="773153675489693198">චක්ර ගණන</translation> +<translation id="7746357909584236306">සංස්කරණය කළ හැකි</translation> <translation id="7747039790905080783">පූර්ව බෙදා ගත් යතුර</translation> <translation id="7752963721013053477">අලුයම සිට අඳුර දක්වා - සුවිශේෂී</translation> <translation id="7762130827864645708">ඔබගේ මුරපදය වෙනස් කිරීම සාර්ථක විය. කරුණාකර මෙතැන් සිට නව මුරපදය භාවිත කරන්න.</translation>
diff --git a/chromeos/strings/chromeos_strings_sl.xtb b/chromeos/strings/chromeos_strings_sl.xtb index cd4ae48..002553e2 100644 --- a/chromeos/strings/chromeos_strings_sl.xtb +++ b/chromeos/strings/chromeos_strings_sl.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Slik ni bilo mogoče naložiti. Preverite omrežno povezavo ali znova poskusite naložiti slike.</translation> <translation id="1751249301761991853">Osebno</translation> <translation id="1753496554272155572">Zapiranje predogleda zaslonskega ozadja</translation> +<translation id="1754578112426924640">Gumb za urejanje za <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplikacija za diagnostiko</translation> <translation id="175763766237925754">Dobra (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android se ne izvaja</translation> <translation id="551689408806449779">Povezava z napravo je prekinjena. Če želite preskusiti, poskusite znova vzpostaviti povezavo.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">zaklenjeno</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Samodejni preklop na temno temo ob sončnem zahodu</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Na sredino</translation> <translation id="5703716265115423771">zmanjšanje glasnosti</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> od <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Gumb za urejanje za <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Posodobi napravo <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Srednji</translation> <translation id="5757187557809630523">naslednja skladba</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Onemogočeno</translation> <translation id="5916664084637901428">Vklopljeno</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Vaša datoteka je bila uspešno pregledana in je shranjena v mapo <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Vaše datoteke so bile uspešno pregledane in so shranjene v mapo <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}two{Vaše datoteke so bile uspešno pregledane in so shranjene v mapo <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Vaše datoteke so bile uspešno pregledane in so shranjene v mapo <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Vaše datoteke so bile uspešno pregledane in so shranjene v mapo <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Gumb za izbris za <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Datoteke ni bilo mogoče najti</translation> <translation id="593880865674747800">Ustvari več v tem slogu</translation> <translation id="5939518447894949180">Ponastavi</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Neuspele razrešitve DNS</translation> <translation id="6768237774506518020">Visoko število napak pri razreševanju DNS</translation> <translation id="6791471867139427246">barva svetlobe tipkovnice</translation> +<translation id="6796229976413584781">Bližnjica je izbrisana</translation> <translation id="6798678288485555829">Premikanje po besedilu</translation> <translation id="680983167891198932">Ključ</translation> <translation id="6816797338148849397">Podatki, ki so na voljo v zvezi z vašim izborom. Za dostop uporabite tipko s puščico gor.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Upravljanje nastavitev APN-ja. APN-ji vzpostavijo povezavo med mobilnim omrežjem in internetom. <ph name="BEGIN_LINK_LEARN_MORE" />Več o tem<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Posodobitve vdelane programske opreme za zunanje naprave</translation> <translation id="7216409898977639127">Ponudnik mobilnih storitev</translation> +<translation id="7233782086689993269">Bližnjica je obnovljena</translation> <translation id="725133483556299729">Izberite e-poštni naslov</translation> <translation id="7271040990581020067">Optični bralnik je trenutno v uporabi. Poskusite pozneje.</translation> <translation id="7271932918253517778">Bližnjica s tipkami zgornje vrstice mora vključevati tipko <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Velika zakasnitev HTTPS</translation> <translation id="7656388927906093505">Naprava je miška.</translation> <translation id="7658239707568436148">Prekliči</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Spremeni avatar</translation> <translation id="7683228889864052081">odtenek osvetlitve tipkovnice</translation> <translation id="7690294790491645610">Potrdite novo geslo</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">lučka za osvetlitev tipkovnice</translation> <translation id="7730077286107534951">Nekateri podatki o računu in sistemu bodo morda poslani Googlu. Te podatke uporabljamo za odpravljanje tehničnih težav in izboljšanje svojih storitev v skladu s <ph name="BEGIN_LINK2" />pravilnikom o zasebnosti<ph name="END_LINK2" /> in <ph name="BEGIN_LINK3" />pogoji storitve<ph name="END_LINK3" />. Če želite zahtevati spremembe vsebine, obiščite stran s <ph name="BEGIN_LINK1" />pravno pomočjo<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Število ciklov</translation> +<translation id="7746357909584236306">omogočeno urejanje</translation> <translation id="7747039790905080783">Vnaprej deljeni ključ</translation> <translation id="7752963721013053477">Od zore do mraka – ekskluzivno</translation> <translation id="7762130827864645708">Sprememba gesla je bila uspešna. Od zdaj naprej uporabljajte novo geslo.</translation>
diff --git a/chromeos/strings/chromeos_strings_sr-Latn.xtb b/chromeos/strings/chromeos_strings_sr-Latn.xtb index d8a5d24b..a1b1378a 100644 --- a/chromeos/strings/chromeos_strings_sr-Latn.xtb +++ b/chromeos/strings/chromeos_strings_sr-Latn.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Učitavanje slika nije uspelo. Proverite mrežnu vezu ili probajte da ponovo učitate sliku.</translation> <translation id="1751249301761991853">Lično</translation> <translation id="1753496554272155572">Izađite iz pregleda pozadine</translation> +<translation id="1754578112426924640">Dugme Izmeni za <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Aplikacija Dijagnostika</translation> <translation id="175763766237925754">Dobar (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android nije pokrenut</translation> <translation id="551689408806449779">Prekinuta je veza sa uređajem. Probajte ponovo da se povežete radi testiranja</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">zaključano</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Automatski prelazite na tamnu temu u vreme zalaska sunca</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Centriraj</translation> <translation id="5703716265115423771">utišaj zvuk</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> od <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Dugme Izmeni za <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Ažurirajte <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Srednja</translation> <translation id="5757187557809630523">sledeća pesma</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Zabranjeno</translation> <translation id="5916664084637901428">Uključeno</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Fajl je skeniran i sačuvan u folderu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Fajlovi su skenirani i sačuvani u folderu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Fajlovi su skenirani i sačuvani u folderu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Fajlovi su skenirani i sačuvani u folderu <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Dugme Izbriši za <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Fajl nije pronađen</translation> <translation id="593880865674747800">Napravite još pozadina u ovom stilu</translation> <translation id="5939518447894949180">Resetuj</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Neuspešna DNS razrešavanja</translation> <translation id="6768237774506518020">Velika stopa neuspeha DNS razrešavanja</translation> <translation id="6791471867139427246">boja osvetljenja tastature</translation> +<translation id="6796229976413584781">Prečica je izbrisana</translation> <translation id="6798678288485555829">Kretanje kroz tekst</translation> <translation id="680983167891198932">Ključ</translation> <translation id="6816797338148849397">Dostupne su informacije vezane za vaš izbor. Koristite taster sa strelicom nagore da biste im pristupili.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Upravljajte podešavanjima naziva pristupne tačke mreže. Nazivi pristupnih tačaka uspostavljaju vezu između mobilne mreže i interneta. <ph name="BEGIN_LINK_LEARN_MORE" />Saznajte više<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Ažuriranja firmvera za eksterne uređaje</translation> <translation id="7216409898977639127">Mobilni operater</translation> +<translation id="7233782086689993269">Prečica je vraćena</translation> <translation id="725133483556299729">Izaberite imejl</translation> <translation id="7271040990581020067">Skener se trenutno koristi. Probajte ponovo kasnije.</translation> <translation id="7271932918253517778">Prečica sa tasterima u gornjem redu treba da sadrži taster <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Veliko HTTPS kašnjenje</translation> <translation id="7656388927906093505">Uređaj je miš.</translation> <translation id="7658239707568436148">Otkaži</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Promenite avatar</translation> <translation id="7683228889864052081">nijansa tastature</translation> <translation id="7690294790491645610">Potvrdite novu lozinku</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">svetlo tastature</translation> <translation id="7730077286107534951">Neke informacije o nalogu i sistemu mogu da se šalju Google-u. Ove informacije koristimo za rešavanje tehničkih problema i poboljšavanje usluga u skladu sa našom <ph name="BEGIN_LINK2" />politikom privatnosti<ph name="END_LINK2" /> i <ph name="BEGIN_LINK3" />uslovima korišćenja usluge<ph name="END_LINK3" />. Da biste zatražili promene sadržaja, idite u odeljak <ph name="BEGIN_LINK1" />Pravna pomoć<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Broj ciklusa</translation> +<translation id="7746357909584236306">može da se menja</translation> <translation id="7747039790905080783">Tajni ključ</translation> <translation id="7752963721013053477">Od svitanja do mraka – ekskluzivno</translation> <translation id="7762130827864645708">Lozinka je promenjena. Od sada koristite novu lozinku.</translation>
diff --git a/chromeos/strings/chromeos_strings_sr.xtb b/chromeos/strings/chromeos_strings_sr.xtb index 5a0d0df6..f2ebb25 100644 --- a/chromeos/strings/chromeos_strings_sr.xtb +++ b/chromeos/strings/chromeos_strings_sr.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Учитавање слика није успело. Проверите мрежну везу или пробајте да поново учитате слику.</translation> <translation id="1751249301761991853">Лично</translation> <translation id="1753496554272155572">Изађите из прегледа позадине</translation> +<translation id="1754578112426924640">Дугме Измени за <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Апликација Дијагностика</translation> <translation id="175763766237925754">Добар (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android није покренут</translation> <translation id="551689408806449779">Прекинута је веза са уређајем. Пробајте поново да се повежете ради тестирања</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">закључано</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Аутоматски прелазите на тамну тему у време заласка сунца</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Центрирај</translation> <translation id="5703716265115423771">утишај звук</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> од <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Дугме Измени за <ph name="SHORTCUT_DESCRIPTION" />.</translation> <translation id="5733298426544876109">Ажурирајте <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Средња</translation> <translation id="5757187557809630523">следећа песма</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Забрањено</translation> <translation id="5916664084637901428">Укључено</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Фајл је скениран и сачуван у фолдеру <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Фајлови су скенирани и сачувани у фолдеру <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Фајлови су скенирани и сачувани у фолдеру <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Фајлови су скенирани и сачувани у фолдеру <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Дугме Избриши за <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Фајл није пронађен</translation> <translation id="593880865674747800">Направите још позадина у овом стилу</translation> <translation id="5939518447894949180">Ресетуј</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">Неуспешна DNS разрешавања</translation> <translation id="6768237774506518020">Велика стопа неуспеха DNS разрешавања</translation> <translation id="6791471867139427246">боја осветљења тастатуре</translation> +<translation id="6796229976413584781">Пречица је избрисана</translation> <translation id="6798678288485555829">Кретање кроз текст</translation> <translation id="680983167891198932">Кључ</translation> <translation id="6816797338148849397">Доступне су информације везане за ваш избор. Користите тастер са стрелицом нагоре да бисте им приступили.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Управљајте подешавањима назива приступне тачке мреже. Називи приступних тачака успостављају везу између мобилне мреже и интернета. <ph name="BEGIN_LINK_LEARN_MORE" />Сазнајте више<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Ажурирања фирмвера за екстерне уређаје</translation> <translation id="7216409898977639127">Мобилни оператер</translation> +<translation id="7233782086689993269">Пречица је враћена</translation> <translation id="725133483556299729">Изаберите имејл</translation> <translation id="7271040990581020067">Скенер се тренутно користи. Пробајте поново касније.</translation> <translation id="7271932918253517778">Пречица са тастерима у горњем реду треба да садржи тастер <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">Велико HTTPS кашњење</translation> <translation id="7656388927906093505">Уређај је миш.</translation> <translation id="7658239707568436148">Откажи</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Промените аватар</translation> <translation id="7683228889864052081">нијанса тастатуре</translation> <translation id="7690294790491645610">Потврдите нову лозинку</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">светло тастатуре</translation> <translation id="7730077286107534951">Неке информације о налогу и систему могу да се шаљу Google-у. Ове информације користимо за решавање техничких проблема и побољшавање услуга у складу са нашом <ph name="BEGIN_LINK2" />политиком приватности<ph name="END_LINK2" /> и <ph name="BEGIN_LINK3" />условима коришћења услуге<ph name="END_LINK3" />. Да бисте затражили промене садржаја, идите у одељак <ph name="BEGIN_LINK1" />Правна помоћ<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Број циклуса</translation> +<translation id="7746357909584236306">може да се мења</translation> <translation id="7747039790905080783">Тајни кључ</translation> <translation id="7752963721013053477">Од свитања до мрака – ексклузивно</translation> <translation id="7762130827864645708">Лозинка је промењена. Од сада користите нову лозинку.</translation>
diff --git a/chromeos/strings/chromeos_strings_th.xtb b/chromeos/strings/chromeos_strings_th.xtb index 2561d62f..f926861 100644 --- a/chromeos/strings/chromeos_strings_th.xtb +++ b/chromeos/strings/chromeos_strings_th.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">โหลดรูปภาพไม่ได้ โปรดตรวจสอบการเชื่อมต่อเครือข่ายหรือลองโหลดรูปภาพอีกครั้ง</translation> <translation id="1751249301761991853">ส่วนบุคคล</translation> <translation id="1753496554272155572">ออกจากตัวอย่างวอลเปเปอร์</translation> +<translation id="1754578112426924640">ปุ่มแก้ไขสำหรับ <ph name="ACCELERATOR_INFO" /></translation> <translation id="1755556344721611131">แอปการวินิจฉัย</translation> <translation id="175763766237925754">ดี (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android ไม่ทำงาน</translation> <translation id="551689408806449779">ยกเลิกการเชื่อมต่ออุปกรณ์แล้ว ลองเชื่อมต่ออีกครั้งเพื่อทดสอบ</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">ล็อกอยู่</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">เปลี่ยนเป็นธีมมืดโดยอัตโนมัติเมื่อพระอาทิตย์ตก</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">กึ่งกลาง</translation> <translation id="5703716265115423771">ลดระดับเสียง</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> จาก <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">ปุ่มแก้ไขสำหรับ<ph name="SHORTCUT_DESCRIPTION" /></translation> <translation id="5733298426544876109">อัปเดต <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">ปานกลาง</translation> <translation id="5757187557809630523">แทร็กถัดไป</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">ห้ามใช้</translation> <translation id="5916664084637901428">เปิด</translation> <translation id="5921506667911082617">{COUNT,plural, =1{สแกนไฟล์และบันทึกไว้ใน <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> เรียบร้อยแล้ว}other{สแกนไฟล์และบันทึกไว้ใน <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> เรียบร้อยแล้ว}}</translation> +<translation id="5928411637936685857">ปุ่มลบสำหรับ <ph name="ACCELERATOR_INFO" /></translation> <translation id="5931523347251946569">ไม่พบไฟล์</translation> <translation id="593880865674747800">สร้างเพิ่มเติมในสไตล์นี้</translation> <translation id="5939518447894949180">รีเซ็ต</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">การแปลง DNS ที่ไม่สำเร็จ</translation> <translation id="6768237774506518020">อัตราการแปลง DNS ไม่สำเร็จสูง</translation> <translation id="6791471867139427246">สีไฟแป้นพิมพ์</translation> +<translation id="6796229976413584781">ลบแป้นพิมพ์ลัดแล้ว</translation> <translation id="6798678288485555829">การนำทางสำหรับข้อความ</translation> <translation id="680983167891198932">คีย์</translation> <translation id="6816797338148849397">มีข้อมูลที่เกี่ยวข้องกับสิ่งที่คุณเลือก ใช้แป้นลูกศรขึ้นเพื่อดูข้อมูลนั้น</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">จัดการการตั้งค่า APN ของเครือข่าย APN จะเริ่มการเชื่อมต่อระหว่างเครือข่ายมือถือกับอินเทอร์เน็ต <ph name="BEGIN_LINK_LEARN_MORE" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">การอัปเดตเฟิร์มแวร์สำหรับอุปกรณ์ภายนอก</translation> <translation id="7216409898977639127">ผู้ให้บริการเครือข่ายมือถือ</translation> +<translation id="7233782086689993269">คืนค่าแป้นพิมพ์ลัดแล้ว</translation> <translation id="725133483556299729">เลือกอีเมล</translation> <translation id="7271040990581020067">เครื่องสแกนกำลังทำงานอยู่ ลองอีกครั้งในภายหลัง</translation> <translation id="7271932918253517778">แป้นพิมพ์ลัดที่ประกอบด้วยแป้นแถวบนสุดต้องมีแป้น<ph name="META_KEY" />รวมอยู่ด้วย</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">เวลาในการตอบสนองของ HTTPS สูง</translation> <translation id="7656388927906093505">อุปกรณ์เป็นเมาส์</translation> <translation id="7658239707568436148">ยกเลิก</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" /></translation> <translation id="7665800271478495366">เปลี่ยนรูปโปรไฟล์</translation> <translation id="7683228889864052081">โทนสีแป้นพิมพ์</translation> <translation id="7690294790491645610">ยืนยันรหัสผ่านใหม่</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">ไฟแป้นพิมพ์</translation> <translation id="7730077286107534951">อาจมีการส่งข้อมูลระบบและบัญชีบางอย่างไปยัง Google เราใช้ข้อมูลนี้เพื่อช่วยแก้ปัญหาด้านเทคนิคและปรับปรุงบริการโดยเป็นไปตาม<ph name="BEGIN_LINK2" />นโยบายความเป็นส่วนตัว<ph name="END_LINK2" />และ<ph name="BEGIN_LINK3" />ข้อกำหนดในการให้บริการ<ph name="END_LINK3" /> หากต้องการส่งคำขอเปลี่ยนแปลงเนื้อหา โปรดไปที่<ph name="BEGIN_LINK1" />ความช่วยเหลือด้านกฎหมาย<ph name="END_LINK1" /></translation> <translation id="773153675489693198">จำนวนรอบ</translation> +<translation id="7746357909584236306">แก้ไขได้</translation> <translation id="7747039790905080783">คีย์ที่แชร์ล่วงหน้า</translation> <translation id="7752963721013053477">รุ่งเช้าจนถึงกลางคืน - พิเศษเฉพาะคุณ</translation> <translation id="7762130827864645708">เปลี่ยนรหัสผ่านสำเร็จ โปรดใช้รหัสผ่านใหม่จากนี้ไป</translation>
diff --git a/chromeos/strings/chromeos_strings_uk.xtb b/chromeos/strings/chromeos_strings_uk.xtb index 794acad..743c9a7 100644 --- a/chromeos/strings/chromeos_strings_uk.xtb +++ b/chromeos/strings/chromeos_strings_uk.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Не вдалося завантажити зображення. Перевірте з’єднання з мережею або повторіть спробу.</translation> <translation id="1751249301761991853">Персоналізація</translation> <translation id="1753496554272155572">Закрити попередній перегляд фонового малюнка</translation> +<translation id="1754578112426924640">Кнопка "Редагувати" для комбінації клавіш <ph name="ACCELERATOR_INFO" />.</translation> <translation id="1755556344721611131">Додаток Діагностика</translation> <translation id="175763766237925754">Добрий сигнал (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android не працює</translation> <translation id="551689408806449779">Пристрій відключено. Щоб продовжити тестування, спробуйте підключитися знову.</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">заблоковано</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Автоматично вмикати темну тему після заходу сонця</translation> <translation id="5578477003638479617">Технологія UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">По центру</translation> <translation id="5703716265115423771">зменшити гучність</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> з <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">Кнопка "Редагувати" для опису "<ph name="SHORTCUT_DESCRIPTION" />".</translation> <translation id="5733298426544876109">Оновити пристрій: <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">Середній</translation> <translation id="5757187557809630523">наступна композиція</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Заборонено</translation> <translation id="5916664084637901428">Увімкнено</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Файл зіскановано та збережено в папку <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}one{Файли зіскановано та збережено в папку <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}few{Файли зіскановано та збережено в папку <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}many{Файли зіскановано та збережено в папку <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}other{Файли зіскановано та збережено в папку <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />.}}</translation> +<translation id="5928411637936685857">Кнопка "Видалити" для комбінації клавіш <ph name="ACCELERATOR_INFO" />.</translation> <translation id="5931523347251946569">Файл не знайдено</translation> <translation id="593880865674747800">Створити більше в цьому стилі</translation> <translation id="5939518447894949180">Скинути</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">невдалі перетворення DNS</translation> <translation id="6768237774506518020">велика частка збоїв під час перетворення DNS</translation> <translation id="6791471867139427246">колір підсвічування клавіатури</translation> +<translation id="6796229976413584781">Комбінацію клавіш видалено</translation> <translation id="6798678288485555829">Навігація текстом</translation> <translation id="680983167891198932">Ключ</translation> <translation id="6816797338148849397">Доступна інформація, пов'язана з виділеним текстом. Щоб перейти до неї, натисніть клавішу зі стрілкою вгору.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Керуйте налаштуваннями APN мережі: за допомогою ідентифікаторів APN установлюється зв’язок між мобільною мережею і Інтернетом. <ph name="BEGIN_LINK_LEARN_MORE" />Докладніше<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Оновлення мікропрограми для зовнішніх пристроїв</translation> <translation id="7216409898977639127">Постачальник мобільного зв’язку</translation> +<translation id="7233782086689993269">Комбінацію клавіш відновлено</translation> <translation id="725133483556299729">Вибрати електронну адресу</translation> <translation id="7271040990581020067">Cканер використовується. Повторіть спробу пізніше.</translation> <translation id="7271932918253517778">Комбінація з клавішами верхнього рядка має містити клавішу <ph name="META_KEY" />.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">велика затримка HTTPS</translation> <translation id="7656388927906093505">Це миша.</translation> <translation id="7658239707568436148">Скасувати</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Змінити аватар</translation> <translation id="7683228889864052081">відтінок клавіатури</translation> <translation id="7690294790491645610">Підтвердьте новий пароль</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">підсвічування клавіатури</translation> <translation id="7730077286107534951">Певні дані про ваш обліковий запис і систему можуть надсилатися в Google. Ми застосовуємо цю інформацію відповідно до <ph name="BEGIN_LINK2" />Політики конфіденційності<ph name="END_LINK2" /> й <ph name="BEGIN_LINK3" />Умов використання<ph name="END_LINK3" />, щоб вирішувати технічні проблеми й покращувати наші сервіси. Щоб надіслати запит на змінення контенту, перейдіть на <ph name="BEGIN_LINK1" />сторінку правової довідки<ph name="END_LINK1" />.</translation> <translation id="773153675489693198">Кількість циклів</translation> +<translation id="7746357909584236306">доступно для редагування</translation> <translation id="7747039790905080783">Спільний ключ</translation> <translation id="7752963721013053477">Від світанку до заходу сонця – ексклюзивно</translation> <translation id="7762130827864645708">Ваш пароль змінено. Відтепер використовуйте новий.</translation>
diff --git a/chromeos/strings/chromeos_strings_ur.xtb b/chromeos/strings/chromeos_strings_ur.xtb index 66a77ba..c2e7543 100644 --- a/chromeos/strings/chromeos_strings_ur.xtb +++ b/chromeos/strings/chromeos_strings_ur.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">تصاویر لوڈ نہیں ہو سکیں۔ اپنا نیٹ ورک کنکشن چیک کریں یا تصاویر کو دوبارہ لوڈ کرنے کی کوشش کریں۔</translation> <translation id="1751249301761991853">ذاتی</translation> <translation id="1753496554272155572">وال پیپر کے پیش منظر سے باہر نکلیں</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> کیلئے ترمیم کریں بٹن۔</translation> <translation id="1755556344721611131">تشخیصات کی ایپ</translation> <translation id="175763766237925754">اچھا (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android نہیں چل رہا ہے</translation> <translation id="551689408806449779">آلہ غیر منسلک ہو گیا ہے۔ ٹیسٹ کرنے کے لیے دوبارہ منسلک ہونے کی کوشش کریں</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">مقفل ہے</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">غروب آفتاب کے وقت خود کار طور پر گہری تھیم پر سوئچ کریں</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">مرکز</translation> <translation id="5703716265115423771">والیوم کم کریں</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> از <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> کیلئے ترمیم کریں بٹن۔</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> اپ ڈیٹ کریں</translation> <translation id="574392208103952083">متوسط</translation> <translation id="5757187557809630523">اگلا ٹریک</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">ممنوعہ</translation> <translation id="5916664084637901428">آن</translation> <translation id="5921506667911082617">{COUNT,plural, =1{آپ کی فائل کامیابی کے ساتھ اسکین ہو گئی ہے اور اسے <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> پر محفوظ کر دیا گیا ہے۔}other{آپ کی فائلیں کامیابی کے ساتھ اسکین ہو گئی ہیں اور انہیں <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> پر محفوظ کر دیا گیا ہے۔}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> کیلئے حذف کریں بٹن۔</translation> <translation id="5931523347251946569">فائل نہیں ملی</translation> <translation id="593880865674747800">اس اسٹائل میں مزید تخلیق کریں</translation> <translation id="5939518447894949180">دوبارہ ترتیب دیں</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">ناکام DNS ریزولیوشنز</translation> <translation id="6768237774506518020">DNS ریزولیوشن ناکام ہونے کی زیادہ شرح</translation> <translation id="6791471867139427246">کی بورڈ کا ہلکا رنگ</translation> +<translation id="6796229976413584781">شارٹ کٹ حذف کیا گیا</translation> <translation id="6798678288485555829">ٹیکسٹ نیویگیشن</translation> <translation id="680983167891198932">کلید</translation> <translation id="6816797338148849397">آپ کے انتخاب سے متعلقہ معلومات دستیاب ہے۔ رسائی حاصل کرنے کے لئے اوپر تیر کے نشان کی کلید کا استعمال کریں۔</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">نیٹ ورک APN کی ترتیبات کا نظم کریں۔ APNs سیلولر نیٹ ورک اور انٹرنیٹ کے درمیان رابطہ قائم کرتے ہیں۔ <ph name="BEGIN_LINK_LEARN_MORE" />مزید جانیں<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">بیرونی آلات کیلئے فرم ویئر اپ ڈیٹس</translation> <translation id="7216409898977639127">سیلولر فراہم کنندہ</translation> +<translation id="7233782086689993269">شارٹ کٹ بحال کیا گیا</translation> <translation id="725133483556299729">ای میل منتخب کریں</translation> <translation id="7271040990581020067">اسکینر فی الحال زیر استعمال ہے۔ بعد میں دوبارہ کوشش کریں۔</translation> <translation id="7271932918253517778">اوپر والی قطار کی کلیدوں والے شارٹ کٹ میں <ph name="META_KEY" /> کلید شامل کرنے کی ضرورت ہے۔</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">زیادہ HTTPS تاخیر</translation> <translation id="7656388927906093505">آلہ ایک ماؤس ہے۔</translation> <translation id="7658239707568436148">منسوخ کریں</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />، <ph name="ACCELERATOR_INFO" />، <ph name="ROW_STATUS" />۔</translation> <translation id="7665800271478495366">اوتار تبدیل کریں</translation> <translation id="7683228889864052081">کی بورڈ کا رنگ</translation> <translation id="7690294790491645610">نئے پاس ورڈ کی توثیق کریں</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">کی بورڈ کی لائٹ</translation> <translation id="7730077286107534951">اکاؤنٹ اور سسٹم کی کچھ معلومات Google کو بھیجی جا سکتی ہے۔ ہم اس معلومات کو اپنی <ph name="BEGIN_LINK2" />رازداری کی پالیسی<ph name="END_LINK2" /> اور <ph name="BEGIN_LINK3" />سروس کی شرائط<ph name="END_LINK3" /> کے ساتھ مشروط، تکنیکی مسائل حل کرنے اور اپنی سروسز کو بہتر بنانے میں مدد کے لیے استعمال کرتے ہیں۔ مواد میں تبدیلی کی درخواست کرنے کے لیے، <ph name="BEGIN_LINK1" />قانونی مدد<ph name="END_LINK1" /> پر جائیں۔</translation> <translation id="773153675489693198">دورانیے کی تعداد</translation> +<translation id="7746357909584236306">قابل ترمیم</translation> <translation id="7747039790905080783">پہلے سے اشتراک کردہ کلید</translation> <translation id="7752963721013053477">ڈان ٹو ڈارک - خصوصی</translation> <translation id="7762130827864645708">آپ کا پاس ورڈ کامیابی سے تبدیل کر دیا گیا۔ براہ کرم اب سے نیا پاس ورڈ استعمال کریں۔</translation>
diff --git a/chromeos/strings/chromeos_strings_uz.xtb b/chromeos/strings/chromeos_strings_uz.xtb index 8b61393..f1f21424 100644 --- a/chromeos/strings/chromeos_strings_uz.xtb +++ b/chromeos/strings/chromeos_strings_uz.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">Rasmlar yuklanmadi. Tarmoq aloqasini tekshiring yoki rasmlarni qaytadan yuklang.</translation> <translation id="1751249301761991853">Shaxsiy</translation> <translation id="1753496554272155572">Fon rasmiga razm solishdan chiqish</translation> +<translation id="1754578112426924640"><ph name="ACCELERATOR_INFO" /> tugmasini tahrirlash.</translation> <translation id="1755556344721611131">Diagnostika ilovasi</translation> <translation id="175763766237925754">Yaxshi (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android orqali bajarilmadi</translation> <translation id="551689408806449779">Qurilma uzilgan. Sinash uchun qayta urining</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">qulflandi</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">Quyosh botganida tungi mavzuga avtomatik almashish</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">Markaz bo‘yicha tartiblash</translation> <translation id="5703716265115423771">ovozni pasaytirish</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" /> / <ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605"><ph name="SHORTCUT_DESCRIPTION" /> tugmasini tahrirlash.</translation> <translation id="5733298426544876109"><ph name="DEVICE_NAME" /> ilovasini yangilang</translation> <translation id="574392208103952083">O‘rtacha</translation> <translation id="5757187557809630523">keyingi trek</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">Taqiqlangan</translation> <translation id="5916664084637901428">Yoniq</translation> <translation id="5921506667911082617">{COUNT,plural, =1{Fayl skanerlandi va <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> jildiga saqlandi.}other{Fayllar skanerlandi va <ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" /> jildiga saqlandi.}}</translation> +<translation id="5928411637936685857"><ph name="ACCELERATOR_INFO" /> tugmasini oʻchirish.</translation> <translation id="5931523347251946569">Fayl topilmadi</translation> <translation id="593880865674747800">Shu uslubda yana yaratish</translation> <translation id="5939518447894949180">Asliga qaytarish</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS manzil ajratilmadi</translation> <translation id="6768237774506518020">DNS manzil ajratilmasligi juda yuqori</translation> <translation id="6791471867139427246">klaviatura chirogʻi rangi</translation> +<translation id="6796229976413584781">Tezkor tugma oʻchirildi</translation> <translation id="6798678288485555829">Matn navigatsiyasi</translation> <translation id="680983167891198932">Kalit</translation> <translation id="6816797338148849397">Tanlovga aloqador axborot mavjud. Uni ochish uchun tepaga strelkani bosing.</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">Tarmoq APN sozlamalarini boshqarish. APN sozlamalari mobil tarmoq va internet orasida aloqani taʼminlaydi. <ph name="BEGIN_LINK_LEARN_MORE" />Batafsil<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">Tashqi qurilmalar uchun mikrodastur yangilanishi</translation> <translation id="7216409898977639127">Mobil tarmoq</translation> +<translation id="7233782086689993269">Tezkor tugma tiklandi</translation> <translation id="725133483556299729">Emailni tanlang</translation> <translation id="7271040990581020067">Skaner hozir band. Keyinroq urining.</translation> <translation id="7271932918253517778">Yuqori qator tugmalari mavjud tezkor tugmada <ph name="META_KEY" /> tugmasi ishlatilishi kerak.</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPS kechikishi yuqori</translation> <translation id="7656388927906093505">Qurilma — sichqoncha.</translation> <translation id="7658239707568436148">Bekor qilish</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />, <ph name="ACCELERATOR_INFO" />, <ph name="ROW_STATUS" />.</translation> <translation id="7665800271478495366">Avatarni almashtirish</translation> <translation id="7683228889864052081">klaviatura tusi</translation> <translation id="7690294790491645610">Yangi parolni tasdiqlang.</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">klaviatura chirogʻi</translation> <translation id="7730077286107534951">Hisob va tizimga oid ayrim axborotlar Google kompaniyasiga yuborilishi mumkin. Google taqdim etilgan maʼlumotlardan texnik muammolarni hal qilish va xizmatlarni yaxshilashda foydalanadi, bunda <ph name="BEGIN_LINK2" />Maxfiylik siyosati<ph name="END_LINK2" /> va <ph name="BEGIN_LINK3" />Xizmat shartlari<ph name="END_LINK3" /> amal qilinadi. Kontentni oʻzgartirish talabini yuborish uchun <ph name="BEGIN_LINK1" />Huquqiy yordam<ph name="END_LINK1" /> sahifasini oching.</translation> <translation id="773153675489693198">Davrlar soni</translation> +<translation id="7746357909584236306">tahrirlash mumkin</translation> <translation id="7747039790905080783">Umumiy kalit</translation> <translation id="7752963721013053477">Tongdan tungacha - ekskluziv</translation> <translation id="7762130827864645708">Parolingiz oʻzgartirildi. Endi yangi paroldan foydalaning.</translation>
diff --git a/chromeos/strings/chromeos_strings_zh-HK.xtb b/chromeos/strings/chromeos_strings_zh-HK.xtb index 40f16929d..de47bee 100644 --- a/chromeos/strings/chromeos_strings_zh-HK.xtb +++ b/chromeos/strings/chromeos_strings_zh-HK.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">無法載入圖片。請檢查網絡連線,或者嘗試再次載入圖片。</translation> <translation id="1751249301761991853">個人化</translation> <translation id="1753496554272155572">結束桌布預覽</translation> +<translation id="1754578112426924640">修改 <ph name="ACCELERATOR_INFO" /> 嘅按鈕。</translation> <translation id="1755556344721611131">診斷應用程式</translation> <translation id="175763766237925754">好 (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android 未執行</translation> <translation id="551689408806449779">裝置已解除連接。請嘗試重新連接以測試</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">鎖定咗</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">日落時自動切換至深色主題背景</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">置中</translation> <translation id="5703716265115423771">調低音量</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />/<ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">修改 <ph name="SHORTCUT_DESCRIPTION" /> 嘅按鈕。</translation> <translation id="5733298426544876109">更新 <ph name="DEVICE_NAME" /></translation> <translation id="574392208103952083">中</translation> <translation id="5757187557809630523">下一首歌</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">禁止</translation> <translation id="5916664084637901428">開啟</translation> <translation id="5921506667911082617">{COUNT,plural, =1{您的檔案已成功掃瞄,並儲存至「<ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />」資料夾。}other{您的檔案已成功掃瞄,並儲存至「<ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />」資料夾。}}</translation> +<translation id="5928411637936685857">刪除 <ph name="ACCELERATOR_INFO" /> 嘅按鈕。</translation> <translation id="5931523347251946569">找不到檔案</translation> <translation id="593880865674747800">以此風格製作更多桌布</translation> <translation id="5939518447894949180">重設</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS 解析失敗</translation> <translation id="6768237774506518020">DNS 解析失敗率高</translation> <translation id="6791471867139427246">鍵盤背光顏色</translation> +<translation id="6796229976413584781">刪除咗捷徑</translation> <translation id="6798678288485555829">文字導覽</translation> <translation id="680983167891198932">金鑰</translation> <translation id="6816797338148849397">你所揀嘅項目有相關資料可以提供。用向上箭咀掣就可以存取。</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">管理網絡 APN 設定。APN 會在流動網絡和互聯網之間建立連線。<ph name="BEGIN_LINK_LEARN_MORE" />瞭解詳情<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">外部裝置適用的韌體更新</translation> <translation id="7216409898977639127">流動服務供應商</translation> +<translation id="7233782086689993269">還原咗快速鍵</translation> <translation id="725133483556299729">揀電郵地址</translation> <translation id="7271040990581020067">掃瞄器目前正在使用中,請稍後再試。</translation> <translation id="7271932918253517778">如果快速鍵包括最上排的按鍵,亦需要使用<ph name="META_KEY" />鍵。</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">HTTPS 延遲時間長</translation> <translation id="7656388927906093505">裝置類型係滑鼠。</translation> <translation id="7658239707568436148">取消</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />,<ph name="ACCELERATOR_INFO" />,<ph name="ROW_STATUS" />。</translation> <translation id="7665800271478495366">改顯示圖片</translation> <translation id="7683228889864052081">鍵盤色調</translation> <translation id="7690294790491645610">確認新密碼</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">鍵盤燈</translation> <translation id="7730077286107534951">部分帳戶和系統資料可能會傳送給 Google。我們會按照《<ph name="BEGIN_LINK2" />私隱權政策<ph name="END_LINK2" />》和《<ph name="BEGIN_LINK3" />服務條款<ph name="END_LINK3" />》使用這些資料,協助處理技術問題並改善服務。如要提出內容變更要求,請前往<ph name="BEGIN_LINK1" />法律說明中心<ph name="END_LINK1" />。</translation> <translation id="773153675489693198">週期數</translation> +<translation id="7746357909584236306">可以編輯</translation> <translation id="7747039790905080783">預先共用密鑰</translation> <translation id="7752963721013053477">黎明到黑夜 - 獨家</translation> <translation id="7762130827864645708">已成功變更您的密碼。請從現在開始改用新的密碼。</translation>
diff --git a/chromeos/strings/chromeos_strings_zh-TW.xtb b/chromeos/strings/chromeos_strings_zh-TW.xtb index 30263ed..509156b 100644 --- a/chromeos/strings/chromeos_strings_zh-TW.xtb +++ b/chromeos/strings/chromeos_strings_zh-TW.xtb
@@ -124,6 +124,7 @@ <translation id="1745577949879301685">無法載入圖片。請檢查網路連線,或嘗試再次載入圖片。</translation> <translation id="1751249301761991853">個人化</translation> <translation id="1753496554272155572">結束桌布預覽</translation> +<translation id="1754578112426924640">「<ph name="ACCELERATOR_INFO" />」的編輯按鈕。</translation> <translation id="1755556344721611131">執行診斷的應用程式</translation> <translation id="175763766237925754">良好 (<ph name="SIGNAL_STRENGTH" />)</translation> <translation id="1758018619400202187">EAP-TLS</translation> @@ -625,6 +626,7 @@ <translation id="5502931783115429516">Android 未執行</translation> <translation id="551689408806449779">裝置已中斷連線,請嘗試重新連線進行測試</translation> <translation id="5519195206574732858">LTE</translation> +<translation id="5543701552415191873">已鎖定</translation> <translation id="554517032089923082">GTC</translation> <translation id="5559898619118303662">日落後自動切換到深色主題</translation> <translation id="5578477003638479617">UMTS</translation> @@ -645,6 +647,7 @@ <translation id="5701381305118179107">置中</translation> <translation id="5703716265115423771">調低音量</translation> <translation id="5707900041990977207"><ph name="CURRENT_PAGE" />/<ph name="TOTAL_PAGES" /></translation> +<translation id="572854785834323605">「<ph name="SHORTCUT_DESCRIPTION" />」的編輯按鈕。</translation> <translation id="5733298426544876109">更新「<ph name="DEVICE_NAME" />」</translation> <translation id="574392208103952083">中</translation> <translation id="5757187557809630523">播放下一首曲目</translation> @@ -675,6 +678,7 @@ <translation id="5916084858004523819">禁止</translation> <translation id="5916664084637901428">開啟</translation> <translation id="5921506667911082617">{COUNT,plural, =1{檔案掃描完成,現已存放在「<ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />」資料夾。}other{檔案掃描完成,現已存放在「<ph name="LINK_BEGIN" /><ph name="FOLDER_NAME" /><ph name="LINK_END" />」資料夾。}}</translation> +<translation id="5928411637936685857">「<ph name="ACCELERATOR_INFO" />」的刪除按鈕。</translation> <translation id="5931523347251946569">找不到檔案</translation> <translation id="593880865674747800">生成更多這種風格的桌布</translation> <translation id="5939518447894949180">重設</translation> @@ -802,6 +806,7 @@ <translation id="6766275201586212568">DNS 解析失敗</translation> <translation id="6768237774506518020">高 DNS 解析失敗率</translation> <translation id="6791471867139427246">鍵盤背光顏色</translation> +<translation id="6796229976413584781">已刪除捷徑</translation> <translation id="6798678288485555829">文字導覽</translation> <translation id="680983167891198932">金鑰</translation> <translation id="6816797338148849397">提供所選內容的相關資訊。請使用向上鍵存取。</translation> @@ -856,6 +861,7 @@ <translation id="7212547870105584639">管理網路 APN 設定。APN 會在行動網路和網際網路之間建立連線。<ph name="BEGIN_LINK_LEARN_MORE" />瞭解詳情<ph name="END_LINK_LEARN_MORE" /></translation> <translation id="7212734716605298123">外部裝置適用的韌體更新</translation> <translation id="7216409898977639127">行動網路提供者</translation> +<translation id="7233782086689993269">已還原捷徑</translation> <translation id="725133483556299729">選取電子郵件地址</translation> <translation id="7271040990581020067">掃描器正在使用中,請稍後再試。</translation> <translation id="7271932918253517778">如果快速鍵會用到最上排的按鍵,請一併按下<ph name="META_KEY" />鍵。</translation> @@ -917,6 +923,7 @@ <translation id="7648838807254605802">高 HTTPS 延遲</translation> <translation id="7656388927906093505">裝置類型為滑鼠。</translation> <translation id="7658239707568436148">取消</translation> +<translation id="7663672983483557630"><ph name="DESCRIPTION" />,<ph name="ACCELERATOR_INFO" />,<ph name="ROW_STATUS" />。</translation> <translation id="7665800271478495366">變更顯示圖片</translation> <translation id="7683228889864052081">鍵盤色調</translation> <translation id="7690294790491645610">確認新密碼</translation> @@ -926,6 +933,7 @@ <translation id="7718231387947923843">鍵盤燈</translation> <translation id="7730077286107534951">部分帳戶和系統資訊可能會傳送給 Google。我們會依《<ph name="BEGIN_LINK2" />隱私權政策<ph name="END_LINK2" />》和《<ph name="BEGIN_LINK3" />服務條款<ph name="END_LINK3" />》的規定使用這類資訊,解決技術問題及改善服務品質。如要提出內容變更要求,請前往<ph name="BEGIN_LINK1" />法律說明中心<ph name="END_LINK1" />。</translation> <translation id="773153675489693198">週期數</translation> +<translation id="7746357909584236306">可編輯</translation> <translation id="7747039790905080783">預先共用金鑰</translation> <translation id="7752963721013053477">黎明到黑夜 - 專屬</translation> <translation id="7762130827864645708">已成功變更你的密碼。請從現在開始改用新的密碼。</translation>
diff --git a/clank b/clank index 923f628..ffa3dc2 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 923f628b8e7644a1c009747dafe7bf61e12896b6 +Subproject commit ffa3dc27fca10f8fc147f85437851f73327551f5
diff --git a/components/BUILD.gn b/components/BUILD.gn index ee7bd78..90ffd4d4 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -217,6 +217,7 @@ "//components/encrypted_messages:unit_tests", "//components/enterprise:unit_tests", "//components/enterprise/common:unit_tests", + "//components/facilitated_payments/core/util:unit_tests", "//components/favicon/core:unit_tests", "//components/favicon_base:unit_tests", "//components/feature_engagement:unit_tests", @@ -451,6 +452,7 @@ "//components/heavy_ad_intervention:unit_tests", "//components/history/content/browser:unit_tests", "//components/history_clusters/core:unit_tests", + "//components/history_embeddings:unit_tests", "//components/invalidation/impl:unit_tests", "//components/javascript_dialogs:unit_tests", "//components/js_injection/common:unit_tests",
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 1197d51..bf964f7 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -1126,78 +1126,10 @@ bool PasswordAutofillAgent::ShowSuggestions( const WebInputElement& element, AutofillSuggestionTriggerSource trigger_source) { - WebInputElement username_element; - WebInputElement password_element; - PasswordInfo* password_info = nullptr; - FindPasswordInfoForElement(element, UseFallbackData(true), &username_element, - &password_element, &password_info); - - if (!password_info) { - MaybeCheckSafeBrowsingReputation(element); - if (!CanShowPopupWithoutPasswords(password_element)) - return false; - } - - // Check that all fillable elements are editable. - if (!element.IsTextField() || !IsElementEditable(element) || - (!password_element.IsNull() && !IsElementEditable(password_element))) { - return true; - } - - // Don't attempt to autofill with values that are too large. - if (element.Value().length() > kMaximumTextSizeForAutocomplete) - return false; - -#if BUILDFLAG(IS_ANDROID) - // Don't call `ShowSuggestionPopup` if a keyboard replacing surface is - // currently showing. Since a keyboard replacing surface in spirit is very - // similar to a suggestion pop-up, return true so that the AutofillAgent does - // not try to show other autofill suggestions instead. - if (keyboard_replacing_surface_state_ == - KeyboardReplacingSurfaceState::kIsShowing) { - return true; - } -#endif - - if (!HasDocumentWithValidFrame(element)) - return false; - - // If a username element is focused, show suggestions unless all possible - // usernames are filtered. - if (!element.IsPasswordFieldForAutofill()) { - std::u16string username_prefix; - if (!ShouldShowFullSuggestionListForPasswordManager(trigger_source, - element) && - !base::FeatureList::IsEnabled( - password_manager::features::kNoPasswordSuggestionFiltering)) { - if (!password_info || - !CanShowUsernameSuggestion(password_info->fill_data, - element.Value().Utf16())) { - return false; - } - username_prefix = element.Value().Utf16(); - } - ShowSuggestionPopup(username_prefix, element, trigger_source, - OnPasswordField(false)); - return true; - } - - // If the element is a password field, do not to show a popup if the user has - // already accepted a password suggestion on another password field. - if (password_info && password_info->password_field_suggestion_was_accepted && - element != password_info->password_field) { - return true; - } - - // Show suggestions for password fields only while they are empty. - if (!element.IsAutofilled() && !element.Value().IsEmpty()) { - HidePopup(); - return false; - } - - ShowSuggestionPopup(std::u16string(), element, trigger_source, - OnPasswordField(true)); - return true; + return trigger_source == + AutofillSuggestionTriggerSource::kManualFallbackPasswords + ? ShowManualFallbackSuggestions(element) + : ShowSuggestionsForDomain(element, trigger_source); } bool PasswordAutofillAgent::FrameCanAccessPasswordManager() { @@ -1642,6 +1574,113 @@ //////////////////////////////////////////////////////////////////////////////// // PasswordAutofillAgent, private: +bool PasswordAutofillAgent::ShowSuggestionsForDomain( + const blink::WebInputElement& element, + AutofillSuggestionTriggerSource trigger_source) { + WebInputElement username_element; + WebInputElement password_element; + PasswordInfo* password_info = nullptr; + FindPasswordInfoForElement(element, UseFallbackData(true), &username_element, + &password_element, &password_info); + + if (!password_info) { + MaybeCheckSafeBrowsingReputation(element); + if (!CanShowPopupWithoutPasswords(password_element)) { + return false; + } + } + + // Check that all fillable elements are editable. + if (!element.IsTextField() || !IsElementEditable(element) || + (!password_element.IsNull() && !IsElementEditable(password_element))) { + return true; + } + + // Don't attempt to autofill with values that are too large. + if (element.Value().length() > kMaximumTextSizeForAutocomplete) { + return false; + } + +#if BUILDFLAG(IS_ANDROID) + // Don't call `ShowSuggestionPopup` if a keyboard replacing surface is + // currently showing. Since a keyboard replacing surface in spirit is very + // similar to a suggestion pop-up, return true so that the AutofillAgent does + // not try to show other autofill suggestions instead. + if (keyboard_replacing_surface_state_ == + KeyboardReplacingSurfaceState::kIsShowing) { + return true; + } +#endif + + if (!HasDocumentWithValidFrame(element)) { + return false; + } + + // If a username element is focused, show suggestions unless all possible + // usernames are filtered. + if (!element.IsPasswordFieldForAutofill()) { + std::u16string username_prefix; + if (!ShouldShowFullSuggestionListForPasswordManager(trigger_source, + element) && + !base::FeatureList::IsEnabled( + password_manager::features::kNoPasswordSuggestionFiltering)) { + if (!password_info || + !CanShowUsernameSuggestion(password_info->fill_data, + element.Value().Utf16())) { + return false; + } + username_prefix = element.Value().Utf16(); + } + ShowSuggestionPopup(username_prefix, element, trigger_source, + OnPasswordField(false)); + return true; + } + + // If the element is a password field, do not to show a popup if the user has + // already accepted a password suggestion on another password field. + if (password_info && password_info->password_field_suggestion_was_accepted && + element != password_info->password_field) { + return true; + } + + // Show suggestions for password fields only while they are empty. + if (!element.IsAutofilled() && !element.Value().IsEmpty()) { + HidePopup(); + return false; + } + + ShowSuggestionPopup(std::u16string(), element, trigger_source, + OnPasswordField(true)); + return true; +} + +bool PasswordAutofillAgent::ShowManualFallbackSuggestions( + const blink::WebInputElement& element) { + WebInputElement username_element; + WebInputElement password_element; + PasswordInfo* password_info = nullptr; + if (!FindPasswordInfoForElement(element, UseFallbackData(false), + &username_element, &password_element, + &password_info)) { + // Perform this action only if there's no passwords saved for the triggering + // field. Manual fallback suggestions can be shown on any field. + MaybeCheckSafeBrowsingReputation(element); + } + + if (!FrameCanAccessPasswordManager()) { + return false; + } + + if (!HasDocumentWithValidFrame(element)) { + return false; + } + + ShowSuggestionPopup(std::u16string(), element, + AutofillSuggestionTriggerSource::kManualFallbackPasswords, + OnPasswordField(element.IsPasswordFieldForAutofill())); + return true; +} + void PasswordAutofillAgent::ShowSuggestionPopup( const std::u16string& typed_username, const WebInputElement& user_input,
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index 728c746..b4c928e 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -344,6 +344,16 @@ // If `only_visible` is true, only forms visible in the layout are sent. void SendPasswordForms(bool only_visible); + // Performs necessary feasibility checks and triggers password suggestions + // for the current domain on the `element`. `trigger_source` is used to + // distinguish between the ways of how Autofill was triggered. + bool ShowSuggestionsForDomain(const blink::WebInputElement& element, + AutofillSuggestionTriggerSource trigger_source); + + // Performs necessary feasibility checks and triggers manual fallback + // suggestion on the provided `element`. + bool ShowManualFallbackSuggestions(const blink::WebInputElement& element); + // Instructs the browser to show a pop-up suggesting which credentials could // be filled. `show_on_password_field` should indicate whether the pop-up is // to be shown on the password field instead of on the username field. If the
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 376e0481..da29a229 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -414,6 +414,8 @@ "payments/payments_data_cleaner.h", "payments/payments_network_interface.cc", "payments/payments_network_interface.h", + "payments/payments_network_interface_base.cc", + "payments/payments_network_interface_base.h", "payments/payments_requests/get_card_upload_details_request.cc", "payments/payments_requests/get_card_upload_details_request.h", "payments/payments_requests/get_details_for_enrollment_request.cc", @@ -909,6 +911,7 @@ "ui/mock_autofill_popup_delegate.h", "ui/mock_fast_checkout_client.cc", "ui/mock_fast_checkout_client.h", + "ui/suggestion_test_helpers.cc", "ui/suggestion_test_helpers.h", "webdata/mock_autofill_webdata_backend.cc", "webdata/mock_autofill_webdata_backend.h", @@ -1072,6 +1075,7 @@ "form_autofill_history_unittest.cc", "form_data_importer_unittest.cc", "form_data_importer_utils_unittest.cc", + "form_filler_unittest.cc", "form_forest_unittest.cc", "form_parsing/address_field_parser_unittest.cc", "form_parsing/credit_card_field_parser_unittest.cc", @@ -1142,6 +1146,8 @@ "payments/iban_save_manager_unittest.cc", "payments/legal_message_line_unittest.cc", "payments/payments_data_cleaner_unittest.cc", + "payments/payments_network_interface_test_base.cc", + "payments/payments_network_interface_test_base.h", "payments/payments_network_interface_unittest.cc", "payments/payments_requests/get_details_for_enrollment_request_unittest.cc", "payments/payments_requests/get_iban_upload_details_request_unittest.cc",
diff --git a/components/autofill/core/browser/address_data_cleaner.cc b/components/autofill/core/browser/address_data_cleaner.cc index 0983adc..ba02b667 100644 --- a/components/autofill/core/browser/address_data_cleaner.cc +++ b/components/autofill/core/browser/address_data_cleaner.cc
@@ -48,96 +48,61 @@ should_wait(syncer::ModelType::CONTACT_INFO); } -// Goes through all the `existing_profiles` and merges all similar profiles -// together. All the profiles except the results of the merges will be added to -// `profile_guids_to_delete`. -// Comparisons are done using `comparator`. -void DeduplicateProfiles( - const AutofillProfileComparator comparator, - std::vector<std::unique_ptr<AutofillProfile>>& existing_profiles, - std::set<std::string>& profiles_to_delete) { - autofill_metrics::LogNumberOfProfilesConsideredForDedupe( - existing_profiles.size()); +// - Merges local profiles occurring earlier in `profiles` with mergeable other +// local profiles later in `profiles`, marking the earlier one as deletable. +// - Marks local profiles that are subsets of account profiles as deletable. +// Mergability is determined using `comparator`. +// The elements of `profiles` are updated and potentially reordered. +void DeduplicateProfiles(const AutofillProfileComparator& comparator, + std::vector<AutofillProfile>& profiles, + std::set<std::string>& profiles_to_delete) { + autofill_metrics::LogNumberOfProfilesConsideredForDedupe(profiles.size()); - // Sort the profiles by ranking score. That way the most relevant profiles - // will get merged into the less relevant profiles, which keeps the syntax of - // the most relevant profiles data. - // Since profiles earlier in the list are merged into profiles later in the - // list, `kLocalOrSyncable` profiles are placed before `kAccount` profiles. - // This is because local profiles can be merged into account profiles, but not - // the other way around. - // TODO(crbug.com/1411114): Remove code duplication for sorting profiles. - base::ranges::sort( - existing_profiles, [comparison_time = AutofillClock::Now()]( - const std::unique_ptr<AutofillProfile>& a, - const std::unique_ptr<AutofillProfile>& b) { - if (a->source() != b->source()) { - return a->source() == AutofillProfile::Source::kLocalOrSyncable; - } - return a->HasGreaterRankingThan(b.get(), comparison_time); + // Partition the profiles into local and account profiles: + // - Local: [profiles.begin(), bgn_account_profiles[ + // - Account: [bgn_account_profiles, profiles.end()[ + auto bgn_account_profiles = + base::ranges::stable_partition(profiles, [](const AutofillProfile& p) { + return p.source() == AutofillProfile::Source::kLocalOrSyncable; }); - for (auto i = existing_profiles.begin(); i != existing_profiles.end(); ++i) { - AutofillProfile* profile_to_merge = i->get(); - - // If the profile was set to be deleted, skip it. This can happen because - // the loop below reassigns `profile_to_merge` to (effectively) `j->get()`. - if (profiles_to_delete.contains(profile_to_merge->guid())) { - continue; - } - - // Profiles in the account storage should not be silently deleted. - if (profile_to_merge->source() == AutofillProfile::Source::kAccount) { - continue; - } - - // Try to merge `profile_to_merge` with a less relevant `existing_profiles`. - for (auto j = i + 1; j < existing_profiles.end(); ++j) { - AutofillProfile& existing_profile = **j; - - // Don't try to merge a profile that was already set for deletion or that - // cannot be merged. - if (profiles_to_delete.contains(existing_profile.guid()) || - !comparator.AreMergeable(existing_profile, *profile_to_merge)) { - continue; - } - - // No new information should silently be introduced to the account - // storage. So for account profiles, only merge if the `kLocalOrSyncable` - // `profile_to_merge` is a subset. - if (existing_profile.source() == AutofillProfile::Source::kAccount && - !profile_to_merge->IsSubsetOf(comparator, existing_profile)) { - continue; - } - - // The profiles are found to be mergeable; update the existing profile. - existing_profile.MergeDataFrom(*profile_to_merge, + for (auto local_profile_it = profiles.begin(); + local_profile_it != bgn_account_profiles; ++local_profile_it) { + // If possible, merge `*local_profile_it` with another local profile and + // remove it. + if (auto merge_candidate = base::ranges::find_if( + local_profile_it + 1, bgn_account_profiles, + [&](const AutofillProfile& local_profile2) { + return comparator.AreMergeable(*local_profile_it, local_profile2); + }); + merge_candidate != bgn_account_profiles) { + merge_candidate->MergeDataFrom(*local_profile_it, comparator.app_locale()); - profiles_to_delete.insert(profile_to_merge->guid()); - + profiles_to_delete.insert(local_profile_it->guid()); + continue; + } + // `*local_profile_it` is not mergeable with another local profile. But it + // might be a subset of an account profile and can thus be removed. + if (auto superset_account_profile = base::ranges::find_if( + bgn_account_profiles, profiles.end(), + [&](const AutofillProfile& account_profile) { + return comparator.AreMergeable(*local_profile_it, + account_profile) && + local_profile_it->IsSubsetOf(comparator, account_profile); + }); + superset_account_profile != profiles.end()) { + profiles_to_delete.insert(local_profile_it->guid()); // Account profiles track from which service they originate. This allows // Autofill to distinguish between Chrome and non-Chrome account // profiles and measure the added utility of non-Chrome profiles. Since - // the `existing_profile` matched the information that was already - // present in Autofill (`profile_to_merge`), the account profile doesn't + // the `superset_account_profile` matched the information that was already + // present in Autofill (`*local_profile_it`), the account profile doesn't // provide any utility. To capture this in the metric, the merged // profile is treated as a Chrome account profile. - if (existing_profile.source() == AutofillProfile::Source::kAccount) { - existing_profile.set_initial_creator_id( - AutofillProfile::kInitialCreatorOrModifierChrome); - existing_profile.set_last_modifier_id( - AutofillProfile::kInitialCreatorOrModifierChrome); - } - - // Now try to merge the new resulting profile with the rest of the - // existing profiles. - profile_to_merge = &existing_profile; - // Account profiles cannot be merged into other profiles, since that - // would delete them. Note that the `existing_profile` (now - // `profile_to_merge`) might be verified. - if (profile_to_merge->source() == AutofillProfile::Source::kAccount) { - break; - } + superset_account_profile->set_initial_creator_id( + AutofillProfile::kInitialCreatorOrModifierChrome); + superset_account_profile->set_last_modifier_id( + AutofillProfile::kInitialCreatorOrModifierChrome); } } autofill_metrics::LogNumberOfProfilesRemovedDuringDedupe( @@ -194,7 +159,8 @@ } const std::vector<AutofillProfile*>& profiles = - personal_data_manager_->GetProfiles(); + personal_data_manager_->GetProfiles( + PersonalDataManager::ProfileOrder::kHighestFrecencyDesc); // Early return to prevent polluting metrics with uninteresting events. if (profiles.size() < 2) { return; @@ -203,21 +169,21 @@ // `profiles` contains pointers to the PDM's state. Modifying them directly // won't update them in the database and calling `PDM:UpdateProfile()` // would discard them as a duplicate. - std::vector<std::unique_ptr<AutofillProfile>> new_profiles; + std::vector<AutofillProfile> deduplicated_profiles; for (const AutofillProfile* profile : profiles) { - new_profiles.push_back(std::make_unique<AutofillProfile>(*profile)); + deduplicated_profiles.push_back(*profile); } std::set<std::string> profiles_to_delete; DeduplicateProfiles( AutofillProfileComparator(personal_data_manager_->app_locale()), - new_profiles, profiles_to_delete); + deduplicated_profiles, profiles_to_delete); // Apply the profile changes to the database. - for (const std::unique_ptr<AutofillProfile>& profile : new_profiles) { - if (profiles_to_delete.contains(profile->guid())) { - personal_data_manager_->RemoveByGUID(profile->guid()); + for (const AutofillProfile& profile : deduplicated_profiles) { + if (profiles_to_delete.contains(profile.guid())) { + personal_data_manager_->RemoveByGUID(profile.guid()); } else { - personal_data_manager_->UpdateProfile(*profile); + personal_data_manager_->UpdateProfile(profile); } } } @@ -253,7 +219,7 @@ // After sync has started, it's possible that the PDM is still reloading any // changed data from the database. In this case, delay the cleanups slightly // longer until `OnPersonalDataFinishedProfileTasks()` is called. - if (!personal_data_manager_->IsAwaitingPendingChanges()) { + if (!personal_data_manager_->IsAwaitingPendingAddressChanges()) { MaybeCleanupAddressData(); } }
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc index 7786c630..734796c 100644 --- a/components/autofill/core/browser/autofill_external_delegate.cc +++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -133,7 +133,6 @@ case PopupItemId::kVirtualCreditCardEntry: return true; case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kAllSavedPasswordsEntry: case PopupItemId::kAutocompleteEntry: case PopupItemId::kAutofillOptions: @@ -160,7 +159,6 @@ case PopupItemId::kSeePromoCodeDetails: case PopupItemId::kSeparator: case PopupItemId::kShowAccountCards: - case PopupItemId::kUsernameEntry: case PopupItemId::kWebauthnCredential: case PopupItemId::kWebauthnSignInWithAnotherDevice: return false; @@ -407,9 +405,7 @@ break; case PopupItemId::kSeparator: case PopupItemId::kPasswordEntry: - case PopupItemId::kUsernameEntry: case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kAllSavedPasswordsEntry: case PopupItemId::kPasswordAccountStorageEmpty: case PopupItemId::kGeneratePasswordEntry: @@ -701,9 +697,7 @@ break; case PopupItemId::kSeparator: case PopupItemId::kPasswordEntry: - case PopupItemId::kUsernameEntry: case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kAllSavedPasswordsEntry: case PopupItemId::kPasswordAccountStorageEmpty: case PopupItemId::kGeneratePasswordEntry: @@ -771,14 +765,12 @@ case PopupItemId::kVirtualCreditCardEntry: case PopupItemId::kIbanEntry: case PopupItemId::kPasswordEntry: - case PopupItemId::kUsernameEntry: case PopupItemId::kAllSavedPasswordsEntry: case PopupItemId::kGeneratePasswordEntry: case PopupItemId::kShowAccountCards: case PopupItemId::kPasswordAccountStorageOptIn: case PopupItemId::kPasswordAccountStorageOptInAndGenerate: case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kPasswordAccountStorageReSignin: case PopupItemId::kPasswordAccountStorageEmpty: case PopupItemId::kCompose:
diff --git a/components/autofill/core/browser/autofill_form_test_utils.cc b/components/autofill/core/browser/autofill_form_test_utils.cc index 31b84a0..87271cfb 100644 --- a/components/autofill/core/browser/autofill_form_test_utils.cc +++ b/components/autofill/core/browser/autofill_form_test_utils.cc
@@ -127,6 +127,7 @@ ff.origin = dd.origin.value_or(f.main_frame_origin); ff.should_autocomplete = dd.should_autocomplete; ff.properties_mask = dd.properties_mask; + ff.check_status = dd.check_status; f.fields.push_back(ff); } return f;
diff --git a/components/autofill/core/browser/autofill_form_test_utils.h b/components/autofill/core/browser/autofill_form_test_utils.h index ba56259..75229869 100644 --- a/components/autofill/core/browser/autofill_form_test_utils.h +++ b/components/autofill/core/browser/autofill_form_test_utils.h
@@ -59,6 +59,8 @@ std::optional<url::Origin> origin; std::vector<SelectOption> select_options = {}; FieldPropertiesMask properties_mask = 0; + FormFieldData::CheckStatus check_status = + FormFieldData::CheckStatus::kNotCheckable; }; // Attributes provided to the test form.
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc index ef939b91..a652101 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
@@ -64,24 +64,6 @@ constexpr auto kDefaultTriggerSource = AutofillSuggestionTriggerSource::kFormControlElementClicked; -Matcher<Suggestion> EqualsSuggestion(PopupItemId id) { - return Field(&Suggestion::popup_item_id, id); -} - -Matcher<Suggestion> EqualsSuggestion(PopupItemId id, - const std::u16string& main_text) { - return AllOf( - Field(&Suggestion::popup_item_id, id), - Field(&Suggestion::main_text, - Suggestion::Text(main_text, Suggestion::Text::IsPrimary(true)))); -} - -Matcher<Suggestion> EqualsSuggestion(PopupItemId id, - const std::u16string& main_text, - Suggestion::Icon icon) { - return AllOf(EqualsSuggestion(id, main_text), Field(&Suggestion::icon, icon)); -} - Matcher<Suggestion> EqualsFieldByFieldFillingSuggestion( PopupItemId id, const std::u16string& main_text,
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index 099adb5..2a92eb4 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -235,7 +235,6 @@ case PopupItemId::kIbanEntry: return FillDataType::kSingleFieldFormFillerIban; case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kAddressEntry: case PopupItemId::kAllSavedPasswordsEntry: case PopupItemId::kAutofillOptions: @@ -266,7 +265,6 @@ case PopupItemId::kSeePromoCodeDetails: case PopupItemId::kSeparator: case PopupItemId::kShowAccountCards: - case PopupItemId::kUsernameEntry: case PopupItemId::kVirtualCreditCardEntry: case PopupItemId::kWebauthnCredential: case PopupItemId::kWebauthnSignInWithAnotherDevice:
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc index 353e3b9..0b37a40 100644 --- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc +++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -512,13 +512,6 @@ return profile; } -CreditCard FillDataToCreditCardInfo(const TestCardFillData& data) { - CreditCard card; - test::SetCreditCardInfo(&card, data.name_on_card, data.card_number, - data.expiration_month, data.expiration_year, "1"); - return card; -} - void ExpectFilledField(const char* expected_label, const char* expected_name, const char* expected_value, @@ -675,7 +668,7 @@ // Advance the mock clock to a fixed, arbitrary, somewhat recent date. base::Time year2020; ASSERT_TRUE(base::Time::FromString("01/01/20", &year2020)); - task_environment_.FastForwardBy(year2020 - base::Time::Now()); + task_environment_.FastForwardBy(year2020 - AutofillClock::Now()); autofill_client_.SetPrefs(test::PrefServiceForTesting()); personal_data().set_auto_accept_address_imports_for_testing(true); @@ -1205,7 +1198,7 @@ AutofillProfile profile1 = FillDataToAutofillProfile(GetElvisAddressFillData()); profile1.set_guid(kElvisProfileGuid); - profile1.set_use_date(base::Time::Now() - base::Days(2)); + profile1.set_use_date(AutofillClock::Now() - base::Days(2)); personal_data().AddProfile(profile1); AutofillProfile profile2( @@ -1214,7 +1207,7 @@ "buddy@gmail.com", "Decca", "123 Apple St.", "unit 6", "Lubbock", "Texas", "79401", "US", "23456789012"); profile2.set_guid(MakeGuid(2)); - profile2.set_use_date(base::Time::Now() - base::Days(1)); + profile2.set_use_date(AutofillClock::Now() - base::Days(1)); personal_data().AddProfile(profile2); AutofillProfile profile3( @@ -1222,7 +1215,7 @@ test::SetProfileInfo(&profile3, "", "", "", "", "", "", "", "", "", "", "", ""); profile3.set_guid(MakeGuid(3)); - profile3.set_use_date(base::Time::Now()); + profile3.set_use_date(AutofillClock::Now()); personal_data().AddProfile(profile3); } @@ -1347,34 +1340,6 @@ 0 /* FORMS_LOADED */, 2); } -// Tests that only fields from `field_types_to_fill` are filled. -TEST_F(BrowserAutofillManagerTest, - FillingDetails_FieldTypesToFill_FillOnlySpecificFields) { - base::test::ScopedFeatureList enabled_features( - features::kAutofillGranularFillingAvailable); - // Set up our form data. - FormData form = test::GetFormData( - {.fields = { - {.role = NAME_FIRST, .autocomplete_attribute = "given-name"}, - {.role = NAME_LAST, .autocomplete_attribute = "family-name"}}}); - FormsSeen({form}); - // Only `NAME_FIRST` fields should be filled. - FieldTypeSet target_fields = FieldTypeSet({NAME_FIRST}); - FormData response_data = FillAutofillFormDataAndGetResults( - form, form.fields[0], MakeGuid(1), - {.trigger_source = AutofillTriggerSource::kPopup, - .field_types_to_fill = target_fields}); - - ASSERT_EQ(response_data.fields.size(), 2u); - // The city field was filled. - EXPECT_EQ(response_data.fields[0].name, u"firstName"); - EXPECT_EQ(response_data.fields[0].value, - UTF8ToUTF16(GetElvisAddressFillData().first)); - // The city field was NOT filled. - EXPECT_EQ(response_data.fields[1].name, u"lastName"); - EXPECT_EQ(response_data.fields[1].value, u""); -} - // Test that when forms are seen, the renderer is updated with the predicted // field types TEST_F(BrowserAutofillManagerTest, @@ -1684,45 +1649,6 @@ AutofillSuggestionGenerator::CreateManageAddressesEntry()}); } -// Test that the call is properly forwarded to its SingleFieldFormFillRouter. -TEST_F(BrowserAutofillManagerTest, OnSingleFieldSuggestionSelected) { - std::u16string test_value = u"TestValue"; - FormData form = CreateTestAddressFormData(); - FormFieldData field = form.fields[0]; - - EXPECT_CALL(single_field_form_fill_router(), - OnSingleFieldSuggestionSelected(test_value, - PopupItemId::kAutocompleteEntry)) - .Times(1); - - browser_autofill_manager_->OnSingleFieldSuggestionSelected( - test_value, PopupItemId::kAutocompleteEntry, form, field); - - EXPECT_CALL(single_field_form_fill_router(), - OnSingleFieldSuggestionSelected(test_value, - PopupItemId::kAutocompleteEntry)) - .Times(1); - - browser_autofill_manager_->OnSingleFieldSuggestionSelected( - test_value, PopupItemId::kAutocompleteEntry, form, field); - - EXPECT_CALL( - single_field_form_fill_router(), - OnSingleFieldSuggestionSelected(test_value, PopupItemId::kIbanEntry)) - .Times(1); - - browser_autofill_manager_->OnSingleFieldSuggestionSelected( - test_value, PopupItemId::kIbanEntry, form, field); - - EXPECT_CALL(single_field_form_fill_router(), - OnSingleFieldSuggestionSelected( - test_value, PopupItemId::kMerchantPromoCodeEntry)) - .Times(1); - - browser_autofill_manager_->OnSingleFieldSuggestionSelected( - test_value, PopupItemId::kMerchantPromoCodeEntry, form, field); -} - // Tests that BrowserAutofillManager correctly returns virtual cards with usage // data and VCN last four for a standalone cvc field. TEST_F(BrowserAutofillManagerTest, GetVirtualCreditCardsForStandaloneCvcField) { @@ -1813,7 +1739,7 @@ // letter for last name. AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); profile1.set_guid(MakeGuid(103)); - profile1.set_use_date(base::Time::Now() - base::Days(2)); + profile1.set_use_date(AutofillClock::Now() - base::Days(2)); profile1.SetInfo(NAME_FIRST, u"Robin", "en-US"); profile1.SetInfo(NAME_LAST, u"Grimes", "en-US"); profile1.SetInfo(ADDRESS_HOME_LINE1, u"1234 Smith Blvd.", "en-US"); @@ -1821,7 +1747,7 @@ AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); profile2.set_guid(MakeGuid(124)); - profile2.set_use_date(base::Time::Now() - base::Days(1)); + profile2.set_use_date(AutofillClock::Now() - base::Days(1)); profile2.SetInfo(NAME_FIRST, u"Carl", "en-US"); profile2.SetInfo(NAME_LAST, u"Grimes", "en-US"); profile2.SetInfo(ADDRESS_HOME_LINE1, u"1234 Smith Blvd.", "en-US"); @@ -1829,7 +1755,7 @@ AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); profile3.set_guid(MakeGuid(126)); - profile3.set_use_date(base::Time::Now()); + profile3.set_use_date(AutofillClock::Now()); profile3.SetInfo(NAME_FIRST, u"Aaron", "en-US"); profile3.SetInfo(NAME_LAST, u"Googler", "en-US"); profile3.SetInfo(ADDRESS_HOME_LINE1, u"1600 Amphitheater pkwy", "en-US"); @@ -2658,7 +2584,7 @@ "378282246310005" /* American Express */, "04", "2910", "1"); credit_card0.set_guid(MakeGuid(1)); - credit_card0.set_use_date(base::Time::Now() - base::Days(1)); + credit_card0.set_use_date(AutofillClock::Now() - base::Days(1)); personal_data().AddCreditCard(credit_card0); CreditCard credit_card1("1141084B-72D7-4B73-90CF-3D6AC154673B", @@ -2797,415 +2723,6 @@ EXPECT_TRUE(external_delegate()->on_suggestions_returned_seen()); } -// Test that the correct section is filled. -TEST_F(BrowserAutofillManagerTest, FillTriggeredSection) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - size_t index_of_trigger_field = form.fields.size(); - base::ranges::move(CreateTestAddressFormData().fields, - std::back_inserter(form.fields)); - FormsSeen({form}); - - // Check that the form has been parsed into two sections. - ASSERT_NE(form.fields.size(), 0u); - ASSERT_EQ(index_of_trigger_field, form.fields.size() / 2); - { - FormStructure* form_structure; - AutofillField* autofill_field; - bool found = browser_autofill_manager_->GetCachedFormAndField( - form, form.fields[index_of_trigger_field], &form_structure, - &autofill_field); - ASSERT_TRUE(found); - for (size_t i = 0; i < form.fields.size() / 2; ++i) { - size_t j = form.fields.size() / 2 + i; - ASSERT_EQ(form_structure->field(i)->name, form_structure->field(j)->name); - ASSERT_NE(form_structure->field(i)->section, - form_structure->field(j)->section); - ASSERT_TRUE(form_structure->field(i)->SameFieldAs(form.fields[j])); - ASSERT_TRUE(form_structure->field(j)->SameFieldAs(form.fields[i])); - } - } - - AutofillProfile* profile = personal_data().GetProfileByGUID(MakeGuid(1)); - ASSERT_TRUE(profile); - EXPECT_EQ(1U, profile->use_count()); - EXPECT_NE(base::Time(), profile->use_date()); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, form.fields[index_of_trigger_field], MakeGuid(1)); - // Extract the sections into individual forms to reduce boiler plate code. - size_t mid = response_data.fields.size() / 2; - FormData section1 = response_data; - FormData section2 = response_data; - section1.fields.erase(section1.fields.begin() + mid, section1.fields.end()); - section2.fields.erase(section2.fields.begin(), section2.fields.end() - mid); - // First section should be empty, second should be filled. - ExpectFilledForm(section1, kEmptyAddressFillData, - /*card_fill_data=*/std::nullopt); - ExpectFilledAddressFormElvis(section2, false); -} - -MATCHER_P(HasValue, value, "") { - return arg.value == value; -} - -// Test that if the form cache is outdated because a field has changed, filling -// is aborted after that field. -TEST_F(BrowserAutofillManagerTest, DoNotFillIfFormFieldChanged) { - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - - FormStructure* form_structure = nullptr; - AutofillField* autofill_field = nullptr; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - - // Modify `form` so that it doesn't match `form_structure` anymore. - ASSERT_GE(form.fields.size(), 3u); - for (auto it = form.fields.begin() + 2; it != form.fields.end(); ++it) - *it = FormFieldData(); - - AutofillProfile* profile = - personal_data().GetProfileByGUID(kElvisProfileGuid); - ASSERT_TRUE(profile); - - FormData response_data; - EXPECT_CALL(*autofill_driver_, ApplyFormAction) - .WillOnce((DoAll(SaveArg<2>(&response_data), - Return(std::vector<FieldGlobalId>{})))); - test_api(*browser_autofill_manager_) - .FillOrPreviewDataModelForm( - mojom::ActionPersistence::kFill, form, form.fields.front(), profile, - /*cvc=*/std::nullopt, form_structure, autofill_field); - std::vector<FormFieldData> filled_fields(response_data.fields.begin(), - response_data.fields.begin() + 2); - std::vector<FormFieldData> skipped_fields(response_data.fields.begin() + 2, - response_data.fields.end()); - - EXPECT_THAT(filled_fields, Each(Not(HasValue(u"")))); - EXPECT_THAT(skipped_fields, Each(HasValue(u""))); -} - -// Test that if the form cache is outdated because the form has changed, filling -// is aborted because of that change. -TEST_F(BrowserAutofillManagerTest, DoNotFillIfFormChanged) { - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - - FormStructure* form_structure = nullptr; - AutofillField* autofill_field = nullptr; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - - // Modify `form` so that it doesn't match `form_structure` anymore. - ASSERT_GE(form.fields.size(), 3u); - form.fields.pop_back(); - - AutofillProfile* profile = - personal_data().GetProfileByGUID(kElvisProfileGuid); - ASSERT_TRUE(profile); - - FormData response_data; - EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); - test_api(*browser_autofill_manager_) - .FillOrPreviewDataModelForm( - mojom::ActionPersistence::kFill, form, form.fields.front(), profile, - /*cvc=*/std::nullopt, form_structure, autofill_field); -} - -TEST_F(BrowserAutofillManagerTest, SkipFillIfFieldIsMeaningfullyPreFilled) { - base::test::ScopedFeatureList placeholders_feature{ - features::kAutofillOverwritePlaceholdersOnly}; - - const FieldType kSkippedType = ADDRESS_HOME_LINE1; - FormData form = test::GetFormData( - {.fields = {{.role = NAME_FIRST, .value = u"Triggering field (filled)"}, - {.role = NAME_LAST, .value = u"Placeholder (filled)"}, - {.role = EMAIL_ADDRESS, .value = u"No data (filled)"}, - {.role = kSkippedType, - .value = u"Meaningfully pre-filled (skipped)"}}}); - FormsSeen({form}); - - FormStructure* form_structure = nullptr; - AutofillField* autofill_field = nullptr; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - form_structure->fields()[0]->set_may_use_prefilled_placeholder(false); - form_structure->fields()[1]->set_may_use_prefilled_placeholder(true); - form_structure->fields()[3]->set_may_use_prefilled_placeholder(false); - - AutofillProfile* profile = - personal_data().GetProfileByGUID(kElvisProfileGuid); - ASSERT_TRUE(profile); - - FormData filled_form; - EXPECT_CALL(*autofill_driver_, ApplyFormAction) - .WillOnce((DoAll(SaveArg<2>(&filled_form), - Return(std::vector<FieldGlobalId>{})))); - test_api(*browser_autofill_manager_) - .FillOrPreviewDataModelForm( - mojom::ActionPersistence::kFill, form, form.fields.front(), profile, - /*cvc=*/std::nullopt, form_structure, autofill_field); - - auto expect_hash = [&](const FormFieldData& field, - std::optional<size_t> expected_hash) { - AutofillField* autofill_field = nullptr; - FormStructure* form_structure = nullptr; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, field, &form_structure, &autofill_field)); - ASSERT_TRUE(autofill_field); - EXPECT_THAT( - autofill_field->field_log_events(), - Contains(VariantWith<FillFieldLogEvent>(Field( - "value_that_would_have_been_filled_in_a_prefilled_field_hash", - &FillFieldLogEvent:: - value_that_would_have_been_filled_in_a_prefilled_field_hash, - testing::Conditional(expected_hash.has_value(), - testing::Optional(expected_hash), - Eq(std::nullopt)))))); - }; - - const auto& filled_fields = filled_form.fields; - EXPECT_TRUE(filled_fields[0].is_autofilled); - EXPECT_EQ(filled_fields[0].value, profile->GetRawInfo(NAME_FIRST)); - expect_hash(filled_fields[0], std::nullopt); - EXPECT_TRUE(filled_fields[1].is_autofilled); - EXPECT_EQ(filled_fields[1].value, profile->GetRawInfo(NAME_LAST)); - expect_hash(filled_fields[1], std::nullopt); - EXPECT_TRUE(filled_fields[2].is_autofilled); - EXPECT_EQ(filled_fields[2].value, profile->GetRawInfo(EMAIL_ADDRESS)); - expect_hash(filled_fields[2], std::nullopt); - EXPECT_FALSE(filled_fields[3].is_autofilled); - EXPECT_EQ(filled_fields[3].value, form.fields[3].value); - expect_hash( - filled_fields[3], - base::FastHash(base::UTF16ToUTF8(profile->GetRawInfo(kSkippedType)))); -} - -TEST_F(BrowserAutofillManagerTest, - SkipAllPreFilledFieldsExceptIfFieldIsAPlaceholder) { - base::test::ScopedFeatureList placeholders_features; - placeholders_features.InitWithFeatures( - {features::kAutofillOverwritePlaceholdersOnly, - features::kAutofillSkipPreFilledFields}, - {}); - - AutofillProfile* profile = - personal_data().GetProfileByGUID(kElvisProfileGuid); - ASSERT_TRUE(profile); - const std::u16string kToBeFilledState = - profile->GetRawInfo(ADDRESS_HOME_STATE); - const std::u16string kSelectedState = u"NC (filled)"; - FormData form = test::GetFormData( - {.fields = { - {.role = NAME_FIRST, .value = u"Triggering field (filled)"}, - {.role = NAME_LAST, .value = u"Placeholder (filled)"}, - {.role = EMAIL_ADDRESS, .value = u"No data (skipped)"}, - {.role = ADDRESS_HOME_LINE1, .value = u"No placeholder (skipped)"}, - {.role = ADDRESS_HOME_STATE, - .value = kSelectedState, - .form_control_type = FormControlType::kSelectOne, - .select_options = {SelectOption{.value = kSelectedState, - .content = kSelectedState}, - SelectOption{.value = kToBeFilledState, - .content = kToBeFilledState}}}}}); - FormsSeen({form}); - - FormStructure* form_structure = nullptr; - AutofillField* autofill_field = nullptr; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - form_structure->fields()[0]->set_may_use_prefilled_placeholder(true); - form_structure->fields()[1]->set_may_use_prefilled_placeholder(true); - form_structure->fields()[3]->set_may_use_prefilled_placeholder(false); - form_structure->fields()[4]->set_may_use_prefilled_placeholder(std::nullopt); - - FormData filled_form; - EXPECT_CALL(*autofill_driver_, ApplyFormAction) - .WillOnce((DoAll(SaveArg<2>(&filled_form), - Return(std::vector<FieldGlobalId>{})))); - test_api(*browser_autofill_manager_) - .FillOrPreviewDataModelForm( - mojom::ActionPersistence::kFill, form, form.fields.front(), profile, - /*cvc=*/std::nullopt, form_structure, autofill_field); - - const auto& filled_fields = filled_form.fields; - EXPECT_TRUE(filled_fields[0].is_autofilled); - EXPECT_EQ(filled_fields[0].value, profile->GetRawInfo(NAME_FIRST)); - EXPECT_TRUE(filled_fields[1].is_autofilled); - EXPECT_EQ(filled_fields[1].value, profile->GetRawInfo(NAME_LAST)); - EXPECT_FALSE(filled_fields[2].is_autofilled); - EXPECT_EQ(filled_fields[2].value, form.fields[2].value); - EXPECT_FALSE(filled_fields[3].is_autofilled); - EXPECT_EQ(filled_fields[3].value, form.fields[3].value); - EXPECT_TRUE(filled_fields[4].is_autofilled); - EXPECT_EQ(filled_fields[4].value, kToBeFilledState); -} - -TEST_F(BrowserAutofillManagerTest, OnlySkipRefillIfFieldIsPreFilled) { - base::test::ScopedFeatureList placeholders_features; - placeholders_features.InitWithFeatures( - {features::kAutofillOverwritePlaceholdersOnly, - features::kAutofillSkipPreFilledFields}, - {}); - - const std::string kCreditCardGuid = MakeGuid(4); - TestCardFillData card_fill_data = kElvisCardFillData; - card_fill_data.card_number = "Pre-filled (skipped)"; - card_fill_data.use_month_type = true; - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); - form.fields[1].value = base::UTF8ToUTF16(card_fill_data.card_number); - - FormsSeen({form}); - FormData first_filled_form = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), kCreditCardGuid); - - ExpectFilledForm(first_filled_form, /*address_fill_data=*/std::nullopt, - card_fill_data); - - // Prepare intercepting the filling operation to the driver and capture - // the re-filled form data. - FormData refilled_form; - EXPECT_CALL(*autofill_driver_, ApplyFormAction) - .Times(1) - .WillOnce(DoAll(SaveArg<2>(&refilled_form), - Return(std::vector<FieldGlobalId>{}))); - - // Simulate that JavaScript modifies the expiration date field. - FormData form_after_js_modification = first_filled_form; - form_after_js_modification.fields[2].value = u"04 / 29"; - browser_autofill_manager_->OnJavaScriptChangedAutofilledValue( - form_after_js_modification, form_after_js_modification.fields[2], - u"04/2999"); - - testing::Mock::VerifyAndClearExpectations(autofill_driver_.get()); - - ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", - FormControlType::kInputText, refilled_form.fields[0]); - ExpectFilledField("Card Number", "cardnumber", card_fill_data.card_number, - FormControlType::kInputText, refilled_form.fields[1]); - ExpectFilledField("Expiration Date", "ccmonth", "04 / 99", - FormControlType::kInputMonth, refilled_form.fields[2]); - ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, - refilled_form.fields[3]); -} - -TEST_F(BrowserAutofillManagerTest, UndoSavesFormFillingData) { - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - FormStructure* form_structure; - AutofillField* autofill_field; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - - base::flat_set<FieldGlobalId> safe_fields{form.fields.front().global_id()}; - EXPECT_CALL(*autofill_driver_, ApplyFormAction) - .Times(2) - .WillRepeatedly(Return(safe_fields)); - - test_api(*browser_autofill_manager_) - .FillOrPreviewDataModelForm( - mojom::ActionPersistence::kFill, form, form.fields.front(), - personal_data().GetProfiles().front(), /*cvc=*/std::nullopt, - form_structure, autofill_field); - - // Undo early returns if it has no filling history for the trigger field, - // which is initially empty, therefore calling the driver is proof that data - // was successfully stored. - browser_autofill_manager_->UndoAutofill(mojom::ActionPersistence::kFill, form, - form.fields.front()); -} - -TEST_F(BrowserAutofillManagerTest, UndoSavesFieldByFieldFillingData) { - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - FormStructure* form_structure; - AutofillField* autofill_field; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - - EXPECT_CALL(*autofill_driver_, ApplyFieldAction); - browser_autofill_manager_->FillOrPreviewField( - mojom::ActionPersistence::kFill, mojom::TextReplacement::kReplaceAll, - form, form.fields.front(), u"Test Value", - PopupItemId::kAddressFieldByFieldFilling); - - // Undo early returns if it has no filling history for the trigger field, - // which is initially empty, therefore calling the driver is proof that data - // was successfully stored. - EXPECT_CALL(*autofill_driver_, ApplyFormAction); - browser_autofill_manager_->UndoAutofill(mojom::ActionPersistence::kFill, form, - form.fields.front()); -} - -TEST_F(BrowserAutofillManagerTest, UndoResetsCachedAutofillState) { - FormData form = CreateTestAddressFormData(); - AutofillField filled_autofill_field(form.fields.front()); - - FormFieldData* field_ptr = &form.fields.front(); - AutofillField* autofill_field_ptr = &filled_autofill_field; - form.fields.front().is_autofilled = false; - test_api(*browser_autofill_manager_) - .AddFormFillEntry(base::make_span(&field_ptr, 1u), - base::make_span(&autofill_field_ptr, 1u), - FillingProduct::kAddress, /*is_refill=*/false); - form.fields.front().is_autofilled = true; - FormsSeen({form}); - - FormStructure* form_structure; - AutofillField* autofill_field; - base::flat_set<FieldGlobalId> safe_fields{form.fields.front().global_id()}; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - ASSERT_TRUE(autofill_field->is_autofilled); - - browser_autofill_manager_->UndoAutofill(mojom::ActionPersistence::kFill, form, - form.fields.front()); - - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - EXPECT_FALSE(autofill_field->is_autofilled); -} - -TEST_F(BrowserAutofillManagerTest, - FillOrPreviewDataModelFormCallsDidFillOrPreviewForm) { - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); - FormsSeen({form}); - FormStructure* form_structure; - AutofillField* autofill_field; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - EXPECT_CALL(autofill_client_, DidFillOrPreviewForm); - test_api(*browser_autofill_manager_) - .FillOrPreviewDataModelForm( - mojom::ActionPersistence::kFill, form, form.fields.front(), - personal_data().GetCreditCards()[0], /*cvc=*/std::nullopt, - form_structure, autofill_field); -} - -// Test that if the form cache is outdated because a field was removed, filling -// is aborted. -TEST_F(BrowserAutofillManagerTest, DoNotFillIfFormFieldRemoved) { - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - - FormStructure* form_structure = nullptr; - AutofillField* autofill_field = nullptr; - ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( - form, form.fields.front(), &form_structure, &autofill_field)); - - // Modify |form| so that it doesn't match |form_structure| anymore. - ASSERT_GE(form.fields.size(), 2u); - form.fields.pop_back(); - - AutofillProfile* profile = personal_data().GetProfileByGUID(MakeGuid(1)); - ASSERT_TRUE(profile); - - EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); -} - // Tests that BrowserAutofillManager ignores loss of focus events sent from the // renderer if the renderer did not have a previously-interacted form. // TODO(crbug.com/1140473): Remove this test when workaround is no longer @@ -3661,96 +3178,6 @@ AutofillSuggestionGenerator::CreateManageAddressesEntry()}); } -// Test that we correctly fill an address form. -TEST_F(BrowserAutofillManagerTest, FillAddressForm) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - - AutofillProfile* profile = personal_data().GetProfileByGUID(MakeGuid(1)); - ASSERT_TRUE(profile); - EXPECT_EQ(1U, profile->use_count()); - const base::Time last_used_date = AutofillClock::Now() - base::Hours(1); - profile->set_use_date(last_used_date); - - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - ExpectFilledAddressFormElvis(response_data, false); - - EXPECT_EQ(2U, profile->use_count()); - EXPECT_LT(last_used_date, profile->use_date()); -} - -// Tests that `ProfileTokenQuality` is correctly integrated into -// `AutofillProfile` and that on form submit, observations are collected. -TEST_F(BrowserAutofillManagerTest, FillAddressForm_CollectObservations) { - base::test::ScopedFeatureList profile_token_quality_feature{ - features::kAutofillTrackProfileTokenQuality}; - AutofillProfile* profile = - personal_data().GetProfileByGUID(kElvisProfileGuid); - profile->token_quality().disable_randomization_for_testing(); - - // Create and fill an address form with profile `kElvisProfileGuid`. - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - FormData filled_form = FillAutofillFormDataAndGetResults(form, form.fields[0], - kElvisProfileGuid); - - // Expect that no observations for any of the form's types were collected yet. - FormStructure* form_structure = - browser_autofill_manager_->FindCachedFormById(filled_form.global_id()); - EXPECT_TRUE(base::ranges::all_of( - *form_structure, [&](const std::unique_ptr<AutofillField>& field) { - return profile->token_quality() - .GetObservationTypesForFieldType(field->Type().GetStorableType()) - .empty(); - })); - - // Submit the form and expect observations for all of the form's types. This - // updates the `profile` in `personal_data()`, invalidating the pointer. - FormSubmitted(filled_form); - profile = personal_data().GetProfileByGUID(kElvisProfileGuid); - EXPECT_TRUE(base::ranges::none_of( - *form_structure, [&](const std::unique_ptr<AutofillField>& field) { - return profile->token_quality() - .GetObservationTypesForFieldType(field->Type().GetStorableType()) - .empty(); - })); -} - -// ac=unrecognized fields: -// - Are not filled by default. -// - Are filled through manual fallbacks. -TEST_F(BrowserAutofillManagerTest, AutocompleteUnrecognizedFillingBehavior) { - // Create a form where the middle name field has ac=unrecognized. - FormData form = CreateTestAddressFormData(); - ASSERT_EQ(form.fields[1].name, u"middlename"); - form.fields[1].parsed_autocomplete = - AutocompleteParsingResult{.field_type = HtmlFieldType::kUnrecognized}; - FormsSeen({form}); - - // Fill the `form` regularly and expect that everything but the middle name - // gets filled. - FormData filled_form = FillAutofillFormDataAndGetResults(form, form.fields[0], - kElvisProfileGuid); - TestAddressFillData fill_data = GetElvisAddressFillData(); - fill_data.middle = ""; - ExpectFilledForm(filled_form, fill_data, /*card_fill_data=*/std::nullopt); - - // Fill the `form` as-if through manual fallbacks. Expect that every field - // gets filled. - EXPECT_CALL(*autofill_driver_, ApplyFormAction) - .WillOnce(DoAll(SaveArg<2>(&filled_form), - Return(base::flat_set<FieldGlobalId>{}))); - browser_autofill_manager_->FillOrPreviewProfileForm( - mojom::ActionPersistence::kFill, form, form.fields[0], - *personal_data().GetProfileByGUID(kElvisProfileGuid), - {.trigger_source = AutofillTriggerSource::kManualFallback}); - - ExpectFilledForm(filled_form, GetElvisAddressFillData(), - /*card_fill_data=*/std::nullopt); -} - // Tests that fields with unrecognized autocomplete attribute don't contribute // to key metrics. TEST_F(BrowserAutofillManagerTest, AutocompleteUnrecognizedFields_KeyMetrics) { @@ -3828,1886 +3255,6 @@ testing::Optional(virtual_card.instrument_id())); } -// Test that we correctly log FIELD_WAS_AUTOFILLED event in UserHappiness. -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_LogFieldWasAutofill) { - // Set up our form data. - FormData form; - // Construct a form with a 4 fields: cardholder name, card number, - // expiration date and cvc. - CreateTestCreditCardFormData(&form, true, true); - FormsSeen({form}); - - base::HistogramTester histogram_tester; - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - // Cardholder name, card number, expiration data were autofilled but cvc was - // not be autofilled. - histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard", - AutofillMetrics::FIELD_WAS_AUTOFILLED, 3); -} - -// Test that we correctly fill a credit card form. -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_Simple) { - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); -} - -// Test that whitespace is stripped from the credit card number. -TEST_F(BrowserAutofillManagerTest, - FillCreditCardForm_StripCardNumberWhitespace) { - // Same as the SetUp(), but generate Elvis card with whitespace in credit - // card number. |credit_card| will be owned by the TestPersonalDataManager. - personal_data().ClearCreditCards(); - CreditCard credit_card; - test::SetCreditCardInfo(&credit_card, "Elvis Presley", - "4234 5678 9012 3456", // Visa - "04", "2999", "1"); - credit_card.set_guid(MakeGuid(8)); - personal_data().AddCreditCard(credit_card); - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(8)); - ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); -} - -// Test that separator characters are stripped from the credit card number. -TEST_F(BrowserAutofillManagerTest, - FillCreditCardForm_StripCardNumberSeparators) { - // Same as the SetUp(), but generate Elvis card with separator characters in - // credit card number. |credit_card| will be owned by the - // TestPersonalDataManager. - personal_data().ClearCreditCards(); - CreditCard credit_card; - test::SetCreditCardInfo(&credit_card, "Elvis Presley", - "4234-5678-9012-3456", // Visa - "04", "2999", "1"); - credit_card.set_guid(MakeGuid(9)); - personal_data().AddCreditCard(credit_card); - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(9)); - ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); -} - -// Test that we correctly fill a credit card form with month input type. -// Test 1 of 4: Empty month, empty year -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_NoYearNoMonth) { - personal_data().ClearCreditCards(); - - TestCardFillData card_fill_data = kElvisCardFillData; - card_fill_data.expiration_month = ""; - card_fill_data.expiration_year = ""; - card_fill_data.use_month_type = true; - CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); - - credit_card.set_guid(MakeGuid(7)); - personal_data().AddCreditCard(credit_card); - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(7)); - ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, - card_fill_data); -} - -// Test that we correctly fill a credit card form with month input type. -// Test 2 of 4: Non-empty month, empty year -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_NoYearMonth) { - personal_data().ClearCreditCards(); - TestCardFillData card_fill_data = kElvisCardFillData; - card_fill_data.expiration_month = "04"; - card_fill_data.expiration_year = ""; - card_fill_data.use_month_type = true; - CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); - - credit_card.set_guid(MakeGuid(7)); - personal_data().AddCreditCard(credit_card); - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(7)); - ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, - card_fill_data); -} - -// Test that we correctly fill a credit card form with month input type. -// Test 3 of 4: Empty month, non-empty year -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_YearNoMonth) { - // Same as the SetUp(), but generate 4 credit cards with year month - // combination. - personal_data().ClearCreditCards(); - TestCardFillData card_fill_data = kElvisCardFillData; - card_fill_data.expiration_month = ""; - card_fill_data.expiration_year = "2999"; - card_fill_data.use_month_type = true; - CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); - credit_card.set_guid(MakeGuid(7)); - personal_data().AddCreditCard(credit_card); - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(7)); - ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, - card_fill_data); -} - -// Test that we correctly fill a credit card form with month input type. -// Test 4 of 4: Non-empty month, non-empty year -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_YearMonth) { - personal_data().ClearCreditCards(); - TestCardFillData card_fill_data = kElvisCardFillData; - card_fill_data.expiration_month = "04"; - card_fill_data.expiration_year = "2999"; - card_fill_data.use_month_type = true; - CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); - credit_card.set_guid(MakeGuid(7)); - personal_data().AddCreditCard(credit_card); - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(7)); - ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, - card_fill_data); -} - -// Test that only the first 16 credit card number fields are filled. -TEST_F(BrowserAutofillManagerTest, - FillOnlyFirstNineteenCreditCardNumberFields) { - // Set up our form data. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = {CreateTestFormField("Card Name", "cardname", "", - FormControlType::kInputText), - CreateTestFormField("Last Name", "cardlastname", "", - FormControlType::kInputText)}; - - // Add 20 credit card number fields with distinct names. - for (int i = 0; i < 20; i++) { - std::u16string field_name = u"Card Number " + base::NumberToString16(i + 1); - form.fields.push_back( - CreateTestFormField(base::UTF16ToASCII(field_name).c_str(), - "cardnumber", "", FormControlType::kInputText)); - } - - form.fields.push_back( - CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)); - - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - ExpectFilledField("Card Name", "cardname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Last Name", "cardlastname", "Presley", - FormControlType::kInputText, response_data.fields[1]); - - // Verify that the first 19 credit card number fields are filled. - for (int i = 0; i < 19; i++) { - std::u16string field_name = u"Card Number " + base::NumberToString16(i + 1); - ExpectFilledField(base::UTF16ToASCII(field_name).c_str(), "cardnumber", - "4234567890123456", FormControlType::kInputText, - response_data.fields[2 + i]); - } - - // Verify that the 20th. credit card number field is not filled. - ExpectFilledField("Card Number 20", "cardnumber", "", - FormControlType::kInputText, response_data.fields[21]); - - ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, - response_data.fields[22]); -} - -// Test that only the first 16 of identical fields are filled. -TEST_F(BrowserAutofillManagerTest, - FillOnlyFirstSixteenIdenticalCreditCardNumberFields) { - // Set up our form data. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = {CreateTestFormField("Card Name", "cardname", "", - FormControlType::kInputText), - CreateTestFormField("Last Name", "cardlastname", "", - FormControlType::kInputText)}; - - // Add 20 identical card number fields. - for (int i = 0; i < 20; i++) { - form.fields.push_back(CreateTestFormField("Card Number", "cardnumber", "", - FormControlType::kInputText)); - } - form.fields.push_back( - CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)); - - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - ExpectFilledField("Card Name", "cardname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Last Name", "cardlastname", "Presley", - FormControlType::kInputText, response_data.fields[1]); - - // Verify that the first 19 card number fields are filled. - for (int i = 0; i < 19; i++) { - ExpectFilledField("Card Number", "cardnumber", "4234567890123456", - FormControlType::kInputText, response_data.fields[2 + i]); - } - // Verify that the 20th. card number field is not filled. - ExpectFilledField("Card Number", "cardnumber", "", - FormControlType::kInputText, response_data.fields[21]); - - ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, - response_data.fields[22]); -} - -// Test the credit card number is filled correctly into single-digit fields. -TEST_F(BrowserAutofillManagerTest, FillCreditCardNumberIntoSingleDigitFields) { - // Set up our form data. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = {CreateTestFormField("Card Name", "cardname", "", - FormControlType::kInputText), - CreateTestFormField("Last Name", "cardlastname", "", - FormControlType::kInputText)}; - - // Add 20 identical card number fields. - for (int i = 0; i < 20; i++) { - FormFieldData field = CreateTestFormField("Card Number", "cardnumber", "", - FormControlType::kInputText); - field.host_frame = form.host_frame; - field.host_form_id = form.renderer_id; - field.max_length = i < 19 ? 1 : std::numeric_limits<int>::max(); - form.fields.push_back(std::move(field)); - } - form.fields.push_back( - CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)); - - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - ExpectFilledField("Card Name", "cardname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Last Name", "cardlastname", "Presley", - FormControlType::kInputText, response_data.fields[1]); - - // Verify that the first 19 card number fields are filled. - std::u16string card_number = u"4234567890123456"; - for (unsigned int i = 0; i < 19; i++) { - ExpectFilledField("Card Number", "cardnumber", - i < card_number.length() - ? base::UTF16ToASCII(card_number.substr(i, 1)).c_str() - : "4234567890123456", - FormControlType::kInputText, response_data.fields[2 + i]); - } - - // Verify that the 20th. card number field is contains the full value. - ExpectFilledField("Card Number", "cardnumber", "", - FormControlType::kInputText, response_data.fields[21]); - - ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, - response_data.fields[22]); -} - -// Test that we correctly fill a credit card form with first and last cardholder -// name. -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_SplitName) { - // Set up our form data. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = { - CreateTestFormField("Card Name", "cardname", "", - FormControlType::kInputText), - CreateTestFormField("Last Name", "cardlastname", "", - FormControlType::kInputText), - CreateTestFormField("Card Number", "cardnumber", "", - FormControlType::kInputText), - CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)}; - - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - ExpectFilledField("Card Name", "cardname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Last Name", "cardlastname", "Presley", - FormControlType::kInputText, response_data.fields[1]); - ExpectFilledField("Card Number", "cardnumber", "4234567890123456", - FormControlType::kInputText, response_data.fields[2]); -} - -// Test that only filled selection boxes are counted for the type filling limit. -TEST_F(BrowserAutofillManagerTest, - OnlyCountFilledSelectionBoxesForTypeFillingLimit) { - test::PopulateAlternativeStateNameMapForTesting( - "US", "Tennessee", - {{.canonical_name = "Tennessee", - .abbreviations = {"TN"}, - .alternative_names = {}}}); - // Set up our form data. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = {CreateTestFormField("First Name", "firstname", "", - FormControlType::kInputText), - CreateTestFormField("Middle Name", "middlename", "", - FormControlType::kInputText), - CreateTestFormField("Last Name", "lastname", "", - FormControlType::kInputText), - - // Create a selection box for the state that hat the correct - // entry to be filled with user data. Note, TN is the official - // abbreviation for Tennessee. - CreateTestSelectField("State", "state", "", {"AA", "BB", "TN"}, - {"AA", "BB", "TN"})}; - - // Add 20 selection boxes that can not be filled since the correct entry - // is missing. - for (int i = 0; i < 20; i++) { - form.fields.push_back(CreateTestSelectField( - "State", "state", "", {"AA", "BB", "CC"}, {"AA", "BB", "CC"})); - } - - // Add 20 other selection boxes that should be fillable since the correct - // entry is present. - for (int i = 0; i < 20; i++) { - form.fields.push_back(CreateTestSelectField( - "State", "state", "", {"AA", "BB", "TN"}, {"AA", "BB", "TN"})); - } - - // Create a selection box for the state that hat the correct entry to be - // filled with user data. Note, TN is the official abbreviation for Tennessee. - for (int i = 0; i < 20; ++i) { - form.fields.push_back(CreateTestSelectField( - "Country", "country", "", {"DE", "FR", "US"}, {"DE", "FR", "US"})); - } - - FormsSeen({form}); - - TestAddressFillData profile_info_data = GetElvisAddressFillData(); - profile_info_data.company = "1987"; - AutofillProfile profile = FillDataToAutofillProfile(profile_info_data); - profile.set_guid(MakeGuid(123)); - personal_data().AddProfile(profile); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(123)); - - // Verify the correct filling of the name entries. - ExpectFilledField("First Name", "firstname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Middle Name", "middlename", "Aaron", - FormControlType::kInputText, response_data.fields[1]); - ExpectFilledField("Last Name", "lastname", "Presley", - FormControlType::kInputText, response_data.fields[2]); - - // Verify that the first selection box is correctly filled. - ExpectFilledField("State", "state", "TN", FormControlType::kSelectOne, - response_data.fields[3]); - - // Verify that the next 20 selection boxes are not filled. - for (int i = 0; i < 20; i++) { - ExpectFilledField("State", "state", "", FormControlType::kSelectOne, - response_data.fields[4 + i]); - } - - // Verify that the remaining selection boxes are correctly filled again - // because there's no limit on filling ADDRESS_HOME_STATE fields. - for (int i = 0; i < 20; i++) { - ExpectFilledField("State", "state", "TN", FormControlType::kSelectOne, - response_data.fields[24 + i]); - } - - // Verify that only the first 9 of the remaining selection boxes are - // correctly filled due to the limit on filling ADDRESS_HOME_COUNTRY fields. - for (int i = 0; i < 20; i++) { - ExpectFilledField("Country", "country", i < 9 ? "US" : "", - FormControlType::kSelectOne, - response_data.fields[44 + i]); - } -} - -// Test that we correctly fill a combined address and credit card form. -TEST_F(BrowserAutofillManagerTest, FillAddressAndCreditCardForm) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - CreateTestCreditCardFormData(&form, true, false); - FormsSeen({form}); - - // First fill the address data. - FormData response_data; - { - SCOPED_TRACE("Address"); - response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - ExpectFilledAddressFormElvis(response_data, true); - } - - // Now fill the credit card data. - { - response_data = FillAutofillFormDataAndGetResults(form, form.fields.back(), - MakeGuid(4)); - SCOPED_TRACE("Credit card"); - ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/true); - } -} - -// Test parameter data for tests with a simple structure: Create a form, -// autofill it, check that values have been correctly filled. -struct AutofillSimpleFormCase { - struct FormFieldExpectedData { - const char* label; - const char* name; - const char* value = ""; - }; - - const std::string test_name; - const std::string cc_guid = ""; - const std::string profile_guid = MakeGuid(1); - - const test::FormDescription form_description; - const std::vector<FormFieldExpectedData> expected_form_fields; -}; - -class AutofillSimpleFormTest - : public BrowserAutofillManagerTest, - public ::testing::WithParamInterface<AutofillSimpleFormCase> {}; - -const AutofillSimpleFormCase kAutofillSimpleFormCases[] = { - // Test that a field with an unrecognized autocomplete attribute is not - // filled. - {.test_name = "FillAddressForm_UnrecognizedAttribute", - .form_description = - {.fields = {{.label = u"First name", - .name = u"firstname", - .autocomplete_attribute = "given-name"}, - {.label = u"Middle name", .name = u"middle"}, - {.label = u"Last name", - .name = u"lastname", - .autocomplete_attribute = "unrecognized"}}}, - .expected_form_fields = - {{.label = "First name", .name = "firstname", .value = "Elvis"}, - {.label = "Middle name", .name = "middle", .value = "Aaron"}, - {.label = "Last name", .name = "lastname"}}}, - - // Test that non credit card related fields with the autocomplete attribute - // set to off are filled on all platforms when the feature to autofill all - // addresses is enabled (default). - {.test_name = "FillAddressForm_AutocompleteOffNotRespected", - .form_description = - {.fields = {{.label = u"First name", .name = u"firstname"}, - {.label = u"Middle name", - .name = u"middle", - .should_autocomplete = false}, - {.label = u"Last name", .name = u"lastname"}, - {.label = u"Address Line 1", - .name = u"addr1", - .should_autocomplete = false}}}, - .expected_form_fields = - {{.label = "First name", .name = "firstname", .value = "Elvis"}, - {.label = "Middle name", .name = "middle", .value = "Aaron"}, - {.label = "Last name", .name = "lastname", .value = "Presley"}, - {.label = "Address Line 1", - .name = "addr1", - .value = "3734 Elvis Presley Blvd."}}}, - - // Test that a field with a value equal to it's placeholder attribute is - // filled. - {.test_name = "FillAddressForm_PlaceholderEqualsValue", - .form_description = {.fields = {{.label = u"First name", - .name = u"firstname", - .value = u"First Name", - .placeholder = u"First Name"}, - {.label = u"Middle name", - .name = u"middle", - .value = u"Middle Name", - .placeholder = u"Middle Name"}, - {.label = u"Last name", - .name = u"lastname", - .value = u"Last Name", - .placeholder = u"Last Name"}}}, - .expected_form_fields = - {{.label = "First name", .name = "firstname", .value = "Elvis"}, - {.label = "Middle name", .name = "middle", .value = "Aaron"}, - {.label = "Last name", .name = "lastname", .value = "Presley"}}}, - - // Test that a credit card field with an unrecognized autocomplete attribute - // gets filled. - {.test_name = "FillCreditCardForm_UnrecognizedAttribute", - .cc_guid = MakeGuid(4), - .profile_guid = "", - .form_description = - {.fields = {{.label = u"Name on Card", - .name = u"nameoncard", - .autocomplete_attribute = "cc-name"}, - {.label = u"Card Number", .name = u"cardnumber"}, - {.label = u"Expiration Date", - .name = u"ccmonth", - .autocomplete_attribute = "unrecognized"}}}, - .expected_form_fields = {{.label = "Name on Card", - .name = "nameoncard", - .value = "Elvis Presley"}, - {.label = "Card Number", - .name = "cardnumber", - .value = "4234567890123456"}, - {.label = "Expiration Date", - .name = "ccmonth", - .value = "04/2999"}}}, - -}; - -TEST_P(AutofillSimpleFormTest, FillSimpleForm) { - const AutofillSimpleFormCase& params = GetParam(); - FormData form = test::GetFormData(params.form_description); - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, form.fields[0], - params.cc_guid.empty() ? params.profile_guid : params.cc_guid); - - ASSERT_EQ(response_data.fields.size(), params.expected_form_fields.size()); - for (size_t i = 0; i < response_data.fields.size(); ++i) { - SCOPED_TRACE(params.test_name + ", fields expectations"); - const auto& [label, name, value] = params.expected_form_fields[i]; - ExpectFilledField(label, name, value, FormControlType::kInputText, - response_data.fields[i]); - } -} - -INSTANTIATE_TEST_SUITE_P( - BrowserAutofillManagerTest, - AutofillSimpleFormTest, - ::testing::ValuesIn(kAutofillSimpleFormCases), - [](const ::testing::TestParamInfo<AutofillSimpleFormTest::ParamType>& - info) { return info.param.test_name; }); - -// Test that credit card fields are filled even if they have the autocomplete -// attribute set to off. -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_AutocompleteOff) { - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); - - // Set the autocomplete=off on all fields. - for (FormFieldData field : form.fields) { - field.should_autocomplete = false; - } - - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - - // All fields should be filled. - ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); -} - -// Test that selecting an expired credit card fills everything except the -// expiration date. -TEST_F(BrowserAutofillManagerTest, FillCreditCardForm_ExpiredCard) { - personal_data().ClearCreditCards(); - CreditCard expired_card; - test::SetCreditCardInfo(&expired_card, "Homer Simpson", - "4234567890654321", // Visa - "05", "2000", "1"); - expired_card.set_guid(MakeGuid(9)); - personal_data().AddCreditCard(expired_card); - - // Set up the form data. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - - // Create a credit card form. - std::vector<const char*> kCreditCardTypes = {"Visa", "Mastercard", "AmEx", - "discover"}; - form.fields = { - CreateTestFormField("Name on Card", "nameoncard", "", - FormControlType::kInputText, "cc-name"), - CreateTestSelectField("Card Type", "cardtype", "", "cc-type", - kCreditCardTypes, kCreditCardTypes), - CreateTestFormField("Card Number", "cardnumber", "", - FormControlType::kInputText, "cc-number"), - CreateTestFormField("Expiration Month", "ccmonth", "", - FormControlType::kInputText, "cc-exp-month"), - CreateTestFormField("Expiration Year", "ccyear", "", - FormControlType::kInputText, "cc-exp-year")}; - FormsSeen({form}); - - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(9)); - - // The credit card name, type and number should be filled. - ExpectFilledField("Name on Card", "nameoncard", "Homer Simpson", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Card Type", "cardtype", "Visa", - FormControlType::kSelectOne, response_data.fields[1]); - ExpectFilledField("Card Number", "cardnumber", "4234567890654321", - FormControlType::kInputText, response_data.fields[2]); - - // The expiration month and year should not be filled. - ExpectFilledField("Expiration Month", "ccmonth", "", - FormControlType::kInputText, response_data.fields[3]); - ExpectFilledField("Expiration Year", "ccyear", "", - FormControlType::kInputText, response_data.fields[4]); -} - -TEST_F(BrowserAutofillManagerTest, PreviewCreditCardForm_VirtualCard) { - personal_data().ClearCreditCards(); - CreditCard virtual_card = test::GetVirtualCard(); - personal_data().AddServerCreditCard(virtual_card); - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); - FormsSeen({form}); - - FormData response_data = PreviewVirtualCardDataAndGetResults( - mojom::ActionPersistence::kPreview, form, form.fields[1], virtual_card); - - std::u16string expected_cardholder_name = u"Lorem Ipsum"; - // Virtual card number using obfuscated dots only: Virtual card Mastercard - // ••••4444 - std::u16string expected_card_number = - u"Virtual card Mastercard " + - virtual_card.ObfuscatedNumberWithVisibleLastFourDigits(); - // Virtual card expiration month using obfuscated dots: •• - std::u16string expected_exp_month = - CreditCard::GetMidlineEllipsisPlainDots(/*num_dots=*/2); - // Virtual card expiration year using obfuscated dots: •••• - std::u16string expected_exp_year = - CreditCard::GetMidlineEllipsisPlainDots(/*num_dots=*/4); - // Virtual card cvc using obfuscated dots: ••• - std::u16string expected_cvc = - CreditCard::GetMidlineEllipsisPlainDots(/*num_dots=*/3); - - EXPECT_EQ(response_data.fields[0].value, expected_cardholder_name); - EXPECT_EQ(response_data.fields[1].value, expected_card_number); - EXPECT_EQ(response_data.fields[2].value, expected_exp_month); - EXPECT_EQ(response_data.fields[3].value, expected_exp_year); - EXPECT_EQ(response_data.fields[4].value, expected_cvc); -} - -// Test that unfocusable fields aren't filled, except for <select> fields (but -// not <selectlist> fields). -TEST_F(BrowserAutofillManagerTest, DoNotFillUnfocusableFieldsExceptForSelect) { - // Create a form with both focusable and non-focusable fields. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = { - CreateTestFormField("First Name", "firstname", "", - FormControlType::kInputText), - CreateTestFormField("", "lastname", "", FormControlType::kInputText), - CreateTestFormField("Postal Code", "postal_code", "", - FormControlType::kInputText)}; - form.fields.back().is_focusable = false; - - form.fields.push_back(CreateTestSelectOrSelectListField( - "Country", "country", "", "", {"CA", "US"}, {"Canada", "United States"}, - FormControlType::kSelectList)); - form.fields.back().is_focusable = false; - - form.fields.push_back(CreateTestSelectOrSelectListField( - "Country", "country", "", "", {"CA", "US"}, {"Canada", "United States"}, - FormControlType::kSelectList)); - form.fields.push_back(CreateTestSelectOrSelectListField( - "Country", "country", "", "", {"CA", "US"}, {"Canada", "United States"}, - FormControlType::kSelectOne)); - form.fields.back().is_focusable = false; - - FormsSeen({form}); - - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - - ASSERT_EQ(6U, response_data.fields.size()); - ExpectFilledField("First Name", "firstname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("", "lastname", "Presley", FormControlType::kInputText, - response_data.fields[1]); - ExpectFilledField("Postal Code", "postal_code", "", - FormControlType::kInputText, response_data.fields[2]); - ExpectFilledField("Country", "country", "", FormControlType::kSelectList, - response_data.fields[3]); - ExpectFilledField("Country", "country", "US", FormControlType::kSelectList, - response_data.fields[4]); - ExpectFilledField("Country", "country", "US", FormControlType::kSelectOne, - response_data.fields[5]); -} - -// Test that non-focusable field is ignored while inferring boundaries between -// sections, but not filled. -TEST_F(BrowserAutofillManagerTest, FillFormWithNonFocusableFields) { - bool default_to_city_and_number = - base::FeatureList::IsEnabled(features::kAutofillDefaultToCityAndNumber); - - // Create a form with both focusable and non-focusable fields. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = { - CreateTestFormField("First Name", "firstname", "", - FormControlType::kInputText), - CreateTestFormField("", "lastname", "", FormControlType::kInputText), - CreateTestFormField("", "email", "", FormControlType::kInputText), - CreateTestFormField("Phone Number", "phonenumber", "", - FormControlType::kInputTelephone), - CreateTestFormField("", "email_", "", FormControlType::kInputText)}; - form.fields.back().is_focusable = false; - form.fields.push_back(CreateTestFormField("Country", "country", "", - FormControlType::kInputText)); - - FormsSeen({form}); - - // Fill the form - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - - // All the visible fields should be filled as all the fields belong to the - // same logical section. - ASSERT_EQ(6U, response_data.fields.size()); - ExpectFilledField("First Name", "firstname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("", "lastname", "Presley", FormControlType::kInputText, - response_data.fields[1]); - ExpectFilledField("", "email", "theking@gmail.com", - FormControlType::kInputText, response_data.fields[2]); - ExpectFilledField("Phone Number", "phonenumber", - default_to_city_and_number ? "2345678901" : "12345678901", - FormControlType::kInputTelephone, response_data.fields[3]); - ExpectFilledField("", "email_", "", FormControlType::kInputText, - response_data.fields[4]); - ExpectFilledField("Country", "country", "United States", - FormControlType::kInputText, response_data.fields[5]); -} - -// Test that we correctly fill a form that has multiple logical sections, e.g. -// both a billing and a shipping address. -TEST_F(BrowserAutofillManagerTest, FillFormWithMultipleSections) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - const size_t kAddressFormSize = form.fields.size(); - base::ranges::move(CreateTestAddressFormData().fields, - std::back_inserter(form.fields)); - for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) { - // Make sure the fields have distinct names. - form.fields[i].name = form.fields[i].name + u"_"; - } - FormsSeen({form}); - - // Fill the first section. - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - { - SCOPED_TRACE("Address 1"); - // The second address section should be empty. - ASSERT_EQ(response_data.fields.size(), 2 * kAddressFormSize); - for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) { - EXPECT_EQ(std::u16string(), response_data.fields[i].value); - } - - // The first address section should be filled with Elvis's data. - response_data.fields.resize(kAddressFormSize); - ExpectFilledAddressFormElvis(response_data, false); - } - - // Fill the second section, with the initiating field somewhere in the middle - // of the section. - ASSERT_LT(9U, kAddressFormSize); - response_data = FillAutofillFormDataAndGetResults( - form, form.fields[kAddressFormSize + 9], MakeGuid(1)); - { - SCOPED_TRACE("Address 2"); - ASSERT_EQ(response_data.fields.size(), form.fields.size()); - - // The first address section should be empty. - ASSERT_EQ(response_data.fields.size(), 2 * kAddressFormSize); - for (size_t i = 0; i < kAddressFormSize; ++i) { - EXPECT_EQ(std::u16string(), response_data.fields[i].value); - } - - // The second address section should be filled with Elvis's data. - FormData secondSection = response_data; - secondSection.fields.erase(secondSection.fields.begin(), - secondSection.fields.begin() + kAddressFormSize); - for (size_t i = 0; i < kAddressFormSize; ++i) { - // Restore the expected field names. - std::u16string name = secondSection.fields[i].name; - std::u16string original_name = name.substr(0, name.size() - 1); - secondSection.fields[i].name = original_name; - } - ExpectFilledAddressFormElvis(secondSection, false); - } -} - -// Test that we correctly fill a form that has author-specified sections, which -// might not match our expected section breakdown. -TEST_F(BrowserAutofillManagerTest, FillFormWithAuthorSpecifiedSections) { - // Create a form with a billing section and an unnamed section, interleaved. - // The billing section includes both address and credit card fields. - FormData form; - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = { - CreateTestFormField("", "country", "", FormControlType::kInputText, - "section-billing country"), - CreateTestFormField("", "firstname", "", FormControlType::kInputText, - "given-name"), - CreateTestFormField("", "lastname", "", FormControlType::kInputText, - "family-name"), - CreateTestFormField("", "address", "", FormControlType::kInputText, - "section-billing address-line1"), - CreateTestFormField("", "city", "", FormControlType::kInputText, - "section-billing locality"), - CreateTestFormField("", "state", "", FormControlType::kInputText, - "section-billing region"), - CreateTestFormField("", "zip", "", FormControlType::kInputText, - "section-billing postal-code"), - CreateTestFormField("", "ccname", "", FormControlType::kInputText, - "section-billing cc-name"), - CreateTestFormField("", "ccnumber", "", FormControlType::kInputText, - "section-billing cc-number"), - CreateTestFormField("", "ccexp", "", FormControlType::kInputText, - "section-billing cc-exp"), - CreateTestFormField("", "email", "", FormControlType::kInputText, - "email")}; - - FormsSeen({form}); - - // Fill the unnamed section. - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[1], MakeGuid(1)); - { - SCOPED_TRACE("Unnamed section"); - EXPECT_EQ(u"MyForm", response_data.name); - EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.url); - EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action); - ASSERT_EQ(11U, response_data.fields.size()); - - ExpectFilledField("", "country", "", FormControlType::kInputText, - response_data.fields[0]); - ExpectFilledField("", "firstname", "Elvis", FormControlType::kInputText, - response_data.fields[1]); - ExpectFilledField("", "lastname", "Presley", FormControlType::kInputText, - response_data.fields[2]); - ExpectFilledField("", "address", "", FormControlType::kInputText, - response_data.fields[3]); - ExpectFilledField("", "city", "", FormControlType::kInputText, - response_data.fields[4]); - ExpectFilledField("", "state", "", FormControlType::kInputText, - response_data.fields[5]); - ExpectFilledField("", "zip", "", FormControlType::kInputText, - response_data.fields[6]); - ExpectFilledField("", "ccname", "", FormControlType::kInputText, - response_data.fields[7]); - ExpectFilledField("", "ccnumber", "", FormControlType::kInputText, - response_data.fields[8]); - ExpectFilledField("", "ccexp", "", FormControlType::kInputText, - response_data.fields[9]); - ExpectFilledField("", "email", "theking@gmail.com", - FormControlType::kInputText, response_data.fields[10]); - } - - // Fill the address portion of the billing section. - response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - { - SCOPED_TRACE("Billing address"); - EXPECT_EQ(u"MyForm", response_data.name); - EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.url); - EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action); - ASSERT_EQ(11U, response_data.fields.size()); - - ExpectFilledField("", "country", "US", FormControlType::kInputText, - response_data.fields[0]); - ExpectFilledField("", "firstname", "", FormControlType::kInputText, - response_data.fields[1]); - ExpectFilledField("", "lastname", "", FormControlType::kInputText, - response_data.fields[2]); - ExpectFilledField("", "address", "3734 Elvis Presley Blvd.", - FormControlType::kInputText, response_data.fields[3]); - ExpectFilledField("", "city", "Memphis", FormControlType::kInputText, - response_data.fields[4]); - ExpectFilledField("", "state", "Tennessee", FormControlType::kInputText, - response_data.fields[5]); - ExpectFilledField("", "zip", "38116", FormControlType::kInputText, - response_data.fields[6]); - ExpectFilledField("", "ccname", "", FormControlType::kInputText, - response_data.fields[7]); - ExpectFilledField("", "ccnumber", "", FormControlType::kInputText, - response_data.fields[8]); - ExpectFilledField("", "ccexp", "", FormControlType::kInputText, - response_data.fields[9]); - ExpectFilledField("", "email", "", FormControlType::kInputText, - response_data.fields[10]); - } - - // Fill the credit card portion of the billing section. - response_data = FillAutofillFormDataAndGetResults( - form, form.fields[form.fields.size() - 2], MakeGuid(4)); - { - SCOPED_TRACE("Credit card"); - EXPECT_EQ(u"MyForm", response_data.name); - EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.url); - EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action); - ASSERT_EQ(11U, response_data.fields.size()); - - ExpectFilledField("", "country", "", FormControlType::kInputText, - response_data.fields[0]); - ExpectFilledField("", "firstname", "", FormControlType::kInputText, - response_data.fields[1]); - ExpectFilledField("", "lastname", "", FormControlType::kInputText, - response_data.fields[2]); - ExpectFilledField("", "address", "", FormControlType::kInputText, - response_data.fields[3]); - ExpectFilledField("", "city", "", FormControlType::kInputText, - response_data.fields[4]); - ExpectFilledField("", "state", "", FormControlType::kInputText, - response_data.fields[5]); - ExpectFilledField("", "zip", "", FormControlType::kInputText, - response_data.fields[6]); - ExpectFilledField("", "ccname", "Elvis Presley", - FormControlType::kInputText, response_data.fields[7]); - ExpectFilledField("", "ccnumber", "4234567890123456", - FormControlType::kInputText, response_data.fields[8]); - ExpectFilledField("", "ccexp", "04/2999", FormControlType::kInputText, - response_data.fields[9]); - ExpectFilledField("", "email", "", FormControlType::kInputText, - response_data.fields[10]); - } -} - -// Test that we correctly fill a form that has a single logical section with -// multiple email address fields. -TEST_F(BrowserAutofillManagerTest, FillFormWithMultipleEmails) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - form.fields.push_back(CreateTestFormField("Confirm email", "email2", "", - FormControlType::kInputText)); - - FormsSeen({form}); - - // Fill the form. - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - - // The second email address should be filled. - EXPECT_EQ(u"theking@gmail.com", response_data.fields.back().value); - - // The remainder of the form should be filled as usual. - response_data.fields.pop_back(); - ExpectFilledAddressFormElvis(response_data, false); -} - -// Test that we correctly fill a previously auto-filled form. -TEST_F(BrowserAutofillManagerTest, FillAutofilledForm) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - // Mark the address fields as autofilled. - for (auto& field : form.fields) { - field.is_autofilled = true; - } - - CreateTestCreditCardFormData(&form, true, false); - FormsSeen({form}); - - // First fill the address data. - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(1)); - { - SCOPED_TRACE("Address"); - TestAddressFillData expected_address_fill_data = kEmptyAddressFillData; - expected_address_fill_data.first = "Elvis"; - ExpectFilledForm(response_data, expected_address_fill_data, - kEmptyCardFillData); - } - - // Now fill the credit card data. - response_data = - FillAutofillFormDataAndGetResults(form, form.fields.back(), MakeGuid(4)); - { - SCOPED_TRACE("Credit card 1"); - ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/true); - } - - // Now set the credit card fields to also be auto-filled, and try again to - // fill the credit card data - for (auto& field : form.fields) { - field.is_autofilled = true; - } - - response_data = FillAutofillFormDataAndGetResults( - form, form.fields[form.fields.size() - 2], MakeGuid(4)); - { - SCOPED_TRACE("Credit card 2"); - TestCardFillData expected_card_fill_data = kEmptyCardFillData; - expected_card_fill_data.expiration_year = "2999"; - ExpectFilledForm(response_data, kEmptyAddressFillData, - expected_card_fill_data); - } -} - -// Test that we correctly fill a previously partly auto-filled form. -TEST_F(BrowserAutofillManagerTest, FillPartlyAutofilledForm) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - // Mark couple of the address fields as autofilled. - form.fields[3].is_autofilled = true; - form.fields[4].is_autofilled = true; - form.fields[5].is_autofilled = true; - form.fields[6].is_autofilled = true; - form.fields[10].is_autofilled = true; - - CreateTestCreditCardFormData(&form, true, false); - FormsSeen({form}); - - // First fill the address data. - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(1)); - { - SCOPED_TRACE("Address"); - TestAddressFillData expected_address_fill_data = kEmptyAddressFillData; - expected_address_fill_data.first = "Elvis"; - expected_address_fill_data.middle = "Aaron"; - expected_address_fill_data.last = "Presley"; - expected_address_fill_data.postal_code = "38116"; - expected_address_fill_data.country = "United States"; - bool default_to_city_and_number = - base::FeatureList::IsEnabled(features::kAutofillDefaultToCityAndNumber); - expected_address_fill_data.phone = - default_to_city_and_number ? "2345678901" : "12345678901"; - - ExpectFilledForm(response_data, expected_address_fill_data, - kEmptyCardFillData); - } - - // Now fill the credit card data. - response_data = - FillAutofillFormDataAndGetResults(form, form.fields.back(), MakeGuid(4)); - { - SCOPED_TRACE("Credit card 1"); - ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/true); - } -} - -// Test that we correctly fill a previously partly auto-filled form. -TEST_F(BrowserAutofillManagerTest, FillPartlyManuallyFilledForm) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - - CreateTestCreditCardFormData(&form, true, false); - FormsSeen({form}); - - // Michael will be overridden with Elvis because Autofill is triggered from - // the first field. - form.fields[0].value = u"Michael"; - form.fields[0].properties_mask |= kUserTyped; - - // Jackson will be preserved. - form.fields[2].value = u"Jackson"; - form.fields[2].properties_mask |= kUserTyped; - - FormsSeen({form}); - - // First fill the address data. - FormData response_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(1)); - { - SCOPED_TRACE("Address"); - TestAddressFillData expected_address_fill_data = GetElvisAddressFillData(); - expected_address_fill_data.last = "Jackson"; - ExpectFilledForm(response_data, expected_address_fill_data, - kEmptyCardFillData); - } - - // Now fill the credit card data. - response_data = - FillAutofillFormDataAndGetResults(form, form.fields.back(), MakeGuid(4)); - { - SCOPED_TRACE("Credit card 1"); - TestAddressFillData expected_address_fill_data = kEmptyAddressFillData; - expected_address_fill_data.first = "Michael"; - expected_address_fill_data.last = "Jackson"; - ExpectFilledForm(response_data, expected_address_fill_data, - kElvisCardFillData); - } -} - -// Test that we correctly fill a phone number split across multiple fields. -TEST_F(BrowserAutofillManagerTest, FillPhoneNumber) { - // In one form, rely on the max length attribute to imply US phone number - // parts. In the other form, rely on the autocomplete type attribute. - FormData form_with_us_number_max_length; - form_with_us_number_max_length.renderer_id = test::MakeFormRendererId(); - form_with_us_number_max_length.name = u"MyMaxlengthPhoneForm"; - form_with_us_number_max_length.url = - GURL("https://myform.com/phone_form.html"); - form_with_us_number_max_length.action = - GURL("https://myform.com/phone_submit.html"); - FormData form_with_autocompletetype = form_with_us_number_max_length; - form_with_autocompletetype.renderer_id = test::MakeFormRendererId(); - form_with_autocompletetype.name = u"MyAutocompletetypePhoneForm"; - - struct { - const char* label; - const char* name; - size_t max_length; - const char* autocomplete_attribute; - } test_fields[] = {{"country code", "country_code", 1, "tel-country-code"}, - {"area code", "area_code", 3, "tel-area-code"}, - {"phone", "phone_prefix", 3, "tel-local-prefix"}, - {"-", "phone_suffix", 4, "tel-local-suffix"}, - {"Phone Extension", "ext", 3, "tel-extension"}}; - - constexpr uint64_t default_max_length = 0; - for (const auto& test_field : test_fields) { - FormFieldData field = CreateTestFormField(test_field.label, test_field.name, - "", FormControlType::kInputText, - "", test_field.max_length); - form_with_us_number_max_length.fields.push_back(field); - - field.max_length = default_max_length; - field.autocomplete_attribute = test_field.autocomplete_attribute; - field.parsed_autocomplete = - ParseAutocompleteAttribute(test_field.autocomplete_attribute); - form_with_autocompletetype.fields.push_back(field); - } - - FormsSeen({form_with_us_number_max_length, form_with_autocompletetype}); - - // We should be able to fill prefix and suffix fields for US numbers. - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - FormData response_data1 = FillAutofillFormDataAndGetResults( - form_with_us_number_max_length, - *form_with_us_number_max_length.fields.begin(), guid); - - ASSERT_EQ(5U, response_data1.fields.size()); - EXPECT_EQ(u"1", response_data1.fields[0].value); - EXPECT_EQ(u"650", response_data1.fields[1].value); - EXPECT_EQ(u"555", response_data1.fields[2].value); - EXPECT_EQ(u"4567", response_data1.fields[3].value); - EXPECT_EQ(std::u16string(), response_data1.fields[4].value); - - FormData response_data2 = FillAutofillFormDataAndGetResults( - form_with_autocompletetype, *form_with_autocompletetype.fields.begin(), - guid); - - ASSERT_EQ(5U, response_data2.fields.size()); - EXPECT_EQ(u"1", response_data2.fields[0].value); - EXPECT_EQ(u"650", response_data2.fields[1].value); - EXPECT_EQ(u"555", response_data2.fields[2].value); - EXPECT_EQ(u"4567", response_data2.fields[3].value); - EXPECT_EQ(std::u16string(), response_data2.fields[4].value); - - // For other countries, fill prefix and suffix fields with best effort. - work_profile->SetRawInfo(ADDRESS_HOME_COUNTRY, u"GB"); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"447700954321"); - FormData response_data3 = FillAutofillFormDataAndGetResults( - form_with_us_number_max_length, - *form_with_us_number_max_length.fields.begin(), guid); - - ASSERT_EQ(5U, response_data3.fields.size()); - EXPECT_EQ(u"4", response_data3.fields[0].value); - EXPECT_EQ(u"700", response_data3.fields[1].value); - EXPECT_EQ(u"95", response_data3.fields[2].value); - EXPECT_EQ(u"4321", response_data3.fields[3].value); - EXPECT_EQ(std::u16string(), response_data3.fields[4].value); - - FormData response_data4 = FillAutofillFormDataAndGetResults( - form_with_autocompletetype, *form_with_autocompletetype.fields.begin(), - guid); - - ASSERT_EQ(5U, response_data4.fields.size()); - EXPECT_EQ(u"44", response_data4.fields[0].value); - EXPECT_EQ(u"7700", response_data4.fields[1].value); - EXPECT_EQ(u"95", response_data4.fields[2].value); - EXPECT_EQ(u"4321", response_data4.fields[3].value); - EXPECT_EQ(std::u16string(), response_data4.fields[4].value); -} - -TEST_F(BrowserAutofillManagerTest, FillPhoneNumber_ForPhonePrefixOrSuffix) { - FormData form = - test::GetFormData({.fields = { - {.label = u"country code", - .name = u"country_code", - .max_length = 1, - .autocomplete_attribute = "tel-country-code"}, - {.label = u"area code", - .name = u"area_code", - .max_length = 3, - .autocomplete_attribute = "tel-area-code"}, - {.label = u"prefix", - .name = u"phone_prefix", - .max_length = 3, - .autocomplete_attribute = "tel-local-prefix"}, - {.label = u"-", - .name = u"phone_suffix", - .max_length = 4, - .autocomplete_attribute = "tel-local-suffix"}, - {.label = u"Phone Extension", - .name = u"ext", - .max_length = 5, - .autocomplete_attribute = "tel-extension"}, - }}); - - FormsSeen({form}); - - personal_data().ClearProfiles(); - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - profile.set_guid(MakeGuid(104)); - profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"1800FLOWERS"); - personal_data().AddProfile(profile); - - FormData response_data1 = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), profile.guid()); - - ASSERT_EQ(5U, response_data1.fields.size()); - EXPECT_EQ(u"356", response_data1.fields[2].value); - EXPECT_EQ(u"9377", response_data1.fields[3].value); -} - -// Tests that the suggestion consists of phone number without the country code -// when a length limit is imposed in the field due to which filling with -// country code is not possible. -TEST_F(BrowserAutofillManagerTest, FillPhoneNumber_WithMaxLengthLimit) { - FormData form = CreateTestAddressFormData(); - form.fields[9].max_length = 10; - FormsSeen({form}); - - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - profile.set_guid(MakeGuid(103)); - profile.SetInfo(NAME_FULL, u"Natty Bumppo", "en-US"); - profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"+886123456789"); - personal_data().ClearProfiles(); - personal_data().AddProfile(profile); - - GetAutofillSuggestions(form, form.fields[9]); - - std::string guid = profile.guid(); - FormData response_data = - FillAutofillFormDataAndGetResults(form, *form.fields.begin(), guid); - - ASSERT_EQ(11U, response_data.fields.size()); - EXPECT_EQ(u"123456789", response_data.fields[9].value); -} - -TEST_F(BrowserAutofillManagerTest, FillFirstPhoneNumber_ComponentizedNumbers) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - // Verify only the first complete number is filled when there are multiple - // componentized number fields. - FormData form_with_multiple_componentized_phone_fields; - form_with_multiple_componentized_phone_fields.renderer_id = - test::MakeFormRendererId(); - form_with_multiple_componentized_phone_fields.url = - GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_multiple_componentized_phone_fields.name = - u"multiple_componentized_number_fields"; - form_with_multiple_componentized_phone_fields.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("country code", "country_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("area code", "area_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("number", "phone_number", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping country code", "shipping_country_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping area code", "shipping_area_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping number", "shipping_phone_number", "", - FormControlType::kInputText, "", kMaxLength)}; - - FormsSeen({form_with_multiple_componentized_phone_fields}); - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_multiple_componentized_phone_fields, - *form_with_multiple_componentized_phone_fields.fields.begin(), guid); - - // Verify only the first complete set of phone number fields are filled. - ASSERT_EQ(8U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(u"1", response_data.fields[1].value); - EXPECT_EQ(u"650", response_data.fields[2].value); - EXPECT_EQ(u"5554567", response_data.fields[3].value); - EXPECT_EQ(std::u16string(), response_data.fields[4].value); - EXPECT_EQ(std::u16string(), response_data.fields[5].value); - EXPECT_EQ(std::u16string(), response_data.fields[6].value); - EXPECT_EQ(std::u16string(), response_data.fields[7].value); -} - -TEST_F(BrowserAutofillManagerTest, FillFirstPhoneNumber_WholeNumbers) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - FormData form_with_multiple_whole_number_fields; - form_with_multiple_whole_number_fields.renderer_id = - test::MakeFormRendererId(); - form_with_multiple_whole_number_fields.url = GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_multiple_whole_number_fields.name = u"multiple_whole_number_fields"; - form_with_multiple_whole_number_fields.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("number", "phone_number", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping number", "shipping_phone_number", "", - FormControlType::kInputText, "", kMaxLength)}; - - FormsSeen({form_with_multiple_whole_number_fields}); - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_multiple_whole_number_fields, - *form_with_multiple_whole_number_fields.fields.begin(), guid); - - // Verify only the first complete set of phone number fields are filled. - ASSERT_EQ(4U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(u"6505554567", response_data.fields[1].value); - EXPECT_EQ(std::u16string(), response_data.fields[2].value); - EXPECT_EQ(std::u16string(), response_data.fields[3].value); -} - -TEST_F(BrowserAutofillManagerTest, FillFirstPhoneNumber_FillPartsOnceOnly) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - // Verify only the first complete number is filled when there are multiple - // componentized number fields. - FormData form_with_multiple_componentized_phone_fields; - form_with_multiple_componentized_phone_fields.renderer_id = - test::MakeFormRendererId(); - form_with_multiple_componentized_phone_fields.url = - GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_multiple_componentized_phone_fields.name = - u"multiple_componentized_number_fields"; - form_with_multiple_componentized_phone_fields.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("country code", "country_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("area code", "area_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("number", "phone_number", "", - FormControlType::kInputText, "tel-national", - kMaxLength), - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping country code", "shipping_country_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping area code", "shipping_area_code", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping number", "shipping_phone_number", "", - FormControlType::kInputText, "", kMaxLength)}; - - FormsSeen({form_with_multiple_componentized_phone_fields}); - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_multiple_componentized_phone_fields, - *form_with_multiple_componentized_phone_fields.fields.begin(), guid); - - // Verify only the first complete set of phone number fields are filled, - // and phone components are not filled more than once. - ASSERT_EQ(8U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(u"1", response_data.fields[1].value); - EXPECT_EQ(std::u16string(), response_data.fields[2].value); - EXPECT_EQ(u"6505554567", response_data.fields[3].value); - EXPECT_EQ(std::u16string(), response_data.fields[4].value); - EXPECT_EQ(std::u16string(), response_data.fields[5].value); - EXPECT_EQ(std::u16string(), response_data.fields[6].value); - EXPECT_EQ(std::u16string(), response_data.fields[7].value); -} - -// Verify when extension is misclassified, and there is a complete -// phone field, we do not fill anything to extension field. -TEST_F(BrowserAutofillManagerTest, - FillFirstPhoneNumber_NotFillMisclassifiedExtention) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - FormData form_with_misclassified_extension; - form_with_misclassified_extension.renderer_id = test::MakeFormRendererId(); - form_with_misclassified_extension.url = GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_misclassified_extension.name = - u"complete_phone_form_with_extension"; - form_with_misclassified_extension.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "name", kMaxLength), - CreateTestFormField("address", "address", "", FormControlType::kInputText, - "addresses", kMaxLength), - CreateTestFormField("area code", "area_code", "", - FormControlType::kInputText, "tel-area-code", - kMaxLength), - CreateTestFormField("number", "phone_number", "", - FormControlType::kInputText, "tel-local", kMaxLength), - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "tel-local", - kMaxLength)}; - - FormsSeen({form_with_misclassified_extension}); - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_misclassified_extension, - *form_with_misclassified_extension.fields.begin(), guid); - - // Verify the misclassified extension field is not filled. - ASSERT_EQ(5U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(std::u16string(), response_data.fields[1].value); - EXPECT_EQ(u"650", response_data.fields[2].value); - EXPECT_EQ(u"5554567", response_data.fields[3].value); - EXPECT_EQ(std::u16string(), response_data.fields[4].value); -} - -// Verify that phone number fields annotated with the autocomplete attribute -// are filled best-effort. -// Phone number local heuristics only succeed if a PHONE_HOME_NUMBER field is -// present. -TEST_F(BrowserAutofillManagerTest, FillFirstPhoneNumber_BestEffortFilling) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - FormData form_with_no_complete_number; - form_with_no_complete_number.renderer_id = test::MakeFormRendererId(); - form_with_no_complete_number.url = GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_no_complete_number.name = u"no_complete_phone_form"; - form_with_no_complete_number.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "name", kMaxLength), - CreateTestFormField("address", "address", "", FormControlType::kInputText, - "address", kMaxLength), - CreateTestFormField("area code", "area_code", "", - FormControlType::kInputText, "tel-area-code", - kMaxLength), - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "extension", - kMaxLength)}; - - FormsSeen({form_with_no_complete_number}); - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_no_complete_number, - *form_with_no_complete_number.fields.begin(), guid); - - // Verify when there is no complete phone number fields, we do best effort - // filling. - ASSERT_EQ(4U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(u"123 Apple St., unit 6", response_data.fields[1].value); - EXPECT_EQ(u"650", response_data.fields[2].value); - EXPECT_EQ(std::u16string(), response_data.fields[3].value); -} - -// When the focus is on second phone field explicitly, we will fill the -// entire form, both first phone field and second phone field included. -TEST_F(BrowserAutofillManagerTest, - FillFirstPhoneNumber_FocusOnSecondPhoneNumber) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - FormData form_with_multiple_whole_number_fields; - form_with_multiple_whole_number_fields.renderer_id = - test::MakeFormRendererId(); - form_with_multiple_whole_number_fields.url = GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_multiple_whole_number_fields.name = u"multiple_whole_number_fields"; - form_with_multiple_whole_number_fields.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("number", "phone_number", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping number", "shipping_phone_number", "", - FormControlType::kInputText, "", kMaxLength)}; - - FormsSeen({form_with_multiple_whole_number_fields}); - auto it = form_with_multiple_whole_number_fields.fields.begin(); - // Move it to point to "shipping number". - std::advance(it, 3); - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_multiple_whole_number_fields, *it, guid); - - // Verify when the second phone number field is being focused, we fill - // that field *AND* the first phone number field. - ASSERT_EQ(4U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(u"6505554567", response_data.fields[1].value); - EXPECT_EQ(std::u16string(), response_data.fields[2].value); - EXPECT_EQ(u"6505554567", response_data.fields[3].value); -} - -TEST_F(BrowserAutofillManagerTest, - FillFirstPhoneNumber_HiddenFieldShouldNotCount) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - FormData form_with_multiple_whole_number_fields; - form_with_multiple_whole_number_fields.renderer_id = - test::MakeFormRendererId(); - form_with_multiple_whole_number_fields.url = GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_multiple_whole_number_fields.name = u"multiple_whole_number_fields"; - form_with_multiple_whole_number_fields.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("number", "phone_number", "", - FormControlType::kInputText, "", kMaxLength)}; - form_with_multiple_whole_number_fields.fields.back().is_focusable = false; - form_with_multiple_whole_number_fields.fields.push_back( - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "", kMaxLength)); - form_with_multiple_whole_number_fields.fields.push_back( - CreateTestFormField("shipping number", "shipping_phone_number", "", - FormControlType::kInputText, "", kMaxLength)); - - FormsSeen({form_with_multiple_whole_number_fields}); - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_multiple_whole_number_fields, - *form_with_multiple_whole_number_fields.fields.begin(), guid); - - // Verify hidden/non-focusable phone field is set to only_fill_when_focused. - ASSERT_EQ(4U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(std::u16string(), response_data.fields[1].value); - EXPECT_EQ(std::u16string(), response_data.fields[2].value); - EXPECT_EQ(u"6505554567", response_data.fields[3].value); -} - -// The hidden and the presentational fields should be filled, only if their -// control type is 'select-one'. This exception is made to support synthetic -// fields. -TEST_F(BrowserAutofillManagerTest, FormWithHiddenOrPresentationalSelects) { - FormData form; - form.renderer_id = test::MakeFormRendererId(); - form.name = u"MyForm"; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = {CreateTestFormField("First name", "firstname", "", - FormControlType::kInputText), - CreateTestFormField("Last name", "lastname", "", - FormControlType::kInputText)}; - - { - const std::vector<const char*> values{"CA", "US", "BR"}; - const std::vector<const char*> contents{"Canada", "United States", - "Banana Republic"}; - form.fields.push_back( - CreateTestSelectField("Country", "country", "", values, contents)); - form.fields.back().is_focusable = false; - } - { - const std::vector<const char*> values{"NY", "CA", "TN"}; - const std::vector<const char*> contents{"New York", "California", - "Tennessee"}; - form.fields.push_back( - CreateTestSelectField("State", "state", "", values, contents)); - form.fields.back().role = FormFieldData::RoleAttribute::kPresentation; - } - - form.fields.push_back( - CreateTestFormField("City", "city", "", FormControlType::kInputText)); - form.fields.back().is_focusable = false; - form.fields.push_back(CreateTestFormField("Street Address", "address", "", - FormControlType::kInputText)); - form.fields.back().role = FormFieldData::RoleAttribute::kPresentation; - - FormsSeen({form}); - - base::HistogramTester histogram_tester; - - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - histogram_tester.ExpectTotalCount( - "Autofill.HiddenOrPresentationalSelectFieldsFilled", 2); - - ExpectFilledField("First name", "firstname", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Last name", "lastname", "Presley", - FormControlType::kInputText, response_data.fields[1]); - ExpectFilledField("Country", "country", "US", FormControlType::kSelectOne, - response_data.fields[2]); - ExpectFilledField("State", "state", "TN", FormControlType::kSelectOne, - response_data.fields[3]); - ExpectFilledField("City", "city", "", FormControlType::kInputText, - response_data.fields[4]); - ExpectFilledField("Street Address", "address", "", - FormControlType::kInputText, response_data.fields[5]); -} - -TEST_F(BrowserAutofillManagerTest, - FillFirstPhoneNumber_MultipleSectionFilledCorrectly) { - AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); - ASSERT_TRUE(work_profile != nullptr); - work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); - - std::string guid = work_profile->guid(); - - FormData form_with_multiple_sections; - form_with_multiple_sections.renderer_id = test::MakeFormRendererId(); - form_with_multiple_sections.url = GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form_with_multiple_sections.name = u"multiple_section_fields"; - form_with_multiple_sections.fields = { - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("Address", "address", "", FormControlType::kInputText, - "", kMaxLength), - CreateTestFormField("number", "phone_number", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("other number", "other_phone_number", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("extension", "extension", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("Full Name", "full_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("Shipping Address", "shipping_address", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("shipping number", "shipping_phone_number", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("other shipping number", - "other_shipping_phone_number", "", - FormControlType::kInputText, "", kMaxLength)}; - - FormsSeen({form_with_multiple_sections}); - // Fill first sections. - FormData response_data = FillAutofillFormDataAndGetResults( - form_with_multiple_sections, *form_with_multiple_sections.fields.begin(), - guid); - - // Verify first section is filled with rationalization. - ASSERT_EQ(9U, response_data.fields.size()); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); - EXPECT_EQ(u"123 Apple St.", response_data.fields[1].value); - EXPECT_EQ(u"6505554567", response_data.fields[2].value); - EXPECT_EQ(std::u16string(), response_data.fields[3].value); - EXPECT_EQ(std::u16string(), response_data.fields[4].value); - EXPECT_EQ(std::u16string(), response_data.fields[5].value); - EXPECT_EQ(std::u16string(), response_data.fields[6].value); - EXPECT_EQ(std::u16string(), response_data.fields[7].value); - EXPECT_EQ(std::u16string(), response_data.fields[8].value); - - // Fill second section. - auto it = form_with_multiple_sections.fields.begin(); - std::advance(it, 6); // Pointing to second section. - - response_data = - FillAutofillFormDataAndGetResults(form_with_multiple_sections, *it, guid); - - // Verify second section is filled with rationalization. - ASSERT_EQ(9U, response_data.fields.size()); - EXPECT_EQ(std::u16string(), response_data.fields[0].value); - EXPECT_EQ(std::u16string(), response_data.fields[1].value); - EXPECT_EQ(std::u16string(), response_data.fields[2].value); - EXPECT_EQ(std::u16string(), response_data.fields[3].value); - EXPECT_EQ(std::u16string(), response_data.fields[4].value); - EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[5].value); - EXPECT_EQ(u"123 Apple St.", response_data.fields[6].value); - EXPECT_EQ(u"6505554567", response_data.fields[7].value); - EXPECT_EQ(std::u16string(), response_data.fields[8].value); -} - -// Test that we can still fill a form when a field has been removed from it. -TEST_F(BrowserAutofillManagerTest, FormChangesRemoveField) { - // Set up our form data. - FormData form = CreateTestAddressFormData(); - - // Add a field -- we'll remove it again later. - form.fields.insert( - form.fields.begin() + 3, - CreateTestFormField("Some", "field", "", FormControlType::kInputText)); - - FormsSeen({form}); - - // Now, after the call to |FormsSeen|, we remove the field before filling. - form.fields.erase(form.fields.begin() + 3); - - FormsSeen({form}); - - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - ExpectFilledAddressFormElvis(response_data, false); -} - -// Test that we can still fill a form when a field has been added to it. -TEST_F(BrowserAutofillManagerTest, FormChangesAddField) { - // The offset of the phone field in the address form. - const int kPhoneFieldOffset = 9; - - // Set up our form data. - FormData form = CreateTestAddressFormData(); - - // Remove the phone field -- we'll add it back later. - auto pos = form.fields.begin() + kPhoneFieldOffset; - FormFieldData field = *pos; - pos = form.fields.erase(pos); - - FormsSeen({form}); - - // Now, after the call to |FormsSeen|, we restore the field before filling. - form.fields.insert(pos, field); - - FormsSeen({form}); - - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - ExpectFilledAddressFormElvis(response_data, false); -} - -// Test that we can still fill a form when the visibility of some fields -// changes. -TEST_F(BrowserAutofillManagerTest, FormChangesVisibilityOfFields) { - // Set up our form data. - FormData form; - form.renderer_id = test::MakeFormRendererId(); - form.url = GURL("https://www.foo.com/"); - - // Default is zero, have to set to a number autofill can process. - constexpr uint64_t kMaxLength = 10; - form.name = u"multiple_groups_fields"; - form.fields = { - CreateTestFormField("First Name", "first_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("Last Name", "last_name", "", - FormControlType::kInputText, "", kMaxLength), - CreateTestFormField("Address", "address", "", FormControlType::kInputText, - "", kMaxLength), - CreateTestFormField("Postal Code", "postal_code", "", - FormControlType::kInputText, "", kMaxLength)}; - form.fields.back().is_focusable = false; - form.fields.push_back(CreateTestFormField("Country", "country", "", - FormControlType::kInputText)); - form.fields.back().is_focusable = false; - - FormsSeen({form}); - - // Fill the form with the first profile. The hidden fields will not get - // filled. - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); - - ASSERT_EQ(5U, response_data.fields.size()); - ExpectFilledField("First Name", "first_name", "Elvis", - FormControlType::kInputText, response_data.fields[0]); - ExpectFilledField("Last Name", "last_name", "Presley", - FormControlType::kInputText, response_data.fields[1]); - ExpectFilledField("Address", "address", "3734 Elvis Presley Blvd.", - FormControlType::kInputText, response_data.fields[2]); - ExpectFilledField("Postal Code", "postal_code", "", - FormControlType::kInputText, response_data.fields[3]); - ExpectFilledField("Country", "country", "", FormControlType::kInputText, - response_data.fields[4]); - - // Two other fields will show up. Select the second profile. The fields that - // were already filled, would be left unchanged, and the rest would be filled - // with the second profile. (Two different profiles are selected, to make sure - // the right fields are getting filled.) - response_data.fields[3].is_focusable = true; - response_data.fields[4].is_focusable = true; - - FormData later_response_data = FillAutofillFormDataAndGetResults( - response_data, response_data.fields[4], MakeGuid(2)); - ASSERT_EQ(5U, later_response_data.fields.size()); - ExpectFilledField("First Name", "first_name", "Elvis", - FormControlType::kInputText, later_response_data.fields[0]); - ExpectFilledField("Last Name", "last_name", "Presley", - FormControlType::kInputText, later_response_data.fields[1]); - ExpectFilledField("Address", "address", "3734 Elvis Presley Blvd.", - FormControlType::kInputText, later_response_data.fields[2]); - ExpectFilledField("Postal Code", "postal_code", "79401", - FormControlType::kInputText, later_response_data.fields[3]); - ExpectFilledField("Country", "country", "United States", - FormControlType::kInputText, later_response_data.fields[4]); -} - // Test that the importing logic is called on form submit. TEST_F(BrowserAutofillManagerTest, FormSubmitted_FormDataImporter) { // Set up our form data. @@ -5797,6 +3344,7 @@ FormSubmitted(response_data); } // Test the field log events at the form submission. +// TODO(crbug.com/1007974): Move those tests out of this file. class BrowserAutofillManagerWithLogEventsTest : public BrowserAutofillManagerTest { protected: @@ -7691,33 +5239,6 @@ SubmissionSource::FORM_SUBMISSION); } -TEST_F(BrowserAutofillManagerTest, FillInUpdatedExpirationDate) { - FormData form; - CreditCard card; - PrepareForRealPanResponse(&form, &card); - - CardUnmaskDelegate::UserProvidedUnmaskDetails details; - details.cvc = u"123"; - details.exp_month = u"02"; - details.exp_year = u"2018"; - full_card_unmask_delegate()->OnUnmaskPromptAccepted(details); - OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, - "4012888888881881"); -} - -TEST_F(BrowserAutofillManagerTest, ProfileDisabledDoesNotFillFormData) { - browser_autofill_manager_->SetAutofillProfileEnabled(autofill_client_, false); - - // Set up our form data. - FormData form = CreateTestAddressFormData(); - FormsSeen({form}); - - // Expect no fields filled, no form data sent to renderer. - EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); - - FillAutofillFormData(form, *form.fields.begin(), MakeGuid(1)); -} - TEST_F(BrowserAutofillManagerTest, ProfileDisabledDoesNotSuggest) { browser_autofill_manager_->SetAutofillProfileEnabled(autofill_client_, false); @@ -7733,20 +5254,6 @@ EXPECT_FALSE(external_delegate()->on_suggestions_returned_seen()); } -TEST_F(BrowserAutofillManagerTest, CreditCardDisabledDoesNotFillFormData) { - browser_autofill_manager_->SetAutofillPaymentMethodsEnabled(autofill_client_, - false); - - // Set up our form data. - FormData form = - CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); - FormsSeen({form}); - - // Expect no fields filled, no form data sent to renderer. - EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); - FillAutofillFormData(form, *form.fields.begin(), MakeGuid(4)); -} - TEST_F(BrowserAutofillManagerTest, CreditCardDisabledDoesNotSuggest) { browser_autofill_manager_->SetAutofillPaymentMethodsEnabled(autofill_client_, false); @@ -9234,121 +6741,6 @@ form_https, card_number_field_https)); } -// Test that fields will be assigned with the source profile that was used for -// autofill. -TEST_F(BrowserAutofillManagerTest, TrackFillingOrigin) { - // Set up our form data. - FormData form = CreateTestPersonalInformationFormData(); - - FormsSeen({form}); - - AutofillProfile profile = test::GetFullProfile(); - personal_data().AddProfile(profile); - FillAutofillFormData(form, form.fields[0], profile.guid()); - - FormStructure* form_structure = - browser_autofill_manager_->FindCachedFormById(form.global_id()); - ASSERT_TRUE(form_structure); - for (const auto& autofill_field_ptr : form_structure->fields()) { - EXPECT_THAT(autofill_field_ptr->autofill_source_profile_guid(), - testing::Optional(profile.guid())); - } -} - -// Test that filling with multiple autofill profiles will set different source -// profiles for fields. -TEST_F(BrowserAutofillManagerTest, - TrackFillingOriginWithUsingMultipleProfiles) { - // Set up our form data. - FormData form = CreateTestPersonalInformationFormData(); - - FormsSeen({form}); - - // Fill the form with a profile without email - AutofillProfile profile1 = test::GetFullProfile(); - profile1.ClearFields({EMAIL_ADDRESS}); - personal_data().AddProfile(profile1); - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], profile1.guid()); - - // Check that the email field has no filling source. - FormStructure* form_structure = - browser_autofill_manager_->FindCachedFormById(form.global_id()); - ASSERT_EQ(form.fields[3].label, u"Email"); - EXPECT_EQ(form_structure->field(3)->autofill_source_profile_guid(), - std::nullopt); - - // Then fill the email field using the second profile - AutofillProfile profile2 = test::GetFullProfile(); - personal_data().AddProfile(profile2); - FormData later_response_data = FillAutofillFormDataAndGetResults( - response_data, form.fields[3], profile2.guid()); - - // Check that the first three fields have the first profile as filling source - // and the last field has the second profile. - form_structure = - browser_autofill_manager_->FindCachedFormById(form.global_id()); - ASSERT_TRUE(form_structure); - EXPECT_THAT(form_structure->field(0)->autofill_source_profile_guid(), - testing::Optional(profile1.guid())); - EXPECT_THAT(form_structure->field(1)->autofill_source_profile_guid(), - testing::Optional(profile1.guid())); - EXPECT_THAT(form_structure->field(2)->autofill_source_profile_guid(), - testing::Optional(profile1.guid())); - EXPECT_THAT(form_structure->field(3)->autofill_source_profile_guid(), - testing::Optional(profile2.guid())); -} - -// Test that an autofilled and edited field will be assigned with the autofill -// profile. -TEST_F(BrowserAutofillManagerTest, TrackFillingOriginOnEditedField) { - // Set up our form data. - FormData form = CreateTestPersonalInformationFormData(); - - FormsSeen({form}); - - AutofillProfile profile = test::GetFullProfile(); - personal_data().AddProfile(profile); - FormData response_data = - FillAutofillFormDataAndGetResults(form, form.fields[0], profile.guid()); - - // Simulate editing the first field. - response_data.fields[0].value = u"Michael"; - browser_autofill_manager_->OnTextFieldDidChange( - response_data, response_data.fields[0], gfx::RectF(), - base::TimeTicks::Now()); - - FormStructure* form_structure = - browser_autofill_manager_->FindCachedFormById(form.global_id()); - ASSERT_TRUE(form_structure); - AutofillField* edited_field = form_structure->field(0); - ASSERT_FALSE(edited_field->is_autofilled); - ASSERT_TRUE(edited_field->previously_autofilled()); - EXPECT_THAT(edited_field->autofill_source_profile_guid(), - testing::Optional(profile.guid())); -} - -// Test that only autofilled fields will be assigned with the autofill profile. -TEST_F(BrowserAutofillManagerTest, TrackFillingOriginWorksOnlyOnFilledField) { - // Set up our form data. - FormData form = CreateTestPersonalInformationFormData(); - - FormsSeen({form}); - - // Fill the form with a profile without email field. - AutofillProfile profile = test::GetFullProfile(); - profile.ClearFields({EMAIL_ADDRESS}); - personal_data().AddProfile(profile); - FillAutofillFormData(form, form.fields[0], profile.guid()); - - FormStructure* form_structure = - browser_autofill_manager_->FindCachedFormById(form.global_id()); - ASSERT_TRUE(form_structure); - // Check that the email field has no filling source. - EXPECT_EQ(form_structure->field(3)->autofill_source_profile_guid(), - std::nullopt); -} - // Ensure that the experimental plus_addresses feature is not shown by default. // This is true even if the PlusAddressService had existing data for the current // domain. @@ -9749,133 +7141,6 @@ /*with_gpay_logo=*/false)}); } -// The following Refill Tests ensure that Autofill can handle the situation -// where it fills a credit card form with an expiration date like 04/2999 -// and the website tries to reformat the input with whitespaces around the -// slash and then sacrifices the wrong digits in the expiration date. I.e., -// the website replaces "04/2099" with "04 / 20". The tests ensure that this -// triggers a refill with "04 / 29". -struct RefillTestCase { - // The value that JavaScript owned by the website sets for the expiration - // date filed. - std::u16string exp_date_from_js; - // Whether we expect a refill from in this test case. - bool triggers_refill; - // What value we expect in the refill. - const char* refilled_exp_date = nullptr; -}; - -class BrowserAutofillManagerRefillTest - : public BrowserAutofillManagerTest, - public testing::WithParamInterface<RefillTestCase> {}; - -TEST_P(BrowserAutofillManagerRefillTest, - RefillModifiedCreditCardExpirationDates) { - RefillTestCase test_case = GetParam(); - - // Set up a CC form with name, cc number and expiration date. - FormData form; - form.url = GURL("https://myform.com/form.html"); - form.action = GURL("https://myform.com/submit.html"); - form.fields = {CreateTestFormField("Name on Card", "nameoncard", "", - FormControlType::kInputText), - CreateTestFormField("Card Number", "cardnumber", "", - FormControlType::kInputText), - CreateTestFormField("Expiration date", "exp_date", "", - FormControlType::kInputText)}; - - // Notify BrowserAutofillManager of the form. - FormsSeen({form}); - - // Simulate filling and store the data to be filled in |first_fill_data|. - FormData first_fill_data = FillAutofillFormDataAndGetResults( - form, *form.fields.begin(), MakeGuid(4)); - ASSERT_EQ(3u, first_fill_data.fields.size()); - ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", - FormControlType::kInputText, first_fill_data.fields[0]); - ExpectFilledField("Card Number", "cardnumber", "4234567890123456", - FormControlType::kInputText, first_fill_data.fields[1]); - ExpectFilledField("Expiration date", "exp_date", "04/2999", - FormControlType::kInputText, first_fill_data.fields[2]); - - FormData refilled_form; - if (test_case.triggers_refill) { - // Prepare intercepting the filling operation to the driver and capture - // the re-filled form data. - EXPECT_CALL(*autofill_driver_, ApplyFormAction) - .Times(1) - .WillOnce(DoAll(SaveArg<2>(&refilled_form), - Return(std::vector<FieldGlobalId>{}))); - } else { - EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); - } - // Simulate that JavaScript modifies the expiration date field. - FormData form_after_js_modification = first_fill_data; - form_after_js_modification.fields[2].value = test_case.exp_date_from_js; - browser_autofill_manager_->OnJavaScriptChangedAutofilledValue( - form_after_js_modification, form_after_js_modification.fields[2], - u"04/2999"); - - testing::Mock::VerifyAndClearExpectations(autofill_driver_.get()); - - if (test_case.triggers_refill) { - ASSERT_EQ(3u, refilled_form.fields.size()); - ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", - FormControlType::kInputText, refilled_form.fields[0]); - EXPECT_FALSE(refilled_form.fields[0].force_override); - ExpectFilledField("Card Number", "cardnumber", "4234567890123456", - FormControlType::kInputText, refilled_form.fields[1]); - EXPECT_FALSE(refilled_form.fields[1].force_override); - ExpectFilledField("Expiration date", "exp_date", - test_case.refilled_exp_date, FormControlType::kInputText, - refilled_form.fields[2]); - EXPECT_TRUE(refilled_form.fields[2].force_override); - } -} - -INSTANTIATE_TEST_SUITE_P( - All, - BrowserAutofillManagerRefillTest, - testing::Values( - // This is the classic case: Autofill filled 04/2999, website overrode - // 04 / 29, we need to fix this to 04 / 99. - RefillTestCase{.exp_date_from_js = u"04 / 29", - .triggers_refill = true, - .refilled_exp_date = "04 / 99"}, - // Maybe the website replaced the separator and added whitespaces. - RefillTestCase{.exp_date_from_js = u"04 - 29", - .triggers_refill = true, - .refilled_exp_date = "04 - 99"}, - // Maybe the website only replaced the separator. - RefillTestCase{.exp_date_from_js = u"04-29", - .triggers_refill = true, - .refilled_exp_date = "04-99"}, - // Maybe the website was smart and dropped the correct digits. - RefillTestCase{ - .exp_date_from_js = u"04 / 99", - .triggers_refill = false, - }, - // Maybe the website did not modify the values at all. - RefillTestCase{ - .exp_date_from_js = u"04/2999", - .triggers_refill = false, - }, - // Maybe the website did something we don't support. - RefillTestCase{ - .exp_date_from_js = u"April / 2999", - .triggers_refill = false, - }, - // Maybe the website just added some whitespaces. - RefillTestCase{ - .exp_date_from_js = u"04 / 2999", - .triggers_refill = false, - }, - // Don't trigger refill on 3 digit years. - RefillTestCase{ - .exp_date_from_js = u"04 / 299", - .triggers_refill = false, - })); - // Tests that analyze metrics logging in case JavaScript clears a field // immediately after it was filled. class BrowserAutofillManagerClearFieldTest : public BrowserAutofillManagerTest {
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc index 8aa96bdd..1d83d01 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
@@ -22,6 +22,7 @@ #include "components/autofill/core/browser/metrics/log_event.h" #include "components/autofill/core/browser/randomized_encoder.h" #include "components/autofill/core/browser/server_prediction_overrides.h" +#include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_internals/log_message.h" #include "components/autofill/core/common/autofill_internals/logging_scope.h" @@ -150,6 +151,16 @@ const FieldTypeSet& contained_types) { for (const auto& field : form) { for (auto type : field->possible_types()) { + // EMAIL_ADDRESS is exempt from the contained_types requirement, if the + // possible_type was determined by a valid email address found within the + // field's content. The kAutofillUploadVotesForFieldsWithEmail feature + // handles this scenario. + if (type == EMAIL_ADDRESS && IsValidEmailAddress(field->value) && + base::FeatureList::IsEnabled( + features::kAutofillUploadVotesForFieldsWithEmail)) { + continue; + } + if (type != UNKNOWN_TYPE && type != EMPTY_TYPE && !contained_types.count(type)) { return type;
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc index 659f319..7bbc0c7 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc
@@ -201,73 +201,54 @@ //////////////// // Setup //////////////// - std::unique_ptr<FormStructure> form_structure; + FormData form = test::GetFormData( + {.fields = { + {.label = u"First Name", + .name = u"firstname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Last Name", + .name = u"lastname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Email", + .name = u"email", + .form_control_type = FormControlType::kInputEmail}, + {.label = u"Phone", + .name = u"phone", + .form_control_type = FormControlType::kInputNumber}, + {.label = u"Country", + .name = u"country", + .form_control_type = FormControlType::kSelectOne}, + // Add checkable field. + {.label = u"Checkable1", + .name = u"Checkable1", + .check_status = FormFieldData::CheckStatus::kCheckableButUnchecked}, + }}); + std::vector<FieldTypeSet> possible_field_types; std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; - FormData form; - form.url = GURL("http://www.foo.com/"); - form.is_form_tag = true; - - FormFieldData field; - field.form_control_type = FormControlType::kInputText; - - field.label = u"First Name"; - field.name = u"firstname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_FIRST}, {AutofillProfile::ValidityState::kUnvalidated}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Last Name"; - field.name = u"lastname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_LAST}, {AutofillProfile::ValidityState::kUnvalidated}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Email"; - field.name = u"email"; - field.form_control_type = FormControlType::kInputEmail; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}, {AutofillProfile::ValidityState::kInvalid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Phone"; - field.name = u"phone"; - field.form_control_type = FormControlType::kInputNumber; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {PHONE_HOME_WHOLE_NUMBER}, {AutofillProfile::ValidityState::kEmpty}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Country"; - field.name = u"country"; - field.form_control_type = FormControlType::kSelectOne; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}, {AutofillProfile::ValidityState::kValid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - // Add checkable field. - FormFieldData checkable_field; - checkable_field.check_status = - FormFieldData::CheckStatus::kCheckableButUnchecked; - checkable_field.label = u"Checkable1"; - checkable_field.name = u"Checkable1"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}, {AutofillProfile::ValidityState::kValid}); - checkable_field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(checkable_field); - form_structure = std::make_unique<FormStructure>(form); - for (auto& fs_field : *form_structure) { + std::unique_ptr<FormStructure> form_structure = + std::make_unique<FormStructure>(form); + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { fs_field->host_form_signature = form_structure->form_signature(); } @@ -312,7 +293,8 @@ //////////////// std::string expected_upload_string; EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true), + /*login_form_signature=*/"", + /*observed_submission=*/true), ElementsSerializeSameAs(upload)); //////////////// @@ -320,6 +302,7 @@ //////////////// // Add 2 address fields - this should be still a valid form. for (size_t i = 0; i < 2; ++i) { + FormFieldData field; field.label = u"Address"; field.name = u"address"; field.form_control_type = FormControlType::kInputText; @@ -333,7 +316,8 @@ } form_structure = std::make_unique<FormStructure>(form); - for (auto& fs_field : *form_structure) { + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { fs_field->host_form_signature = form_structure->form_signature(); } @@ -355,7 +339,8 @@ test::FillUploadField(upload.add_field(), 509334676U, {30U, 31U}, {2, 2}); EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true), + /*login_form_signature=*/"", + /*observed_submission=*/true), ElementsSerializeSameAs(upload)); } @@ -364,72 +349,54 @@ //////////////// // Setup //////////////// - std::unique_ptr<FormStructure> form_structure; + FormData form = test::GetFormData( + {.fields = { + {.label = u"First Name", + .name = u"firstname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Last Name", + .name = u"lastname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Email", + .name = u"email", + .form_control_type = FormControlType::kInputEmail}, + {.label = u"Phone", + .name = u"phone", + .form_control_type = FormControlType::kInputNumber}, + {.label = u"Country", + .name = u"country", + .form_control_type = FormControlType::kSelectOne}, + // Add checkable field. + {.label = u"Checkable1", + .name = u"Checkable1", + .check_status = FormFieldData::CheckStatus::kCheckableButUnchecked}, + }}); + std::vector<FieldTypeSet> possible_field_types; std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; - FormData form; - form.url = GURL("http://www.foo.com/"); - - FormFieldData field; - field.form_control_type = FormControlType::kInputText; - - field.label = u"First Name"; - field.name = u"firstname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_FIRST}, {AutofillProfile::ValidityState::kUnvalidated}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Last Name"; - field.name = u"lastname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_LAST}, {AutofillProfile::ValidityState::kUnvalidated}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Email"; - field.name = u"email"; - field.form_control_type = FormControlType::kInputEmail; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}, {AutofillProfile::ValidityState::kInvalid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Phone"; - field.name = u"phone"; - field.form_control_type = FormControlType::kInputNumber; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {PHONE_HOME_WHOLE_NUMBER}, {AutofillProfile::ValidityState::kEmpty}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Country"; - field.name = u"country"; - field.form_control_type = FormControlType::kSelectOne; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}, {AutofillProfile::ValidityState::kValid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - // Add checkable field. - FormFieldData checkable_field; - checkable_field.check_status = - FormFieldData::CheckStatus::kCheckableButUnchecked; - checkable_field.label = u"Checkable1"; - checkable_field.name = u"Checkable1"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}, {AutofillProfile::ValidityState::kValid}); - checkable_field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(checkable_field); - form_structure = std::make_unique<FormStructure>(form); - for (auto& fs_field : *form_structure) { + std::unique_ptr<FormStructure> form_structure = + std::make_unique<FormStructure>(form); + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { fs_field->host_form_signature = form_structure->form_signature(); } @@ -468,7 +435,8 @@ 1); // Non-matching validities EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true), + /*login_form_signature=*/"", + /*observed_submission=*/true), ElementsAre(Not(SerializesSameAs(upload)))); } @@ -477,82 +445,62 @@ //////////////// // Setup //////////////// - std::unique_ptr<FormStructure> form_structure; + FormData form = test::GetFormData( + {.fields = { + {.label = u"First Name", + .name = u"firstname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Last Name", + .name = u"lastname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Email", + .name = u"email", + .form_control_type = FormControlType::kInputEmail}, + {.label = u"Phone", + .name = u"phone", + .form_control_type = FormControlType::kInputNumber}, + {.label = u"Country", + .name = u"country", + .form_control_type = FormControlType::kSelectOne}, + // Add checkable field. + {.label = u"Checkable1", + .name = u"Checkable1", + .check_status = FormFieldData::CheckStatus::kCheckableButUnchecked}, + }}); + std::vector<FieldTypeSet> possible_field_types; std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; - FormData form; - form.url = GURL("http://www.foo.com/"); - form.is_form_tag = true; - - FormFieldData field; - field.form_control_type = FormControlType::kInputText; - - field.label = u"First Name"; - field.name = u"firstname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_FIRST}, {AutofillProfile::ValidityState::kUnvalidated, AutofillProfile::ValidityState::kValid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Last Name"; - field.name = u"lastname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_LAST}, {AutofillProfile::ValidityState::kUnvalidated, AutofillProfile::ValidityState::kValid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Email"; - field.name = u"email"; - field.form_control_type = FormControlType::kInputEmail; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}, {AutofillProfile::ValidityState::kInvalid, AutofillProfile::ValidityState::kValid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Phone"; - field.name = u"phone"; - field.form_control_type = FormControlType::kInputNumber; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {PHONE_HOME_WHOLE_NUMBER}, {AutofillProfile::ValidityState::kEmpty, AutofillProfile::ValidityState::kValid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Country"; - field.name = u"country"; - field.form_control_type = FormControlType::kSelectOne; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}, {AutofillProfile::ValidityState::kValid, AutofillProfile::ValidityState::kValid}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - // Add checkable field. - FormFieldData checkable_field; - checkable_field.check_status = - FormFieldData::CheckStatus::kCheckableButUnchecked; - checkable_field.label = u"Checkable1"; - checkable_field.name = u"Checkable1"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}, {AutofillProfile::ValidityState::kValid, AutofillProfile::ValidityState::kValid}); - checkable_field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(checkable_field); - - form_structure = std::make_unique<FormStructure>(form); - for (auto& fs_field : *form_structure) { + std::unique_ptr<FormStructure> form_structure = + std::make_unique<FormStructure>(form); + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { fs_field->host_form_signature = form_structure->form_signature(); } @@ -593,77 +541,59 @@ test::FillUploadField(upload.add_field(), 2799270304U, 36U, {2, 2}); EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true), + /*login_form_signature=*/"", + /*observed_submission=*/true), ElementsSerializeSameAs(upload)); } TEST_F(AutofillCrowdsourcingEncoding, EncodeUploadRequest) { - std::unique_ptr<FormStructure> form_structure; + FormData form = test::GetFormData( + {.fields = { + {.label = u"First Name", + .name = u"firstname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Last Name", + .name = u"lastname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Email", + .name = u"email", + .form_control_type = FormControlType::kInputEmail}, + {.label = u"Phone", + .name = u"phone", + .form_control_type = FormControlType::kInputNumber}, + {.label = u"Country", + .name = u"country", + .form_control_type = FormControlType::kSelectOne}, + // Add checkable field. + {.label = u"Checkable1", + .name = u"Checkable1", + .check_status = FormFieldData::CheckStatus::kCheckableButUnchecked}, + }}); + std::vector<FieldTypeSet> possible_field_types; std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; - FormData form; - form.url = GURL("http://www.foo.com/"); - form.is_form_tag = true; - - FormFieldData field; - field.form_control_type = FormControlType::kInputText; - - field.label = u"First Name"; - field.name = u"firstname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_FIRST}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Last Name"; - field.name = u"lastname"; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_LAST}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Email"; - field.name = u"email"; - field.form_control_type = FormControlType::kInputEmail; test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Phone"; - field.name = u"phone"; - field.form_control_type = FormControlType::kInputNumber; test::InitializePossibleTypesAndValidities(possible_field_types, possible_field_types_validities, {PHONE_HOME_WHOLE_NUMBER}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - field.label = u"Country"; - field.name = u"country"; - field.form_control_type = FormControlType::kSelectOne; test::InitializePossibleTypesAndValidities(possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}); - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); - - // Add checkable field. - FormFieldData checkable_field; - checkable_field.check_status = - FormFieldData::CheckStatus::kCheckableButUnchecked; - checkable_field.label = u"Checkable1"; - checkable_field.name = u"Checkable1"; test::InitializePossibleTypesAndValidities(possible_field_types, possible_field_types_validities, {ADDRESS_HOME_COUNTRY}); - checkable_field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(checkable_field); - form_structure = std::make_unique<FormStructure>(form); + std::unique_ptr<FormStructure> form_structure = + std::make_unique<FormStructure>(form); form_structure->set_submission_event( SubmissionIndicatorEvent::HTML_FORM_SUBMISSION); - for (auto& fs_field : *form_structure) { + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { fs_field->host_form_signature = form_structure->form_signature(); } @@ -703,11 +633,13 @@ test::FillUploadField(upload.add_field(), 2799270304U, 36U); EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true), + /*login_form_signature=*/"", + /*observed_submission=*/true), ElementsSerializeSameAs(upload)); // Add 2 address fields - this should be still a valid form. for (size_t i = 0; i < 2; ++i) { + FormFieldData field; field.label = u"Address"; field.name = u"address"; field.form_control_type = FormControlType::kInputText; @@ -747,12 +679,14 @@ test::FillUploadField(upload.mutable_field(6), 509334676U, 31U); EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true), + /*login_form_signature=*/"", + /*observed_submission=*/true), ElementsSerializeSameAs(upload)); // Add 300 address fields - now the form is invalid, as it has too many // fields. for (size_t i = 0; i < 300; ++i) { + FormFieldData field; field.label = u"Address"; field.name = u"address"; field.form_control_type = FormControlType::kInputText; @@ -773,7 +707,8 @@ } EXPECT_TRUE(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true) + /*login_form_signature=*/"", + /*observed_submission=*/true) .empty()); } @@ -971,43 +906,32 @@ TEST_F(AutofillCrowdsourcingEncoding, EncodeUploadRequest_ObservedSubmissionFalse) { - std::unique_ptr<FormStructure> form_structure; + FormData form = test::GetFormData( + {.fields = { + {.label = u"First Name", + .name = u"firstname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Last Name", + .name = u"lastname", + .form_control_type = FormControlType::kInputText}, + {.label = u"Email", + .name = u"email", + .form_control_type = FormControlType::kInputEmail}, + }}); + std::vector<FieldTypeSet> possible_field_types; std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; - FormData form; - form.url = GURL("http://www.foo.com/"); - form.is_form_tag = true; - - FormFieldData field; - field.form_control_type = FormControlType::kInputText; - - field.label = u"First Name"; - field.name = u"firstname"; - field.name_attribute = field.name; - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_FIRST}); - - field.label = u"Last Name"; - field.name = u"lastname"; - field.name_attribute = field.name; - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_LAST}); - - field.label = u"Email"; - field.name = u"email"; - field.name_attribute = field.name; - field.form_control_type = FormControlType::kInputEmail; - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}); - form_structure = std::make_unique<FormStructure>(form); - for (auto& fs_field : *form_structure) { + std::unique_ptr<FormStructure> form_structure = + std::make_unique<FormStructure>(form); + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { fs_field->host_form_signature = form_structure->form_signature(); } @@ -1042,43 +966,36 @@ test::FillUploadField(upload.add_field(), 3494530716U, 5U); test::FillUploadField(upload.add_field(), 1029417091U, 9U); - EXPECT_THAT( - EncodeUploadRequest(*form_structure, available_field_types, std::string(), - /* observed_submission= */ false), - ElementsSerializeSameAs(upload)); + EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, + /*login_form_signature=*/"", + /* observed_submission=*/false), + ElementsSerializeSameAs(upload)); } TEST_F(AutofillCrowdsourcingEncoding, EncodeUploadRequest_WithLabels) { - std::unique_ptr<FormStructure> form_structure; + FormData form = + test::GetFormData({.fields = { + // No label for the first field. + {.form_control_type = FormControlType::kInputText}, + {.label = u"Last Name", + .form_control_type = FormControlType::kInputText}, + {.label = u"Email", + .form_control_type = FormControlType::kInputText}, + }}); + std::vector<FieldTypeSet> possible_field_types; std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; - FormData form; - form.url = GURL("http://www.foo.com/"); - form.is_form_tag = true; - - FormFieldData field; - field.form_control_type = FormControlType::kInputText; - - // No label for the first field. - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_FIRST}); - - field.label = u"Last Name"; - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {NAME_LAST}); - - field.label = u"Email"; - field.renderer_id = test::MakeFieldRendererId(); - form.fields.push_back(field); test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}); - form_structure = std::make_unique<FormStructure>(form); - for (auto& fs_field : *form_structure) { + std::unique_ptr<FormStructure> form_structure = + std::make_unique<FormStructure>(form); + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { fs_field->host_form_signature = form_structure->form_signature(); } @@ -1114,7 +1031,72 @@ test::FillUploadField(upload.add_field(), 1318412689U, 9U); EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, - std::string(), true), + /*login_form_signature=*/"", + /*observed_submission=*/true), + ElementsSerializeSameAs(upload)); +} +// Tests the EMAIL_ADDRESS exception on `FirstNonCapturedType`, where email is +// not required as part of the `contained_types`. +TEST_F(AutofillCrowdsourcingEncoding, + EncodeUploadRequest_EmailFieldContentMatched) { + base::test::ScopedFeatureList feature{ + features::kAutofillUploadVotesForFieldsWithEmail}; + FormData form = test::GetFormData( + {.fields = + {{.label = u"First Name", .name = u"firstname"}, + {.label = u"Last Name"}, + // No label or name for the email field, only a valid email value. + {.value = u"foo@email.com"}}, + .url = "http://www.foo.com/"}); + + std::vector<FieldTypeSet> possible_field_types; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; + test::InitializePossibleTypesAndValidities( + possible_field_types, possible_field_types_validities, {NAME_FIRST}); + test::InitializePossibleTypesAndValidities( + possible_field_types, possible_field_types_validities, {NAME_LAST}); + test::InitializePossibleTypesAndValidities( + possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}); + + std::unique_ptr<FormStructure> form_structure = + std::make_unique<FormStructure>(form); + for (const std::unique_ptr<autofill::AutofillField>& fs_field : + *form_structure) { + fs_field->host_form_signature = form_structure->form_signature(); + } + + ASSERT_EQ(form_structure->field_count(), possible_field_types.size()); + ASSERT_EQ(form_structure->field_count(), + possible_field_types_validities.size()); + + for (size_t i = 0; i < form_structure->field_count(); ++i) { + form_structure->field(i)->set_possible_types(possible_field_types[i]); + form_structure->field(i)->set_possible_types_validities( + possible_field_types_validities[i]); + } + + // No available EMAIL_ADRESS on field_types. + FieldTypeSet available_field_types = {NAME_FIRST, NAME_LAST}; + + // Prepare the expected proto string. + AutofillUploadContents upload; + upload.set_submission(true); + upload.set_client_version( + std::string(GetProductNameAndVersionForUserAgent())); + upload.set_form_signature(form_structure->form_signature().value()); + upload.set_autofill_used(false); + upload.set_data_present("14"); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); + + test::FillUploadField(upload.add_field(), 3763331450U, 3U); + test::FillUploadField(upload.add_field(), 1318412689U, 5U); + test::FillUploadField(upload.add_field(), 1318412689U, 9U); + + EXPECT_THAT(EncodeUploadRequest(*form_structure, available_field_types, + /*login_form_signature=*/"", + /*observed_submission=*/true), ElementsSerializeSameAs(upload)); }
diff --git a/components/autofill/core/browser/filling_product.cc b/components/autofill/core/browser/filling_product.cc index e1399c4..19ebafe3 100644 --- a/components/autofill/core/browser/filling_product.cc +++ b/components/autofill/core/browser/filling_product.cc
@@ -61,13 +61,11 @@ case PopupItemId::kAutocompleteEntry: return FillingProduct::kAutocomplete; case PopupItemId::kPasswordEntry: - case PopupItemId::kUsernameEntry: case PopupItemId::kAllSavedPasswordsEntry: case PopupItemId::kGeneratePasswordEntry: case PopupItemId::kPasswordAccountStorageOptIn: case PopupItemId::kPasswordAccountStorageOptInAndGenerate: case PopupItemId::kAccountStoragePasswordEntry: - case PopupItemId::kAccountStorageUsernameEntry: case PopupItemId::kPasswordAccountStorageReSignin: case PopupItemId::kPasswordAccountStorageEmpty: case PopupItemId::kWebauthnCredential:
diff --git a/components/autofill/core/browser/form_filler_unittest.cc b/components/autofill/core/browser/form_filler_unittest.cc new file mode 100644 index 0000000..791ff06 --- /dev/null +++ b/components/autofill/core/browser/form_filler_unittest.cc
@@ -0,0 +1,3403 @@ +// 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 <stddef.h> + +#include <memory> +#include <optional> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +#include "base/containers/span.h" +#include "base/feature_list.h" +#include "base/ranges/algorithm.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "build/build_config.h" +#include "build/chromeos_buildflags.h" +#include "components/autofill/core/browser/autofill_form_test_utils.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/browser_autofill_manager.h" +#include "components/autofill/core/browser/browser_autofill_manager_test_api.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/data_model/credit_card.h" +#include "components/autofill/core/browser/filling_product.h" +#include "components/autofill/core/browser/form_structure_test_api.h" +#include "components/autofill/core/browser/geo/alternative_state_name_map_test_utils.h" +#include "components/autofill/core/browser/mock_single_field_form_fill_router.h" +#include "components/autofill/core/browser/payments/test_credit_card_save_manager.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/profile_token_quality.h" +#include "components/autofill/core/browser/test_autofill_client.h" +#include "components/autofill/core/browser/test_autofill_driver.h" +#include "components/autofill/core/browser/test_autofill_manager_waiter.h" +#include "components/autofill/core/browser/test_browser_autofill_manager.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/autofill/core/common/autofill_clock.h" +#include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_payments_features.h" +#include "components/autofill/core/common/autofill_prefs.h" +#include "components/autofill/core/common/autofill_test_utils.h" +#include "components/autofill/core/common/autofill_util.h" +#include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/form_field_data.h" +#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" +#include "components/prefs/pref_service.h" +#include "components/sync/test/test_sync_service.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { + +namespace { + +using ::base::UTF8ToUTF16; +using mojom::SubmissionSource; +using test::CreateTestAddressFormData; +using test::CreateTestFormField; +using test::CreateTestPersonalInformationFormData; +using test::CreateTestSelectField; +using test::CreateTestSelectOrSelectListField; +using ::testing::AtLeast; +using ::testing::DoAll; +using ::testing::Each; +using ::testing::Eq; +using ::testing::Field; +using ::testing::NiceMock; +using ::testing::Not; +using ::testing::Return; +using ::testing::SaveArg; + +struct TestAddressFillData { + TestAddressFillData(const char* first, + const char* middle, + const char* last, + const char* address1, + const char* address2, + const char* city, + const char* state, + const char* postal_code, + const char* country, + const char* country_short, + const char* phone, + const char* email, + const char* company) + : first(first), + middle(middle), + last(last), + address1(address1), + address2(address2), + city(city), + state(state), + postal_code(postal_code), + country(country), + country_short(country_short), + phone(phone), + email(email), + company(company) {} + + const char* first; + const char* middle; + const char* last; + const char* address1; + const char* address2; + const char* city; + const char* state; + const char* postal_code; + const char* country; + const char* country_short; + const char* phone; + const char* email; + const char* company; +}; + +struct TestCardFillData { + TestCardFillData(const char* name_on_card, + const char* card_number, + const char* expiration_month, + const char* expiration_year, + bool use_month_type) + : name_on_card(name_on_card), + card_number(card_number), + expiration_month(expiration_month), + expiration_year(expiration_year), + use_month_type(use_month_type) {} + const char* name_on_card; + const char* card_number; + const char* expiration_month; + const char* expiration_year; + bool use_month_type; +}; + +const TestAddressFillData + kEmptyAddressFillData("", "", "", "", "", "", "", "", "", "", "", "", ""); + +const TestCardFillData kEmptyCardFillData("", + "", + "", + "", + /*use_month_type=*/false); + +const TestCardFillData kElvisCardFillData("Elvis Presley", + "4234567890123456", + "04", + "2999", + /*use_month_type*/ false); + +TestAddressFillData GetElvisAddressFillData() { + return { + "Elvis", + "Aaron", + "Presley", + "3734 Elvis Presley Blvd.", + "Apt. 10", + "Memphis", + "Tennessee", + "38116", + "United States", + "US", + base::FeatureList::IsEnabled(features::kAutofillDefaultToCityAndNumber) + ? "2345678901" + : "12345678901", + "theking@gmail.com", + "RCA"}; +} + +// Creates a GUID for testing. For example, +// MakeGuid(123) = "00000000-0000-0000-0000-000000000123"; +std::string MakeGuid(size_t last_digit) { + return base::StringPrintf("00000000-0000-0000-0000-%012zu", last_digit); +} + +std::string kElvisProfileGuid = MakeGuid(1); + +class MockAutofillClient : public TestAutofillClient { + public: + MockAutofillClient() { + ON_CALL(*this, GetChannel()) + .WillByDefault(Return(version_info::Channel::UNKNOWN)); + ON_CALL(*this, IsPasswordManagerEnabled()).WillByDefault(Return(true)); + } + MockAutofillClient(const MockAutofillClient&) = delete; + MockAutofillClient& operator=(const MockAutofillClient&) = delete; + ~MockAutofillClient() override = default; + + MOCK_METHOD(version_info::Channel, GetChannel, (), (const override)); + MOCK_METHOD(AutofillOptimizationGuide*, + GetAutofillOptimizationGuide, + (), + (const override)); + MOCK_METHOD(profile_metrics::BrowserProfileType, + GetProfileType, + (), + (const override)); + MOCK_METHOD(void, HideAutofillPopup, (PopupHidingReason reason), (override)); + MOCK_METHOD(bool, IsPasswordManagerEnabled, (), (override)); + MOCK_METHOD(void, + DidFillOrPreviewForm, + (mojom::ActionPersistence action_persistence, + AutofillTriggerSource trigger_source, + bool is_refill), + (override)); + MOCK_METHOD(bool, HasCreditCardScanFeature, (), (const override)); + MOCK_METHOD(void, + TriggerUserPerceptionOfAutofillSurvey, + ((const std::map<std::string, std::string>&)), + (override)); + MOCK_METHOD(AutofillComposeDelegate*, GetComposeDelegate, (), (override)); + MOCK_METHOD(void, + OnVirtualCardDataAvailable, + (const VirtualCardManualFallbackBubbleOptions&), + (override)); +}; + +AutofillProfile FillDataToAutofillProfile(const TestAddressFillData& data) { + AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); + test::SetProfileInfo(&profile, data.first, data.middle, data.last, data.email, + data.company, data.address1, data.address2, data.city, + data.state, data.postal_code, data.country_short, + data.phone); + return profile; +} + +CreditCard FillDataToCreditCardInfo(const TestCardFillData& data) { + CreditCard card; + test::SetCreditCardInfo(&card, data.name_on_card, data.card_number, + data.expiration_month, data.expiration_year, "1"); + return card; +} + +void ExpectFilledField(const char* expected_label, + const char* expected_name, + const char* expected_value, + FormControlType expected_form_control_type, + const FormFieldData& field) { + SCOPED_TRACE(expected_label); + EXPECT_EQ(UTF8ToUTF16(expected_label), field.label); + EXPECT_EQ(UTF8ToUTF16(expected_name), field.name); + EXPECT_EQ(UTF8ToUTF16(expected_value), field.value); + EXPECT_EQ(expected_form_control_type, field.form_control_type); +} + +// Verifies that the |filled_form| has been filled with the given data. +// Verifies address fields if |has_address_fields| is true, and verifies +// credit card fields if |has_credit_card_fields| is true. Verifies both if both +// are true. |use_month_type| is used for credit card input month type. +void ExpectFilledForm( + const FormData& filled_form, + const std::optional<TestAddressFillData>& address_fill_data, + const std::optional<TestCardFillData>& card_fill_data) { + // The number of fields in the address and credit card forms created above. + const size_t kAddressFormSize = 11; + const size_t kCreditCardFormSizeMonthType = 4; + const size_t kCreditCardFormSizeNotMonthType = 5; + + EXPECT_EQ(u"MyForm", filled_form.name); + EXPECT_EQ(GURL("https://myform.com/form.html"), filled_form.url); + EXPECT_EQ(GURL("https://myform.com/submit.html"), filled_form.action); + + size_t form_size = 0; + if (address_fill_data) { + form_size += kAddressFormSize; + } + if (card_fill_data) { + form_size += card_fill_data->use_month_type + ? kCreditCardFormSizeMonthType + : kCreditCardFormSizeNotMonthType; + } + ASSERT_EQ(form_size, filled_form.fields.size()); + + if (address_fill_data) { + ExpectFilledField("First Name", "firstname", address_fill_data->first, + FormControlType::kInputText, filled_form.fields[0]); + ExpectFilledField("Middle Name", "middlename", address_fill_data->middle, + FormControlType::kInputText, filled_form.fields[1]); + ExpectFilledField("Last Name", "lastname", address_fill_data->last, + FormControlType::kInputText, filled_form.fields[2]); + ExpectFilledField("Address Line 1", "addr1", address_fill_data->address1, + FormControlType::kInputText, filled_form.fields[3]); + ExpectFilledField("Address Line 2", "addr2", address_fill_data->address2, + FormControlType::kInputText, filled_form.fields[4]); + ExpectFilledField("City", "city", address_fill_data->city, + FormControlType::kInputText, filled_form.fields[5]); + ExpectFilledField("State", "state", address_fill_data->state, + FormControlType::kInputText, filled_form.fields[6]); + ExpectFilledField("Postal Code", "zipcode", address_fill_data->postal_code, + FormControlType::kInputText, filled_form.fields[7]); + ExpectFilledField("Country", "country", address_fill_data->country, + FormControlType::kInputText, filled_form.fields[8]); + ExpectFilledField("Phone Number", "phonenumber", address_fill_data->phone, + FormControlType::kInputTelephone, filled_form.fields[9]); + ExpectFilledField("Email", "email", address_fill_data->email, + FormControlType::kInputEmail, filled_form.fields[10]); + } + + if (card_fill_data) { + size_t offset = address_fill_data ? kAddressFormSize : 0; + ExpectFilledField("Name on Card", "nameoncard", + card_fill_data->name_on_card, FormControlType::kInputText, + filled_form.fields[offset + 0]); + ExpectFilledField("Card Number", "cardnumber", card_fill_data->card_number, + FormControlType::kInputText, + filled_form.fields[offset + 1]); + if (card_fill_data->use_month_type) { + std::string exp_year = card_fill_data->expiration_year; + std::string exp_month = card_fill_data->expiration_month; + std::string date; + if (!exp_year.empty() && !exp_month.empty()) { + date = exp_year + "-" + exp_month; + } + + ExpectFilledField("Expiration Date", "ccmonth", date.c_str(), + FormControlType::kInputMonth, + filled_form.fields[offset + 2]); + } else { + ExpectFilledField( + "Expiration Date", "ccmonth", card_fill_data->expiration_month, + FormControlType::kInputText, filled_form.fields[offset + 2]); + ExpectFilledField("", "ccyear", card_fill_data->expiration_year, + FormControlType::kInputText, + filled_form.fields[offset + 3]); + } + } +} + +void ExpectFilledAddressFormElvis(const FormData& filled_form, + bool has_credit_card_fields) { + std::optional<TestCardFillData> expected_card_fill_data; + if (has_credit_card_fields) { + expected_card_fill_data = kEmptyCardFillData; + } + ExpectFilledForm(filled_form, GetElvisAddressFillData(), + expected_card_fill_data); +} + +void ExpectFilledCreditCardFormElvis(const FormData& filled_form, + bool has_address_fields) { + std::optional<TestAddressFillData> expected_address_fill_data; + if (has_address_fields) { + expected_address_fill_data = kEmptyAddressFillData; + } + ExpectFilledForm(filled_form, expected_address_fill_data, kElvisCardFillData); +} + +class MockAutofillDriver : public TestAutofillDriver { + public: + MockAutofillDriver() = default; + MockAutofillDriver(const MockAutofillDriver&) = delete; + MockAutofillDriver& operator=(const MockAutofillDriver&) = delete; + + // Mock methods to enable testability. + MOCK_METHOD((base::flat_set<FieldGlobalId>), + ApplyFormAction, + (mojom::ActionType action_type, + mojom::ActionPersistence action_persistence, + const FormData& data, + const url::Origin& triggered_origin, + (const base::flat_map<FieldGlobalId, FieldType>&)), + (override)); + MOCK_METHOD(void, + ApplyFieldAction, + (mojom::ActionPersistence action_persistence, + mojom::TextReplacement text_replacement, + const FieldGlobalId& field_id, + const std::u16string& value), + (override)); + MOCK_METHOD( + void, + SendAutofillTypePredictionsToRenderer, + (const std::vector<vector_experimental_raw_ptr<FormStructure>>& forms), + (override)); +}; + +MATCHER_P(HasValue, value, "") { + return arg.value == value; +} + +} // namespace + +class FormFillerTest : public testing::Test { + public: + void SetUp() override { + // Advance the mock clock to a fixed, arbitrary, somewhat recent date. + base::Time year2020; + ASSERT_TRUE(base::Time::FromString("01/01/20", &year2020)); + task_environment_.FastForwardBy(year2020 - AutofillClock::Now()); + + autofill_client_.SetPrefs(test::PrefServiceForTesting()); + personal_data().set_auto_accept_address_imports_for_testing(true); + personal_data().SetPrefService(autofill_client_.GetPrefs()); + personal_data().SetSyncServiceForTest(&sync_service_); + + autofill_driver_ = std::make_unique<NiceMock<MockAutofillDriver>>(); + autofill_client_.set_test_payments_network_interface( + std::make_unique<payments::TestPaymentsNetworkInterface>( + autofill_client_.GetURLLoaderFactory(), + autofill_client_.GetIdentityManager(), &personal_data())); + auto credit_card_save_manager = std::make_unique<TestCreditCardSaveManager>( + autofill_driver_.get(), &autofill_client_, &personal_data()); + credit_card_save_manager->SetCreditCardUploadEnabled(true); + autofill_client_.set_test_form_data_importer( + std::make_unique<autofill::TestFormDataImporter>( + &autofill_client_, std::move(credit_card_save_manager), + /*iban_save_manager=*/nullptr, &personal_data(), "en-US")); + + ResetBrowserAutofillManager(); + // By default, if we offer single field form fill, suggestions should be + // returned because it is assumed |field.should_autocomplete| is set to + // true. This should be overridden in tests where + // |field.should_autocomplete| is set to false. + ON_CALL(single_field_form_fill_router(), OnGetSingleFieldSuggestions) + .WillByDefault(Return(true)); + + autofill_client_.set_test_strike_database( + std::make_unique<TestStrikeDatabase>()); + + // Initialize the TestPersonalDataManager with some default data. + CreateTestAutofillProfiles(); + CreateTestCreditCards(); + + // Mandatory re-auth is required for credit card autofill on automotive, so + // the authenticator response needs to be properly mocked. +#if BUILDFLAG(IS_ANDROID) + autofill_client_.SetUpDeviceBiometricAuthenticatorSuccessOnAutomotive(); +#endif + } + + void TearDown() override { + // Order of destruction is important as BrowserAutofillManager relies on + // PersonalDataManager to be around when it gets destroyed. + browser_autofill_manager_.reset(); + + personal_data().SetPrefService(nullptr); + personal_data().ClearCreditCards(); + } + + void FormsSeen(const std::vector<FormData>& forms) { + browser_autofill_manager_->OnFormsSeen(/*updated_forms=*/forms, + /*removed_forms=*/{}); + } + + void FormSubmitted(const FormData& form) { + browser_autofill_manager_->OnFormSubmitted( + form, false, SubmissionSource::FORM_SUBMISSION); + } + + // TODO(crbug.com/1330108): Have separate functions for profile and credit + // card filling. + void FillAutofillFormData( + const FormData& form, + const FormFieldData& field, + std::string guid, + AutofillTriggerDetails trigger_details = { + .trigger_source = AutofillTriggerSource::kPopup}) { + browser_autofill_manager_->OnAskForValuesToFill( + form, field, {}, + AutofillSuggestionTriggerSource::kTextFieldDidReceiveKeyDown); + if (const AutofillProfile* profile = + personal_data().GetProfileByGUID(guid)) { + browser_autofill_manager_->FillOrPreviewProfileForm( + mojom::ActionPersistence::kFill, form, field, *profile, + trigger_details); + } else if (const CreditCard* card = + personal_data().GetCreditCardByGUID(guid)) { + browser_autofill_manager_->FillOrPreviewCreditCardForm( + mojom::ActionPersistence::kFill, form, field, *card, trigger_details); + } + } + + // Calls |browser_autofill_manager_->OnFillAutofillFormData()| with the + // specified input parameters after setting up the expectation that the mock + // driver's |ApplyFormAction()| method will be called and saving the parameter + // of that call into the |response_data| output parameter. + FormData FillAutofillFormDataAndGetResults( + const FormData& input_form, + const FormFieldData& input_field, + std::string guid, + AutofillTriggerDetails trigger_details = { + .trigger_source = AutofillTriggerSource::kPopup}) { + FormData response_data; + std::vector<FieldGlobalId> global_ids; + for (const auto& field : input_form.fields) { + global_ids.push_back(field.global_id()); + } + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .WillOnce(DoAll(SaveArg<2>(&response_data), Return(global_ids))); + FillAutofillFormData(input_form, input_field, guid, trigger_details); + return response_data; + } + + FormData PreviewVirtualCardDataAndGetResults( + mojom::ActionPersistence action_persistence, + const FormData& input_form, + const FormFieldData& input_field, + const CreditCard& virtual_card) { + FormData response_data; + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .WillOnce((DoAll(SaveArg<2>(&response_data), + Return(std::vector<FieldGlobalId>{})))); + browser_autofill_manager_->FillOrPreviewCreditCardForm( + action_persistence, input_form, input_field, virtual_card, + {.trigger_source = AutofillTriggerSource::kPopup}); + return response_data; + } + + FormData CreateTestCreditCardFormData(bool is_https, bool use_month_type) { + FormData form; + CreateTestCreditCardFormData(&form, is_https, use_month_type); + return form; + } + + // Populates |form| with data corresponding to a simple credit card form. + // Note that this actually appends fields to the form data, which can be + // useful for building up more complex test forms. + void CreateTestCreditCardFormData(FormData* form, + bool is_https, + bool use_month_type) { + form->name = u"MyForm"; + if (is_https) { + GURL::Replacements replacements; + replacements.SetSchemeStr(url::kHttpsScheme); + autofill_client_.set_form_origin( + autofill_client_.form_origin().ReplaceComponents(replacements)); + form->url = GURL("https://myform.com/form.html"); + form->action = GURL("https://myform.com/submit.html"); + } else { + // If we are testing a form that submits over HTTP, we also need to set + // the main frame to HTTP, otherwise mixed form warnings will trigger and + // autofill will be disabled. + GURL::Replacements replacements; + replacements.SetSchemeStr(url::kHttpScheme); + autofill_client_.set_form_origin( + autofill_client_.form_origin().ReplaceComponents(replacements)); + form->url = GURL("http://myform.com/form.html"); + form->action = GURL("http://myform.com/submit.html"); + } + + form->fields.push_back(CreateTestFormField("Name on Card", "nameoncard", "", + FormControlType::kInputText)); + form->fields.push_back(CreateTestFormField("Card Number", "cardnumber", "", + FormControlType::kInputText)); + if (use_month_type) { + form->fields.push_back(CreateTestFormField( + "Expiration Date", "ccmonth", "", FormControlType::kInputMonth)); + } else { + form->fields.push_back(CreateTestFormField( + "Expiration Date", "ccmonth", "", FormControlType::kInputText)); + form->fields.push_back( + CreateTestFormField("", "ccyear", "", FormControlType::kInputText)); + } + form->fields.push_back( + CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)); + } + + void PrepareForRealPanResponse(FormData* form, CreditCard* card) { + // This line silences the warning from PaymentsNetworkInterface about + // matching sync and Payments server types. + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + "sync-url", "https://google.com"); + + CreateTestCreditCardFormData(form, true, false); + FormsSeen({*form}); + *card = CreditCard(CreditCard::RecordType::kMaskedServerCard, "a123"); + test::SetCreditCardInfo(card, "John Dillinger", "1881" /* Visa */, "01", + "2017", "1"); + card->SetNetworkForMaskedCard(kVisaCard); + + EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(AtLeast(1)); + browser_autofill_manager_->FillOrPreviewCreditCardForm( + mojom::ActionPersistence::kFill, *form, form->fields[0], *card, + {.trigger_source = AutofillTriggerSource::kPopup}); + } + + void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result, + const std::string& real_pan, + bool is_virtual_card = false) { + payments::FullCardRequest* full_card_request = + browser_autofill_manager_->client() + .GetCvcAuthenticator() + ->full_card_request_.get(); + DCHECK(full_card_request); + + // Mock user response. + payments::FullCardRequest::UserProvidedUnmaskDetails details; + details.cvc = u"123"; + full_card_request->OnUnmaskPromptAccepted(details); + + // Mock payments response. + payments::PaymentsNetworkInterface::UnmaskResponseDetails response; + response.card_type = is_virtual_card + ? AutofillClient::PaymentsRpcCardType::kVirtualCard + : AutofillClient::PaymentsRpcCardType::kServerCard; + full_card_request->OnDidGetRealPan(result, + response.with_real_pan(real_pan)); + } + + // Convenience method to cast the FullCardRequest into a CardUnmaskDelegate. + CardUnmaskDelegate* full_card_unmask_delegate() { + payments::FullCardRequest* full_card_request = + browser_autofill_manager_->client() + .GetCvcAuthenticator() + ->full_card_request_.get(); + DCHECK(full_card_request); + return static_cast<CardUnmaskDelegate*>(full_card_request); + } + + void ResetBrowserAutofillManager() { + browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>( + autofill_driver_.get(), &autofill_client_); + + test_api(*browser_autofill_manager_) + .set_single_field_form_fill_router( + std::make_unique<NiceMock<MockSingleFieldFormFillRouter>>( + autofill_client_.GetMockAutocompleteHistoryManager(), + autofill_client_.GetMockIbanManager(), + autofill_client_.GetMockMerchantPromoCodeManager())); + } + + TestPersonalDataManager& personal_data() { + return *autofill_client_.GetPersonalDataManager(); + } + + protected: + MockSingleFieldFormFillRouter& single_field_form_fill_router() { + return static_cast<MockSingleFieldFormFillRouter&>( + test_api(*browser_autofill_manager_).single_field_form_fill_router()); + } + + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + test::AutofillUnitTestEnvironment autofill_test_environment_; + NiceMock<MockAutofillClient> autofill_client_; + std::unique_ptr<MockAutofillDriver> autofill_driver_; + syncer::TestSyncService sync_service_; + std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_; + + private: + void CreateTestAutofillProfiles() { + AutofillProfile profile1 = + FillDataToAutofillProfile(GetElvisAddressFillData()); + profile1.set_guid(kElvisProfileGuid); + profile1.set_use_date(AutofillClock::Now() - base::Days(2)); + personal_data().AddProfile(profile1); + + AutofillProfile profile2( + i18n_model_definition::kLegacyHierarchyCountryCode); + test::SetProfileInfo(&profile2, "Charles", "Hardin", "Holley", + "buddy@gmail.com", "Decca", "123 Apple St.", "unit 6", + "Lubbock", "Texas", "79401", "US", "23456789012"); + profile2.set_guid(MakeGuid(2)); + profile2.set_use_date(AutofillClock::Now() - base::Days(1)); + personal_data().AddProfile(profile2); + + AutofillProfile profile3( + i18n_model_definition::kLegacyHierarchyCountryCode); + test::SetProfileInfo(&profile3, "", "", "", "", "", "", "", "", "", "", "", + ""); + profile3.set_guid(MakeGuid(3)); + profile3.set_use_date(AutofillClock::Now()); + personal_data().AddProfile(profile3); + } + + void CreateTestCreditCards() { + CreditCard credit_card1; + test::SetCreditCardInfo(&credit_card1, "Elvis Presley", + "4234567890123456", // Visa + "04", "2999", "1"); + credit_card1.set_guid(MakeGuid(4)); + credit_card1.set_use_count(10); + credit_card1.set_use_date(AutofillClock::Now() - base::Days(5)); + personal_data().AddCreditCard(credit_card1); + + CreditCard credit_card2; + test::SetCreditCardInfo(&credit_card2, "Buddy Holly", + "5187654321098765", // Mastercard + "10", "2998", "1"); + credit_card2.set_guid(MakeGuid(5)); + credit_card2.set_use_count(5); + credit_card2.set_use_date(AutofillClock::Now() - base::Days(4)); + personal_data().AddCreditCard(credit_card2); + + CreditCard credit_card3; + test::SetCreditCardInfo(&credit_card3, "", "", "08", "2999", ""); + credit_card3.set_guid(MakeGuid(6)); + personal_data().AddCreditCard(credit_card3); + } +}; + +// Tests that only fields from `field_types_to_fill` are filled. +TEST_F(FormFillerTest, FillingDetails_FieldTypesToFill_FillOnlySpecificFields) { + base::test::ScopedFeatureList enabled_features( + features::kAutofillGranularFillingAvailable); + // Set up our form data. + FormData form = test::GetFormData( + {.fields = { + {.role = NAME_FIRST, .autocomplete_attribute = "given-name"}, + {.role = NAME_LAST, .autocomplete_attribute = "family-name"}}}); + FormsSeen({form}); + // Only `NAME_FIRST` fields should be filled. + FieldTypeSet target_fields = FieldTypeSet({NAME_FIRST}); + FormData response_data = FillAutofillFormDataAndGetResults( + form, form.fields[0], MakeGuid(1), + {.trigger_source = AutofillTriggerSource::kPopup, + .field_types_to_fill = target_fields}); + + ASSERT_EQ(response_data.fields.size(), 2u); + // The city field was filled. + EXPECT_EQ(response_data.fields[0].name, u"firstName"); + EXPECT_EQ(response_data.fields[0].value, + UTF8ToUTF16(GetElvisAddressFillData().first)); + // The city field was NOT filled. + EXPECT_EQ(response_data.fields[1].name, u"lastName"); + EXPECT_EQ(response_data.fields[1].value, u""); +} + +// Test that the call is properly forwarded to its SingleFieldFormFillRouter. +TEST_F(FormFillerTest, OnSingleFieldSuggestionSelected) { + std::u16string test_value = u"TestValue"; + FormData form = CreateTestAddressFormData(); + FormFieldData field = form.fields[0]; + + EXPECT_CALL(single_field_form_fill_router(), + OnSingleFieldSuggestionSelected(test_value, + PopupItemId::kAutocompleteEntry)) + .Times(1); + + browser_autofill_manager_->OnSingleFieldSuggestionSelected( + test_value, PopupItemId::kAutocompleteEntry, form, field); + + EXPECT_CALL(single_field_form_fill_router(), + OnSingleFieldSuggestionSelected(test_value, + PopupItemId::kAutocompleteEntry)) + .Times(1); + + browser_autofill_manager_->OnSingleFieldSuggestionSelected( + test_value, PopupItemId::kAutocompleteEntry, form, field); + + EXPECT_CALL( + single_field_form_fill_router(), + OnSingleFieldSuggestionSelected(test_value, PopupItemId::kIbanEntry)) + .Times(1); + + browser_autofill_manager_->OnSingleFieldSuggestionSelected( + test_value, PopupItemId::kIbanEntry, form, field); + + EXPECT_CALL(single_field_form_fill_router(), + OnSingleFieldSuggestionSelected( + test_value, PopupItemId::kMerchantPromoCodeEntry)) + .Times(1); + + browser_autofill_manager_->OnSingleFieldSuggestionSelected( + test_value, PopupItemId::kMerchantPromoCodeEntry, form, field); +} + +// Test that the correct section is filled. +TEST_F(FormFillerTest, FillTriggeredSection) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + size_t index_of_trigger_field = form.fields.size(); + base::ranges::move(CreateTestAddressFormData().fields, + std::back_inserter(form.fields)); + FormsSeen({form}); + + // Check that the form has been parsed into two sections. + ASSERT_NE(form.fields.size(), 0u); + ASSERT_EQ(index_of_trigger_field, form.fields.size() / 2); + { + FormStructure* form_structure; + AutofillField* autofill_field; + bool found = browser_autofill_manager_->GetCachedFormAndField( + form, form.fields[index_of_trigger_field], &form_structure, + &autofill_field); + ASSERT_TRUE(found); + for (size_t i = 0; i < form.fields.size() / 2; ++i) { + size_t j = form.fields.size() / 2 + i; + ASSERT_EQ(form_structure->field(i)->name, form_structure->field(j)->name); + ASSERT_NE(form_structure->field(i)->section, + form_structure->field(j)->section); + ASSERT_TRUE(form_structure->field(i)->SameFieldAs(form.fields[j])); + ASSERT_TRUE(form_structure->field(j)->SameFieldAs(form.fields[i])); + } + } + + AutofillProfile* profile = personal_data().GetProfileByGUID(MakeGuid(1)); + ASSERT_TRUE(profile); + EXPECT_EQ(1U, profile->use_count()); + EXPECT_NE(base::Time(), profile->use_date()); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, form.fields[index_of_trigger_field], MakeGuid(1)); + // Extract the sections into individual forms to reduce boiler plate code. + size_t mid = response_data.fields.size() / 2; + FormData section1 = response_data; + FormData section2 = response_data; + section1.fields.erase(section1.fields.begin() + mid, section1.fields.end()); + section2.fields.erase(section2.fields.begin(), section2.fields.end() - mid); + // First section should be empty, second should be filled. + ExpectFilledForm(section1, kEmptyAddressFillData, + /*card_fill_data=*/std::nullopt); + ExpectFilledAddressFormElvis(section2, false); +} + +// Test that if the form cache is outdated because a field has changed, filling +// is aborted after that field. +TEST_F(FormFillerTest, DoNotFillIfFormFieldChanged) { + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + + FormStructure* form_structure = nullptr; + AutofillField* autofill_field = nullptr; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + + // Modify `form` so that it doesn't match `form_structure` anymore. + ASSERT_GE(form.fields.size(), 3u); + for (auto it = form.fields.begin() + 2; it != form.fields.end(); ++it) { + *it = FormFieldData(); + } + + AutofillProfile* profile = + personal_data().GetProfileByGUID(kElvisProfileGuid); + ASSERT_TRUE(profile); + + FormData response_data; + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .WillOnce((DoAll(SaveArg<2>(&response_data), + Return(std::vector<FieldGlobalId>{})))); + test_api(*browser_autofill_manager_) + .FillOrPreviewDataModelForm(mojom::ActionPersistence::kFill, form, + form.fields.front(), profile, std::nullopt, + form_structure, autofill_field); + std::vector<FormFieldData> filled_fields(response_data.fields.begin(), + response_data.fields.begin() + 2); + std::vector<FormFieldData> skipped_fields(response_data.fields.begin() + 2, + response_data.fields.end()); + + EXPECT_THAT(filled_fields, Each(Not(HasValue(u"")))); + EXPECT_THAT(skipped_fields, Each(HasValue(u""))); +} + +// Test that if the form cache is outdated because the form has changed, filling +// is aborted because of that change. +TEST_F(FormFillerTest, DoNotFillIfFormChanged) { + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + + FormStructure* form_structure = nullptr; + AutofillField* autofill_field = nullptr; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + + // Modify `form` so that it doesn't match `form_structure` anymore. + ASSERT_GE(form.fields.size(), 3u); + form.fields.pop_back(); + + AutofillProfile* profile = + personal_data().GetProfileByGUID(kElvisProfileGuid); + ASSERT_TRUE(profile); + + FormData response_data; + EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); + test_api(*browser_autofill_manager_) + .FillOrPreviewDataModelForm(mojom::ActionPersistence::kFill, form, + form.fields.front(), profile, std::nullopt, + form_structure, autofill_field); +} + +TEST_F(FormFillerTest, SkipFillIfFieldIsMeaningfullyPreFilled) { + base::test::ScopedFeatureList placeholders_feature{ + features::kAutofillOverwritePlaceholdersOnly}; + + const FieldType kSkippedType = ADDRESS_HOME_LINE1; + FormData form = test::GetFormData( + {.fields = {{.role = NAME_FIRST, .value = u"Triggering field (filled)"}, + {.role = NAME_LAST, .value = u"Placeholder (filled)"}, + {.role = EMAIL_ADDRESS, .value = u"No data (filled)"}, + {.role = kSkippedType, + .value = u"Meaningfully pre-filled (skipped)"}}}); + FormsSeen({form}); + + FormStructure* form_structure = nullptr; + AutofillField* autofill_field = nullptr; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + form_structure->fields()[0]->set_may_use_prefilled_placeholder(false); + form_structure->fields()[1]->set_may_use_prefilled_placeholder(true); + form_structure->fields()[3]->set_may_use_prefilled_placeholder(false); + + AutofillProfile* profile = + personal_data().GetProfileByGUID(kElvisProfileGuid); + ASSERT_TRUE(profile); + + FormData filled_form; + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .WillOnce((DoAll(SaveArg<2>(&filled_form), + Return(std::vector<FieldGlobalId>{})))); + test_api(*browser_autofill_manager_) + .FillOrPreviewDataModelForm(mojom::ActionPersistence::kFill, form, + form.fields.front(), profile, std::nullopt, + form_structure, autofill_field); + + auto expect_hash = [&](const FormFieldData& field, + std::optional<size_t> expected_hash) { + AutofillField* autofill_field = nullptr; + FormStructure* form_structure = nullptr; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, field, &form_structure, &autofill_field)); + ASSERT_TRUE(autofill_field); + EXPECT_THAT( + autofill_field->field_log_events(), + Contains(VariantWith<FillFieldLogEvent>(Field( + "value_that_would_have_been_filled_in_a_prefilled_field_hash", + &FillFieldLogEvent:: + value_that_would_have_been_filled_in_a_prefilled_field_hash, + testing::Conditional(expected_hash.has_value(), + testing::Optional(expected_hash), + Eq(std::nullopt)))))); + }; + + const auto& filled_fields = filled_form.fields; + EXPECT_TRUE(filled_fields[0].is_autofilled); + EXPECT_EQ(filled_fields[0].value, profile->GetRawInfo(NAME_FIRST)); + expect_hash(filled_fields[0], std::nullopt); + EXPECT_TRUE(filled_fields[1].is_autofilled); + EXPECT_EQ(filled_fields[1].value, profile->GetRawInfo(NAME_LAST)); + expect_hash(filled_fields[1], std::nullopt); + EXPECT_TRUE(filled_fields[2].is_autofilled); + EXPECT_EQ(filled_fields[2].value, profile->GetRawInfo(EMAIL_ADDRESS)); + expect_hash(filled_fields[2], std::nullopt); + EXPECT_FALSE(filled_fields[3].is_autofilled); + EXPECT_EQ(filled_fields[3].value, form.fields[3].value); + expect_hash( + filled_fields[3], + base::FastHash(base::UTF16ToUTF8(profile->GetRawInfo(kSkippedType)))); +} + +TEST_F(FormFillerTest, SkipAllPreFilledFieldsExceptIfFieldIsAPlaceholder) { + base::test::ScopedFeatureList placeholders_features; + placeholders_features.InitWithFeatures( + {features::kAutofillOverwritePlaceholdersOnly, + features::kAutofillSkipPreFilledFields}, + {}); + + AutofillProfile* profile = + personal_data().GetProfileByGUID(kElvisProfileGuid); + ASSERT_TRUE(profile); + const std::u16string kToBeFilledState = + profile->GetRawInfo(ADDRESS_HOME_STATE); + const std::u16string kSelectedState = u"NC (filled)"; + FormData form = test::GetFormData( + {.fields = { + {.role = NAME_FIRST, .value = u"Triggering field (filled)"}, + {.role = NAME_LAST, .value = u"Placeholder (filled)"}, + {.role = EMAIL_ADDRESS, .value = u"No data (skipped)"}, + {.role = ADDRESS_HOME_LINE1, .value = u"No placeholder (skipped)"}, + {.role = ADDRESS_HOME_STATE, + .value = kSelectedState, + .form_control_type = FormControlType::kSelectOne, + .select_options = {SelectOption{.value = kSelectedState, + .content = kSelectedState}, + SelectOption{.value = kToBeFilledState, + .content = kToBeFilledState}}}}}); + FormsSeen({form}); + + FormStructure* form_structure = nullptr; + AutofillField* autofill_field = nullptr; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + form_structure->fields()[0]->set_may_use_prefilled_placeholder(true); + form_structure->fields()[1]->set_may_use_prefilled_placeholder(true); + form_structure->fields()[3]->set_may_use_prefilled_placeholder(false); + form_structure->fields()[4]->set_may_use_prefilled_placeholder(std::nullopt); + + FormData filled_form; + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .WillOnce((DoAll(SaveArg<2>(&filled_form), + Return(std::vector<FieldGlobalId>{})))); + test_api(*browser_autofill_manager_) + .FillOrPreviewDataModelForm( + mojom::ActionPersistence::kFill, form, form.fields.front(), profile, + /*cvc=*/std::nullopt, form_structure, autofill_field); + + const auto& filled_fields = filled_form.fields; + EXPECT_TRUE(filled_fields[0].is_autofilled); + EXPECT_EQ(filled_fields[0].value, profile->GetRawInfo(NAME_FIRST)); + EXPECT_TRUE(filled_fields[1].is_autofilled); + EXPECT_EQ(filled_fields[1].value, profile->GetRawInfo(NAME_LAST)); + EXPECT_FALSE(filled_fields[2].is_autofilled); + EXPECT_EQ(filled_fields[2].value, form.fields[2].value); + EXPECT_FALSE(filled_fields[3].is_autofilled); + EXPECT_EQ(filled_fields[3].value, form.fields[3].value); + EXPECT_TRUE(filled_fields[4].is_autofilled); + EXPECT_EQ(filled_fields[4].value, kToBeFilledState); +} + +TEST_F(FormFillerTest, OnlySkipRefillIfFieldIsPreFilled) { + base::test::ScopedFeatureList placeholders_features; + placeholders_features.InitWithFeatures( + {features::kAutofillOverwritePlaceholdersOnly, + features::kAutofillSkipPreFilledFields}, + {}); + + const std::string kCreditCardGuid = MakeGuid(4); + TestCardFillData card_fill_data = kElvisCardFillData; + card_fill_data.card_number = "Pre-filled (skipped)"; + card_fill_data.use_month_type = true; + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); + form.fields[1].value = base::UTF8ToUTF16(card_fill_data.card_number); + + FormsSeen({form}); + FormData first_filled_form = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), kCreditCardGuid); + + ExpectFilledForm(first_filled_form, /*address_fill_data=*/std::nullopt, + card_fill_data); + + // Prepare intercepting the filling operation to the driver and capture + // the re-filled form data. + FormData refilled_form; + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .Times(1) + .WillOnce(DoAll(SaveArg<2>(&refilled_form), + Return(std::vector<FieldGlobalId>{}))); + + // Simulate that JavaScript modifies the expiration date field. + FormData form_after_js_modification = first_filled_form; + form_after_js_modification.fields[2].value = u"04 / 29"; + browser_autofill_manager_->OnJavaScriptChangedAutofilledValue( + form_after_js_modification, form_after_js_modification.fields[2], + u"04/2999"); + + testing::Mock::VerifyAndClearExpectations(autofill_driver_.get()); + + ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", + FormControlType::kInputText, refilled_form.fields[0]); + ExpectFilledField("Card Number", "cardnumber", card_fill_data.card_number, + FormControlType::kInputText, refilled_form.fields[1]); + ExpectFilledField("Expiration Date", "ccmonth", "04 / 99", + FormControlType::kInputMonth, refilled_form.fields[2]); + ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, + refilled_form.fields[3]); +} + +TEST_F(FormFillerTest, UndoSavesFormFillingData) { + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + FormStructure* form_structure; + AutofillField* autofill_field; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + + base::flat_set<FieldGlobalId> safe_fields{form.fields.front().global_id()}; + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .Times(2) + .WillRepeatedly(Return(safe_fields)); + + test_api(*browser_autofill_manager_) + .FillOrPreviewDataModelForm( + mojom::ActionPersistence::kFill, form, form.fields.front(), + personal_data().GetProfiles().front(), /*optional_cvc=*/std::nullopt, + form_structure, autofill_field); + + // Undo early returns if it has no filling history for the trigger field, + // which is initially empty, therefore calling the driver is proof that data + // was successfully stored. + browser_autofill_manager_->UndoAutofill(mojom::ActionPersistence::kFill, form, + form.fields.front()); +} + +TEST_F(FormFillerTest, UndoSavesFieldByFieldFillingData) { + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + FormStructure* form_structure; + AutofillField* autofill_field; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + + EXPECT_CALL(*autofill_driver_, ApplyFieldAction); + browser_autofill_manager_->FillOrPreviewField( + mojom::ActionPersistence::kFill, mojom::TextReplacement::kReplaceAll, + form, form.fields.front(), u"Test Value", + PopupItemId::kAddressFieldByFieldFilling); + + // Undo early returns if it has no filling history for the trigger field, + // which is initially empty, therefore calling the driver is proof that data + // was successfully stored. + EXPECT_CALL(*autofill_driver_, ApplyFormAction); + browser_autofill_manager_->UndoAutofill(mojom::ActionPersistence::kFill, form, + form.fields.front()); +} + +TEST_F(FormFillerTest, UndoResetsCachedAutofillState) { + FormData form = CreateTestAddressFormData(); + AutofillField filled_autofill_field(form.fields.front()); + + FormFieldData* field_ptr = &form.fields.front(); + AutofillField* autofill_field_ptr = &filled_autofill_field; + form.fields.front().is_autofilled = false; + test_api(*browser_autofill_manager_) + .AddFormFillEntry(base::make_span(&field_ptr, 1u), + base::make_span(&autofill_field_ptr, 1u), + FillingProduct::kAddress, /*is_refill=*/false); + form.fields.front().is_autofilled = true; + FormsSeen({form}); + + FormStructure* form_structure; + AutofillField* autofill_field; + base::flat_set<FieldGlobalId> safe_fields{form.fields.front().global_id()}; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + ASSERT_TRUE(autofill_field->is_autofilled); + + browser_autofill_manager_->UndoAutofill(mojom::ActionPersistence::kFill, form, + form.fields.front()); + + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + EXPECT_FALSE(autofill_field->is_autofilled); +} + +TEST_F(FormFillerTest, FillOrPreviewDataModelFormCallsDidFillOrPreviewForm) { + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); + FormsSeen({form}); + FormStructure* form_structure; + AutofillField* autofill_field; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + EXPECT_CALL(autofill_client_, DidFillOrPreviewForm); + test_api(*browser_autofill_manager_) + .FillOrPreviewDataModelForm( + mojom::ActionPersistence::kFill, form, form.fields.front(), + personal_data().GetCreditCards()[0], /*optional_cvc=*/std::nullopt, + form_structure, autofill_field); +} + +// Test that if the form cache is outdated because a field was removed, filling +// is aborted. +TEST_F(FormFillerTest, DoNotFillIfFormFieldRemoved) { + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + + FormStructure* form_structure = nullptr; + AutofillField* autofill_field = nullptr; + ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField( + form, form.fields.front(), &form_structure, &autofill_field)); + + // Modify |form| so that it doesn't match |form_structure| anymore. + ASSERT_GE(form.fields.size(), 2u); + form.fields.pop_back(); + + AutofillProfile* profile = personal_data().GetProfileByGUID(MakeGuid(1)); + ASSERT_TRUE(profile); + + EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); +} + +// Test that we correctly fill an address form. +TEST_F(FormFillerTest, FillAddressForm) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + + AutofillProfile* profile = personal_data().GetProfileByGUID(MakeGuid(1)); + ASSERT_TRUE(profile); + EXPECT_EQ(1U, profile->use_count()); + const base::Time last_used_date = AutofillClock::Now() - base::Hours(1); + profile->set_use_date(last_used_date); + + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + ExpectFilledAddressFormElvis(response_data, false); + + EXPECT_EQ(2U, profile->use_count()); + EXPECT_LT(last_used_date, profile->use_date()); +} + +// Tests that `ProfileTokenQuality` is correctly integrated into +// `AutofillProfile` and that on form submit, observations are collected. +TEST_F(FormFillerTest, FillAddressForm_CollectObservations) { + base::test::ScopedFeatureList profile_token_quality_feature{ + features::kAutofillTrackProfileTokenQuality}; + AutofillProfile* profile = + personal_data().GetProfileByGUID(kElvisProfileGuid); + profile->token_quality().disable_randomization_for_testing(); + + // Create and fill an address form with profile `kElvisProfileGuid`. + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + FormData filled_form = FillAutofillFormDataAndGetResults(form, form.fields[0], + kElvisProfileGuid); + + // Expect that no observations for any of the form's types were collected yet. + FormStructure* form_structure = + browser_autofill_manager_->FindCachedFormById(filled_form.global_id()); + EXPECT_TRUE(base::ranges::all_of( + *form_structure, [&](const std::unique_ptr<AutofillField>& field) { + return profile->token_quality() + .GetObservationTypesForFieldType(field->Type().GetStorableType()) + .empty(); + })); + + // Submit the form and expect observations for all of the form's types. This + // updates the `profile` in `personal_data()`, invalidating the pointer. + FormSubmitted(filled_form); + profile = personal_data().GetProfileByGUID(kElvisProfileGuid); + EXPECT_TRUE(base::ranges::none_of( + *form_structure, [&](const std::unique_ptr<AutofillField>& field) { + return profile->token_quality() + .GetObservationTypesForFieldType(field->Type().GetStorableType()) + .empty(); + })); +} + +// Tests that for ac=unrecognized fields: +// - Are not filled by default. +// - Are filled through manual fallbacks. +TEST_F(FormFillerTest, AutocompleteUnrecognizedFillingBehavior) { + // Create a form where the middle name field has ac=unrecognized. + FormData form = CreateTestAddressFormData(); + ASSERT_EQ(form.fields[1].name, u"middlename"); + form.fields[1].parsed_autocomplete = + AutocompleteParsingResult{.field_type = HtmlFieldType::kUnrecognized}; + FormsSeen({form}); + + // Fill the `form` regularly and expect that everything but the middle name + // gets filled. + FormData filled_form = FillAutofillFormDataAndGetResults(form, form.fields[0], + kElvisProfileGuid); + TestAddressFillData fill_data = GetElvisAddressFillData(); + fill_data.middle = ""; + ExpectFilledForm(filled_form, fill_data, /*card_fill_data=*/std::nullopt); + + // Fill the `form` as-if through manual fallbacks. Expect that every field + // gets filled. + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .WillOnce(DoAll(SaveArg<2>(&filled_form), + Return(base::flat_set<FieldGlobalId>{}))); + browser_autofill_manager_->FillOrPreviewProfileForm( + mojom::ActionPersistence::kFill, form, form.fields[0], + *personal_data().GetProfileByGUID(kElvisProfileGuid), + {.trigger_source = AutofillTriggerSource::kManualFallback}); + + ExpectFilledForm(filled_form, GetElvisAddressFillData(), + /*card_fill_data=*/std::nullopt); +} + +// Test that we correctly log FIELD_WAS_AUTOFILLED event in UserHappiness. +TEST_F(FormFillerTest, FillCreditCardForm_LogFieldWasAutofill) { + // Set up our form data. + FormData form; + // Construct a form with a 4 fields: cardholder name, card number, + // expiration date and cvc. + CreateTestCreditCardFormData(&form, true, true); + FormsSeen({form}); + + base::HistogramTester histogram_tester; + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + // Cardholder name, card number, expiration data were autofilled but cvc was + // not be autofilled. + histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard", + AutofillMetrics::FIELD_WAS_AUTOFILLED, 3); +} + +// Test that we correctly fill a credit card form. +TEST_F(FormFillerTest, FillCreditCardForm_Simple) { + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); +} + +// Test that whitespace is stripped from the credit card number. +TEST_F(FormFillerTest, FillCreditCardForm_StripCardNumberWhitespace) { + // Same as the SetUp(), but generate Elvis card with whitespace in credit + // card number. |credit_card| will be owned by the TestPersonalDataManager. + personal_data().ClearCreditCards(); + CreditCard credit_card; + test::SetCreditCardInfo(&credit_card, "Elvis Presley", + "4234 5678 9012 3456", // Visa + "04", "2999", "1"); + credit_card.set_guid(MakeGuid(8)); + personal_data().AddCreditCard(credit_card); + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(8)); + ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); +} + +// Test that separator characters are stripped from the credit card number. +TEST_F(FormFillerTest, FillCreditCardForm_StripCardNumberSeparators) { + // Same as the SetUp(), but generate Elvis card with separator characters in + // credit card number. |credit_card| will be owned by the + // TestPersonalDataManager. + personal_data().ClearCreditCards(); + CreditCard credit_card; + test::SetCreditCardInfo(&credit_card, "Elvis Presley", + "4234-5678-9012-3456", // Visa + "04", "2999", "1"); + credit_card.set_guid(MakeGuid(9)); + personal_data().AddCreditCard(credit_card); + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(9)); + ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); +} + +// Test that we correctly fill a credit card form with month input type. +// Test 1 of 4: Empty month, empty year +TEST_F(FormFillerTest, FillCreditCardForm_NoYearNoMonth) { + personal_data().ClearCreditCards(); + + TestCardFillData card_fill_data = kElvisCardFillData; + card_fill_data.expiration_month = ""; + card_fill_data.expiration_year = ""; + card_fill_data.use_month_type = true; + CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); + + credit_card.set_guid(MakeGuid(7)); + personal_data().AddCreditCard(credit_card); + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(7)); + ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, + card_fill_data); +} + +// Test that we correctly fill a credit card form with month input type. +// Test 2 of 4: Non-empty month, empty year +TEST_F(FormFillerTest, FillCreditCardForm_NoYearMonth) { + personal_data().ClearCreditCards(); + TestCardFillData card_fill_data = kElvisCardFillData; + card_fill_data.expiration_month = "04"; + card_fill_data.expiration_year = ""; + card_fill_data.use_month_type = true; + CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); + + credit_card.set_guid(MakeGuid(7)); + personal_data().AddCreditCard(credit_card); + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(7)); + ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, + card_fill_data); +} + +// Test that we correctly fill a credit card form with month input type. +// Test 3 of 4: Empty month, non-empty year +TEST_F(FormFillerTest, FillCreditCardForm_YearNoMonth) { + // Same as the SetUp(), but generate 4 credit cards with year month + // combination. + personal_data().ClearCreditCards(); + TestCardFillData card_fill_data = kElvisCardFillData; + card_fill_data.expiration_month = ""; + card_fill_data.expiration_year = "2999"; + card_fill_data.use_month_type = true; + CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); + credit_card.set_guid(MakeGuid(7)); + personal_data().AddCreditCard(credit_card); + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(7)); + ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, + card_fill_data); +} + +// Test that we correctly fill a credit card form with month input type. +// Test 4 of 4: Non-empty month, non-empty year +TEST_F(FormFillerTest, FillCreditCardForm_YearMonth) { + personal_data().ClearCreditCards(); + TestCardFillData card_fill_data = kElvisCardFillData; + card_fill_data.expiration_month = "04"; + card_fill_data.expiration_year = "2999"; + card_fill_data.use_month_type = true; + CreditCard credit_card = FillDataToCreditCardInfo(card_fill_data); + credit_card.set_guid(MakeGuid(7)); + personal_data().AddCreditCard(credit_card); + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/true); + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(7)); + ExpectFilledForm(response_data, /*address_fill_data=*/std::nullopt, + card_fill_data); +} + +// Test that only the first 16 credit card number fields are filled. +TEST_F(FormFillerTest, FillOnlyFirstNineteenCreditCardNumberFields) { + // Set up our form data. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = {CreateTestFormField("Card Name", "cardname", "", + FormControlType::kInputText), + CreateTestFormField("Last Name", "cardlastname", "", + FormControlType::kInputText)}; + + // Add 20 credit card number fields with distinct names. + for (int i = 0; i < 20; i++) { + std::u16string field_name = u"Card Number " + base::NumberToString16(i + 1); + form.fields.push_back( + CreateTestFormField(base::UTF16ToASCII(field_name).c_str(), + "cardnumber", "", FormControlType::kInputText)); + } + + form.fields.push_back( + CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)); + + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + ExpectFilledField("Card Name", "cardname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Last Name", "cardlastname", "Presley", + FormControlType::kInputText, response_data.fields[1]); + + // Verify that the first 19 credit card number fields are filled. + for (int i = 0; i < 19; i++) { + std::u16string field_name = u"Card Number " + base::NumberToString16(i + 1); + ExpectFilledField(base::UTF16ToASCII(field_name).c_str(), "cardnumber", + "4234567890123456", FormControlType::kInputText, + response_data.fields[2 + i]); + } + + // Verify that the 20th. credit card number field is not filled. + ExpectFilledField("Card Number 20", "cardnumber", "", + FormControlType::kInputText, response_data.fields[21]); + + ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, + response_data.fields[22]); +} + +// Test that only the first 16 of identical fields are filled. +TEST_F(FormFillerTest, FillOnlyFirstSixteenIdenticalCreditCardNumberFields) { + // Set up our form data. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = {CreateTestFormField("Card Name", "cardname", "", + FormControlType::kInputText), + CreateTestFormField("Last Name", "cardlastname", "", + FormControlType::kInputText)}; + + // Add 20 identical card number fields. + for (int i = 0; i < 20; i++) { + form.fields.push_back(CreateTestFormField("Card Number", "cardnumber", "", + FormControlType::kInputText)); + } + form.fields.push_back( + CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)); + + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + ExpectFilledField("Card Name", "cardname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Last Name", "cardlastname", "Presley", + FormControlType::kInputText, response_data.fields[1]); + + // Verify that the first 19 card number fields are filled. + for (int i = 0; i < 19; i++) { + ExpectFilledField("Card Number", "cardnumber", "4234567890123456", + FormControlType::kInputText, response_data.fields[2 + i]); + } + // Verify that the 20th. card number field is not filled. + ExpectFilledField("Card Number", "cardnumber", "", + FormControlType::kInputText, response_data.fields[21]); + + ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, + response_data.fields[22]); +} + +// Test the credit card number is filled correctly into single-digit fields. +TEST_F(FormFillerTest, FillCreditCardNumberIntoSingleDigitFields) { + // Set up our form data. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = {CreateTestFormField("Card Name", "cardname", "", + FormControlType::kInputText), + CreateTestFormField("Last Name", "cardlastname", "", + FormControlType::kInputText)}; + + // Add 20 identical card number fields. + for (int i = 0; i < 20; i++) { + FormFieldData field = CreateTestFormField("Card Number", "cardnumber", "", + FormControlType::kInputText); + field.host_frame = form.host_frame; + field.host_form_id = form.renderer_id; + field.max_length = i < 19 ? 1 : std::numeric_limits<int>::max(); + form.fields.push_back(std::move(field)); + } + form.fields.push_back( + CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)); + + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + ExpectFilledField("Card Name", "cardname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Last Name", "cardlastname", "Presley", + FormControlType::kInputText, response_data.fields[1]); + + // Verify that the first 19 card number fields are filled. + std::u16string card_number = u"4234567890123456"; + for (unsigned int i = 0; i < 19; i++) { + ExpectFilledField("Card Number", "cardnumber", + i < card_number.length() + ? base::UTF16ToASCII(card_number.substr(i, 1)).c_str() + : "4234567890123456", + FormControlType::kInputText, response_data.fields[2 + i]); + } + + // Verify that the 20th. card number field is contains the full value. + ExpectFilledField("Card Number", "cardnumber", "", + FormControlType::kInputText, response_data.fields[21]); + + ExpectFilledField("CVC", "cvc", "", FormControlType::kInputText, + response_data.fields[22]); +} + +// Test that we correctly fill a credit card form with first and last cardholder +// name. +TEST_F(FormFillerTest, FillCreditCardForm_SplitName) { + // Set up our form data. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = { + CreateTestFormField("Card Name", "cardname", "", + FormControlType::kInputText), + CreateTestFormField("Last Name", "cardlastname", "", + FormControlType::kInputText), + CreateTestFormField("Card Number", "cardnumber", "", + FormControlType::kInputText), + CreateTestFormField("CVC", "cvc", "", FormControlType::kInputText)}; + + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + ExpectFilledField("Card Name", "cardname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Last Name", "cardlastname", "Presley", + FormControlType::kInputText, response_data.fields[1]); + ExpectFilledField("Card Number", "cardnumber", "4234567890123456", + FormControlType::kInputText, response_data.fields[2]); +} + +// Test that only filled selection boxes are counted for the type filling limit. +TEST_F(FormFillerTest, OnlyCountFilledSelectionBoxesForTypeFillingLimit) { + test::PopulateAlternativeStateNameMapForTesting( + "US", "Tennessee", + {{.canonical_name = "Tennessee", + .abbreviations = {"TN"}, + .alternative_names = {}}}); + // Set up our form data. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = {CreateTestFormField("First Name", "firstname", "", + FormControlType::kInputText), + CreateTestFormField("Middle Name", "middlename", "", + FormControlType::kInputText), + CreateTestFormField("Last Name", "lastname", "", + FormControlType::kInputText), + + // Create a selection box for the state that hat the correct + // entry to be filled with user data. Note, TN is the official + // abbreviation for Tennessee. + CreateTestSelectField("State", "state", "", {"AA", "BB", "TN"}, + {"AA", "BB", "TN"})}; + + // Add 20 selection boxes that can not be filled since the correct entry + // is missing. + for (int i = 0; i < 20; i++) { + form.fields.push_back(CreateTestSelectField( + "State", "state", "", {"AA", "BB", "CC"}, {"AA", "BB", "CC"})); + } + + // Add 20 other selection boxes that should be fillable since the correct + // entry is present. + for (int i = 0; i < 20; i++) { + form.fields.push_back(CreateTestSelectField( + "State", "state", "", {"AA", "BB", "TN"}, {"AA", "BB", "TN"})); + } + + // Create a selection box for the state that hat the correct entry to be + // filled with user data. Note, TN is the official abbreviation for Tennessee. + for (int i = 0; i < 20; ++i) { + form.fields.push_back(CreateTestSelectField( + "Country", "country", "", {"DE", "FR", "US"}, {"DE", "FR", "US"})); + } + + FormsSeen({form}); + + TestAddressFillData profile_info_data = GetElvisAddressFillData(); + profile_info_data.company = "1987"; + AutofillProfile profile = FillDataToAutofillProfile(profile_info_data); + profile.set_guid(MakeGuid(123)); + personal_data().AddProfile(profile); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(123)); + + // Verify the correct filling of the name entries. + ExpectFilledField("First Name", "firstname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Middle Name", "middlename", "Aaron", + FormControlType::kInputText, response_data.fields[1]); + ExpectFilledField("Last Name", "lastname", "Presley", + FormControlType::kInputText, response_data.fields[2]); + + // Verify that the first selection box is correctly filled. + ExpectFilledField("State", "state", "TN", FormControlType::kSelectOne, + response_data.fields[3]); + + // Verify that the next 20 selection boxes are not filled. + for (int i = 0; i < 20; i++) { + ExpectFilledField("State", "state", "", FormControlType::kSelectOne, + response_data.fields[4 + i]); + } + + // Verify that the remaining selection boxes are correctly filled again + // because there's no limit on filling ADDRESS_HOME_STATE fields. + for (int i = 0; i < 20; i++) { + ExpectFilledField("State", "state", "TN", FormControlType::kSelectOne, + response_data.fields[24 + i]); + } + + // Verify that only the first 9 of the remaining selection boxes are + // correctly filled due to the limit on filling ADDRESS_HOME_COUNTRY fields. + for (int i = 0; i < 20; i++) { + ExpectFilledField("Country", "country", i < 9 ? "US" : "", + FormControlType::kSelectOne, + response_data.fields[44 + i]); + } +} + +// Test that we correctly fill a combined address and credit card form. +TEST_F(FormFillerTest, FillAddressAndCreditCardForm) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + CreateTestCreditCardFormData(&form, true, false); + FormsSeen({form}); + + // First fill the address data. + FormData response_data; + { + SCOPED_TRACE("Address"); + response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + ExpectFilledAddressFormElvis(response_data, true); + } + + // Now fill the credit card data. + { + response_data = FillAutofillFormDataAndGetResults(form, form.fields.back(), + MakeGuid(4)); + SCOPED_TRACE("Credit card"); + ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/true); + } +} + +// Test parameter data for tests with a simple structure: Create a form, +// autofill it, check that values have been correctly filled. +struct FormFillerSimpleFormTestCase { + struct FormFieldExpectedData { + const char* label; + const char* name; + const char* value = ""; + }; + + const std::string test_name; + const std::string cc_guid = ""; + const std::string profile_guid = MakeGuid(1); + + const test::FormDescription form_description; + const std::vector<FormFieldExpectedData> expected_form_fields; +}; + +class FormFillerSimpleFormTest + : public FormFillerTest, + public ::testing::WithParamInterface<FormFillerSimpleFormTestCase> {}; + +const FormFillerSimpleFormTestCase kFormFillerSimpleFormTestCases[] = { + // Test that a field with an unrecognized autocomplete attribute is not + // filled. + {.test_name = "FillAddressForm_UnrecognizedAttribute", + .form_description = + {.fields = {{.label = u"First name", + .name = u"firstname", + .autocomplete_attribute = "given-name"}, + {.label = u"Middle name", .name = u"middle"}, + {.label = u"Last name", + .name = u"lastname", + .autocomplete_attribute = "unrecognized"}}}, + .expected_form_fields = + {{.label = "First name", .name = "firstname", .value = "Elvis"}, + {.label = "Middle name", .name = "middle", .value = "Aaron"}, + {.label = "Last name", .name = "lastname"}}}, + + // Test that non credit card related fields with the autocomplete attribute + // set to off are filled on all platforms when the feature to autofill all + // addresses is enabled (default). + {.test_name = "FillAddressForm_AutocompleteOffNotRespected", + .form_description = + {.fields = {{.label = u"First name", .name = u"firstname"}, + {.label = u"Middle name", + .name = u"middle", + .should_autocomplete = false}, + {.label = u"Last name", .name = u"lastname"}, + {.label = u"Address Line 1", + .name = u"addr1", + .should_autocomplete = false}}}, + .expected_form_fields = + {{.label = "First name", .name = "firstname", .value = "Elvis"}, + {.label = "Middle name", .name = "middle", .value = "Aaron"}, + {.label = "Last name", .name = "lastname", .value = "Presley"}, + {.label = "Address Line 1", + .name = "addr1", + .value = "3734 Elvis Presley Blvd."}}}, + + // Test that a field with a value equal to it's placeholder attribute is + // filled. + {.test_name = "FillAddressForm_PlaceholderEqualsValue", + .form_description = {.fields = {{.label = u"First name", + .name = u"firstname", + .value = u"First Name", + .placeholder = u"First Name"}, + {.label = u"Middle name", + .name = u"middle", + .value = u"Middle Name", + .placeholder = u"Middle Name"}, + {.label = u"Last name", + .name = u"lastname", + .value = u"Last Name", + .placeholder = u"Last Name"}}}, + .expected_form_fields = + {{.label = "First name", .name = "firstname", .value = "Elvis"}, + {.label = "Middle name", .name = "middle", .value = "Aaron"}, + {.label = "Last name", .name = "lastname", .value = "Presley"}}}, + + // Test that a credit card field with an unrecognized autocomplete attribute + // gets filled. + {.test_name = "FillCreditCardForm_UnrecognizedAttribute", + .cc_guid = MakeGuid(4), + .profile_guid = "", + .form_description = + {.fields = {{.label = u"Name on Card", + .name = u"nameoncard", + .autocomplete_attribute = "cc-name"}, + {.label = u"Card Number", .name = u"cardnumber"}, + {.label = u"Expiration Date", + .name = u"ccmonth", + .autocomplete_attribute = "unrecognized"}}}, + .expected_form_fields = {{.label = "Name on Card", + .name = "nameoncard", + .value = "Elvis Presley"}, + {.label = "Card Number", + .name = "cardnumber", + .value = "4234567890123456"}, + {.label = "Expiration Date", + .name = "ccmonth", + .value = "04/2999"}}}, + +}; + +TEST_P(FormFillerSimpleFormTest, FillSimpleForm) { + const FormFillerSimpleFormTestCase& params = GetParam(); + FormData form = test::GetFormData(params.form_description); + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, form.fields[0], + params.cc_guid.empty() ? params.profile_guid : params.cc_guid); + + ASSERT_EQ(response_data.fields.size(), params.expected_form_fields.size()); + for (size_t i = 0; i < response_data.fields.size(); ++i) { + SCOPED_TRACE(params.test_name + ", fields expectations"); + const auto& [label, name, value] = params.expected_form_fields[i]; + ExpectFilledField(label, name, value, FormControlType::kInputText, + response_data.fields[i]); + } +} + +INSTANTIATE_TEST_SUITE_P( + FormFillerTest, + FormFillerSimpleFormTest, + ::testing::ValuesIn(kFormFillerSimpleFormTestCases), + [](const ::testing::TestParamInfo<FormFillerSimpleFormTest::ParamType>& + info) { return info.param.test_name; }); + +// Test that credit card fields are filled even if they have the autocomplete +// attribute set to off. +TEST_F(FormFillerTest, FillCreditCardForm_AutocompleteOff) { + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); + + // Set the autocomplete=off on all fields. + for (FormFieldData field : form.fields) { + field.should_autocomplete = false; + } + + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + + // All fields should be filled. + ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); +} + +// Test that selecting an expired credit card fills everything except the +// expiration date. +TEST_F(FormFillerTest, FillCreditCardForm_ExpiredCard) { + personal_data().ClearCreditCards(); + CreditCard expired_card; + test::SetCreditCardInfo(&expired_card, "Homer Simpson", + "4234567890654321", // Visa + "05", "2000", "1"); + expired_card.set_guid(MakeGuid(9)); + personal_data().AddCreditCard(expired_card); + + // Set up the form data. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + + // Create a credit card form. + std::vector<const char*> kCreditCardTypes = {"Visa", "Mastercard", "AmEx", + "discover"}; + form.fields = { + CreateTestFormField("Name on Card", "nameoncard", "", + FormControlType::kInputText, "cc-name"), + CreateTestSelectField("Card Type", "cardtype", "", "cc-type", + kCreditCardTypes, kCreditCardTypes), + CreateTestFormField("Card Number", "cardnumber", "", + FormControlType::kInputText, "cc-number"), + CreateTestFormField("Expiration Month", "ccmonth", "", + FormControlType::kInputText, "cc-exp-month"), + CreateTestFormField("Expiration Year", "ccyear", "", + FormControlType::kInputText, "cc-exp-year")}; + FormsSeen({form}); + + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(9)); + + // The credit card name, type and number should be filled. + ExpectFilledField("Name on Card", "nameoncard", "Homer Simpson", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Card Type", "cardtype", "Visa", + FormControlType::kSelectOne, response_data.fields[1]); + ExpectFilledField("Card Number", "cardnumber", "4234567890654321", + FormControlType::kInputText, response_data.fields[2]); + + // The expiration month and year should not be filled. + ExpectFilledField("Expiration Month", "ccmonth", "", + FormControlType::kInputText, response_data.fields[3]); + ExpectFilledField("Expiration Year", "ccyear", "", + FormControlType::kInputText, response_data.fields[4]); +} + +TEST_F(FormFillerTest, PreviewCreditCardForm_VirtualCard) { + personal_data().ClearCreditCards(); + CreditCard virtual_card = test::GetVirtualCard(); + personal_data().AddServerCreditCard(virtual_card); + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); + FormsSeen({form}); + + FormData response_data = PreviewVirtualCardDataAndGetResults( + mojom::ActionPersistence::kPreview, form, form.fields[1], virtual_card); + + std::u16string expected_cardholder_name = u"Lorem Ipsum"; + // Virtual card number using obfuscated dots only: Virtual card Mastercard + // ••••4444 + std::u16string expected_card_number = + u"Virtual card Mastercard " + + virtual_card.ObfuscatedNumberWithVisibleLastFourDigits(); + // Virtual card expiration month using obfuscated dots: •• + std::u16string expected_exp_month = + CreditCard::GetMidlineEllipsisPlainDots(/*num_dots=*/2); + // Virtual card expiration year using obfuscated dots: •••• + std::u16string expected_exp_year = + CreditCard::GetMidlineEllipsisPlainDots(/*num_dots=*/4); + // Virtual card cvc using obfuscated dots: ••• + std::u16string expected_cvc = + CreditCard::GetMidlineEllipsisPlainDots(/*num_dots=*/3); + + EXPECT_EQ(response_data.fields[0].value, expected_cardholder_name); + EXPECT_EQ(response_data.fields[1].value, expected_card_number); + EXPECT_EQ(response_data.fields[2].value, expected_exp_month); + EXPECT_EQ(response_data.fields[3].value, expected_exp_year); + EXPECT_EQ(response_data.fields[4].value, expected_cvc); +} + +// Test that unfocusable fields aren't filled, except for <select> fields (but +// not <selectlist> fields). +TEST_F(FormFillerTest, DoNotFillUnfocusableFieldsExceptForSelect) { + // Create a form with both focusable and non-focusable fields. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = { + CreateTestFormField("First Name", "firstname", "", + FormControlType::kInputText), + CreateTestFormField("", "lastname", "", FormControlType::kInputText), + CreateTestFormField("Postal Code", "postal_code", "", + FormControlType::kInputText)}; + form.fields.back().is_focusable = false; + + form.fields.push_back(CreateTestSelectOrSelectListField( + "Country", "country", "", "", {"CA", "US"}, {"Canada", "United States"}, + FormControlType::kSelectList)); + form.fields.back().is_focusable = false; + + form.fields.push_back(CreateTestSelectOrSelectListField( + "Country", "country", "", "", {"CA", "US"}, {"Canada", "United States"}, + FormControlType::kSelectList)); + form.fields.push_back(CreateTestSelectOrSelectListField( + "Country", "country", "", "", {"CA", "US"}, {"Canada", "United States"}, + FormControlType::kSelectOne)); + form.fields.back().is_focusable = false; + + FormsSeen({form}); + + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + + ASSERT_EQ(6U, response_data.fields.size()); + ExpectFilledField("First Name", "firstname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("", "lastname", "Presley", FormControlType::kInputText, + response_data.fields[1]); + ExpectFilledField("Postal Code", "postal_code", "", + FormControlType::kInputText, response_data.fields[2]); + ExpectFilledField("Country", "country", "", FormControlType::kSelectList, + response_data.fields[3]); + ExpectFilledField("Country", "country", "US", FormControlType::kSelectList, + response_data.fields[4]); + ExpectFilledField("Country", "country", "US", FormControlType::kSelectOne, + response_data.fields[5]); +} + +// Test that non-focusable field is ignored while inferring boundaries between +// sections, but not filled. +TEST_F(FormFillerTest, FillFormWithNonFocusableFields) { + bool default_to_city_and_number = + base::FeatureList::IsEnabled(features::kAutofillDefaultToCityAndNumber); + + // Create a form with both focusable and non-focusable fields. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = { + CreateTestFormField("First Name", "firstname", "", + FormControlType::kInputText), + CreateTestFormField("", "lastname", "", FormControlType::kInputText), + CreateTestFormField("", "email", "", FormControlType::kInputText), + CreateTestFormField("Phone Number", "phonenumber", "", + FormControlType::kInputTelephone), + CreateTestFormField("", "email_", "", FormControlType::kInputText)}; + form.fields.back().is_focusable = false; + form.fields.push_back(CreateTestFormField("Country", "country", "", + FormControlType::kInputText)); + + FormsSeen({form}); + + // Fill the form + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + + // All the visible fields should be filled as all the fields belong to the + // same logical section. + ASSERT_EQ(6U, response_data.fields.size()); + ExpectFilledField("First Name", "firstname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("", "lastname", "Presley", FormControlType::kInputText, + response_data.fields[1]); + ExpectFilledField("", "email", "theking@gmail.com", + FormControlType::kInputText, response_data.fields[2]); + ExpectFilledField("Phone Number", "phonenumber", + default_to_city_and_number ? "2345678901" : "12345678901", + FormControlType::kInputTelephone, response_data.fields[3]); + ExpectFilledField("", "email_", "", FormControlType::kInputText, + response_data.fields[4]); + ExpectFilledField("Country", "country", "United States", + FormControlType::kInputText, response_data.fields[5]); +} + +// Test that we correctly fill a form that has multiple logical sections, e.g. +// both a billing and a shipping address. +TEST_F(FormFillerTest, FillFormWithMultipleSections) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + const size_t kAddressFormSize = form.fields.size(); + base::ranges::move(CreateTestAddressFormData().fields, + std::back_inserter(form.fields)); + for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) { + // Make sure the fields have distinct names. + form.fields[i].name = form.fields[i].name + u"_"; + } + FormsSeen({form}); + + // Fill the first section. + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + { + SCOPED_TRACE("Address 1"); + // The second address section should be empty. + ASSERT_EQ(response_data.fields.size(), 2 * kAddressFormSize); + for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) { + EXPECT_EQ(std::u16string(), response_data.fields[i].value); + } + + // The first address section should be filled with Elvis's data. + response_data.fields.resize(kAddressFormSize); + ExpectFilledAddressFormElvis(response_data, false); + } + + // Fill the second section, with the initiating field somewhere in the middle + // of the section. + ASSERT_LT(9U, kAddressFormSize); + response_data = FillAutofillFormDataAndGetResults( + form, form.fields[kAddressFormSize + 9], MakeGuid(1)); + { + SCOPED_TRACE("Address 2"); + ASSERT_EQ(response_data.fields.size(), form.fields.size()); + + // The first address section should be empty. + ASSERT_EQ(response_data.fields.size(), 2 * kAddressFormSize); + for (size_t i = 0; i < kAddressFormSize; ++i) { + EXPECT_EQ(std::u16string(), response_data.fields[i].value); + } + + // The second address section should be filled with Elvis's data. + FormData secondSection = response_data; + secondSection.fields.erase(secondSection.fields.begin(), + secondSection.fields.begin() + kAddressFormSize); + for (size_t i = 0; i < kAddressFormSize; ++i) { + // Restore the expected field names. + std::u16string name = secondSection.fields[i].name; + std::u16string original_name = name.substr(0, name.size() - 1); + secondSection.fields[i].name = original_name; + } + ExpectFilledAddressFormElvis(secondSection, false); + } +} + +// Test that we correctly fill a form that has author-specified sections, which +// might not match our expected section breakdown. +TEST_F(FormFillerTest, FillFormWithAuthorSpecifiedSections) { + // Create a form with a billing section and an unnamed section, interleaved. + // The billing section includes both address and credit card fields. + FormData form; + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = { + CreateTestFormField("", "country", "", FormControlType::kInputText, + "section-billing country"), + CreateTestFormField("", "firstname", "", FormControlType::kInputText, + "given-name"), + CreateTestFormField("", "lastname", "", FormControlType::kInputText, + "family-name"), + CreateTestFormField("", "address", "", FormControlType::kInputText, + "section-billing address-line1"), + CreateTestFormField("", "city", "", FormControlType::kInputText, + "section-billing locality"), + CreateTestFormField("", "state", "", FormControlType::kInputText, + "section-billing region"), + CreateTestFormField("", "zip", "", FormControlType::kInputText, + "section-billing postal-code"), + CreateTestFormField("", "ccname", "", FormControlType::kInputText, + "section-billing cc-name"), + CreateTestFormField("", "ccnumber", "", FormControlType::kInputText, + "section-billing cc-number"), + CreateTestFormField("", "ccexp", "", FormControlType::kInputText, + "section-billing cc-exp"), + CreateTestFormField("", "email", "", FormControlType::kInputText, + "email")}; + + FormsSeen({form}); + + // Fill the unnamed section. + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[1], MakeGuid(1)); + { + SCOPED_TRACE("Unnamed section"); + EXPECT_EQ(u"MyForm", response_data.name); + EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.url); + EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action); + ASSERT_EQ(11U, response_data.fields.size()); + + ExpectFilledField("", "country", "", FormControlType::kInputText, + response_data.fields[0]); + ExpectFilledField("", "firstname", "Elvis", FormControlType::kInputText, + response_data.fields[1]); + ExpectFilledField("", "lastname", "Presley", FormControlType::kInputText, + response_data.fields[2]); + ExpectFilledField("", "address", "", FormControlType::kInputText, + response_data.fields[3]); + ExpectFilledField("", "city", "", FormControlType::kInputText, + response_data.fields[4]); + ExpectFilledField("", "state", "", FormControlType::kInputText, + response_data.fields[5]); + ExpectFilledField("", "zip", "", FormControlType::kInputText, + response_data.fields[6]); + ExpectFilledField("", "ccname", "", FormControlType::kInputText, + response_data.fields[7]); + ExpectFilledField("", "ccnumber", "", FormControlType::kInputText, + response_data.fields[8]); + ExpectFilledField("", "ccexp", "", FormControlType::kInputText, + response_data.fields[9]); + ExpectFilledField("", "email", "theking@gmail.com", + FormControlType::kInputText, response_data.fields[10]); + } + + // Fill the address portion of the billing section. + response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + { + SCOPED_TRACE("Billing address"); + EXPECT_EQ(u"MyForm", response_data.name); + EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.url); + EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action); + ASSERT_EQ(11U, response_data.fields.size()); + + ExpectFilledField("", "country", "US", FormControlType::kInputText, + response_data.fields[0]); + ExpectFilledField("", "firstname", "", FormControlType::kInputText, + response_data.fields[1]); + ExpectFilledField("", "lastname", "", FormControlType::kInputText, + response_data.fields[2]); + ExpectFilledField("", "address", "3734 Elvis Presley Blvd.", + FormControlType::kInputText, response_data.fields[3]); + ExpectFilledField("", "city", "Memphis", FormControlType::kInputText, + response_data.fields[4]); + ExpectFilledField("", "state", "Tennessee", FormControlType::kInputText, + response_data.fields[5]); + ExpectFilledField("", "zip", "38116", FormControlType::kInputText, + response_data.fields[6]); + ExpectFilledField("", "ccname", "", FormControlType::kInputText, + response_data.fields[7]); + ExpectFilledField("", "ccnumber", "", FormControlType::kInputText, + response_data.fields[8]); + ExpectFilledField("", "ccexp", "", FormControlType::kInputText, + response_data.fields[9]); + ExpectFilledField("", "email", "", FormControlType::kInputText, + response_data.fields[10]); + } + + // Fill the credit card portion of the billing section. + response_data = FillAutofillFormDataAndGetResults( + form, form.fields[form.fields.size() - 2], MakeGuid(4)); + { + SCOPED_TRACE("Credit card"); + EXPECT_EQ(u"MyForm", response_data.name); + EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.url); + EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action); + ASSERT_EQ(11U, response_data.fields.size()); + + ExpectFilledField("", "country", "", FormControlType::kInputText, + response_data.fields[0]); + ExpectFilledField("", "firstname", "", FormControlType::kInputText, + response_data.fields[1]); + ExpectFilledField("", "lastname", "", FormControlType::kInputText, + response_data.fields[2]); + ExpectFilledField("", "address", "", FormControlType::kInputText, + response_data.fields[3]); + ExpectFilledField("", "city", "", FormControlType::kInputText, + response_data.fields[4]); + ExpectFilledField("", "state", "", FormControlType::kInputText, + response_data.fields[5]); + ExpectFilledField("", "zip", "", FormControlType::kInputText, + response_data.fields[6]); + ExpectFilledField("", "ccname", "Elvis Presley", + FormControlType::kInputText, response_data.fields[7]); + ExpectFilledField("", "ccnumber", "4234567890123456", + FormControlType::kInputText, response_data.fields[8]); + ExpectFilledField("", "ccexp", "04/2999", FormControlType::kInputText, + response_data.fields[9]); + ExpectFilledField("", "email", "", FormControlType::kInputText, + response_data.fields[10]); + } +} + +// Test that we correctly fill a form that has a single logical section with +// multiple email address fields. +TEST_F(FormFillerTest, FillFormWithMultipleEmails) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + form.fields.push_back(CreateTestFormField("Confirm email", "email2", "", + FormControlType::kInputText)); + + FormsSeen({form}); + + // Fill the form. + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + + // The second email address should be filled. + EXPECT_EQ(u"theking@gmail.com", response_data.fields.back().value); + + // The remainder of the form should be filled as usual. + response_data.fields.pop_back(); + ExpectFilledAddressFormElvis(response_data, false); +} + +// Test that we correctly fill a previously auto-filled form. +TEST_F(FormFillerTest, FillAutofilledForm) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + // Mark the address fields as autofilled. + for (auto& field : form.fields) { + field.is_autofilled = true; + } + + CreateTestCreditCardFormData(&form, true, false); + FormsSeen({form}); + + // First fill the address data. + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(1)); + { + SCOPED_TRACE("Address"); + TestAddressFillData expected_address_fill_data = kEmptyAddressFillData; + expected_address_fill_data.first = "Elvis"; + ExpectFilledForm(response_data, expected_address_fill_data, + kEmptyCardFillData); + } + + // Now fill the credit card data. + response_data = + FillAutofillFormDataAndGetResults(form, form.fields.back(), MakeGuid(4)); + { + SCOPED_TRACE("Credit card 1"); + ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/true); + } + + // Now set the credit card fields to also be auto-filled, and try again to + // fill the credit card data + for (auto& field : form.fields) { + field.is_autofilled = true; + } + + response_data = FillAutofillFormDataAndGetResults( + form, form.fields[form.fields.size() - 2], MakeGuid(4)); + { + SCOPED_TRACE("Credit card 2"); + TestCardFillData expected_card_fill_data = kEmptyCardFillData; + expected_card_fill_data.expiration_year = "2999"; + ExpectFilledForm(response_data, kEmptyAddressFillData, + expected_card_fill_data); + } +} + +// Test that we correctly fill a previously partly auto-filled form. +TEST_F(FormFillerTest, FillPartlyAutofilledForm) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + // Mark couple of the address fields as autofilled. + form.fields[3].is_autofilled = true; + form.fields[4].is_autofilled = true; + form.fields[5].is_autofilled = true; + form.fields[6].is_autofilled = true; + form.fields[10].is_autofilled = true; + + CreateTestCreditCardFormData(&form, true, false); + FormsSeen({form}); + + // First fill the address data. + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(1)); + { + SCOPED_TRACE("Address"); + TestAddressFillData expected_address_fill_data = kEmptyAddressFillData; + expected_address_fill_data.first = "Elvis"; + expected_address_fill_data.middle = "Aaron"; + expected_address_fill_data.last = "Presley"; + expected_address_fill_data.postal_code = "38116"; + expected_address_fill_data.country = "United States"; + bool default_to_city_and_number = + base::FeatureList::IsEnabled(features::kAutofillDefaultToCityAndNumber); + expected_address_fill_data.phone = + default_to_city_and_number ? "2345678901" : "12345678901"; + + ExpectFilledForm(response_data, expected_address_fill_data, + kEmptyCardFillData); + } + + // Now fill the credit card data. + response_data = + FillAutofillFormDataAndGetResults(form, form.fields.back(), MakeGuid(4)); + { + SCOPED_TRACE("Credit card 1"); + ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/true); + } +} + +// Test that we correctly fill a previously partly auto-filled form. +TEST_F(FormFillerTest, FillPartlyManuallyFilledForm) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + + CreateTestCreditCardFormData(&form, true, false); + FormsSeen({form}); + + // Michael will be overridden with Elvis because Autofill is triggered from + // the first field. + form.fields[0].value = u"Michael"; + form.fields[0].properties_mask |= kUserTyped; + + // Jackson will be preserved. + form.fields[2].value = u"Jackson"; + form.fields[2].properties_mask |= kUserTyped; + + FormsSeen({form}); + + // First fill the address data. + FormData response_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(1)); + { + SCOPED_TRACE("Address"); + TestAddressFillData expected_address_fill_data = GetElvisAddressFillData(); + expected_address_fill_data.last = "Jackson"; + ExpectFilledForm(response_data, expected_address_fill_data, + kEmptyCardFillData); + } + + // Now fill the credit card data. + response_data = + FillAutofillFormDataAndGetResults(form, form.fields.back(), MakeGuid(4)); + { + SCOPED_TRACE("Credit card 1"); + TestAddressFillData expected_address_fill_data = kEmptyAddressFillData; + expected_address_fill_data.first = "Michael"; + expected_address_fill_data.last = "Jackson"; + ExpectFilledForm(response_data, expected_address_fill_data, + kElvisCardFillData); + } +} + +// Test that we correctly fill a phone number split across multiple fields. +TEST_F(FormFillerTest, FillPhoneNumber) { + // In one form, rely on the max length attribute to imply US phone number + // parts. In the other form, rely on the autocomplete type attribute. + FormData form_with_us_number_max_length; + form_with_us_number_max_length.renderer_id = test::MakeFormRendererId(); + form_with_us_number_max_length.name = u"MyMaxlengthPhoneForm"; + form_with_us_number_max_length.url = + GURL("https://myform.com/phone_form.html"); + form_with_us_number_max_length.action = + GURL("https://myform.com/phone_submit.html"); + FormData form_with_autocompletetype = form_with_us_number_max_length; + form_with_autocompletetype.renderer_id = test::MakeFormRendererId(); + form_with_autocompletetype.name = u"MyAutocompletetypePhoneForm"; + + struct { + const char* label; + const char* name; + size_t max_length; + const char* autocomplete_attribute; + } test_fields[] = {{"country code", "country_code", 1, "tel-country-code"}, + {"area code", "area_code", 3, "tel-area-code"}, + {"phone", "phone_prefix", 3, "tel-local-prefix"}, + {"-", "phone_suffix", 4, "tel-local-suffix"}, + {"Phone Extension", "ext", 3, "tel-extension"}}; + + constexpr uint64_t default_max_length = 0; + for (const auto& test_field : test_fields) { + FormFieldData field = CreateTestFormField(test_field.label, test_field.name, + "", FormControlType::kInputText, + "", test_field.max_length); + form_with_us_number_max_length.fields.push_back(field); + + field.max_length = default_max_length; + field.autocomplete_attribute = test_field.autocomplete_attribute; + field.parsed_autocomplete = + ParseAutocompleteAttribute(test_field.autocomplete_attribute); + form_with_autocompletetype.fields.push_back(field); + } + + FormsSeen({form_with_us_number_max_length, form_with_autocompletetype}); + + // We should be able to fill prefix and suffix fields for US numbers. + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + FormData response_data1 = FillAutofillFormDataAndGetResults( + form_with_us_number_max_length, + *form_with_us_number_max_length.fields.begin(), guid); + + ASSERT_EQ(5U, response_data1.fields.size()); + EXPECT_EQ(u"1", response_data1.fields[0].value); + EXPECT_EQ(u"650", response_data1.fields[1].value); + EXPECT_EQ(u"555", response_data1.fields[2].value); + EXPECT_EQ(u"4567", response_data1.fields[3].value); + EXPECT_EQ(std::u16string(), response_data1.fields[4].value); + + FormData response_data2 = FillAutofillFormDataAndGetResults( + form_with_autocompletetype, *form_with_autocompletetype.fields.begin(), + guid); + + ASSERT_EQ(5U, response_data2.fields.size()); + EXPECT_EQ(u"1", response_data2.fields[0].value); + EXPECT_EQ(u"650", response_data2.fields[1].value); + EXPECT_EQ(u"555", response_data2.fields[2].value); + EXPECT_EQ(u"4567", response_data2.fields[3].value); + EXPECT_EQ(std::u16string(), response_data2.fields[4].value); + + // For other countries, fill prefix and suffix fields with best effort. + work_profile->SetRawInfo(ADDRESS_HOME_COUNTRY, u"GB"); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"447700954321"); + FormData response_data3 = FillAutofillFormDataAndGetResults( + form_with_us_number_max_length, + *form_with_us_number_max_length.fields.begin(), guid); + + ASSERT_EQ(5U, response_data3.fields.size()); + EXPECT_EQ(u"4", response_data3.fields[0].value); + EXPECT_EQ(u"700", response_data3.fields[1].value); + EXPECT_EQ(u"95", response_data3.fields[2].value); + EXPECT_EQ(u"4321", response_data3.fields[3].value); + EXPECT_EQ(std::u16string(), response_data3.fields[4].value); + + FormData response_data4 = FillAutofillFormDataAndGetResults( + form_with_autocompletetype, *form_with_autocompletetype.fields.begin(), + guid); + + ASSERT_EQ(5U, response_data4.fields.size()); + EXPECT_EQ(u"44", response_data4.fields[0].value); + EXPECT_EQ(u"7700", response_data4.fields[1].value); + EXPECT_EQ(u"95", response_data4.fields[2].value); + EXPECT_EQ(u"4321", response_data4.fields[3].value); + EXPECT_EQ(std::u16string(), response_data4.fields[4].value); +} + +TEST_F(FormFillerTest, FillPhoneNumber_ForPhonePrefixOrSuffix) { + FormData form = + test::GetFormData({.fields = { + {.label = u"country code", + .name = u"country_code", + .max_length = 1, + .autocomplete_attribute = "tel-country-code"}, + {.label = u"area code", + .name = u"area_code", + .max_length = 3, + .autocomplete_attribute = "tel-area-code"}, + {.label = u"prefix", + .name = u"phone_prefix", + .max_length = 3, + .autocomplete_attribute = "tel-local-prefix"}, + {.label = u"-", + .name = u"phone_suffix", + .max_length = 4, + .autocomplete_attribute = "tel-local-suffix"}, + {.label = u"Phone Extension", + .name = u"ext", + .max_length = 5, + .autocomplete_attribute = "tel-extension"}, + }}); + + FormsSeen({form}); + + personal_data().ClearProfiles(); + AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); + profile.set_guid(MakeGuid(104)); + profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"1800FLOWERS"); + personal_data().AddProfile(profile); + + FormData response_data1 = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), profile.guid()); + + ASSERT_EQ(5U, response_data1.fields.size()); + EXPECT_EQ(u"356", response_data1.fields[2].value); + EXPECT_EQ(u"9377", response_data1.fields[3].value); +} + +// Tests that the suggestion consists of phone number without the country code +// when a length limit is imposed in the field due to which filling with +// country code is not possible. +TEST_F(FormFillerTest, FillPhoneNumber_WithMaxLengthLimit) { + FormData form = CreateTestAddressFormData(); + form.fields[9].max_length = 10; + FormsSeen({form}); + + AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); + profile.set_guid(MakeGuid(103)); + profile.SetInfo(NAME_FULL, u"Natty Bumppo", "en-US"); + profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"+886123456789"); + personal_data().ClearProfiles(); + personal_data().AddProfile(profile); + + std::string guid = profile.guid(); + FormData response_data = + FillAutofillFormDataAndGetResults(form, *form.fields.begin(), guid); + + ASSERT_EQ(11U, response_data.fields.size()); + EXPECT_EQ(u"123456789", response_data.fields[9].value); +} + +TEST_F(FormFillerTest, FillFirstPhoneNumber_ComponentizedNumbers) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + // Verify only the first complete number is filled when there are multiple + // componentized number fields. + FormData form_with_multiple_componentized_phone_fields; + form_with_multiple_componentized_phone_fields.renderer_id = + test::MakeFormRendererId(); + form_with_multiple_componentized_phone_fields.url = + GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_multiple_componentized_phone_fields.name = + u"multiple_componentized_number_fields"; + form_with_multiple_componentized_phone_fields.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("country code", "country_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("area code", "area_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("number", "phone_number", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping country code", "shipping_country_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping area code", "shipping_area_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping number", "shipping_phone_number", "", + FormControlType::kInputText, "", kMaxLength)}; + + FormsSeen({form_with_multiple_componentized_phone_fields}); + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_multiple_componentized_phone_fields, + *form_with_multiple_componentized_phone_fields.fields.begin(), guid); + + // Verify only the first complete set of phone number fields are filled. + ASSERT_EQ(8U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(u"1", response_data.fields[1].value); + EXPECT_EQ(u"650", response_data.fields[2].value); + EXPECT_EQ(u"5554567", response_data.fields[3].value); + EXPECT_EQ(std::u16string(), response_data.fields[4].value); + EXPECT_EQ(std::u16string(), response_data.fields[5].value); + EXPECT_EQ(std::u16string(), response_data.fields[6].value); + EXPECT_EQ(std::u16string(), response_data.fields[7].value); +} + +TEST_F(FormFillerTest, FillFirstPhoneNumber_WholeNumbers) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + FormData form_with_multiple_whole_number_fields; + form_with_multiple_whole_number_fields.renderer_id = + test::MakeFormRendererId(); + form_with_multiple_whole_number_fields.url = GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_multiple_whole_number_fields.name = u"multiple_whole_number_fields"; + form_with_multiple_whole_number_fields.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("number", "phone_number", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping number", "shipping_phone_number", "", + FormControlType::kInputText, "", kMaxLength)}; + + FormsSeen({form_with_multiple_whole_number_fields}); + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_multiple_whole_number_fields, + *form_with_multiple_whole_number_fields.fields.begin(), guid); + + // Verify only the first complete set of phone number fields are filled. + ASSERT_EQ(4U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(u"6505554567", response_data.fields[1].value); + EXPECT_EQ(std::u16string(), response_data.fields[2].value); + EXPECT_EQ(std::u16string(), response_data.fields[3].value); +} + +TEST_F(FormFillerTest, FillFirstPhoneNumber_FillPartsOnceOnly) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + // Verify only the first complete number is filled when there are multiple + // componentized number fields. + FormData form_with_multiple_componentized_phone_fields; + form_with_multiple_componentized_phone_fields.renderer_id = + test::MakeFormRendererId(); + form_with_multiple_componentized_phone_fields.url = + GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_multiple_componentized_phone_fields.name = + u"multiple_componentized_number_fields"; + form_with_multiple_componentized_phone_fields.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("country code", "country_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("area code", "area_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("number", "phone_number", "", + FormControlType::kInputText, "tel-national", + kMaxLength), + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping country code", "shipping_country_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping area code", "shipping_area_code", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping number", "shipping_phone_number", "", + FormControlType::kInputText, "", kMaxLength)}; + + FormsSeen({form_with_multiple_componentized_phone_fields}); + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_multiple_componentized_phone_fields, + *form_with_multiple_componentized_phone_fields.fields.begin(), guid); + + // Verify only the first complete set of phone number fields are filled, + // and phone components are not filled more than once. + ASSERT_EQ(8U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(u"1", response_data.fields[1].value); + EXPECT_EQ(std::u16string(), response_data.fields[2].value); + EXPECT_EQ(u"6505554567", response_data.fields[3].value); + EXPECT_EQ(std::u16string(), response_data.fields[4].value); + EXPECT_EQ(std::u16string(), response_data.fields[5].value); + EXPECT_EQ(std::u16string(), response_data.fields[6].value); + EXPECT_EQ(std::u16string(), response_data.fields[7].value); +} + +// Verify when extension is misclassified, and there is a complete +// phone field, we do not fill anything to extension field. +TEST_F(FormFillerTest, FillFirstPhoneNumber_NotFillMisclassifiedExtention) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + FormData form_with_misclassified_extension; + form_with_misclassified_extension.renderer_id = test::MakeFormRendererId(); + form_with_misclassified_extension.url = GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_misclassified_extension.name = + u"complete_phone_form_with_extension"; + form_with_misclassified_extension.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "name", kMaxLength), + CreateTestFormField("address", "address", "", FormControlType::kInputText, + "addresses", kMaxLength), + CreateTestFormField("area code", "area_code", "", + FormControlType::kInputText, "tel-area-code", + kMaxLength), + CreateTestFormField("number", "phone_number", "", + FormControlType::kInputText, "tel-local", kMaxLength), + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "tel-local", + kMaxLength)}; + + FormsSeen({form_with_misclassified_extension}); + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_misclassified_extension, + *form_with_misclassified_extension.fields.begin(), guid); + + // Verify the misclassified extension field is not filled. + ASSERT_EQ(5U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(std::u16string(), response_data.fields[1].value); + EXPECT_EQ(u"650", response_data.fields[2].value); + EXPECT_EQ(u"5554567", response_data.fields[3].value); + EXPECT_EQ(std::u16string(), response_data.fields[4].value); +} + +// Verify that phone number fields annotated with the autocomplete attribute +// are filled best-effort. +// Phone number local heuristics only succeed if a PHONE_HOME_NUMBER field is +// present. +TEST_F(FormFillerTest, FillFirstPhoneNumber_BestEffortFilling) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + FormData form_with_no_complete_number; + form_with_no_complete_number.renderer_id = test::MakeFormRendererId(); + form_with_no_complete_number.url = GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_no_complete_number.name = u"no_complete_phone_form"; + form_with_no_complete_number.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "name", kMaxLength), + CreateTestFormField("address", "address", "", FormControlType::kInputText, + "address", kMaxLength), + CreateTestFormField("area code", "area_code", "", + FormControlType::kInputText, "tel-area-code", + kMaxLength), + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "extension", + kMaxLength)}; + + FormsSeen({form_with_no_complete_number}); + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_no_complete_number, + *form_with_no_complete_number.fields.begin(), guid); + + // Verify when there is no complete phone number fields, we do best effort + // filling. + ASSERT_EQ(4U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(u"123 Apple St., unit 6", response_data.fields[1].value); + EXPECT_EQ(u"650", response_data.fields[2].value); + EXPECT_EQ(std::u16string(), response_data.fields[3].value); +} + +// When the focus is on second phone field explicitly, we will fill the +// entire form, both first phone field and second phone field included. +TEST_F(FormFillerTest, FillFirstPhoneNumber_FocusOnSecondPhoneNumber) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + FormData form_with_multiple_whole_number_fields; + form_with_multiple_whole_number_fields.renderer_id = + test::MakeFormRendererId(); + form_with_multiple_whole_number_fields.url = GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_multiple_whole_number_fields.name = u"multiple_whole_number_fields"; + form_with_multiple_whole_number_fields.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("number", "phone_number", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping number", "shipping_phone_number", "", + FormControlType::kInputText, "", kMaxLength)}; + + FormsSeen({form_with_multiple_whole_number_fields}); + auto it = form_with_multiple_whole_number_fields.fields.begin(); + // Move it to point to "shipping number". + std::advance(it, 3); + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_multiple_whole_number_fields, *it, guid); + + // Verify when the second phone number field is being focused, we fill + // that field *AND* the first phone number field. + ASSERT_EQ(4U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(u"6505554567", response_data.fields[1].value); + EXPECT_EQ(std::u16string(), response_data.fields[2].value); + EXPECT_EQ(u"6505554567", response_data.fields[3].value); +} + +TEST_F(FormFillerTest, FillFirstPhoneNumber_HiddenFieldShouldNotCount) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + FormData form_with_multiple_whole_number_fields; + form_with_multiple_whole_number_fields.renderer_id = + test::MakeFormRendererId(); + form_with_multiple_whole_number_fields.url = GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_multiple_whole_number_fields.name = u"multiple_whole_number_fields"; + form_with_multiple_whole_number_fields.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("number", "phone_number", "", + FormControlType::kInputText, "", kMaxLength)}; + form_with_multiple_whole_number_fields.fields.back().is_focusable = false; + form_with_multiple_whole_number_fields.fields.push_back( + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "", kMaxLength)); + form_with_multiple_whole_number_fields.fields.push_back( + CreateTestFormField("shipping number", "shipping_phone_number", "", + FormControlType::kInputText, "", kMaxLength)); + + FormsSeen({form_with_multiple_whole_number_fields}); + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_multiple_whole_number_fields, + *form_with_multiple_whole_number_fields.fields.begin(), guid); + + // Verify hidden/non-focusable phone field is set to only_fill_when_focused. + ASSERT_EQ(4U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(std::u16string(), response_data.fields[1].value); + EXPECT_EQ(std::u16string(), response_data.fields[2].value); + EXPECT_EQ(u"6505554567", response_data.fields[3].value); +} + +// The hidden and the presentational fields should be filled, only if their +// control type is 'select-one'. This exception is made to support synthetic +// fields. +TEST_F(FormFillerTest, FormWithHiddenOrPresentationalSelects) { + FormData form; + form.renderer_id = test::MakeFormRendererId(); + form.name = u"MyForm"; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = {CreateTestFormField("First name", "firstname", "", + FormControlType::kInputText), + CreateTestFormField("Last name", "lastname", "", + FormControlType::kInputText)}; + + { + const std::vector<const char*> values{"CA", "US", "BR"}; + const std::vector<const char*> contents{"Canada", "United States", + "Banana Republic"}; + form.fields.push_back( + CreateTestSelectField("Country", "country", "", values, contents)); + form.fields.back().is_focusable = false; + } + { + const std::vector<const char*> values{"NY", "CA", "TN"}; + const std::vector<const char*> contents{"New York", "California", + "Tennessee"}; + form.fields.push_back( + CreateTestSelectField("State", "state", "", values, contents)); + form.fields.back().role = FormFieldData::RoleAttribute::kPresentation; + } + + form.fields.push_back( + CreateTestFormField("City", "city", "", FormControlType::kInputText)); + form.fields.back().is_focusable = false; + form.fields.push_back(CreateTestFormField("Street Address", "address", "", + FormControlType::kInputText)); + form.fields.back().role = FormFieldData::RoleAttribute::kPresentation; + + FormsSeen({form}); + + base::HistogramTester histogram_tester; + + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + histogram_tester.ExpectTotalCount( + "Autofill.HiddenOrPresentationalSelectFieldsFilled", 2); + + ExpectFilledField("First name", "firstname", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Last name", "lastname", "Presley", + FormControlType::kInputText, response_data.fields[1]); + ExpectFilledField("Country", "country", "US", FormControlType::kSelectOne, + response_data.fields[2]); + ExpectFilledField("State", "state", "TN", FormControlType::kSelectOne, + response_data.fields[3]); + ExpectFilledField("City", "city", "", FormControlType::kInputText, + response_data.fields[4]); + ExpectFilledField("Street Address", "address", "", + FormControlType::kInputText, response_data.fields[5]); +} + +TEST_F(FormFillerTest, FillFirstPhoneNumber_MultipleSectionFilledCorrectly) { + AutofillProfile* work_profile = personal_data().GetProfileByGUID(MakeGuid(2)); + ASSERT_TRUE(work_profile != nullptr); + work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567"); + + std::string guid = work_profile->guid(); + + FormData form_with_multiple_sections; + form_with_multiple_sections.renderer_id = test::MakeFormRendererId(); + form_with_multiple_sections.url = GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form_with_multiple_sections.name = u"multiple_section_fields"; + form_with_multiple_sections.fields = { + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("Address", "address", "", FormControlType::kInputText, + "", kMaxLength), + CreateTestFormField("number", "phone_number", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("other number", "other_phone_number", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("extension", "extension", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("Full Name", "full_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("Shipping Address", "shipping_address", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("shipping number", "shipping_phone_number", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("other shipping number", + "other_shipping_phone_number", "", + FormControlType::kInputText, "", kMaxLength)}; + + FormsSeen({form_with_multiple_sections}); + // Fill first sections. + FormData response_data = FillAutofillFormDataAndGetResults( + form_with_multiple_sections, *form_with_multiple_sections.fields.begin(), + guid); + + // Verify first section is filled with rationalization. + ASSERT_EQ(9U, response_data.fields.size()); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[0].value); + EXPECT_EQ(u"123 Apple St.", response_data.fields[1].value); + EXPECT_EQ(u"6505554567", response_data.fields[2].value); + EXPECT_EQ(std::u16string(), response_data.fields[3].value); + EXPECT_EQ(std::u16string(), response_data.fields[4].value); + EXPECT_EQ(std::u16string(), response_data.fields[5].value); + EXPECT_EQ(std::u16string(), response_data.fields[6].value); + EXPECT_EQ(std::u16string(), response_data.fields[7].value); + EXPECT_EQ(std::u16string(), response_data.fields[8].value); + + // Fill second section. + auto it = form_with_multiple_sections.fields.begin(); + std::advance(it, 6); // Pointing to second section. + + response_data = + FillAutofillFormDataAndGetResults(form_with_multiple_sections, *it, guid); + + // Verify second section is filled with rationalization. + ASSERT_EQ(9U, response_data.fields.size()); + EXPECT_EQ(std::u16string(), response_data.fields[0].value); + EXPECT_EQ(std::u16string(), response_data.fields[1].value); + EXPECT_EQ(std::u16string(), response_data.fields[2].value); + EXPECT_EQ(std::u16string(), response_data.fields[3].value); + EXPECT_EQ(std::u16string(), response_data.fields[4].value); + EXPECT_EQ(u"Charles Hardin Holley", response_data.fields[5].value); + EXPECT_EQ(u"123 Apple St.", response_data.fields[6].value); + EXPECT_EQ(u"6505554567", response_data.fields[7].value); + EXPECT_EQ(std::u16string(), response_data.fields[8].value); +} + +// Test that we can still fill a form when a field has been removed from it. +TEST_F(FormFillerTest, FormChangesRemoveField) { + // Set up our form data. + FormData form = CreateTestAddressFormData(); + + // Add a field -- we'll remove it again later. + form.fields.insert( + form.fields.begin() + 3, + CreateTestFormField("Some", "field", "", FormControlType::kInputText)); + + FormsSeen({form}); + + // Now, after the call to |FormsSeen|, we remove the field before filling. + form.fields.erase(form.fields.begin() + 3); + + FormsSeen({form}); + + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + ExpectFilledAddressFormElvis(response_data, false); +} + +// Test that we can still fill a form when a field has been added to it. +TEST_F(FormFillerTest, FormChangesAddField) { + // The offset of the phone field in the address form. + const int kPhoneFieldOffset = 9; + + // Set up our form data. + FormData form = CreateTestAddressFormData(); + + // Remove the phone field -- we'll add it back later. + auto pos = form.fields.begin() + kPhoneFieldOffset; + FormFieldData field = *pos; + pos = form.fields.erase(pos); + + FormsSeen({form}); + + // Now, after the call to |FormsSeen|, we restore the field before filling. + form.fields.insert(pos, field); + + FormsSeen({form}); + + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + ExpectFilledAddressFormElvis(response_data, false); +} + +// Test that we can still fill a form when the visibility of some fields +// changes. +TEST_F(FormFillerTest, FormChangesVisibilityOfFields) { + // Set up our form data. + FormData form; + form.renderer_id = test::MakeFormRendererId(); + form.url = GURL("https://www.foo.com/"); + + // Default is zero, have to set to a number autofill can process. + constexpr uint64_t kMaxLength = 10; + form.name = u"multiple_groups_fields"; + form.fields = { + CreateTestFormField("First Name", "first_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("Last Name", "last_name", "", + FormControlType::kInputText, "", kMaxLength), + CreateTestFormField("Address", "address", "", FormControlType::kInputText, + "", kMaxLength), + CreateTestFormField("Postal Code", "postal_code", "", + FormControlType::kInputText, "", kMaxLength)}; + form.fields.back().is_focusable = false; + form.fields.push_back(CreateTestFormField("Country", "country", "", + FormControlType::kInputText)); + form.fields.back().is_focusable = false; + + FormsSeen({form}); + + // Fill the form with the first profile. The hidden fields will not get + // filled. + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], MakeGuid(1)); + + ASSERT_EQ(5U, response_data.fields.size()); + ExpectFilledField("First Name", "first_name", "Elvis", + FormControlType::kInputText, response_data.fields[0]); + ExpectFilledField("Last Name", "last_name", "Presley", + FormControlType::kInputText, response_data.fields[1]); + ExpectFilledField("Address", "address", "3734 Elvis Presley Blvd.", + FormControlType::kInputText, response_data.fields[2]); + ExpectFilledField("Postal Code", "postal_code", "", + FormControlType::kInputText, response_data.fields[3]); + ExpectFilledField("Country", "country", "", FormControlType::kInputText, + response_data.fields[4]); + + // Two other fields will show up. Select the second profile. The fields that + // were already filled, would be left unchanged, and the rest would be filled + // with the second profile. (Two different profiles are selected, to make sure + // the right fields are getting filled.) + response_data.fields[3].is_focusable = true; + response_data.fields[4].is_focusable = true; + + FormData later_response_data = FillAutofillFormDataAndGetResults( + response_data, response_data.fields[4], MakeGuid(2)); + ASSERT_EQ(5U, later_response_data.fields.size()); + ExpectFilledField("First Name", "first_name", "Elvis", + FormControlType::kInputText, later_response_data.fields[0]); + ExpectFilledField("Last Name", "last_name", "Presley", + FormControlType::kInputText, later_response_data.fields[1]); + ExpectFilledField("Address", "address", "3734 Elvis Presley Blvd.", + FormControlType::kInputText, later_response_data.fields[2]); + ExpectFilledField("Postal Code", "postal_code", "79401", + FormControlType::kInputText, later_response_data.fields[3]); + ExpectFilledField("Country", "country", "United States", + FormControlType::kInputText, later_response_data.fields[4]); +} + +TEST_F(FormFillerTest, FillInUpdatedExpirationDate) { + FormData form; + CreditCard card; + PrepareForRealPanResponse(&form, &card); + + CardUnmaskDelegate::UserProvidedUnmaskDetails details; + details.cvc = u"123"; + details.exp_month = u"02"; + details.exp_year = u"2018"; + full_card_unmask_delegate()->OnUnmaskPromptAccepted(details); + OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, + "4012888888881881"); +} + +TEST_F(FormFillerTest, ProfileDisabledDoesNotFillFormData) { + browser_autofill_manager_->SetAutofillProfileEnabled(autofill_client_, false); + + // Set up our form data. + FormData form = CreateTestAddressFormData(); + FormsSeen({form}); + + // Expect no fields filled, no form data sent to renderer. + EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); + + FillAutofillFormData(form, *form.fields.begin(), MakeGuid(1)); +} + +TEST_F(FormFillerTest, CreditCardDisabledDoesNotFillFormData) { + browser_autofill_manager_->SetAutofillPaymentMethodsEnabled(autofill_client_, + false); + + // Set up our form data. + FormData form = + CreateTestCreditCardFormData(/*is_https=*/true, /*use_month_type=*/false); + FormsSeen({form}); + + // Expect no fields filled, no form data sent to renderer. + EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); + FillAutofillFormData(form, *form.fields.begin(), MakeGuid(4)); +} + +// Test that fields will be assigned with the source profile that was used for +// autofill. +TEST_F(FormFillerTest, TrackFillingOrigin) { + // Set up our form data. + FormData form = CreateTestPersonalInformationFormData(); + + FormsSeen({form}); + + AutofillProfile profile = test::GetFullProfile(); + personal_data().AddProfile(profile); + FillAutofillFormData(form, form.fields[0], profile.guid()); + + FormStructure* form_structure = + browser_autofill_manager_->FindCachedFormById(form.global_id()); + ASSERT_TRUE(form_structure); + for (const auto& autofill_field_ptr : form_structure->fields()) { + EXPECT_THAT(autofill_field_ptr->autofill_source_profile_guid(), + testing::Optional(profile.guid())); + } +} + +// Test that filling with multiple autofill profiles will set different source +// profiles for fields. +TEST_F(FormFillerTest, TrackFillingOriginWithUsingMultipleProfiles) { + // Set up our form data. + FormData form = CreateTestPersonalInformationFormData(); + + FormsSeen({form}); + + // Fill the form with a profile without email + AutofillProfile profile1 = test::GetFullProfile(); + profile1.ClearFields({EMAIL_ADDRESS}); + personal_data().AddProfile(profile1); + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], profile1.guid()); + + // Check that the email field has no filling source. + FormStructure* form_structure = + browser_autofill_manager_->FindCachedFormById(form.global_id()); + ASSERT_EQ(form.fields[3].label, u"Email"); + EXPECT_EQ(form_structure->field(3)->autofill_source_profile_guid(), + std::nullopt); + + // Then fill the email field using the second profile + AutofillProfile profile2 = test::GetFullProfile(); + personal_data().AddProfile(profile2); + FormData later_response_data = FillAutofillFormDataAndGetResults( + response_data, form.fields[3], profile2.guid()); + + // Check that the first three fields have the first profile as filling source + // and the last field has the second profile. + form_structure = + browser_autofill_manager_->FindCachedFormById(form.global_id()); + ASSERT_TRUE(form_structure); + EXPECT_THAT(form_structure->field(0)->autofill_source_profile_guid(), + testing::Optional(profile1.guid())); + EXPECT_THAT(form_structure->field(1)->autofill_source_profile_guid(), + testing::Optional(profile1.guid())); + EXPECT_THAT(form_structure->field(2)->autofill_source_profile_guid(), + testing::Optional(profile1.guid())); + EXPECT_THAT(form_structure->field(3)->autofill_source_profile_guid(), + testing::Optional(profile2.guid())); +} + +// Test that an autofilled and edited field will be assigned with the autofill +// profile. +TEST_F(FormFillerTest, TrackFillingOriginOnEditedField) { + // Set up our form data. + FormData form = CreateTestPersonalInformationFormData(); + + FormsSeen({form}); + + AutofillProfile profile = test::GetFullProfile(); + personal_data().AddProfile(profile); + FormData response_data = + FillAutofillFormDataAndGetResults(form, form.fields[0], profile.guid()); + + // Simulate editing the first field. + response_data.fields[0].value = u"Michael"; + browser_autofill_manager_->OnTextFieldDidChange( + response_data, response_data.fields[0], gfx::RectF(), + base::TimeTicks::Now()); + + FormStructure* form_structure = + browser_autofill_manager_->FindCachedFormById(form.global_id()); + ASSERT_TRUE(form_structure); + AutofillField* edited_field = form_structure->field(0); + ASSERT_FALSE(edited_field->is_autofilled); + ASSERT_TRUE(edited_field->previously_autofilled()); + EXPECT_THAT(edited_field->autofill_source_profile_guid(), + testing::Optional(profile.guid())); +} + +// Test that only autofilled fields will be assigned with the autofill profile. +TEST_F(FormFillerTest, TrackFillingOriginWorksOnlyOnFilledField) { + // Set up our form data. + FormData form = CreateTestPersonalInformationFormData(); + + FormsSeen({form}); + + // Fill the form with a profile without email field. + AutofillProfile profile = test::GetFullProfile(); + profile.ClearFields({EMAIL_ADDRESS}); + personal_data().AddProfile(profile); + FillAutofillFormData(form, form.fields[0], profile.guid()); + + FormStructure* form_structure = + browser_autofill_manager_->FindCachedFormById(form.global_id()); + ASSERT_TRUE(form_structure); + // Check that the email field has no filling source. + EXPECT_EQ(form_structure->field(3)->autofill_source_profile_guid(), + std::nullopt); +} + +// The following Refill Tests ensure that Autofill can handle the situation +// where it fills a credit card form with an expiration date like 04/2999 +// and the website tries to reformat the input with whitespaces around the +// slash and then sacrifices the wrong digits in the expiration date. I.e., +// the website replaces "04/2099" with "04 / 20". The tests ensure that this +// triggers a refill with "04 / 29". +struct RefillTestCase { + // The value that JavaScript owned by the website sets for the expiration + // date filed. + std::u16string exp_date_from_js; + // Whether we expect a refill from in this test case. + bool triggers_refill; + // What value we expect in the refill. + const char* refilled_exp_date = nullptr; +}; + +class FormFillerRefillTest + : public FormFillerTest, + public testing::WithParamInterface<RefillTestCase> {}; + +TEST_P(FormFillerRefillTest, RefillModifiedCreditCardExpirationDates) { + RefillTestCase test_case = GetParam(); + + // Set up a CC form with name, cc number and expiration date. + FormData form; + form.url = GURL("https://myform.com/form.html"); + form.action = GURL("https://myform.com/submit.html"); + form.fields = {CreateTestFormField("Name on Card", "nameoncard", "", + FormControlType::kInputText), + CreateTestFormField("Card Number", "cardnumber", "", + FormControlType::kInputText), + CreateTestFormField("Expiration date", "exp_date", "", + FormControlType::kInputText)}; + + // Notify BrowserAutofillManager of the form. + FormsSeen({form}); + + // Simulate filling and store the data to be filled in |first_fill_data|. + FormData first_fill_data = FillAutofillFormDataAndGetResults( + form, *form.fields.begin(), MakeGuid(4)); + ASSERT_EQ(3u, first_fill_data.fields.size()); + ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", + FormControlType::kInputText, first_fill_data.fields[0]); + ExpectFilledField("Card Number", "cardnumber", "4234567890123456", + FormControlType::kInputText, first_fill_data.fields[1]); + ExpectFilledField("Expiration date", "exp_date", "04/2999", + FormControlType::kInputText, first_fill_data.fields[2]); + + FormData refilled_form; + if (test_case.triggers_refill) { + // Prepare intercepting the filling operation to the driver and capture + // the re-filled form data. + EXPECT_CALL(*autofill_driver_, ApplyFormAction) + .Times(1) + .WillOnce(DoAll(SaveArg<2>(&refilled_form), + Return(std::vector<FieldGlobalId>{}))); + } else { + EXPECT_CALL(*autofill_driver_, ApplyFormAction).Times(0); + } + // Simulate that JavaScript modifies the expiration date field. + FormData form_after_js_modification = first_fill_data; + form_after_js_modification.fields[2].value = test_case.exp_date_from_js; + browser_autofill_manager_->OnJavaScriptChangedAutofilledValue( + form_after_js_modification, form_after_js_modification.fields[2], + u"04/2999"); + + testing::Mock::VerifyAndClearExpectations(autofill_driver_.get()); + + if (test_case.triggers_refill) { + ASSERT_EQ(3u, refilled_form.fields.size()); + ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", + FormControlType::kInputText, refilled_form.fields[0]); + EXPECT_FALSE(refilled_form.fields[0].force_override); + ExpectFilledField("Card Number", "cardnumber", "4234567890123456", + FormControlType::kInputText, refilled_form.fields[1]); + EXPECT_FALSE(refilled_form.fields[1].force_override); + ExpectFilledField("Expiration date", "exp_date", + test_case.refilled_exp_date, FormControlType::kInputText, + refilled_form.fields[2]); + EXPECT_TRUE(refilled_form.fields[2].force_override); + } +} + +INSTANTIATE_TEST_SUITE_P( + All, + FormFillerRefillTest, + testing::Values( + // This is the classic case: Autofill filled 04/2999, website overrode + // 04 / 29, we need to fix this to 04 / 99. + RefillTestCase{.exp_date_from_js = u"04 / 29", + .triggers_refill = true, + .refilled_exp_date = "04 / 99"}, + // Maybe the website replaced the separator and added whitespaces. + RefillTestCase{.exp_date_from_js = u"04 - 29", + .triggers_refill = true, + .refilled_exp_date = "04 - 99"}, + // Maybe the website only replaced the separator. + RefillTestCase{.exp_date_from_js = u"04-29", + .triggers_refill = true, + .refilled_exp_date = "04-99"}, + // Maybe the website was smart and dropped the correct digits. + RefillTestCase{ + .exp_date_from_js = u"04 / 99", + .triggers_refill = false, + }, + // Maybe the website did not modify the values at all. + RefillTestCase{ + .exp_date_from_js = u"04/2999", + .triggers_refill = false, + }, + // Maybe the website did something we don't support. + RefillTestCase{ + .exp_date_from_js = u"April / 2999", + .triggers_refill = false, + }, + // Maybe the website just added some whitespaces. + RefillTestCase{ + .exp_date_from_js = u"04 / 2999", + .triggers_refill = false, + }, + // Don't trigger refill on 3 digit years. + RefillTestCase{ + .exp_date_from_js = u"04 / 299", + .triggers_refill = false, + })); + +} // namespace autofill
diff --git a/components/autofill/core/browser/metrics/payments/offers_metrics.cc b/components/autofill/core/browser/metrics/payments/offers_metrics.cc index 20f5c745..8cef6bc 100644 --- a/components/autofill/core/browser/metrics/payments/offers_metrics.cc +++ b/components/autofill/core/browser/metrics/payments/offers_metrics.cc
@@ -221,25 +221,12 @@ void LogPageLoadsWithOfferIconShown(AutofillOfferData::OfferType offer_type, const GURL& url) { - std::string histogram_name = "Autofill.PageLoadsWithOfferIconShowing"; - // Switch to different sub-histogram depending on offer type being displayed. - switch (offer_type) { - case AutofillOfferData::OfferType::FREE_LISTING_COUPON_OFFER: - histogram_name += ".FreeListingCouponOffer"; - base::UmaHistogramBoolean(histogram_name + ".FromHistoryCluster", - commerce::UrlContainsDiscountUtmTag(url)); - break; - case AutofillOfferData::OfferType::GPAY_CARD_LINKED_OFFER: - histogram_name += "CardLinkedOffer"; - break; - case AutofillOfferData::OfferType::GPAY_PROMO_CODE_OFFER: - histogram_name += ".GPayPromoCodeOffer"; - break; - case AutofillOfferData::OfferType::UNKNOWN: - NOTREACHED(); - return; + if (offer_type == AutofillOfferData::OfferType::FREE_LISTING_COUPON_OFFER) { + base::UmaHistogramBoolean( + "Autofill.PageLoadsWithOfferIconShowing.FreeListingCouponOffer." + "FromHistoryCluster", + commerce::UrlContainsDiscountUtmTag(url)); } - base::UmaHistogramBoolean(histogram_name, true); } } // namespace autofill::autofill_metrics
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h index 35243778..3475888 100644 --- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h +++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
@@ -130,6 +130,7 @@ friend class autofill_metrics::AutofillMetricsBaseTest; friend class CreditCardAccessManagerTest; friend class CreditCardCvcAuthenticatorTest; + friend class FormFillerTest; // The associated autofill client. Weak reference. const raw_ptr<AutofillClient> client_;
diff --git a/components/autofill/core/browser/payments/full_card_request.h b/components/autofill/core/browser/payments/full_card_request.h index 44280a3..db94303 100644 --- a/components/autofill/core/browser/payments/full_card_request.h +++ b/components/autofill/core/browser/payments/full_card_request.h
@@ -26,6 +26,7 @@ class CreditCardAccessManagerTest; class CreditCardCvcAuthenticatorTest; class CreditCard; +class FormFillerTest; class PersonalDataManager; namespace autofill_metrics { @@ -199,6 +200,7 @@ friend class autofill::autofill_metrics::AutofillMetricsBaseTest; friend class autofill::CreditCardAccessManagerTest; friend class autofill::CreditCardCvcAuthenticatorTest; + friend class autofill::FormFillerTest; // Retrieves the pan for `card` and invokes // `Delegate::OnFullCardRequestSucceeded()` or
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.cc b/components/autofill/core/browser/payments/payments_autofill_client.cc index 4c85b27dc..7e8ab3e 100644 --- a/components/autofill/core/browser/payments/payments_autofill_client.cc +++ b/components/autofill/core/browser/payments/payments_autofill_client.cc
@@ -25,6 +25,8 @@ const std::u16string& tip_message, const std::vector<MigratableCreditCard>& migratable_credit_cards, MigrationDeleteCardCallback delete_local_card_callback) {} + +void PaymentsAutofillClient::VirtualCardEnrollCompleted(bool is_vcn_enrolled) {} #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) } // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.h b/components/autofill/core/browser/payments/payments_autofill_client.h index 801e6b2..bbeed3e6 100644 --- a/components/autofill/core/browser/payments/payments_autofill_client.h +++ b/components/autofill/core/browser/payments/payments_autofill_client.h
@@ -66,6 +66,11 @@ const std::u16string& tip_message, const std::vector<MigratableCreditCard>& migratable_credit_cards, MigrationDeleteCardCallback delete_local_card_callback); + + // Called after virtual card enrollment is finished. Shows enrollment + // result to users. `is_vcn_enrolled` indicates if the card was successfully + // enrolled as a virtual card. + virtual void VirtualCardEnrollCompleted(bool is_vcn_enrolled); #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) };
diff --git a/components/autofill/core/browser/payments/payments_network_interface.cc b/components/autofill/core/browser/payments/payments_network_interface.cc index d0b15ff..fc53070f 100644 --- a/components/autofill/core/browser/payments/payments_network_interface.cc +++ b/components/autofill/core/browser/payments/payments_network_interface.cc
@@ -10,9 +10,7 @@ #include <utility> #include <vector> -#include "base/command_line.h" #include "base/functional/bind.h" -#include "base/json/json_reader.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/values.h" @@ -35,22 +33,8 @@ #include "components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request.h" #include "components/autofill/core/browser/payments/payments_requests/upload_card_request.h" #include "components/autofill/core/browser/payments/payments_requests/upload_iban_request.h" -#include "components/autofill/core/browser/payments/payments_service_url.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_payments_features.h" -#include "components/signin/public/identity_manager/access_token_fetcher.h" -#include "components/signin/public/identity_manager/access_token_info.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h" -#include "components/signin/public/identity_manager/scope_set.h" -#include "components/variations/net/variations_http_headers.h" -#include "net/base/load_flags.h" -#include "net/http/http_status_code.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/simple_url_loader.h" -#include "services/network/public/mojom/url_response_head.mojom.h" #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) #include "components/autofill/core/browser/payments/local_card_migration_manager.h" @@ -59,32 +43,6 @@ namespace autofill::payments { -namespace { - -const char kTokenFetchId[] = "wallet_client"; -const char kPaymentsOAuth2Scope[] = - "https://www.googleapis.com/auth/wallet.chrome"; - -GURL GetRequestUrl(const std::string& path) { - if (base::CommandLine::ForCurrentProcess()->HasSwitch("sync-url")) { - if (IsPaymentsProductionEnabled()) { - LOG(ERROR) << "You are using production Payments but you specified a " - "--sync-url. You likely want to disable the sync sandbox " - "or switch to sandbox Payments. Both are controlled in " - "about:flags."; - } - } else if (!IsPaymentsProductionEnabled()) { - LOG(ERROR) << "You are using sandbox Payments but you didn't specify a " - "--sync-url. You likely want to enable the sync sandbox " - "or switch to production Payments. Both are controlled in " - "about:flags."; - } - - return GetBaseSecureUrl().Resolve(path); -} - -} // namespace - PaymentsNetworkInterface::UnmaskDetails::UnmaskDetails() = default; PaymentsNetworkInterface::UnmaskDetails::UnmaskDetails(const UnmaskDetails& other) { @@ -275,11 +233,10 @@ signin::IdentityManager* identity_manager, AccountInfoGetter* account_info_getter, bool is_off_the_record) - : url_loader_factory_(url_loader_factory), - identity_manager_(identity_manager), - account_info_getter_(account_info_getter), - is_off_the_record_(is_off_the_record), - has_retried_authorization_(false) {} + : PaymentsNetworkInterfaceBase(url_loader_factory, + identity_manager, + account_info_getter, + is_off_the_record) {} PaymentsNetworkInterface::~PaymentsNetworkInterface() = default; @@ -415,250 +372,4 @@ request_details, std::move(callback))); } -void PaymentsNetworkInterface::CancelRequest() { - request_.reset(); - resource_request_.reset(); - simple_url_loader_.reset(); - token_fetcher_.reset(); - access_token_.clear(); - has_retried_authorization_ = false; -} - -void PaymentsNetworkInterface::set_url_loader_factory_for_testing( - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { - url_loader_factory_ = std::move(url_loader_factory); -} - -void PaymentsNetworkInterface::set_access_token_for_testing(std::string access_token) { - access_token_ = access_token; -} - -void PaymentsNetworkInterface::IssueRequest(std::unique_ptr<PaymentsRequest> request) { - request_ = std::move(request); - has_retried_authorization_ = false; - - InitializeResourceRequest(); - - if (access_token_.empty()) { - StartTokenFetch(false); - } else { - SetOAuth2TokenAndStartRequest(); - } -} - -void PaymentsNetworkInterface::InitializeResourceRequest() { - resource_request_ = std::make_unique<network::ResourceRequest>(); - resource_request_->url = GetRequestUrl(request_->GetRequestUrlPath()); - resource_request_->load_flags = net::LOAD_DISABLE_CACHE; - resource_request_->credentials_mode = network::mojom::CredentialsMode::kOmit; - resource_request_->method = "POST"; - - // Add Chrome experiment state to the request headers. - net::HttpRequestHeaders headers; - // User is always signed-in to be able to upload card to Google Payments. - variations::AppendVariationsHeader( - resource_request_->url, - is_off_the_record_ ? variations::InIncognito::kYes - : variations::InIncognito::kNo, - variations::SignedIn::kYes, resource_request_.get()); -} - -void PaymentsNetworkInterface::OnSimpleLoaderComplete( - std::unique_ptr<std::string> response_body) { - int response_code = -1; - if (simple_url_loader_->ResponseInfo() && - simple_url_loader_->ResponseInfo()->headers) { - response_code = - simple_url_loader_->ResponseInfo()->headers->response_code(); - } - std::string data; - if (response_body) - data = std::move(*response_body); - OnSimpleLoaderCompleteInternal(response_code, data); -} - -void PaymentsNetworkInterface::OnSimpleLoaderCompleteInternal(int response_code, - const std::string& data) { - VLOG(2) << "Got data: " << data; - - AutofillClient::PaymentsRpcResult result = - AutofillClient::PaymentsRpcResult::kSuccess; - - if (!request_) - return; - - switch (response_code) { - // Valid response. - case net::HTTP_OK: { - std::string error_code; - std::string error_api_error_reason; - std::optional<base::Value> message_value = base::JSONReader::Read(data); - if (message_value && message_value->is_dict()) { - const auto* found_error_code = - message_value->GetDict().FindStringByDottedPath("error.code"); - if (found_error_code) - error_code = *found_error_code; - - const auto* found_error_reason = - message_value->GetDict().FindStringByDottedPath( - "error.api_error_reason"); - if (found_error_reason) - error_api_error_reason = *found_error_reason; - - request_->ParseResponse(message_value->GetDict()); - } - - if (base::EqualsCaseInsensitiveASCII(error_api_error_reason, - "virtual_card_temporary_error")) { - result = - AutofillClient::PaymentsRpcResult::kVcnRetrievalTryAgainFailure; - } else if (base::EqualsCaseInsensitiveASCII( - error_api_error_reason, "virtual_card_permanent_error")) { - result = - AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure; - } else if (request_->IsRetryableFailure(error_code)) { - result = AutofillClient::PaymentsRpcResult::kTryAgainFailure; - } else if (!error_code.empty() || !request_->IsResponseComplete()) { - result = AutofillClient::PaymentsRpcResult::kPermanentFailure; - } - - break; - } - - case net::HTTP_UNAUTHORIZED: { - if (has_retried_authorization_) { - result = AutofillClient::PaymentsRpcResult::kPermanentFailure; - break; - } - has_retried_authorization_ = true; - - InitializeResourceRequest(); - StartTokenFetch(true); - return; - } - - // TODO(estade): is this actually how network connectivity issues are - // reported? - case net::HTTP_REQUEST_TIMEOUT: { - result = AutofillClient::PaymentsRpcResult::kNetworkError; - break; - } - - // Handle anything else as a generic (permanent) failure. - default: { - result = AutofillClient::PaymentsRpcResult::kPermanentFailure; - break; - } - } - - if (result != AutofillClient::PaymentsRpcResult::kSuccess) { - VLOG(1) << "Payments returned error: " << response_code - << " with data: " << data; - } - - request_->RespondToDelegate(result); -} - -void PaymentsNetworkInterface::AccessTokenFetchFinished( - GoogleServiceAuthError error, - signin::AccessTokenInfo access_token_info) { - DCHECK(token_fetcher_); - token_fetcher_.reset(); - - if (error.state() != GoogleServiceAuthError::NONE) { - AccessTokenError(error); - return; - } - - access_token_ = access_token_info.token; - if (resource_request_) - SetOAuth2TokenAndStartRequest(); -} - -void PaymentsNetworkInterface::AccessTokenError(const GoogleServiceAuthError& error) { - VLOG(1) << "Unhandled OAuth2 error: " << error.ToString(); - if (simple_url_loader_) - simple_url_loader_.reset(); - if (request_) - request_->RespondToDelegate( - AutofillClient::PaymentsRpcResult::kPermanentFailure); -} - -void PaymentsNetworkInterface::StartTokenFetch(bool invalidate_old) { - // We're still waiting for the last request to come back. - if (!invalidate_old && token_fetcher_) - return; - - DCHECK(account_info_getter_); - - signin::ScopeSet payments_scopes; - payments_scopes.insert(kPaymentsOAuth2Scope); - CoreAccountId account_id = - account_info_getter_->GetAccountInfoForPaymentsServer().account_id; - if (invalidate_old) { - DCHECK(!access_token_.empty()); - identity_manager_->RemoveAccessTokenFromCache(account_id, payments_scopes, - access_token_); - } - access_token_.clear(); - token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount( - account_id, kTokenFetchId, payments_scopes, - base::BindOnce(&PaymentsNetworkInterface::AccessTokenFetchFinished, - base::Unretained(this)), - signin::AccessTokenFetcher::Mode::kImmediate); -} - -void PaymentsNetworkInterface::SetOAuth2TokenAndStartRequest() { - // Set OAuth2 token: - DCHECK(resource_request_); - resource_request_->headers.SetHeader(net::HttpRequestHeaders::kAuthorization, - std::string("Bearer ") + access_token_); - - // Start request: - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("payments_sync_cards", R"( - semantics { - sender: "Payments" - description: - "This service communicates with Google Payments servers to upload " - "(save) or receive the user's credit card info." - trigger: - "Requests are triggered by a user action, such as selecting a " - "masked server card from Chromium's credit card autofill dropdown, " - "submitting a form which has credit card information, or accepting " - "the prompt to save a credit card to Payments servers." - data: - "In case of save, a protocol buffer containing relevant address " - "and credit card information which should be saved in Google " - "Payments servers, along with user credentials. In case of load, a " - "protocol buffer containing the id of the credit card to unmask, " - "an encrypted cvc value, an optional updated card expiration date, " - "and user credentials." - destination: GOOGLE_OWNED_SERVICE - } - policy { - cookies_allowed: NO - setting: - "Users can enable or disable this feature in Chromium settings by " - "toggling 'Credit cards and addresses using Google Payments', " - "under 'Advanced sync settings...'. This feature is enabled by " - "default." - chrome_policy { - AutoFillEnabled { - policy_options {mode: MANDATORY} - AutoFillEnabled: false - } - } - })"); - simple_url_loader_ = network::SimpleURLLoader::Create( - std::move(resource_request_), traffic_annotation); - simple_url_loader_->AttachStringForUpload(request_->GetRequestContent(), - request_->GetRequestContentType()); - - simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( - url_loader_factory_.get(), - base::BindOnce(&PaymentsNetworkInterface::OnSimpleLoaderComplete, - base::Unretained(this))); -} - } // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_network_interface.h b/components/autofill/core/browser/payments/payments_network_interface.h index df35fbd..3ac2d1d 100644 --- a/components/autofill/core/browser/payments/payments_network_interface.h +++ b/components/autofill/core/browser/payments/payments_network_interface.h
@@ -26,19 +26,16 @@ #include "components/autofill/core/browser/payments/card_unmask_challenge_option.h" #include "components/autofill/core/browser/payments/card_unmask_delegate.h" #include "components/autofill/core/browser/payments/client_behavior_constants.h" +#include "components/autofill/core/browser/payments/payments_network_interface_base.h" #include "components/autofill/core/browser/payments/virtual_card_enrollment_flow.h" #include "google_apis/gaia/google_service_auth_error.h" #include "url/origin.h" namespace signin { -class AccessTokenFetcher; -struct AccessTokenInfo; class IdentityManager; } // namespace signin namespace network { -struct ResourceRequest; -class SimpleURLLoader; class SharedURLLoaderFactory; } // namespace network @@ -69,14 +66,12 @@ inline constexpr int kUploadPaymentMethodBillableServiceNumber = 70073; inline constexpr int kMigrateCardsBillableServiceNumber = 70264; -class PaymentsRequest; - // PaymentsNetworkInterface issues Payments RPCs and manages responses and failure // conditions. Only one request may be active at a time. Initiating a new // request will cancel a pending request. // Tests are located in // src/components/autofill/content/browser/payments/payments_network_interface_unittest.cc. -class PaymentsNetworkInterface { +class PaymentsNetworkInterface : public PaymentsNetworkInterfaceBase { public: // The names of the fields used to send non-location elements as part of an // address. Used in the implementation and in tests which verify that these @@ -460,7 +455,7 @@ PaymentsNetworkInterface(const PaymentsNetworkInterface&) = delete; PaymentsNetworkInterface& operator=(const PaymentsNetworkInterface&) = delete; - virtual ~PaymentsNetworkInterface(); + ~PaymentsNetworkInterface() override; // Starts fetching the OAuth2 token in anticipation of future Payments // requests. Called as an optimization, but not strictly necessary. Should @@ -596,79 +591,8 @@ const UpdateVirtualCardEnrollmentRequestDetails& request_details, base::OnceCallback<void(AutofillClient::PaymentsRpcResult)> callback); - // Cancels and clears the current |request_|. - void CancelRequest(); - - // Exposed for testing. - void set_url_loader_factory_for_testing( - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); - void set_access_token_for_testing(std::string access_token); - private: friend class PaymentsNetworkInterfaceTest; - - // Initiates a Payments request using the state in `request`, ensuring that an - // OAuth token is available first. Takes ownership of `request`. - void IssueRequest(std::unique_ptr<PaymentsRequest> request); - - // Creates `resource_request_` to be used later in - // SetOAuth2TokenAndStartRequest(). - void InitializeResourceRequest(); - - // Callback from |simple_url_loader_|. - void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body); - void OnSimpleLoaderCompleteInternal(int response_code, - const std::string& data); - - // Callback that handles a completed access token request. - void AccessTokenFetchFinished(GoogleServiceAuthError error, - signin::AccessTokenInfo access_token_info); - - // Handles a completed access token request in the case of failure. - void AccessTokenError(const GoogleServiceAuthError& error); - - // Initiates a new OAuth2 token request. - void StartTokenFetch(bool invalidate_old); - - // Creates `simple_url_loader_`, adds the token to it, and starts the request. - void SetOAuth2TokenAndStartRequest(); - - // The URL loader factory for the request. - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; - - // Provided in constructor; not owned by PaymentsNetworkInterface. - const raw_ptr<signin::IdentityManager> identity_manager_; - - // Provided in constructor; not owned by PaymentsNetworkInterface. - const raw_ptr<AccountInfoGetter> account_info_getter_; - - // The current request. - std::unique_ptr<PaymentsRequest> request_; - - // The resource request being used to issue the current request. - std::unique_ptr<network::ResourceRequest> resource_request_; - - // The URL loader being used to issue the current request. - std::unique_ptr<network::SimpleURLLoader> simple_url_loader_; - - // The OAuth2 token fetcher for any account. - std::unique_ptr<signin::AccessTokenFetcher> token_fetcher_; - - // The OAuth2 token, or empty if not fetched. - std::string access_token_; - - // Denotes incognito mode. - // TODO(crbug.com/1409158): Remove this variable, as it should not be the - // PaymentsNetworkInterface's responsibility to check if the user is off the record. The - // sole responsibility of the PaymentsNetworkInterface is to send requests to the Google - // Payments server. - bool is_off_the_record_; - - // True if |request_| has already retried due to a 401 response from the - // server. - bool has_retried_authorization_; - - base::WeakPtrFactory<PaymentsNetworkInterface> weak_ptr_factory_{this}; }; } // namespace payments
diff --git a/components/autofill/core/browser/payments/payments_network_interface_base.cc b/components/autofill/core/browser/payments/payments_network_interface_base.cc new file mode 100644 index 0000000..f7c5670 --- /dev/null +++ b/components/autofill/core/browser/payments/payments_network_interface_base.cc
@@ -0,0 +1,345 @@ +// 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 "components/autofill/core/browser/payments/payments_network_interface_base.h" + +#include "base/command_line.h" +#include "base/json/json_reader.h" + +#include "components/autofill/core/browser/payments/account_info_getter.h" +#include "components/autofill/core/browser/payments/payments_requests/payments_request.h" +#include "components/autofill/core/browser/payments/payments_service_url.h" +#include "components/signin/public/identity_manager/access_token_fetcher.h" +#include "components/signin/public/identity_manager/access_token_info.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/variations/net/variations_http_headers.h" +#include "net/base/load_flags.h" +#include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +namespace autofill::payments { + +namespace { + +const char kTokenFetchId[] = "wallet_client"; +const char kPaymentsOAuth2Scope[] = + "https://www.googleapis.com/auth/wallet.chrome"; + +GURL GetRequestUrl(const std::string& path) { + if (base::CommandLine::ForCurrentProcess()->HasSwitch("sync-url")) { + if (IsPaymentsProductionEnabled()) { + LOG(ERROR) << "You are using production Payments but you specified a " + "--sync-url. You likely want to disable the sync sandbox " + "or switch to sandbox Payments. Both are controlled in " + "about:flags."; + } + } else if (!IsPaymentsProductionEnabled()) { + LOG(ERROR) << "You are using sandbox Payments but you didn't specify a " + "--sync-url. You likely want to enable the sync sandbox " + "or switch to production Payments. Both are controlled in " + "about:flags."; + } + + return GetBaseSecureUrl().Resolve(path); +} + +} // namespace + +PaymentsNetworkInterfaceBase::PaymentsNetworkInterfaceBase( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + signin::IdentityManager* identity_manager, + AccountInfoGetter* account_info_getter, + bool is_off_the_record) + : url_loader_factory_(url_loader_factory), + identity_manager_(identity_manager), + account_info_getter_(account_info_getter), + is_off_the_record_(is_off_the_record), + has_retried_authorization_(false) {} + +PaymentsNetworkInterfaceBase::~PaymentsNetworkInterfaceBase() = default; + +void PaymentsNetworkInterfaceBase::CancelRequest() { + request_.reset(); + resource_request_.reset(); + simple_url_loader_.reset(); + token_fetcher_.reset(); + access_token_.clear(); + has_retried_authorization_ = false; +} + +void PaymentsNetworkInterfaceBase::set_url_loader_factory_for_testing( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { + url_loader_factory_ = std::move(url_loader_factory); +} + +void PaymentsNetworkInterfaceBase::set_access_token_for_testing( + std::string access_token) { + access_token_ = access_token; +} + +void PaymentsNetworkInterfaceBase::IssueRequest( + std::unique_ptr<PaymentsRequest> request) { + request_ = std::move(request); + has_retried_authorization_ = false; + + InitializeResourceRequest(); + + if (access_token_.empty()) { + StartTokenFetch(false); + } else { + SetOAuth2TokenAndStartRequest(); + } +} + +void PaymentsNetworkInterfaceBase::InitializeResourceRequest() { + resource_request_ = std::make_unique<network::ResourceRequest>(); + resource_request_->url = GetRequestUrl(request_->GetRequestUrlPath()); + resource_request_->load_flags = net::LOAD_DISABLE_CACHE; + resource_request_->credentials_mode = network::mojom::CredentialsMode::kOmit; + resource_request_->method = "POST"; + + // Add Chrome experiment state to the request headers. + net::HttpRequestHeaders headers; + // User is always signed-in to be able to upload card to Google Payments. + variations::AppendVariationsHeader( + resource_request_->url, + is_off_the_record_ ? variations::InIncognito::kYes + : variations::InIncognito::kNo, + variations::SignedIn::kYes, resource_request_.get()); +} + +void PaymentsNetworkInterfaceBase::OnSimpleLoaderComplete( + std::unique_ptr<std::string> response_body) { + int response_code = -1; + if (simple_url_loader_->ResponseInfo() && + simple_url_loader_->ResponseInfo()->headers) { + response_code = + simple_url_loader_->ResponseInfo()->headers->response_code(); + } + std::string data; + if (response_body) { + data = std::move(*response_body); + } + OnSimpleLoaderCompleteInternal(response_code, data); +} + +void PaymentsNetworkInterfaceBase::OnSimpleLoaderCompleteInternal( + int response_code, + const std::string& data) { + VLOG(2) << "Got data: " << data; + + AutofillClient::PaymentsRpcResult result = + AutofillClient::PaymentsRpcResult::kSuccess; + + if (!request_) { + return; + } + + switch (response_code) { + // Valid response. + case net::HTTP_OK: { + std::string error_code; + std::string error_api_error_reason; + std::optional<base::Value> message_value = base::JSONReader::Read(data); + if (message_value && message_value->is_dict()) { + const auto* found_error_code = + message_value->GetDict().FindStringByDottedPath("error.code"); + if (found_error_code) { + error_code = *found_error_code; + } + + const auto* found_error_reason = + message_value->GetDict().FindStringByDottedPath( + "error.api_error_reason"); + if (found_error_reason) { + error_api_error_reason = *found_error_reason; + } + + request_->ParseResponse(message_value->GetDict()); + } + + if (base::EqualsCaseInsensitiveASCII(error_api_error_reason, + "virtual_card_temporary_error")) { + result = + AutofillClient::PaymentsRpcResult::kVcnRetrievalTryAgainFailure; + } else if (base::EqualsCaseInsensitiveASCII( + error_api_error_reason, "virtual_card_permanent_error")) { + result = + AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure; + } else if (request_->IsRetryableFailure(error_code)) { + result = AutofillClient::PaymentsRpcResult::kTryAgainFailure; + } else if (!error_code.empty() || !request_->IsResponseComplete()) { + result = AutofillClient::PaymentsRpcResult::kPermanentFailure; + } + + break; + } + + case net::HTTP_UNAUTHORIZED: { + if (has_retried_authorization_) { + result = AutofillClient::PaymentsRpcResult::kPermanentFailure; + break; + } + has_retried_authorization_ = true; + + InitializeResourceRequest(); + StartTokenFetch(true); + return; + } + + // TODO(estade): is this actually how network connectivity issues are + // reported? + case net::HTTP_REQUEST_TIMEOUT: { + result = AutofillClient::PaymentsRpcResult::kNetworkError; + break; + } + + // Handle anything else as a generic (permanent) failure. + default: { + result = AutofillClient::PaymentsRpcResult::kPermanentFailure; + break; + } + } + + if (result != AutofillClient::PaymentsRpcResult::kSuccess) { + VLOG(1) << "Payments returned error: " << response_code + << " with data: " << data; + } + + request_->RespondToDelegate(result); +} + +void PaymentsNetworkInterfaceBase::AccessTokenFetchFinished( + GoogleServiceAuthError error, + signin::AccessTokenInfo access_token_info) { + DCHECK(token_fetcher_); + token_fetcher_.reset(); + + if (error.state() != GoogleServiceAuthError::NONE) { + AccessTokenError(error); + return; + } + + access_token_ = access_token_info.token; + if (resource_request_) { + SetOAuth2TokenAndStartRequest(); + } +} + +void PaymentsNetworkInterfaceBase::AccessTokenError( + const GoogleServiceAuthError& error) { + VLOG(1) << "Unhandled OAuth2 error: " << error.ToString(); + if (simple_url_loader_) { + simple_url_loader_.reset(); + } + if (request_) { + request_->RespondToDelegate( + AutofillClient::PaymentsRpcResult::kPermanentFailure); + } +} + +void PaymentsNetworkInterfaceBase::StartTokenFetch(bool invalidate_old) { + // We're still waiting for the last request to come back. + if (!invalidate_old && token_fetcher_) { + return; + } + + DCHECK(account_info_getter_); + + signin::ScopeSet payments_scopes; + payments_scopes.insert(kPaymentsOAuth2Scope); + CoreAccountId account_id = + account_info_getter_->GetAccountInfoForPaymentsServer().account_id; + if (invalidate_old) { + DCHECK(!access_token_.empty()); + identity_manager_->RemoveAccessTokenFromCache(account_id, payments_scopes, + access_token_); + } + access_token_.clear(); + token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount( + account_id, kTokenFetchId, payments_scopes, + base::BindOnce(&PaymentsNetworkInterfaceBase::AccessTokenFetchFinished, + base::Unretained(this)), + signin::AccessTokenFetcher::Mode::kImmediate); +} + +void PaymentsNetworkInterfaceBase::SetOAuth2TokenAndStartRequest() { + // Set OAuth2 token: + DCHECK(resource_request_); + resource_request_->headers.SetHeader(net::HttpRequestHeaders::kAuthorization, + std::string("Bearer ") + access_token_); + + // Start request: + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("payments_sync_cards", R"( + semantics { + sender: "Payments" + description: + "This service communicates with Google Payments servers to " + "save/retrieve the user's payment methods (e.g., credit cards, " + "IBANs) as well as facilitate payments for Pix QR codes." + trigger: + "Requests are triggered by a user action, such as selecting a " + "masked server card from Chromium's credit card autofill dropdown, " + "submitting a form which has credit card information, or accepting " + "the prompt to save a credit card to Payments servers." + data: + "In case of save, a protocol buffer containing relevant address, " + "credit card and nickname information which should be saved in " + "Google Payments servers, along with user credentials. In case of " + "load, a protocol buffer containing the id of the credit card to " + "unmask, an encrypted cvc value, an optional updated card " + "expiration date, and user credentials. For virtual card numbers, " + "the merchant domain and last 4 digits of cards are extracted from " + "the web page. For virtual card verification, OTP and 3CSC etc " + "are collected from the user and sent to Google Payments servers. " + "For Pix, the QR code detected from the web page is sent to Google " + "Payments servers. User agent is sent to Google Payments servers " + "to determine the platform and return the corresponding response." + destination: GOOGLE_OWNED_SERVICE + internal { + contacts: { + email: "payments-autofill-team@google.com" + } + } + user_data { + type: USER_CONTENT + type: CREDIT_CARD_DATA + type: SENSITIVE_URL + type: PROFILE_DATA + type: WEB_CONTENT + type: GAIA_ID + type: USER_AGENT + } + last_reviewed: "2024-01-24" + } + policy { + cookies_allowed: NO + setting: + "Users can enable or disable this feature in Chromium settings by " + "toggling 'Credit cards and addresses using Google Payments', " + "under 'Advanced sync settings...'. This feature is enabled by " + "default." + chrome_policy { + AutoFillEnabled { + policy_options {mode: MANDATORY} + AutoFillEnabled: false + } + } + })"); + simple_url_loader_ = network::SimpleURLLoader::Create( + std::move(resource_request_), traffic_annotation); + simple_url_loader_->AttachStringForUpload(request_->GetRequestContent(), + request_->GetRequestContentType()); + + simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory_.get(), + base::BindOnce(&PaymentsNetworkInterfaceBase::OnSimpleLoaderComplete, + base::Unretained(this))); +} + +} // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_network_interface_base.h b/components/autofill/core/browser/payments/payments_network_interface_base.h new file mode 100644 index 0000000..6c4f70b5 --- /dev/null +++ b/components/autofill/core/browser/payments/payments_network_interface_base.h
@@ -0,0 +1,138 @@ +// 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 COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_NETWORK_INTERFACE_BASE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_NETWORK_INTERFACE_BASE_H_ + +#include <string> + +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/payments/client_behavior_constants.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "url/origin.h" + +namespace signin { +class AccessTokenFetcher; +struct AccessTokenInfo; +class IdentityManager; +} // namespace signin + +namespace network { +struct ResourceRequest; +class SimpleURLLoader; +class SharedURLLoaderFactory; +} // namespace network + +namespace autofill { + +class AccountInfoGetter; + +namespace payments { + +class PaymentsRequest; + +// PaymentsNetworkInterfaceBase issues Payments RPCs and manages responses and +// failure conditions. Only one request may be active at a time. Initiating a +// new request will cancel a pending request. +class PaymentsNetworkInterfaceBase { + public: + // Cancels and clears the current `request_`. + void CancelRequest(); + + // Exposed for testing. + void set_url_loader_factory_for_testing( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); + void set_access_token_for_testing(std::string access_token); + + protected: + friend class PaymentsNetworkInterfaceTestBase; + + // `url_loader_factory` is reference counted so it has no lifetime or + // ownership requirements. `identity_manager` and `account_info_getter` must + // all outlive `this`. Either delegate might be nullptr. `is_off_the_record` + // denotes incognito mode. + PaymentsNetworkInterfaceBase( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + signin::IdentityManager* const identity_manager, + AccountInfoGetter* const account_info_getter, + bool is_off_the_record = false); + + PaymentsNetworkInterfaceBase(const PaymentsNetworkInterfaceBase&) = delete; + PaymentsNetworkInterfaceBase& operator=(const PaymentsNetworkInterfaceBase&) = + delete; + + virtual ~PaymentsNetworkInterfaceBase(); + + // Initiates a Payments request using the state in `request`, ensuring that an + // OAuth token is available first. Takes ownership of `request`. + void IssueRequest(std::unique_ptr<PaymentsRequest> request); + + // Creates `resource_request_` to be used later in + // SetOAuth2TokenAndStartRequest(). + void InitializeResourceRequest(); + + // Callback from `simple_url_loader_`. + void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body); + void OnSimpleLoaderCompleteInternal(int response_code, + const std::string& data); + + // Callback that handles a completed access token request. + void AccessTokenFetchFinished(GoogleServiceAuthError error, + signin::AccessTokenInfo access_token_info); + + // Handles a completed access token request in the case of failure. + void AccessTokenError(const GoogleServiceAuthError& error); + + // Initiates a new OAuth2 token request. + void StartTokenFetch(bool invalidate_old); + + // Creates `simple_url_loader_`, adds the token to it, and starts the request. + void SetOAuth2TokenAndStartRequest(); + + // The URL loader factory for the request. + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + + // Provided in constructor; not owned by PaymentsNetworkInterface. + const raw_ptr<signin::IdentityManager> identity_manager_; + + // Provided in constructor; not owned by PaymentsNetworkInterface. + const raw_ptr<AccountInfoGetter> account_info_getter_; + + // The current request. + std::unique_ptr<PaymentsRequest> request_; + + // The resource request being used to issue the current request. + std::unique_ptr<network::ResourceRequest> resource_request_; + + // The URL loader being used to issue the current request. + std::unique_ptr<network::SimpleURLLoader> simple_url_loader_; + + // The OAuth2 token fetcher for any account. + std::unique_ptr<signin::AccessTokenFetcher> token_fetcher_; + + // The OAuth2 token, or empty if not fetched. + std::string access_token_; + + // Denotes incognito mode. + // TODO(crbug.com/1409158): Remove this variable, as it should not be the + // PaymentsNetworkInterface's responsibility to check if the user is off the + // record. The sole responsibility of the PaymentsNetworkInterface is to send + // requests to the Google Payments server. + bool is_off_the_record_; + + // True if `request_` has already retried due to a 401 response from the + // server. + bool has_retried_authorization_; + + base::WeakPtrFactory<PaymentsNetworkInterfaceBase> weak_ptr_factory_{this}; +}; + +} // namespace payments +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_NETWORK_INTERFACE_BASE_H_
diff --git a/components/autofill/core/browser/payments/payments_network_interface_test_base.cc b/components/autofill/core/browser/payments/payments_network_interface_test_base.cc new file mode 100644 index 0000000..832ddba --- /dev/null +++ b/components/autofill/core/browser/payments/payments_network_interface_test_base.cc
@@ -0,0 +1,123 @@ +// 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 "components/autofill/core/browser/payments/payments_network_interface_test_base.h" + +#include <string> +#include <string_view> +#include <utility> +#include <vector> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/bind.h" +#include "base/values.h" +#include "components/autofill/core/common/autofill_clock.h" +#include "components/autofill/core/common/autofill_switches.h" +#include "services/network/test/test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::HasSubstr; + +namespace autofill::payments { + +PaymentsNetworkInterfaceTestBase::PaymentsNetworkInterfaceTestBase() = default; +PaymentsNetworkInterfaceTestBase::~PaymentsNetworkInterfaceTestBase() = default; + +void PaymentsNetworkInterfaceTestBase::SetUpTest() { + // Silence the warning for mismatching sync and Payments servers. + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kWalletServiceUseSandbox, "0"); + + result_ = AutofillClient::PaymentsRpcResult::kNone; + has_variations_header_ = false; + + factory()->SetInterceptor( + base::BindLambdaForTesting([&](const network::ResourceRequest& request) { + intercepted_headers_ = request.headers; + intercepted_body_ = network::GetUploadData(request); + has_variations_header_ = variations::HasVariationsHeader(request); + })); + test_shared_loader_factory_ = + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_); + test_personal_data_.SetAccountInfoForPayments( + identity_test_env_.MakePrimaryAccountAvailable( + "example@gmail.com", signin::ConsentLevel::kSync)); +} + +void PaymentsNetworkInterfaceTestBase::CreateFieldTrialWithId( + const std::string& trial_name, + const std::string& group_name, + int variation_id) { + variations::AssociateGoogleVariationID( + variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, trial_name, group_name, + static_cast<variations::VariationID>(variation_id)); + base::FieldTrialList::CreateFieldTrial(trial_name, group_name)->Activate(); +} + +void PaymentsNetworkInterfaceTestBase::IssueOAuthToken() { + identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( + "totally_real_token", AutofillClock::Now() + base::Days(10)); + + // Verify the auth header. + std::string auth_header_value; + EXPECT_TRUE(intercepted_headers_.GetHeader( + net::HttpRequestHeaders::kAuthorization, &auth_header_value)) + << intercepted_headers_.ToString(); + EXPECT_EQ("Bearer totally_real_token", auth_header_value); +} + +void PaymentsNetworkInterfaceTestBase::ReturnResponse( + PaymentsNetworkInterfaceBase* payments_network_interface_base, + net::HttpStatusCode response_code, + const std::string& response_body) { + payments_network_interface_base->OnSimpleLoaderCompleteInternal( + response_code, response_body); +} + +void PaymentsNetworkInterfaceTestBase::assertIncludedInRequest( + std::string field_name_or_value) { + EXPECT_TRUE(GetUploadData().find(field_name_or_value) != std::string::npos); +} + +void PaymentsNetworkInterfaceTestBase::assertNotIncludedInRequest( + std::string field_name_or_value) { + EXPECT_TRUE(GetUploadData().find(field_name_or_value) == std::string::npos); +} + +std::vector<AutofillProfile> +PaymentsNetworkInterfaceTestBase::BuildTestProfiles() { + std::vector<AutofillProfile> profiles; + profiles.push_back(BuildProfile("John", "Smith", "1234 Main St.", "Miami", + "FL", "32006", "212-555-0162")); + profiles.push_back(BuildProfile("Pat", "Jones", "432 Oak Lane", "Lincoln", + "OH", "43005", "(834)555-0090")); + return profiles; +} + +AutofillProfile PaymentsNetworkInterfaceTestBase::BuildProfile( + std::string_view first_name, + std::string_view last_name, + std::string_view address_line, + std::string_view city, + std::string_view state, + std::string_view zip, + std::string_view phone_number) { + AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); + + profile.SetInfo(NAME_FIRST, base::ASCIIToUTF16(first_name), "en-US"); + profile.SetInfo(NAME_LAST, base::ASCIIToUTF16(last_name), "en-US"); + profile.SetInfo(ADDRESS_HOME_LINE1, base::ASCIIToUTF16(address_line), + "en-US"); + profile.SetInfo(ADDRESS_HOME_CITY, base::ASCIIToUTF16(city), "en-US"); + profile.SetInfo(ADDRESS_HOME_STATE, base::ASCIIToUTF16(state), "en-US"); + profile.SetInfo(ADDRESS_HOME_ZIP, base::ASCIIToUTF16(zip), "en-US"); + profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16(phone_number), + "en-US"); + profile.FinalizeAfterImport(); + return profile; +} + +} // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_network_interface_test_base.h b/components/autofill/core/browser/payments/payments_network_interface_test_base.h new file mode 100644 index 0000000..2af1bea1 --- /dev/null +++ b/components/autofill/core/browser/payments/payments_network_interface_test_base.h
@@ -0,0 +1,91 @@ +// 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 COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_NETWORK_INTERFACE_TEST_BASE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_NETWORK_INTERFACE_TEST_BASE_H_ + +#include <string> +#include <string_view> +#include <vector> + +#include "base/test/task_environment.h" +#include "components/autofill/core/browser/payments/payments_network_interface_base.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/variations/net/variations_http_headers.h" +#include "components/variations/scoped_variations_ids_provider.h" +#include "components/variations/variations_associated_data.h" +#include "components/variations/variations_ids_provider.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" + +namespace autofill::payments { + +// Base class for tests for the derived class of `PaymentsNetworkInterfaceBase`. +// This class should only contain infrastructure related methods that helps +// test the client server communication between Chrome and Payments backend. +class PaymentsNetworkInterfaceTestBase { + public: + PaymentsNetworkInterfaceTestBase(); + PaymentsNetworkInterfaceTestBase(const PaymentsNetworkInterfaceTestBase&) = + delete; + PaymentsNetworkInterfaceTestBase& operator=( + const PaymentsNetworkInterfaceTestBase&) = delete; + virtual ~PaymentsNetworkInterfaceTestBase(); + + void SetUpTest(); + + // Registers a field trial with the specified name and group and an associated + // google web property variation id. + void CreateFieldTrialWithId(const std::string& trial_name, + const std::string& group_name, + int variation_id); + + protected: + network::TestURLLoaderFactory* factory() { return &test_url_loader_factory_; } + + const std::string& GetUploadData() { return intercepted_body_; } + + bool HasVariationsHeader() { return has_variations_header_; } + + // Issues access token in response to any access token request. This will + // start the Payments Request which requires the authentication. + void IssueOAuthToken(); + void ReturnResponse( + PaymentsNetworkInterfaceBase* payments_network_interface_base, + net::HttpStatusCode response_code, + const std::string& response_body); + + void assertIncludedInRequest(std::string field_name_or_value); + + void assertNotIncludedInRequest(std::string field_name_or_value); + + AutofillClient::PaymentsRpcResult result_ = + AutofillClient::PaymentsRpcResult::kNone; + + base::test::TaskEnvironment task_environment_; + variations::ScopedVariationsIdsProvider scoped_variations_ids_provider_{ + variations::VariationsIdsProvider::Mode::kUseSignedInState}; + network::TestURLLoaderFactory test_url_loader_factory_; + scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; + TestPersonalDataManager test_personal_data_; + signin::IdentityTestEnvironment identity_test_env_; + + net::HttpRequestHeaders intercepted_headers_; + bool has_variations_header_; + std::string intercepted_body_; + std::vector<AutofillProfile> BuildTestProfiles(); + + AutofillProfile BuildProfile(std::string_view first_name, + std::string_view last_name, + std::string_view address_line, + std::string_view city, + std::string_view state, + std::string_view zip, + std::string_view phone_number); +}; + +} // namespace autofill::payments + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_NETWORK_INTERFACE_TEST_BASE_H_
diff --git a/components/autofill/core/browser/payments/payments_network_interface_unittest.cc b/components/autofill/core/browser/payments/payments_network_interface_unittest.cc index 8854fef..7ba01de 100644 --- a/components/autofill/core/browser/payments/payments_network_interface_unittest.cc +++ b/components/autofill/core/browser/payments/payments_network_interface_unittest.cc
@@ -27,6 +27,7 @@ #include "components/autofill/core/browser/payments/credit_card_save_manager.h" #include "components/autofill/core/browser/payments/local_card_migration_manager.h" #include "components/autofill/core/browser/payments/payments_network_interface.h" +#include "components/autofill/core/browser/payments/payments_network_interface_test_base.h" #include "components/autofill/core/browser/payments/virtual_card_enrollment_flow.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/autofill/core/common/autofill_clock.h" @@ -186,7 +187,8 @@ } // namespace -class PaymentsNetworkInterfaceTest : public testing::Test { +class PaymentsNetworkInterfaceTest : public PaymentsNetworkInterfaceTestBase, + public testing::Test { public: PaymentsNetworkInterfaceTest() = default; @@ -196,44 +198,15 @@ ~PaymentsNetworkInterfaceTest() override = default; void SetUp() override { - // Silence the warning for mismatching sync and Payments servers. - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kWalletServiceUseSandbox, "0"); - - result_ = AutofillClient::PaymentsRpcResult::kNone; + SetUpTest(); legal_message_.reset(); - has_variations_header_ = false; - - factory()->SetInterceptor(base::BindLambdaForTesting( - [&](const network::ResourceRequest& request) { - intercepted_headers_ = request.headers; - intercepted_body_ = network::GetUploadData(request); - has_variations_header_ = variations::HasVariationsHeader(request); - })); - test_shared_loader_factory_ = - base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &test_url_loader_factory_); payments_network_interface_ = std::make_unique<PaymentsNetworkInterface>( test_shared_loader_factory_, identity_test_env_.identity_manager(), &test_personal_data_); - test_personal_data_.SetAccountInfoForPayments( - identity_test_env_.MakePrimaryAccountAvailable( - "example@gmail.com", signin::ConsentLevel::kSync)); } void TearDown() override { payments_network_interface_.reset(); } - // Registers a field trial with the specified name and group and an associated - // google web property variation id. - void CreateFieldTrialWithId(const std::string& trial_name, - const std::string& group_name, - int variation_id) { - variations::AssociateGoogleVariationID( - variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, trial_name, group_name, - static_cast<variations::VariationID>(variation_id)); - base::FieldTrialList::CreateFieldTrial(trial_name, group_name)->Activate(); - } - void OnDidGetUnmaskDetails( AutofillClient::PaymentsRpcResult result, payments::PaymentsNetworkInterface::UnmaskDetails& unmask_details) { @@ -308,6 +281,8 @@ } protected: + std::unique_ptr<PaymentsNetworkInterface> payments_network_interface_; + // Issue a GetUnmaskDetails request. This requires an OAuth token before // starting the request. void StartGettingUnmaskDetails() { @@ -454,31 +429,6 @@ GetWeakPtr())); } - network::TestURLLoaderFactory* factory() { return &test_url_loader_factory_; } - - const std::string& GetUploadData() { return intercepted_body_; } - - bool HasVariationsHeader() { return has_variations_header_; } - - // Issues access token in response to any access token request. This will - // start the Payments Request which requires the authentication. - void IssueOAuthToken() { - identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "totally_real_token", AutofillClock::Now() + base::Days(10)); - - // Verify the auth header. - std::string auth_header_value; - EXPECT_TRUE(intercepted_headers_.GetHeader( - net::HttpRequestHeaders::kAuthorization, &auth_header_value)) - << intercepted_headers_.ToString(); - EXPECT_EQ("Bearer totally_real_token", auth_header_value); - } - - void ReturnResponse(net::HttpStatusCode response_code, - const std::string& response_body) { - payments_network_interface_->OnSimpleLoaderCompleteInternal(response_code, response_body); - } - void assertCvcIncludedInRequest(std::string cvc) { EXPECT_TRUE(!GetUploadData().empty()); // Verify that the encrypted_cvc and s7e_13_cvc parameters were both @@ -572,50 +522,7 @@ std::string display_text_; #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - base::test::TaskEnvironment task_environment_; - variations::ScopedVariationsIdsProvider scoped_variations_ids_provider_{ - variations::VariationsIdsProvider::Mode::kUseSignedInState}; - network::TestURLLoaderFactory test_url_loader_factory_; - scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; - TestPersonalDataManager test_personal_data_; - std::unique_ptr<PaymentsNetworkInterface> payments_network_interface_; - signin::IdentityTestEnvironment identity_test_env_; - - net::HttpRequestHeaders intercepted_headers_; - bool has_variations_header_; - std::string intercepted_body_; private: - std::vector<AutofillProfile> BuildTestProfiles() { - std::vector<AutofillProfile> profiles; - profiles.push_back(BuildProfile("John", "Smith", "1234 Main St.", "Miami", - "FL", "32006", "212-555-0162")); - profiles.push_back(BuildProfile("Pat", "Jones", "432 Oak Lane", "Lincoln", - "OH", "43005", "(834)555-0090")); - return profiles; - } - - AutofillProfile BuildProfile(std::string_view first_name, - std::string_view last_name, - std::string_view address_line, - std::string_view city, - std::string_view state, - std::string_view zip, - std::string_view phone_number) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - - profile.SetInfo(NAME_FIRST, base::ASCIIToUTF16(first_name), "en-US"); - profile.SetInfo(NAME_LAST, base::ASCIIToUTF16(last_name), "en-US"); - profile.SetInfo(ADDRESS_HOME_LINE1, base::ASCIIToUTF16(address_line), - "en-US"); - profile.SetInfo(ADDRESS_HOME_CITY, base::ASCIIToUTF16(city), "en-US"); - profile.SetInfo(ADDRESS_HOME_STATE, base::ASCIIToUTF16(state), "en-US"); - profile.SetInfo(ADDRESS_HOME_ZIP, base::ASCIIToUTF16(zip), "en-US"); - profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16(phone_number), - "en-US"); - profile.FinalizeAfterImport(); - return profile; - } - std::optional<PaymentsNetworkInterface::UnmaskDetails> unmask_details_; // The UnmaskResponseDetails retrieved from an UnmaskRequest. Includes PAN. std::optional<PaymentsNetworkInterface::UnmaskResponseDetails> @@ -626,7 +533,7 @@ TEST_F(PaymentsNetworkInterfaceTest, GetUnmaskDetailsSuccess) { StartGettingUnmaskDetails(); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"offer_fido_opt_in\": \"false\", " "\"authentication_method\": \"CVC\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); @@ -638,7 +545,7 @@ TEST_F(PaymentsNetworkInterfaceTest, GetUnmaskDetailsIncludesChromeUserContext) { StartGettingUnmaskDetails(); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); // ChromeUserContext was set. EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); @@ -667,7 +574,8 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskSuccessViaCVC) { StartUnmasking(CardUnmaskOptions().with_cvc("111")); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"pan\": \"1234\" }"); assertCvcIncludedInRequest("111"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); @@ -677,7 +585,8 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskSuccessViaFIDO) { StartUnmasking(CardUnmaskOptions().with_fido()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"pan\": \"1234\" }"); assertCvcNotIncludedInRequest(); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); @@ -687,7 +596,8 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskSuccessViaCVCWithCreationOptions) { StartUnmasking(CardUnmaskOptions().with_cvc("111")); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\", \"dcvv\": \"321\"}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"pan\": \"1234\", \"dcvv\": \"321\"}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ("1234", unmask_response_details()->real_pan); EXPECT_EQ("321", unmask_response_details()->dcvv); @@ -696,7 +606,8 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskSuccessAccountFromSyncTest) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"pan\": \"1234\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ("1234", unmask_response_details()->real_pan); } @@ -704,7 +615,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskSuccessWithVirtualCardCvcAuth) { StartUnmasking(CardUnmaskOptions().with_virtual_card().with_cvc("222")); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"pan\": \"4111111111111111\", \"dcvv\": \"999\", " "\"expiration\": { \"month\":12, \"year\":2099 } }"); @@ -723,7 +634,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskSuccessWithVirtualCardFidoAuth) { StartUnmasking(CardUnmaskOptions().with_virtual_card().with_fido()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"pan\": \"4111111111111111\", \"dcvv\": \"999\", " "\"expiration\": { \"month\":12, \"year\":2099 } }"); @@ -739,7 +650,7 @@ TEST_F(PaymentsNetworkInterfaceTest, VirtualCardRiskBasedGreenPathResponse) { StartUnmasking(CardUnmaskOptions().with_virtual_card_risk_based()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"pan\": \"4111111111111111\", \"dcvv\": \"999\", " "\"expiration\": { \"month\":12, \"year\":2099 } }"); @@ -762,7 +673,7 @@ TEST_F(PaymentsNetworkInterfaceTest, VirtualCardRiskBasedRedPathResponse_Error) { StartUnmasking(CardUnmaskOptions().with_virtual_card_risk_based()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"NON-INTERNAL\", " "\"api_error_reason\": \"virtual_card_permanent_error\"} }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure, @@ -773,7 +684,8 @@ VirtualCardRiskBasedRedPathResponse_NoOptionProvided) { StartUnmasking(CardUnmaskOptions().with_virtual_card_risk_based()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"context_token\": \"fake_context_token\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"context_token\": \"fake_context_token\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); } @@ -781,7 +693,7 @@ StartUnmasking(CardUnmaskOptions().with_virtual_card_risk_based()); IssueOAuthToken(); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"fido_request_options\": { \"challenge\": \"fake_fido_challenge\" }, " "\"context_token\": \"fake_context_token\", \"idv_challenge_options\": " "[{ \"sms_otp_challenge_option\": { \"challenge_id\": " @@ -828,7 +740,7 @@ CardUnmaskOptions().with_virtual_card_risk_based().with_cvc("123")); IssueOAuthToken(); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{\"flow_status\": \"FLOW_STATUS_INCORRECT_ACCOUNT_SECURITY_CODE\"}"); // Ensure that it is treated as a try again failure when a flow status is @@ -841,7 +753,7 @@ StartUnmasking(CardUnmaskOptions().with_virtual_card_risk_based()); IssueOAuthToken(); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"fido_request_options\": { \"challenge\": \"fake_fido_challenge\" }, " "\"context_token\": \"fake_context_token\", \"idv_challenge_options\": " "[{ \"sms_otp_challenge_option\": { \"challenge_id\": " @@ -871,7 +783,7 @@ TEST_F(PaymentsNetworkInterfaceTest, VirtualCardRiskBasedThenFido) { StartUnmasking(CardUnmaskOptions().with_virtual_card_risk_based_then_fido()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"pan\": \"4111111111111111\", \"dcvv\": \"999\", " "\"expiration\": { \"month\":12, \"year\":2099 } }"); @@ -896,7 +808,7 @@ StartUnmasking( CardUnmaskOptions().with_virtual_card_risk_based_then_otp(otp)); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"pan\": \"4111111111111111\", \"dcvv\": \"999\", " "\"expiration\": { \"month\":12, \"year\":2099 } }"); @@ -921,7 +833,7 @@ StartUnmasking( CardUnmaskOptions().with_virtual_card_risk_based_then_otp(otp)); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"context_token\": \"fake_context_token\", " "\"flow_status\": \"FLOW_STATUS_EXPIRED_OTP\" }"); @@ -941,7 +853,7 @@ StartUnmasking( CardUnmaskOptions().with_virtual_card_risk_based_then_otp(otp)); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"context_token\": \"fake_context_token\", " "\"flow_status\": \"FLOW_STATUS_INCORRECT_OTP\" }"); @@ -960,7 +872,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskIncludesLegacyAndNonLegacyId) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); // Non-legacy Instrument id and legacy server id are both set. EXPECT_TRUE(GetUploadData().find("%22instrument_id%22:%221%22") != @@ -972,7 +884,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskIncludesOnlyLegacyId) { StartUnmasking(CardUnmaskOptions().with_only_legacy_id()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); // Only legacy server id is set. EXPECT_TRUE(GetUploadData().find("instrument_id") == std::string::npos); @@ -983,7 +895,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskIncludesOnlyNonLegacyId) { StartUnmasking(CardUnmaskOptions().with_only_non_legacy_id()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); // Only non-legacy instrument id is set. EXPECT_TRUE(GetUploadData().find("%22instrument_id%22:%221%22") != @@ -994,7 +906,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskIncludesChromeUserContext) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); // ChromeUserContext was set. EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); @@ -1004,7 +916,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskIncludesMerchantDomain) { StartUnmasking(CardUnmaskOptions().with_virtual_card()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); // last_committed_primary_main_frame_origin was set. EXPECT_TRUE(GetUploadData().find("merchant_domain") != std::string::npos); @@ -1013,7 +925,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskResponseIncludesDeclineDetails) { StartUnmasking(CardUnmaskOptions().with_virtual_card()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{\"error\": {\"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_temporary_error\"}, " "\"decline_details\": {\"user_message_title\": " @@ -1035,7 +947,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskResponseIncludesEmptyDeclineDetails) { StartUnmasking(CardUnmaskOptions().with_virtual_card()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{\"error\": {\"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_temporary_error\"}, " "\"decline_details\": {\"user_message_title\": " @@ -1052,7 +964,7 @@ StartOptChangeRequest( PaymentsNetworkInterface::OptChangeRequestDetails::ENABLE_FIDO_AUTH); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"fido_authentication_info\": { \"user_status\": " "\"FIDO_AUTH_ENABLED\"}}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); @@ -1063,7 +975,8 @@ StartOptChangeRequest( PaymentsNetworkInterface::OptChangeRequestDetails::ENABLE_FIDO_AUTH); IssueOAuthToken(); - ReturnResponse(net::HTTP_REQUEST_TIMEOUT, ""); + ReturnResponse(payments_network_interface_.get(), net::HTTP_REQUEST_TIMEOUT, + ""); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kNetworkError, result_); EXPECT_FALSE(opt_change_response_.user_is_opted_in.has_value()); } @@ -1072,7 +985,7 @@ StartOptChangeRequest( PaymentsNetworkInterface::OptChangeRequestDetails::DISABLE_FIDO_AUTH); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"fido_authentication_info\": { \"user_status\": " "\"FIDO_AUTH_DISABLED\"}}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); @@ -1083,7 +996,7 @@ StartOptChangeRequest( PaymentsNetworkInterface::OptChangeRequestDetails::ENABLE_FIDO_AUTH); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"fido_authentication_info\": { \"user_status\": " "\"FIDO_AUTH_DISABLED\"," "\"fido_creation_options\": {" @@ -1099,7 +1012,7 @@ StartGettingUploadDetails(GetUploadDetailsOptions()); IssueOAuthToken(); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"context_token\": \"some_token\", \"legal_message\": {} }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_NE(nullptr, legal_message_.get()); @@ -1286,28 +1199,30 @@ StartGettingUploadDetails(GetUploadDetailsOptions()); IssueOAuthToken(); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"context_token\": \"some_token\", \"legal_message\": {} }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); result_ = AutofillClient::PaymentsRpcResult::kNone; StartUploading(UploadCardOptions()); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); } TEST_F(PaymentsNetworkInterfaceTest, GetDetailsMissingContextToken) { StartGettingUploadDetails(GetUploadDetailsOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"legal_message\": {} }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"legal_message\": {} }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); } TEST_F(PaymentsNetworkInterfaceTest, GetDetailsMissingLegalMessage) { StartGettingUploadDetails(GetUploadDetailsOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"context_token\": \"some_token\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"context_token\": \"some_token\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); EXPECT_EQ(nullptr, legal_message_.get()); } @@ -1316,7 +1231,7 @@ StartGettingUploadDetails(GetUploadDetailsOptions()); IssueOAuthToken(); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{" " \"context_token\" : \"some_token\"," " \"legal_message\" : {}," @@ -1324,7 +1239,7 @@ "}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); // Check that |supported_card_bin_ranges_| has the two entries specified in - // ReturnResponse(~) above. + // ReturnResponse(payments_network_interface_.get(),~) above. ASSERT_EQ(3U, supported_card_bin_ranges_.size()); EXPECT_EQ(1234, supported_card_bin_ranges_[0].first); EXPECT_EQ(1234, supported_card_bin_ranges_[0].second); @@ -1341,7 +1256,7 @@ test_personal_data_.SetAccountInfoForPayments(secondary_account_info); StartUploading(UploadCardOptions()); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); // Issue a token for the secondary account. identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( @@ -1381,7 +1296,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UploadSuccessEmptyResponse) { StartUploading(UploadCardOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_FALSE(upload_card_response_details_.instrument_id.has_value()); EXPECT_TRUE(upload_card_response_details_.virtual_card_enrollment_state == @@ -1395,7 +1310,7 @@ upload_card_response_details_.instrument_id = std::nullopt; // Test the conversion from string to int64_t using the max value for int64_t. - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"instrument_id\": \"9223372036854775807\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ(upload_card_response_details_.instrument_id, 9223372036854775807); @@ -1418,18 +1333,18 @@ } switch (virtual_card_enrollment_state) { case CreditCard::VirtualCardEnrollmentState::kUnenrolledAndNotEligible: - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"virtual_card_metadata\": { \"status\": " "\"ENROLLMENT_STATUS_UNSPECIFIED\" } }"); break; case CreditCard::VirtualCardEnrollmentState::kUnenrolledAndEligible: - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"virtual_card_metadata\": { \"status\": " "\"ENROLLMENT_ELIGIBLE\" } }"); break; case CreditCard::VirtualCardEnrollmentState::kEnrolled: ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"virtual_card_metadata\": { \"status\": \"ENROLLED\" } }"); break; case CreditCard::VirtualCardEnrollmentState::kUnenrolled: @@ -1446,7 +1361,7 @@ UploadSuccessGetDetailsForEnrollmentResponseDetailsPresent) { StartUploading(UploadCardOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"virtual_card_metadata\": " "{\"status\": \"ENROLLMENT_ELIGIBLE\", " "\"virtual_card_enrollment_data\": { " @@ -1477,7 +1392,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UploadSuccessCardArtUrlPresent) { StartUploading(UploadCardOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"card_art_url\": \"https://www.example.com/\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ(upload_card_response_details_.card_art_url.spec(), @@ -1616,14 +1531,15 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskMissingPan) { StartUnmasking(CardUnmaskOptions()); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); } TEST_F(PaymentsNetworkInterfaceTest, UnmaskRetryFailure) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"error\": { \"code\": \"INTERNAL\" } }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"error\": { \"code\": \"INTERNAL\" } }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kTryAgainFailure, result_); EXPECT_EQ("", unmask_response_details()->real_pan); } @@ -1631,7 +1547,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskPermanentFailure) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\" } }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); EXPECT_EQ("", unmask_response_details()->real_pan); @@ -1640,7 +1556,8 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskMalformedResponse) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"error_code\": \"WRONG_JSON_FORMAT\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"error_code\": \"WRONG_JSON_FORMAT\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); EXPECT_EQ("", unmask_response_details()->real_pan); } @@ -1649,14 +1566,16 @@ { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_UNAUTHORIZED, ""); + ReturnResponse(payments_network_interface_.get(), net::HTTP_UNAUTHORIZED, + ""); // No response yet. EXPECT_EQ(AutofillClient::PaymentsRpcResult::kNone, result_); EXPECT_EQ(nullptr, unmask_response_details()); // Second HTTP_UNAUTHORIZED causes permanent failure. IssueOAuthToken(); - ReturnResponse(net::HTTP_UNAUTHORIZED, ""); + ReturnResponse(payments_network_interface_.get(), net::HTTP_UNAUTHORIZED, + ""); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); EXPECT_EQ("", unmask_response_details()->real_pan); } @@ -1670,14 +1589,16 @@ // first waits for the access token request to be received, but here there // should be no access token request because PaymentsNetworkInterface should reuse the // access token from the previous request. - ReturnResponse(net::HTTP_UNAUTHORIZED, ""); + ReturnResponse(payments_network_interface_.get(), net::HTTP_UNAUTHORIZED, + ""); // No response yet. EXPECT_EQ(AutofillClient::PaymentsRpcResult::kNone, result_); EXPECT_EQ(nullptr, unmask_response_details()); // HTTP_OK after first HTTP_UNAUTHORIZED results in success. IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"pan\": \"1234\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ("1234", unmask_response_details()->real_pan); } @@ -1686,7 +1607,8 @@ TEST_F(PaymentsNetworkInterfaceTest, NetworkError) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_REQUEST_TIMEOUT, std::string()); + ReturnResponse(payments_network_interface_.get(), net::HTTP_REQUEST_TIMEOUT, + std::string()); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kNetworkError, result_); EXPECT_EQ("", unmask_response_details()->real_pan); } @@ -1694,7 +1616,8 @@ TEST_F(PaymentsNetworkInterfaceTest, OtherError) { StartUnmasking(CardUnmaskOptions()); IssueOAuthToken(); - ReturnResponse(net::HTTP_FORBIDDEN, std::string()); + ReturnResponse(payments_network_interface_.get(), net::HTTP_FORBIDDEN, + std::string()); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); EXPECT_EQ("", unmask_response_details()->real_pan); } @@ -1702,7 +1625,7 @@ TEST_F(PaymentsNetworkInterfaceTest, VcnRetrievalTryAgainFailure) { StartUnmasking(CardUnmaskOptions().with_virtual_card()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_temporary_error\" } }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kVcnRetrievalTryAgainFailure, @@ -1712,7 +1635,7 @@ TEST_F(PaymentsNetworkInterfaceTest, VcnRetrievalPermanentFailure) { StartUnmasking(CardUnmaskOptions().with_virtual_card()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_permanent_error\"} }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure, @@ -1722,7 +1645,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskPermanentFailureWhenVcnMissingExpiration) { StartUnmasking(CardUnmaskOptions().with_virtual_card()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"pan\": \"4111111111111111\", \"dcvv\": \"999\" }"); EXPECT_EQ("4111111111111111", unmask_response_details()->real_pan); @@ -1732,7 +1655,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UnmaskPermanentFailureWhenVcnMissingCvv) { StartUnmasking(CardUnmaskOptions().with_virtual_card()); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"pan\": \"4111111111111111\", \"expiration\": { " "\"month\":12, \"year\":2099 } }"); @@ -1746,7 +1669,7 @@ StartGettingUploadDetails(GetUploadDetailsOptions()); IssueOAuthToken(); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"context_token\": \"some_token\", \"legal_message\": {} }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); @@ -1754,7 +1677,7 @@ StartMigrating(/*has_cardholder_name=*/true); ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{\"save_result\":[],\"value_prop_display_text\":\"display text\"}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); } @@ -1849,7 +1772,7 @@ TEST_F(PaymentsNetworkInterfaceTest, MigrationSuccessWithSaveResult) { StartMigrating(/*has_cardholder_name=*/true); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{\"save_result\":[{\"unique_id\":\"0\",\"status\":" "\"SUCCESS\"},{\"unique_id\":\"1\",\"status\":\"TEMPORARY_" "FAILURE\"}],\"value_prop_display_text\":\"display text\"}"); @@ -1867,7 +1790,7 @@ TEST_F(PaymentsNetworkInterfaceTest, MigrationMissingSaveResult) { StartMigrating(/*has_cardholder_name=*/true); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{\"value_prop_display_text\":\"display text\"}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); EXPECT_EQ(nullptr, migration_save_results_.get()); @@ -1876,7 +1799,7 @@ TEST_F(PaymentsNetworkInterfaceTest, MigrationSuccessWithDisplayText) { StartMigrating(/*has_cardholder_name=*/true); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{\"save_result\":[{\"unique_id\":\"0\",\"status\":" "\"SUCCESS\"}],\"value_prop_display_text\":\"display text\"}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); @@ -1888,7 +1811,8 @@ StartSelectingChallengeOption(CardUnmaskChallengeOptionType::kSmsOtp, "arbitrary id for sms otp"); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"context_token\": \"new context token\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"context_token\": \"new context token\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); assertIncludedInRequest("context_token"); @@ -1905,7 +1829,8 @@ TEST_F(PaymentsNetworkInterfaceTest, SelectChallengeOptionSuccess) { StartSelectingChallengeOption(); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{ \"context_token\": \"new context token\" }"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, + "{ \"context_token\": \"new context token\" }"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ("new context token", context_token_); @@ -1914,7 +1839,7 @@ TEST_F(PaymentsNetworkInterfaceTest, SelectChallengeOptionTemporaryFailure) { StartSelectingChallengeOption(); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_temporary_error\"} }"); @@ -1925,7 +1850,7 @@ TEST_F(PaymentsNetworkInterfaceTest, SelectChallengeOptionVcnFlowPermanentFailure) { StartSelectingChallengeOption(); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_permanent_error\"} }"); @@ -1936,7 +1861,7 @@ TEST_F(PaymentsNetworkInterfaceTest, SelectChallengeOptionResponseMissingContextToken) { StartSelectingChallengeOption(); IssueOAuthToken(); - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); EXPECT_EQ(AutofillClient::PaymentsRpcResult::kPermanentFailure, result_); } @@ -1973,36 +1898,37 @@ case AutofillClient::PaymentsRpcResult::kSuccess: if (virtual_card_enrollment_request_type == VirtualCardEnrollmentRequestType::kEnroll) { - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"enroll_result\": \"ENROLL_SUCCESS\" }"); } else if (virtual_card_enrollment_request_type == VirtualCardEnrollmentRequestType::kUnenroll) { - ReturnResponse(net::HTTP_OK, "{}"); + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{}"); } break; case AutofillClient::PaymentsRpcResult::kVcnRetrievalTryAgainFailure: ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_temporary_error\"} }"); break; case AutofillClient::PaymentsRpcResult::kTryAgainFailure: - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"INTERNAL\", " "\"api_error_reason\": \"ANYTHING_ELSE\"} }"); break; case AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure: ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_permanent_error\"} }"); break; case AutofillClient::PaymentsRpcResult::kPermanentFailure: - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\" } }"); break; case AutofillClient::PaymentsRpcResult::kNetworkError: - ReturnResponse(net::HTTP_REQUEST_TIMEOUT, ""); + ReturnResponse(payments_network_interface_.get(), + net::HTTP_REQUEST_TIMEOUT, ""); break; case AutofillClient::PaymentsRpcResult::kNone: NOTREACHED(); @@ -2115,34 +2041,35 @@ switch (result) { case AutofillClient::PaymentsRpcResult::kSuccess: ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"google_legal_message\": { \"line\" : [{ \"template\": \"This is " "the entire message.\" }] }, \"external_legal_message\": {}, " "\"context_token\": \"some_token\" }"); break; case AutofillClient::PaymentsRpcResult::kVcnRetrievalTryAgainFailure: ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_temporary_error\"} }"); break; case AutofillClient::PaymentsRpcResult::kTryAgainFailure: - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"INTERNAL\", " "\"api_error_reason\": \"ANYTHING_ELSE\"} }"); break; case AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure: ReturnResponse( - net::HTTP_OK, + payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\", " "\"api_error_reason\": \"virtual_card_permanent_error\"} }"); break; case AutofillClient::PaymentsRpcResult::kPermanentFailure: - ReturnResponse(net::HTTP_OK, + ReturnResponse(payments_network_interface_.get(), net::HTTP_OK, "{ \"error\": { \"code\": \"ANYTHING_ELSE\" } }"); break; case AutofillClient::PaymentsRpcResult::kNetworkError: - ReturnResponse(net::HTTP_REQUEST_TIMEOUT, ""); + ReturnResponse(payments_network_interface_.get(), + net::HTTP_REQUEST_TIMEOUT, ""); break; case AutofillClient::PaymentsRpcResult::kNone: NOTREACHED();
diff --git a/components/autofill/core/browser/payments/test_virtual_card_enrollment_manager.h b/components/autofill/core/browser/payments/test_virtual_card_enrollment_manager.h index 0536e64..c6d0784 100644 --- a/components/autofill/core/browser/payments/test_virtual_card_enrollment_manager.h +++ b/components/autofill/core/browser/payments/test_virtual_card_enrollment_manager.h
@@ -24,12 +24,6 @@ const TestVirtualCardEnrollmentManager&) = delete; ~TestVirtualCardEnrollmentManager() override; - bool GetAvatarAnimationComplete() const { return avatar_animation_complete_; } - - void SetAvatarAnimationComplete(bool avatar_animation_complete) { - avatar_animation_complete_ = avatar_animation_complete; - } - bool GetEnrollResponseDetailsReceived() const { return enroll_response_details_received_; }
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc index b85405c..57e3bc4 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc
@@ -121,18 +121,6 @@ weak_ptr_factory_.GetWeakPtr())); } -void VirtualCardEnrollmentManager::OnCardSavedAnimationComplete() { - if (state_.virtual_card_enrollment_fields.virtual_card_enrollment_source == - VirtualCardEnrollmentSource::kUpstream) { - avatar_animation_complete_ = true; - - if (enroll_response_details_received_) { - EnsureCardArtImageIsSetBeforeShowingUI(); - ShowVirtualCardEnrollBubble(); - } - } -} - void VirtualCardEnrollmentManager::Enroll( std::optional<VirtualCardEnrollmentUpdateResponseCallback> virtual_card_enrollment_update_response_callback) { @@ -282,25 +270,33 @@ state_.virtual_card_enrollment_fields.credit_card.instrument_id())); } - LogUpdateVirtualCardEnrollmentRequestResult( - state_.virtual_card_enrollment_fields.virtual_card_enrollment_source, - type, result == AutofillClient::PaymentsRpcResult::kSuccess); - Reset(); // Relay the response to the server card editor page. This also destroys the // payments delegate if the editor was already closed. if (virtual_card_enrollment_update_response_callback_.has_value()) { std::move(virtual_card_enrollment_update_response_callback_.value()) .Run(result == AutofillClient::PaymentsRpcResult::kSuccess); } - virtual_card_enrollment_update_response_callback_.reset(); + + LogUpdateVirtualCardEnrollmentRequestResult( + state_.virtual_card_enrollment_fields.virtual_card_enrollment_source, + type, result == AutofillClient::PaymentsRpcResult::kSuccess); + Reset(); +} + +void VirtualCardEnrollmentManager::OnVirtualCardEnrollCompleted( + bool is_vcn_enrolled) { +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) + autofill_client_->GetPaymentsAutofillClient()->VirtualCardEnrollCompleted( + /*is_vcn_enrolled=*/is_vcn_enrolled); +#endif } void VirtualCardEnrollmentManager::Reset() { payments_network_interface_->CancelRequest(); weak_ptr_factory_.InvalidateWeakPtrs(); state_ = VirtualCardEnrollmentProcessState(); - avatar_animation_complete_ = false; enroll_response_details_received_ = false; + virtual_card_enrollment_update_response_callback_.reset(); } VirtualCardEnrollmentStrikeDatabase* @@ -356,7 +352,10 @@ state_.virtual_card_enrollment_fields, base::BindOnce( &VirtualCardEnrollmentManager::Enroll, weak_ptr_factory_.GetWeakPtr(), - /*virtual_card_enrollment_update_response_callback=*/std::nullopt), + /*virtual_card_enrollment_update_response_callback=*/ + base::BindOnce( + &VirtualCardEnrollmentManager::OnVirtualCardEnrollCompleted, + weak_ptr_factory_.GetWeakPtr())), base::BindOnce( &VirtualCardEnrollmentManager::OnVirtualCardEnrollmentBubbleCancelled, weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h index 3f9fccbad..4bc0ac0 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h
@@ -148,11 +148,6 @@ // enrollment dialog in the Settings page on Android. VirtualCardEnrollmentFieldsLoadedCallback = base::DoNothing()); - // Updates |avatar_animation_complete| to true if the user is beginning the - // upstream enrollment flow. This is a prerequisite to showing the enrollment - // bubble. - void OnCardSavedAnimationComplete(); - // Uses `payments_network_interface_` to send the enroll request. `state_`'s // `vcn_context_token_`, which should be set when we receive the // GetDetailsForEnrollResponse, is used in the @@ -204,6 +199,10 @@ VirtualCardEnrollmentRequestType type, AutofillClient::PaymentsRpcResult result); + // Called after virtual card enrollment is completed. Will show enroll result + // to users. + void OnVirtualCardEnrollCompleted(bool is_vcn_enrolled); + // Resets the state of this VirtualCardEnrollmentManager. virtual void Reset(); @@ -225,10 +224,6 @@ VirtualCardEnrollmentStrikeDatabase* GetVirtualCardEnrollmentStrikeDatabase() const; - // Whether the card saved avatar animation has been completed on upstream - // enrollment flow. - bool avatar_animation_complete_ = false; - // Whether we've received GetDetailsForEnrollResponseDetails. bool enroll_response_details_received_ = false;
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 04f56e3..000e0dd6 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -619,8 +619,23 @@ } } - if (HasPendingQueries()) + if (!is_address_data_loaded_ && !HasPendingAddressQueries()) { + is_address_data_loaded_ = true; + LogStoredAddressDataMetrics(); + } + + // TODO(b/322170538): Move this block below the `GetServerDatabase()` if, + // once address reading logic was moved into a separate class. + if (!is_payments_data_loaded_ && !HasPendingPaymentQueries() && + database_helper_->GetServerDatabase()) { + is_payments_data_loaded_ = true; + LogStoredPaymentsDataMetrics(); + payments_data_cleaner_->CleanupPaymentsData(); + } + + if (HasPendingAddressQueries() || HasPendingPaymentQueries()) { return; + } if (!database_helper_->GetServerDatabase()) { DLOG(WARNING) << "There are no pending queries but the server database " @@ -629,13 +644,6 @@ return; } - // All personal data is loaded, notify observers. |is_data_loaded_| is false - // if this is the initial load. - if (!is_data_loaded_) { - is_data_loaded_ = true; - LogStoredDataMetrics(); - payments_data_cleaner_->CleanupPaymentsData(); - } NotifyPersonalDataObserver(); } @@ -1336,7 +1344,7 @@ } bool PersonalDataManager::IsDataLoaded() const { - return is_data_loaded_; + return is_address_data_loaded_ && is_payments_data_loaded_; } std::vector<AutofillProfile*> PersonalDataManager::GetProfiles( @@ -2348,19 +2356,15 @@ return guid; } -void PersonalDataManager::LogStoredDataMetrics() const { - if (has_logged_stored_data_metrics_) { - return; - } - // Only log this info once per Chrome user profile load. - has_logged_stored_data_metrics_ = true; - +void PersonalDataManager::LogStoredAddressDataMetrics() const { const std::vector<AutofillProfile*> profiles = GetProfiles(); autofill_metrics::LogStoredProfileMetrics(profiles); autofill_metrics::LogStoredProfileTokenQualityMetrics(profiles); autofill_metrics::LogLocalProfileSupersetMetrics(std::move(profiles), app_locale_); +} +void PersonalDataManager::LogStoredPaymentsDataMetrics() const { AutofillMetrics::LogStoredCreditCardMetrics( local_credit_cards_, server_credit_cards_, GetServerCardWithArtImageCount(), kDisusedDataModelTimeDelta); @@ -2546,7 +2550,8 @@ } void PersonalDataManager::NotifyPersonalDataObserver() { - bool pending_changes = IsAwaitingPendingChanges(); + bool pending_changes = + IsAwaitingPendingAddressChanges() || HasPendingPaymentQueries(); for (PersonalDataManagerObserver& observer : observers_) { observer.OnPersonalDataChanged(); } @@ -2675,10 +2680,13 @@ HandleNextProfileChange(guid); } -bool PersonalDataManager::HasPendingQueries() const { +bool PersonalDataManager::HasPendingAddressQueries() const { return pending_synced_local_profiles_query_ != 0 || - pending_account_profiles_query_ != 0 || - pending_creditcards_query_ != 0 || + pending_account_profiles_query_ != 0; +} + +bool PersonalDataManager::HasPendingPaymentQueries() const { + return pending_creditcards_query_ != 0 || pending_server_creditcards_query_ != 0 || pending_server_creditcard_cloud_token_data_query_ != 0 || pending_customer_data_query_ != 0 || pending_offer_data_query_ != 0 ||
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 922690e..7506f81 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -57,7 +57,6 @@ #include "components/sync/service/sync_service_observer.h" #include "components/webdata/common/web_data_service_consumer.h" -class PaymentsSuggestionBottomSheetMediatorTest; class Profile; class PrefService; @@ -187,15 +186,13 @@ // KeyedService: void Shutdown() override; - // Returns true if the PDM is currently awaiting responses from the database. - // In this case, the PDM's state is currently potentially inconsistent with - // the database. Once the state has converged, PersonalDataManagerObserver:: - // OnPersonalDataFinishedProfileTasks() will be called. - // The PDM's state is inconsistent with the database in two cases: - // - When profile modifications are still pending: ProfileChangesAreOngoing(). - // - When reads are still pending. - bool IsAwaitingPendingChanges() const { - return ProfileChangesAreOngoing() || HasPendingQueries(); + // Returns true if the PDM is currently awaiting an address-related responses + // from the database. In this case, the PDM's address data is currently + // potentially inconsistent with the database. Once the state has converged, + // PersonalDataManagerObserver:: OnPersonalDataFinishedProfileTasks() will be + // called. + bool IsAwaitingPendingAddressChanges() const { + return ProfileChangesAreOngoing() || HasPendingAddressQueries(); } // history::HistoryServiceObserver @@ -555,8 +552,9 @@ // Cancels any pending queries to the server web database. void CancelPendingServerQueries(); - // Returns if there are any pending queries to the web database. - bool HasPendingQueriesForTesting() { return HasPendingQueries(); } + bool HasPendingPaymentQueriesForTesting() const { + return HasPendingPaymentQueries(); + } // This function assumes |credit_card| contains the full PAN. Returns |true| // if the card number of |credit_card| is equal to any local card or any @@ -750,7 +748,6 @@ AddAndGetCreditCardArtImage); FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, LogStoredCreditCardMetrics); - friend class ::PaymentsSuggestionBottomSheetMediatorTest; friend class PaymentsDataCleaner; friend class VirtualCardEnrollmentManagerTest; @@ -805,8 +802,9 @@ void CancelPendingServerQuery(WebDataServiceBase::Handle* handle); // The first time this is called, logs a UMA metrics about the user's autofill - // addresses, credit card, offer and IBAN. On subsequent calls, does nothing. - void LogStoredDataMetrics() const; + // addresses, credit card, offer and IBAN. + void LogStoredAddressDataMetrics() const; + void LogStoredPaymentsDataMetrics() const; // Whether server cards or IBANs are enabled and should be suggested to the // user. @@ -838,7 +836,8 @@ std::unique_ptr<PersonalDatabaseHelper> database_helper_; // True if personal data has been loaded from the web database. - bool is_data_loaded_ = false; + bool is_address_data_loaded_ = false; + bool is_payments_data_loaded_ = false; // The loaded profiles from the AutofillTable come from two sources: // - kLocalOrSyncable: Stored in `synced_local_profiles_`. @@ -947,7 +946,8 @@ void OnProfileChangeDone(const std::string& guid); // Returns if there are any pending queries to the web database. - bool HasPendingQueries() const; + bool HasPendingAddressQueries() const; + bool HasPendingPaymentQueries() const; // Returns the database that is used for storing local data. scoped_refptr<AutofillWebDataService> GetLocalDatabase(); @@ -1018,10 +1018,6 @@ // The image fetcher to fetch customized images for Autofill data. raw_ptr<AutofillImageFetcherBase> image_fetcher_ = nullptr; - // Whether we have already logged the stored profile, credit card, IBAN, offer - // and virtual card usage metrics this session. - mutable bool has_logged_stored_data_metrics_ = false; - // An observer to listen for changes to prefs::kAutofillCreditCardEnabled. std::unique_ptr<BooleanPrefMember> credit_card_enabled_pref_;
diff --git a/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h b/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h index 2a65563f..f7e2432d 100644 --- a/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h +++ b/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h
@@ -50,10 +50,16 @@ #if !BUILDFLAG(IS_ANDROID) // Hides the bubble and icon if it is showing. virtual void HideIconAndBubble() = 0; + + // Returns true if bubble is already accepted and the virtual card enrollment + // process is in progress. + virtual bool IsEnrollmentInProgress() const = 0; #endif // Virtual card enroll button takes card information to enroll into a VCN. - virtual void OnAcceptButton() = 0; + // `did_switch_to_loading_state` denotes if bubble is waiting for enrollment + // to finish on server before closing. + virtual void OnAcceptButton(bool did_switch_to_loading_state = false) = 0; virtual void OnDeclineButton() = 0; virtual void OnLinkClicked(VirtualCardEnrollmentLinkType link_type, const GURL& url) = 0;
diff --git a/components/autofill/core/browser/ui/popup_item_ids.h b/components/autofill/core/browser/ui/popup_item_ids.h index 30a2afe2..6dc5d23 100644 --- a/components/autofill/core/browser/ui/popup_item_ids.h +++ b/components/autofill/core/browser/ui/popup_item_ids.h
@@ -50,14 +50,12 @@ // Password suggestions. kPasswordEntry, - kUsernameEntry, kAllSavedPasswordsEntry, kGeneratePasswordEntry, kShowAccountCards, kPasswordAccountStorageOptIn, kPasswordAccountStorageOptInAndGenerate, kAccountStoragePasswordEntry, - kAccountStorageUsernameEntry, kPasswordAccountStorageReSignin, kPasswordAccountStorageEmpty, @@ -99,13 +97,12 @@ // Set of `PopupItemId`s that trigger filling a value into an input element // when the user selects a suggestion with that id. inline constexpr auto kItemsTriggeringFieldFilling = DenseSet<PopupItemId>( - {PopupItemId::kAccountStoragePasswordEntry, - PopupItemId::kAccountStorageUsernameEntry, PopupItemId::kAddressEntry, + {PopupItemId::kAccountStoragePasswordEntry, PopupItemId::kAddressEntry, PopupItemId::kAutocompleteEntry, PopupItemId::kCompose, PopupItemId::kCreditCardEntry, PopupItemId::kDatalistEntry, PopupItemId::kFillEverythingFromAddressProfile, PopupItemId::kMerchantPromoCodeEntry, PopupItemId::kPasswordEntry, - PopupItemId::kUsernameEntry, PopupItemId::kVirtualCreditCardEntry}); + PopupItemId::kVirtualCreditCardEntry}); } // namespace autofill
diff --git a/components/autofill/core/browser/ui/suggestion_test_helpers.cc b/components/autofill/core/browser/ui/suggestion_test_helpers.cc new file mode 100644 index 0000000..f06d39a3 --- /dev/null +++ b/components/autofill/core/browser/ui/suggestion_test_helpers.cc
@@ -0,0 +1,31 @@ +// 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 "components/autofill/core/browser/ui/suggestion_test_helpers.h" + +namespace autofill { + +using ::testing::AllOf; +using ::testing::Field; +using ::testing::Matcher; + +Matcher<Suggestion> EqualsSuggestion(PopupItemId id) { + return Field(&Suggestion::popup_item_id, id); +} + +Matcher<Suggestion> EqualsSuggestion(PopupItemId id, + const std::u16string& main_text) { + return AllOf( + Field(&Suggestion::popup_item_id, id), + Field(&Suggestion::main_text, + Suggestion::Text(main_text, Suggestion::Text::IsPrimary(true)))); +} + +Matcher<Suggestion> EqualsSuggestion(PopupItemId id, + const std::u16string& main_text, + Suggestion::Icon icon) { + return AllOf(EqualsSuggestion(id, main_text), Field(&Suggestion::icon, icon)); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/ui/suggestion_test_helpers.h b/components/autofill/core/browser/ui/suggestion_test_helpers.h index 0949122..9c8cf4b 100644 --- a/components/autofill/core/browser/ui/suggestion_test_helpers.h +++ b/components/autofill/core/browser/ui/suggestion_test_helpers.h
@@ -11,6 +11,16 @@ namespace autofill { +::testing::Matcher<Suggestion> EqualsSuggestion(PopupItemId id); + +::testing::Matcher<Suggestion> EqualsSuggestion( + PopupItemId id, + const std::u16string& main_text); + +::testing::Matcher<Suggestion> EqualsSuggestion(PopupItemId id, + const std::u16string& main_text, + Suggestion::Icon icon); + template <class... Matchers> inline auto SuggestionVectorIdsAre(const Matchers&... matchers) { return ::testing::ElementsAre(::testing::Field(
diff --git a/components/bookmarks/browser/bookmark_client.h b/components/bookmarks/browser/bookmark_client.h index 6c7f731..d56d5db 100644 --- a/components/bookmarks/browser/bookmark_client.h +++ b/components/bookmarks/browser/bookmark_client.h
@@ -49,8 +49,8 @@ // default folder if relevant for the URL. virtual const BookmarkNode* GetSuggestedSaveLocation(const GURL& url); - // Requests a favicon from the history cache for the web page at |page_url| - // for icon type favicon_base::IconType::kFavicon. |callback| is run when the + // Requests a favicon from the history cache for the web page at `page_url` + // for icon type favicon_base::IconType::kFavicon. `callback` is run when the // favicon has been fetched, which returns gfx::Image is a multi-resolution // image of gfx::kFaviconSize DIP width and height. The data from the history // cache is resized if need be. @@ -63,9 +63,9 @@ virtual bool SupportsTypedCountForUrls(); // Retrieves the number of times each bookmark URL has been typed in - // the Omnibox by the user. For each key (URL) in |url_typed_count_map|, + // the Omnibox by the user. For each key (URL) in `url_typed_count_map`, // the corresponding value will be updated with the typed count of that URL. - // |url_typed_count_map| must not be null. + // `url_typed_count_map` must not be null. virtual void GetTypedCountForUrls(UrlTypedCountMap* url_typed_count_map); // Returns a task that will be used to load a managed root node. This task @@ -73,27 +73,34 @@ virtual LoadManagedNodeCallback GetLoadManagedNodeCallback() = 0; // Returns the current storage state to be added as suffix to metrics. - // TODO(crbug.com/1520418): Revisit this function as the notion of storage + // TODO(b/41493391): Revisit this function as the notion of storage // type is no longer an attribute of BookmarkModel or BookmarkClient and may // need to be BookmarkNode-specific. virtual metrics::StorageStateForUma GetStorageStateForUma() = 0; - // Returns true if the |permanent_node| can have its title updated. + // Returns true if the `permanent_node` can have its title updated. virtual bool CanSetPermanentNodeTitle(const BookmarkNode* permanent_node) = 0; - // Returns true if |node| is considered a managed node. + // Returns true if `node` is considered a managed node. virtual bool IsNodeManaged(const BookmarkNode* node) = 0; // Encodes the bookmark sync data into a string blob. It's used by the // bookmark model to persist the sync metadata together with the bookmark - // model. - virtual std::string EncodeBookmarkSyncMetadata() = 0; + // model. It comes with two variants: the blob corresponding to the + // local-or-syncable bookmarks and the one for account bookmarks. In + // normal circumnstances, at most one of them is non-empty. + virtual std::string EncodeLocalOrSyncableBookmarkSyncMetadata() = 0; + virtual std::string EncodeAccountBookmarkSyncMetadata() = 0; - // Decodes a string represeting the sync metadata stored in |metadata_str|. - // The model calls this method after it has loaded the model data. - // |schedule_save_closure| is a repeating call back to trigger a model and - // metadata persistence process. - virtual void DecodeBookmarkSyncMetadata( + // Decodes a string representing the sync metadata stored in `metadata_str`. + // Same as with encoding, it comes with two variants, one for + // local-or-syncable bookmarks and one for account bookmarks. The model calls + // this method after it has loaded the model data. `schedule_save_closure` is + // a repeating call back to trigger a model and metadata persistence process. + virtual void DecodeLocalOrSyncableBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) = 0; + virtual void DecodeAccountBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) = 0;
diff --git a/components/bookmarks/browser/bookmark_load_details.cc b/components/bookmarks/browser/bookmark_load_details.cc index de9f097..24439ad 100644 --- a/components/bookmarks/browser/bookmark_load_details.cc +++ b/components/bookmarks/browser/bookmark_load_details.cc
@@ -89,6 +89,15 @@ url_index_ = base::MakeRefCounted<UrlIndex>(std::move(root_node_)); } +void BookmarkLoadDetails::ResetPermanentNodePointers() { + bb_node_ = nullptr; + other_folder_node_ = nullptr; + mobile_folder_node_ = nullptr; + account_bb_node_ = nullptr; + account_other_folder_node_ = nullptr; + account_mobile_folder_node_ = nullptr; +} + const BookmarkNode* BookmarkLoadDetails::RootNodeForTest() const { return url_index_ ? url_index_->root() : root_node_.get(); }
diff --git a/components/bookmarks/browser/bookmark_load_details.h b/components/bookmarks/browser/bookmark_load_details.h index ec6bc83f..39c331e 100644 --- a/components/bookmarks/browser/bookmark_load_details.h +++ b/components/bookmarks/browser/bookmark_load_details.h
@@ -108,6 +108,8 @@ void CreateIndices(); + void ResetPermanentNodePointers(); + const scoped_refptr<UrlIndex>& url_index() { return url_index_; } const UrlIndex* url_index() const { return url_index_.get(); }
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index 18e7f858..08a466a 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -177,11 +177,10 @@ base::FilePath account_file_path; if (AreFoldersForAccountStorageAllowed()) { - // TODO(crbug.com/1520418): `storage_type` doesn't fit well in this case and - // it is ignored. Consider alternatives such as adding another Load() - // overload or adding a third value to StorageType (which would likely - // require forking the enum to - // ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h. + // TODO(b/41493391): `storage_type` doesn't fit well in this case and it is + // ignored. Consider alternatives such as adding another Load() overload or + // adding a third value to StorageType (which would likely require forking + // the enum to ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h. local_or_syncable_file_path = GetStorageFilePath(profile_path, StorageType::kLocalOrSyncable); account_file_path = GetStorageFilePath(profile_path, StorageType::kAccount); @@ -945,8 +944,6 @@ std::optional<base::Time> creation_time, std::optional<base::Uuid> uuid, bool added_by_user) { - // TODO(b/294100289): We should ensure that the specified UUID does not - // conflict with a reserved folder ID. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(loaded_); DCHECK(url.is_valid()); @@ -1183,10 +1180,13 @@ // here, after loading completes. root_->SortChildren(VisibilityComparator(client_.get())); + // Decoding of sync metadata may invoke `RemoveAccountPermanentFolders()`, + // which can lead to dangling raw_ptr members. + details->ResetPermanentNodePointers(); + loaded_ = true; - // TODO(crbug.com/1520418): Plumb account sync metadata too as well as - // ScheduleSave() for `account_store_`. - client_->DecodeBookmarkSyncMetadata( + + client_->DecodeLocalOrSyncableBookmarkSyncMetadata( details->local_or_syncable_sync_metadata_str(), local_or_syncable_store_ ? base::BindRepeating( @@ -1194,6 +1194,15 @@ base::Unretained(local_or_syncable_store_.get())) : base::DoNothing()); + if (AreFoldersForAccountStorageAllowed()) { + client_->DecodeAccountBookmarkSyncMetadata( + details->account_sync_metadata_str(), + account_store_ + ? base::BindRepeating(&BookmarkStorage::ScheduleSave, + base::Unretained(account_store_.get())) + : base::DoNothing()); + } + const base::TimeDelta load_duration = base::TimeTicks::Now() - details->load_start(); metrics::RecordTimeToLoadAtStartup(load_duration, @@ -1434,8 +1443,8 @@ void BookmarkModel::ScheduleSave() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug.com/1520418): Consider optimizing the save here if only one of - // the two stores has changed. + // TODO(b/41493391): Consider optimizing the save here if only one of the two + // stores has changed. if (local_or_syncable_store_) { local_or_syncable_store_->ScheduleSave();
diff --git a/components/bookmarks/browser/bookmark_storage.cc b/components/bookmarks/browser/bookmark_storage.cc index b3c629a1..f3cde78 100644 --- a/components/bookmarks/browser/bookmark_storage.cc +++ b/components/bookmarks/browser/bookmark_storage.cc
@@ -43,9 +43,9 @@ BookmarkCodec codec; switch (permanent_node_selection) { case BookmarkStorage::kSelectLocalOrSyncableNodes: - return codec.Encode(model->bookmark_bar_node(), model->other_node(), - model->mobile_node(), - model->client()->EncodeBookmarkSyncMetadata()); + return codec.Encode( + model->bookmark_bar_node(), model->other_node(), model->mobile_node(), + model->client()->EncodeLocalOrSyncableBookmarkSyncMetadata()); case BookmarkStorage::kSelectAccountNodes: if (!model->account_bookmark_bar_node()) { CHECK(!model->account_other_node()); @@ -56,10 +56,10 @@ CHECK(model->account_other_node()); CHECK(model->account_mobile_node()); - // TODO(crbug.com/1520418): Plumb sync metadata for account nodes. return codec.Encode(model->account_bookmark_bar_node(), model->account_other_node(), - model->account_mobile_node(), std::string()); + model->account_mobile_node(), + model->client()->EncodeAccountBookmarkSyncMetadata()); } NOTREACHED_NORETURN();
diff --git a/components/bookmarks/browser/bookmark_test_util.cc b/components/bookmarks/browser/bookmark_test_util.cc index a6f7bf51..174bc5f 100644 --- a/components/bookmarks/browser/bookmark_test_util.cc +++ b/components/bookmarks/browser/bookmark_test_util.cc
@@ -46,7 +46,11 @@ } void PrintTo(const BookmarkNode* node, std::ostream* os) { - PrintTo(*node, os); + if (node) { + PrintTo(*node, os); + } else { + *os << "null"; + } } } // namespace bookmarks
diff --git a/components/bookmarks/test/test_bookmark_client.cc b/components/bookmarks/test/test_bookmark_client.cc index efd14a8f..41e6edb 100644 --- a/components/bookmarks/test/test_bookmark_client.cc +++ b/components/bookmarks/test/test_bookmark_client.cc
@@ -108,11 +108,19 @@ return node && node->HasAncestor(unowned_managed_node_.get()); } -std::string TestBookmarkClient::EncodeBookmarkSyncMetadata() { +std::string TestBookmarkClient::EncodeLocalOrSyncableBookmarkSyncMetadata() { return std::string(); } -void TestBookmarkClient::DecodeBookmarkSyncMetadata( +std::string TestBookmarkClient::EncodeAccountBookmarkSyncMetadata() { + return std::string(); +} + +void TestBookmarkClient::DecodeLocalOrSyncableBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) {} + +void TestBookmarkClient::DecodeAccountBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) {}
diff --git a/components/bookmarks/test/test_bookmark_client.h b/components/bookmarks/test/test_bookmark_client.h index f95a66e..b08fcb1 100644 --- a/components/bookmarks/test/test_bookmark_client.h +++ b/components/bookmarks/test/test_bookmark_client.h
@@ -71,8 +71,12 @@ metrics::StorageStateForUma GetStorageStateForUma() override; bool CanSetPermanentNodeTitle(const BookmarkNode* permanent_node) override; bool IsNodeManaged(const BookmarkNode* node) override; - std::string EncodeBookmarkSyncMetadata() override; - void DecodeBookmarkSyncMetadata( + std::string EncodeLocalOrSyncableBookmarkSyncMetadata() override; + std::string EncodeAccountBookmarkSyncMetadata() override; + void DecodeLocalOrSyncableBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) override; + void DecodeAccountBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) override; base::CancelableTaskTracker::TaskId GetFaviconImageForPageURL(
diff --git a/components/browser_ui/DIR_METADATA b/components/browser_ui/DIR_METADATA index 496d412..3aade9c 100644 --- a/components/browser_ui/DIR_METADATA +++ b/components/browser_ui/DIR_METADATA
@@ -1,7 +1,8 @@ -monorail { +monorail: { component: "UI>Browser>Mobile" } - team_email: "clank-app-team@google.com" - os: ANDROID +buganizer_public: { + component_id: 1457074 +}
diff --git a/components/browser_ui/bottomsheet/android/DIR_METADATA b/components/browser_ui/bottomsheet/android/DIR_METADATA index b87b2836..9d84a7c5 100644 --- a/components/browser_ui/bottomsheet/android/DIR_METADATA +++ b/components/browser_ui/bottomsheet/android/DIR_METADATA
@@ -1,4 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Mobile>NavPanel" } - +buganizer_public: { + component_id: 1457471 +}
diff --git a/components/browser_ui/client_certificate/DIR_METADATA b/components/browser_ui/client_certificate/DIR_METADATA index 7e674fb..68a682f 100644 --- a/components/browser_ui/client_certificate/DIR_METADATA +++ b/components/browser_ui/client_certificate/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Network>Auth" } +buganizer_public: { + component_id: 1456376 +}
diff --git a/components/browser_ui/contacts_picker/android/DIR_METADATA b/components/browser_ui/contacts_picker/android/DIR_METADATA index a111896..1fd058b 100644 --- a/components/browser_ui/contacts_picker/android/DIR_METADATA +++ b/components/browser_ui/contacts_picker/android/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Blink>Contacts" } - team_email: "fugu-dev@chromium.org" +buganizer_public: { + component_id: 1456198 +}
diff --git a/components/browser_ui/display_cutout/DIR_METADATA b/components/browser_ui/display_cutout/DIR_METADATA index 53108245..389640d 100644 --- a/components/browser_ui/display_cutout/DIR_METADATA +++ b/components/browser_ui/display_cutout/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Blink>Layout" } +buganizer_public: { + component_id: 1456721 +}
diff --git a/components/browser_ui/media/DIR_METADATA b/components/browser_ui/media/DIR_METADATA index 87867de..69ade52 100644 --- a/components/browser_ui/media/DIR_METADATA +++ b/components/browser_ui/media/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Internals>Media>UI" } - team_email: "media-dev@chromium.org" +buganizer_public: { + component_id: 1456838 +}
diff --git a/components/browser_ui/notifications/android/DIR_METADATA b/components/browser_ui/notifications/android/DIR_METADATA index 0584aa3..29ec9ae 100644 --- a/components/browser_ui/notifications/android/DIR_METADATA +++ b/components/browser_ui/notifications/android/DIR_METADATA
@@ -1,6 +1,7 @@ -monorail { +monorail: { component: "UI>Notifications" } - team_email: "chrome-notifications@google.com" - +buganizer_public: { + component_id: 1457361 +}
diff --git a/components/browser_ui/photo_picker/android/DIR_METADATA b/components/browser_ui/photo_picker/android/DIR_METADATA index 32b2e15..96b404fb 100644 --- a/components/browser_ui/photo_picker/android/DIR_METADATA +++ b/components/browser_ui/photo_picker/android/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "UI>Browser>MediaPicker" } - team_email: "fugu-dev@chromium.org" +buganizer_public: { + component_id: 1457395 +}
diff --git a/components/browser_ui/settings/android/DIR_METADATA b/components/browser_ui/settings/android/DIR_METADATA index 7996c86e..84dffae 100644 --- a/components/browser_ui/settings/android/DIR_METADATA +++ b/components/browser_ui/settings/android/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { - component: "UI>Browser>Mobile>Settings" -} \ No newline at end of file +monorail: { + component: "UI>Browser>Mobile>Settings" +} +buganizer_public: { + component_id: 1456628 +}
diff --git a/components/browser_ui/share/DIR_METADATA b/components/browser_ui/share/DIR_METADATA index 3593292b..8677140 100644 --- a/components/browser_ui/share/DIR_METADATA +++ b/components/browser_ui/share/DIR_METADATA
@@ -1,4 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Sharing" } - +buganizer_public: { + component_id: 1457306 +}
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/DIR_METADATA b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/DIR_METADATA index 7617fd5d..0521819 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/DIR_METADATA +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { - component: "UI>Browser>SiteSettings" -} \ No newline at end of file +monorail: { + component: "UI>Browser>SiteSettings" +} +buganizer_public: { + component_id: 1457356 +}
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb index 930e894d..0f10602e 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">የሦስተኛ ወገን ኩኪዎች የተገደቡ ናቸው</translation> <translation id="3008272652534848354">ፈቃዶችን ዳግም ያቀናብሩ</translation> <translation id="301521992641321250">በራስ-ሰር ታግዷል</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">ለአንድ የተወሰነ ጣቢያ የሦስተኛ ወገን መግባትን ይፍቀዱ።</translation> <translation id="3082992102194421695">{COUNT,plural, =1{ነገ ጊዜው ያበቃል}one{በ# ቀን ውስጥ ጊዜው ያበቃል}other{በ# ቀናት ውስጥ ጊዜው ያበቃል}}</translation> <translation id="310297983047869047">ቀዳሚ ተንሸራታች</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">ከዩኤስቢ መሣሪያ ጋር ተገናኝቷል</translation> <translation id="4194328954146351878">ጣቢያዎች በኤንኤፍሲ መሣሪያዎች ላይ መረጃ እንዲያዩ እና እንዲቀይሩ ከመፈቀዱ በፊት ይጠይቅ (የሚመከር)</translation> <translation id="4200726100658658164">የአካባቢ ቅንብሮችን ክፈት</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> ከ<ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">ማሳወቂያዎች መሣሪያውን እንዲነዝር ሊያደርጉት ይችላሉ</translation> <translation id="4259722352634471385">ዳሰሳ ታግዷል፦ <ph name="URL" /></translation> <translation id="4278390842282768270">ተፈቅዷል</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">«<ph name="TITLE_OF_MODULE" />»ን ደብቅ</translation> <translation id="7781829728241885113">ትናንት</translation> <translation id="7791543448312431591">ያክሉ</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{በዚህ ትር ላይ ይቀጥሉ}one{በዚህ ትር ላይ ይቀጥሉ}other{በእነዚህ ትሮች ላይ ይቀጥሉ}}</translation> <translation id="780301667611848630">አይ፣ አመሰግናለሁ</translation> <translation id="7804248752222191302">አንድ ጣቢያ ካሜራዎን እየተጠቀመ ነው</translation> <translation id="7807060072011926525">በGoogle የቀረበ</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb index bd57d7f..7cc4051 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">তৃতীয় পক্ষৰ কুকি সীমিত কৰা হৈছে</translation> <translation id="3008272652534848354">অনুমতি ৰিছেট কৰক</translation> <translation id="301521992641321250">স্বয়ংক্ৰিয়ভাৱে অৱৰোধ কৰা হৈছে</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">নিৰ্দিষ্ট কোনো ছাইটৰ বাবে তৃতীয় পক্ষৰ ছাইন ইনৰ অনুমতি দিয়ক।</translation> <translation id="3082992102194421695">{COUNT,plural, =1{কাইলৈ ম্যাদ উকলিব}one{# দিনত ম্যাদ উকলিব}other{# দিনত ম্যাদ উকলিব}}</translation> <translation id="310297983047869047">পূৰ্বৱৰ্তী শ্লাইড</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">এটা ইউএছবি ডিভাইচৰ সৈতে সংযোগ কৰা হৈছে</translation> <translation id="4194328954146351878">ছাইটসমূহক NFC ডিভাইচত তথ্য চোৱা আৰু সলনি কৰাৰ অনুমতি দিয়াৰ পূৰ্বে সোধক (চুপাৰিছ কৰা হয়)</translation> <translation id="4200726100658658164">অৱস্থানৰ ছেটিংসমূহ খোলক</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="FROM_DEVICE" />ৰ পৰা</translation> <translation id="4226663524361240545">জাননীয়ে ডিভাইচটো কম্পন কৰিব পাৰে</translation> <translation id="4259722352634471385">নেভিগে’শ্বন অৱৰোধ কৰা আছে: <ph name="URL" /></translation> <translation id="4278390842282768270">অনুমতি দিয়া হৈছে</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">"<ph name="TITLE_OF_MODULE" />" লুকুৱাওক</translation> <translation id="7781829728241885113">কালি</translation> <translation id="7791543448312431591">যোগ কৰক</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{এই টেবটোৰ জৰিয়তে অব্যাহত ৰাখক}one{এই টেবসমূহৰ জৰিয়তে অব্যাহত ৰাখক}other{এই টেবসমূহৰ জৰিয়তে অব্যাহত ৰাখক}}</translation> <translation id="780301667611848630">নালাগে, ধন্যবাদ</translation> <translation id="7804248752222191302">এটা ছাইটে আপোনাৰ কেমেৰা ব্যৱহাৰ কৰি আছে</translation> <translation id="7807060072011926525">Googleএ প্ৰদান কৰিছে</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb index 22eb90dc..3d1971f 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Kolačići trećih strana su ograničeni</translation> <translation id="3008272652534848354">Poništi odobrenja</translation> <translation id="301521992641321250">Automatski blokirano</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Dozvolite prijavu trećih stana za određenu web lokaciju.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Ističe sutra}one{Ističe za # dan}few{Ističe za # dana}other{Ističe za # dana}}</translation> <translation id="310297983047869047">Prethodni slajd</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">Povezano s USB uređajem</translation> <translation id="4194328954146351878">Web lokacije moraju tražiti odobrenje za pregled i izmjenu informacija na NFC uređajima (preporučeno)</translation> <translation id="4200726100658658164">Otvaranje postavki lokacije</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> S uređaja <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Obavještenja mogu aktivirati vibraciju uređaja</translation> <translation id="4259722352634471385">Navigacija je blokirana: <ph name="URL" /></translation> <translation id="4278390842282768270">Dozvoljeno</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">Sakrij "<ph name="TITLE_OF_MODULE" />"</translation> <translation id="7781829728241885113">Jučer</translation> <translation id="7791543448312431591">Dodaj</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Nastavite s ovom karticom}one{Nastavite s ovim karticama}few{Nastavite s ovim karticama}other{Nastavite s ovim karticama}}</translation> <translation id="780301667611848630">Ne, hvala</translation> <translation id="7804248752222191302">Web lokacija koristi vašu kameru</translation> <translation id="7807060072011926525">Pruža Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb index a39547e..74dd7c5 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Limitado ang third-party na cookies</translation> <translation id="3008272652534848354">I-reset ang mga pahintulot</translation> <translation id="301521992641321250">Awtomatikong na-block</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Payagan ang third-party na pag-sign in para sa partikular na site.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Mag-e-expire bukas}one{Mag-e-expire sa loob ng # araw}other{Mag-e-expire sa loob ng # na araw}}</translation> <translation id="310297983047869047">Nakaraang slide</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">Nakakonekta sa USB device</translation> <translation id="4194328954146351878">Magtanong bago payagan ang mga site na tingnan at baguhin ang impormasyon sa mga NFC device (inirerekomenda)</translation> <translation id="4200726100658658164">Buksan ang Mga Setting ng Lokasyon</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> Mula sa <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Maaaring mag-vibrate ang device dahil sa mga notification</translation> <translation id="4259722352634471385">Naka-block ang navigation: <ph name="URL" /></translation> <translation id="4278390842282768270">Pinapayagan</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">I-hide ang "<ph name="TITLE_OF_MODULE" />"</translation> <translation id="7781829728241885113">Kahapon</translation> <translation id="7791543448312431591">Idagdag</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Magpatuloy sa tab na ito}one{Magpatuloy sa mga tab na ito}other{Magpatuloy sa mga tab na ito}}</translation> <translation id="780301667611848630">Hindi salamat</translation> <translation id="7804248752222191302">Ginagamit ng isang site ang iyong camera</translation> <translation id="7807060072011926525">Ibinibigay ng Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb index 3378d22..7bbb670 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Kolačići treće strane su ograničeni</translation> <translation id="3008272652534848354">Poništi dopuštenja</translation> <translation id="301521992641321250">Automatski blokirano</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Dopusti prijavu treće strane za određenu web-lokaciju.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Istječe sutra}one{Istječe za # dan}few{Istječe za # dana}other{Istječe za # dana}}</translation> <translation id="310297983047869047">Prethodni slajd</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">Povezano s USB uređajem</translation> <translation id="4194328954146351878">Pitaj prije omogućavanja web-lokacijama da vide i mijenjaju podatke na NFC uređajima (preporučeno)</translation> <translation id="4200726100658658164">Otvori postavke lokacije</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> S uređaja <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Obavijesti mogu uključiti vibriranje uređaja</translation> <translation id="4259722352634471385">Otvaranje je blokirano: <ph name="URL" /></translation> <translation id="4278390842282768270">Dopušteno</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">Sakrij <ph name="TITLE_OF_MODULE" /></translation> <translation id="7781829728241885113">Danas</translation> <translation id="7791543448312431591">Dodajte</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Nastavite s ovom karticom}one{Nastavite s ovim karticama}few{Nastavite s ovim karticama}other{Nastavite s ovim karticama}}</translation> <translation id="780301667611848630">Ne, hvala</translation> <translation id="7804248752222191302">Web-lokacija upotrebljava vašu kameru</translation> <translation id="7807060072011926525">Omogućuje Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb index 3543b03..1266985 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">ខូគីភាគីទីបីត្រូវបានដាក់កំហិត</translation> <translation id="3008272652534848354">កំណត់ការអនុញ្ញាតឡើងវិញ</translation> <translation id="301521992641321250">បានទប់ស្កាត់ដោយស្វ័យប្រវត្តិ</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">អនុញ្ញាតការចូលរបស់ភាគីទីបីសម្រាប់គេហទំព័រជាក់លាក់។</translation> <translation id="3082992102194421695">{COUNT,plural, =1{ផុតកំណត់ថ្ងៃស្អែក}other{ផុតកំណត់ក្នុងរយៈពេល # ថ្ងៃ}}</translation> <translation id="310297983047869047">ស្លាយមុន</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">បានភ្ជាប់ទៅឧបករណ៍ USB</translation> <translation id="4194328954146351878">សួរមុនពេលអនុញ្ញាតឱ្យគេហទំព័រមើលឃើញ និងផ្លាស់ប្ដូរព័ត៌មាននៅលើឧបករណ៍ NFC (បានណែនាំ)</translation> <translation id="4200726100658658164">បើកការកំណត់ទីតាំង</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> ពី <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">ការជូនដំណឹងអាចនឹងធ្វើឲ្យឧបករណ៍ញ័រ</translation> <translation id="4259722352634471385">ការរុករកត្រូវបានរារាំង៖ <ph name="URL" /></translation> <translation id="4278390842282768270">បានអនុញ្ញាត</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">លាក់ "<ph name="TITLE_OF_MODULE" />"</translation> <translation id="7781829728241885113">ម្សិលមិញ</translation> <translation id="7791543448312431591">បន្ថែម</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{បន្តជាមួយផ្ទាំងនេះ}other{បន្តជាមួយផ្ទាំងទាំងនេះ}}</translation> <translation id="780301667611848630">ទេ អរគុណ</translation> <translation id="7804248752222191302">គេហទំព័រមួយកំពុងប្រើប្រាស់កាមេរ៉ារបស់អ្នក</translation> <translation id="7807060072011926525">បានផ្ដល់ដោយ Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb index 354ad666b..7bd6bc0 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">ຄຸກກີ້ພາກສ່ວນທີສາມຖືກຈຳກັດໄວ້</translation> <translation id="3008272652534848354">ຣີເຊັດການອະນຸຍາດ</translation> <translation id="301521992641321250">ບລັອກອັດຕະໂນມັດແລ້ວ</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">ອະນຸຍາດໃຫ້ເຂົ້າສູ່ລະບົບພາກສ່ວນທີສາມສຳລັບເວັບໄຊສະເພາະໃດໜຶ່ງ.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{ໝົດອາຍຸມື້ອື່ນ}other{ໝົດອາຍຸໃນ # ມື້}}</translation> <translation id="310297983047869047">ສະໄລ້ກ່ອນໜ້າ</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">ເຊື່ອມຕໍ່ຫາອຸປະກອນ USB ແລ້ວ</translation> <translation id="4194328954146351878">ຖາມກ່ອນການອະນຸຍາດໃຫ້ເວັບໄຊເບິ່ງເຫັນ ແລະ ປ່ຽນຂໍ້ມູນຢູ່ອຸປະກອນ NFC (ແນະນຳ)</translation> <translation id="4200726100658658164">ເປີດການຕັ້ງຄ່າສະຖານທີ່</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> ຈາກ <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">ການແຈ້ງເຕືອນອາດຈະເຮັດໃຫ້ອຸປະກອນສັ່ນ</translation> <translation id="4259722352634471385">ການນໍາທາງຖືກບລັອກໄວ້: <ph name="URL" /></translation> <translation id="4278390842282768270">ອະນຸຍາດແລ້ວ</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">ເຊື່ອງ "<ph name="TITLE_OF_MODULE" />"</translation> <translation id="7781829728241885113">ມື້ວານນີ້</translation> <translation id="7791543448312431591">ເພີ່ມ</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{ສືບຕໍ່ໃຊ້ແຖບນີ້}other{ສືບຕໍ່ໃຊ້ແຖບເຫຼົ່ານີ້}}</translation> <translation id="780301667611848630">ບໍ່, ຂອບໃຈ</translation> <translation id="7804248752222191302">ເວັບໄຊກຳລັງໃຊ້ກ້ອງຂອງທ່ານຢູ່</translation> <translation id="7807060072011926525">ສະໜອງໃຫ້ໂດຍ Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb index cf2485e..8c6ea8e 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Kuki pihak ketiga adalah terhad</translation> <translation id="3008272652534848354">Tetapkan semula kebenaran</translation> <translation id="301521992641321250">Disekat secara automatik</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Benarkan log masuk pihak ketiga untuk laman tertentu.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Tamat tempoh esok}other{Tamat tempoh dalam masa # hari}}</translation> <translation id="310297983047869047">Slaid sebelumnya</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">Disambungkan kepada peranti USB</translation> <translation id="4194328954146351878">Tanya sebelum membenarkan laman melihat dan menukar maklumat pada peranti NFC (disyorkan)</translation> <translation id="4200726100658658164">Buka Tetapan Lokasi</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> Daripada <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Pemberitahuan boleh menggetarkan peranti</translation> <translation id="4259722352634471385">Navigasi disekat: <ph name="URL" /></translation> <translation id="4278390842282768270">Dibenarkan</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">Sembunyikan "<ph name="TITLE_OF_MODULE" />"</translation> <translation id="7781829728241885113">Semalam</translation> <translation id="7791543448312431591">Tambah</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Teruskan dengan tab ini}other{Teruskan dengan tab ini}}</translation> <translation id="780301667611848630">Tidak, terima kasih</translation> <translation id="7804248752222191302">Suatu tapak sedang menggunakan kamera anda</translation> <translation id="7807060072011926525">Disediakan oleh Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb index ecf0b462..778886cc 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Cookies van derden zijn beperkt</translation> <translation id="3008272652534848354">Rechten resetten</translation> <translation id="301521992641321250">Automatisch geblokkeerd</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Externe login toestaan voor een specifieke site.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Verloopt morgen}other{Verloopt over # dagen}}</translation> <translation id="310297983047869047">Vorige dia</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">Verbonden met een USB-apparaat</translation> <translation id="4194328954146351878">Vragen voordat sites informatie op NFC-apparaten mogen zien en wijzigen (aanbevolen)</translation> <translation id="4200726100658658164">Locatie-instellingen openen</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> Vanaf <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Het apparaat kan trillen bij meldingen</translation> <translation id="4259722352634471385">Navigatie is geblokkeerd: <ph name="URL" /></translation> <translation id="4278390842282768270">Toegestaan</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015"><ph name="TITLE_OF_MODULE" /> verbergen</translation> <translation id="7781829728241885113">Gisteren</translation> <translation id="7791543448312431591">Toevoegen</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Doorgaan met dit tabblad}other{Doorgaan met deze tabbladen}}</translation> <translation id="780301667611848630">Nee, bedankt</translation> <translation id="7804248752222191302">Een site gebruikt de camera</translation> <translation id="7807060072011926525">Geleverd door Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb index 87274984..95d0a6f 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Informasjonskapsler fra tredjeparter er begrenset</translation> <translation id="3008272652534848354">Tilbakestill tillatelser</translation> <translation id="301521992641321250">Automatisk blokkert</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Tillat tredjepartspålogging for et bestemt nettsted.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Utløper i morgen}other{Utløper om # dager}}</translation> <translation id="310297983047869047">Forrige lysbilde</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">Koblet til en USB-enhet</translation> <translation id="4194328954146351878">Spør før nettsteder får lov til å se og endre informasjon på NFC-enheter (anbefales)</translation> <translation id="4200726100658658164">Åpne posisjonsinnstillingene</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> fra <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Varsler kan gjøre at enheten vibrerer</translation> <translation id="4259722352634471385">Nettadressen er blokkert: <ph name="URL" /></translation> <translation id="4278390842282768270">Tillatt</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">Skjul «<ph name="TITLE_OF_MODULE" />»</translation> <translation id="7781829728241885113">I går</translation> <translation id="7791543448312431591">Legg til</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Fortsett med denne fanen}other{Fortsett med disse fanene}}</translation> <translation id="780301667611848630">Nei takk</translation> <translation id="7804248752222191302">Et nettsted bruker kameraet ditt</translation> <translation id="7807060072011926525">Levert av Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb index b02367b..03c463e 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">థర్డ్-పార్టీ కుక్కీలు పరిమితం చేయబడ్డాయి</translation> <translation id="3008272652534848354">అనుమతులను రీసెట్ చేయండి</translation> <translation id="301521992641321250">ఆటోమేటిక్గా బ్లాక్ చేయబడింది</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">నిర్దిష్ట సైట్ కోసం థర్డ్-పార్టీ సైన్-ఇన్ను అనుమతిస్తుంది.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{రేపు గడువు ముగుస్తుంది}other{# రోజుల్లో గడువు ముగుస్తుంది}}</translation> <translation id="310297983047869047">మునుపటి స్లయిడ్</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">USB పరికరానికి కనెక్ట్ చేయబడింది</translation> <translation id="4194328954146351878">NFC పరికరాలలో సమాచారాన్ని చూడటానికి, మార్చడానికి సైట్లను అనుమతించే ముందు అడగాలి (సిఫార్సు చేయడమైనది)</translation> <translation id="4200726100658658164">లొకేషన్ సెట్టింగ్లను తెరవండి</translation> +<translation id="4206661981211220935"><ph name="FROM_DEVICE" /> నుండి <ph name="RECENCY" /> <ph name="SEPARATOR" /></translation> <translation id="4226663524361240545">నోటిఫికేషన్లు పరికరాన్ని వైబ్రేట్ చేయవచ్చు</translation> <translation id="4259722352634471385">నావిగేషన్ బ్లాక్ చేయబడింది: <ph name="URL" /></translation> <translation id="4278390842282768270">అనుమతించబడింది</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">"<ph name="TITLE_OF_MODULE" />"ను దాచండి</translation> <translation id="7781829728241885113">నిన్న</translation> <translation id="7791543448312431591">జోడించండి</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{ఈ ట్యాబ్తో కొనసాగించండి}other{ఈ ట్యాబ్లతో కొనసాగించండి}}</translation> <translation id="780301667611848630">వద్దు , ధన్యవాదాలు</translation> <translation id="7804248752222191302">ఒక సైట్ మీ కెమెరాను ఉపయోగిస్తోంది</translation> <translation id="7807060072011926525">దీనిని Google అందించినది</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb index 0ae2097..fa776b3 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">มีการจำกัดคุกกี้ของบุคคลที่สาม</translation> <translation id="3008272652534848354">รีเซ็ตสิทธิ์</translation> <translation id="301521992641321250">ถูกบล็อกโดยอัตโนมัติ</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">อนุญาตการลงชื่อเข้าใช้ของบุคคลที่สามสำหรับบางเว็บไซต์</translation> <translation id="3082992102194421695">{COUNT,plural, =1{หมดอายุวันพรุ่งนี้}other{หมดอายุในอีก # วัน}}</translation> <translation id="310297983047869047">สไลด์ก่อนหน้า</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">เชื่อมต่ออยู่กับอุปกรณ์ USB</translation> <translation id="4194328954146351878">ถามก่อนที่จะอนุญาตให้เว็บไซต์ดูและเปลี่ยนแปลงข้อมูลในอุปกรณ์ NFC (แนะนำ)</translation> <translation id="4200726100658658164">เปิดการตั้งค่าตำแหน่ง</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> จาก <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">การแจ้งเตือนอาจทำให้อุปกรณ์สั่น</translation> <translation id="4259722352634471385">มีการบล็อกการนำทาง: <ph name="URL" /></translation> <translation id="4278390842282768270">อนุญาตแล้ว</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">ซ่อน "<ph name="TITLE_OF_MODULE" />"</translation> <translation id="7781829728241885113">เมื่อวานนี้</translation> <translation id="7791543448312431591">เพิ่ม</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{ดำเนินการต่อโดยใช้แท็บนี้}other{ดำเนินการต่อโดยใช้แท็บเหล่านี้}}</translation> <translation id="780301667611848630">ไม่ ขอบคุณ</translation> <translation id="7804248752222191302">มีเว็บไซต์กำลังใช้กล้อง</translation> <translation id="7807060072011926525">ให้บริการโดย Google</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb index e44475c..1e63233b 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Tashqi cookie fayllar cheklangan</translation> <translation id="3008272652534848354">Ruxsatlarni qasliga qaytarish</translation> <translation id="301521992641321250">Avtomatik bloklangan</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Muayyan sayt uchun tashqi xizmatga kirishga ruxsat bering.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Muddati ertaga tugaydi}other{# kundan keyin muddati tugaydi}}</translation> <translation id="310297983047869047">Avvalgi slaydi</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">USB qurilmaga ulandi</translation> <translation id="4194328954146351878">Saytlar NFC qurilmalarni koʻrishi va ulardagi axborotni oʻzgartirishidan oldin ruxsat olsin (tavsiya etiladi)</translation> <translation id="4200726100658658164">Joylashuv sozlamalarini ochish</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> Manba: <ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Bildirishnoma kelganida qurilma tebranishi mumkin</translation> <translation id="4259722352634471385">Sahifa bloklandi: <ph name="URL" /></translation> <translation id="4278390842282768270">Berilgan ruxsatnomalar</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015"><ph name="TITLE_OF_MODULE" /> panelini yopish</translation> <translation id="7781829728241885113">Kecha</translation> <translation id="7791543448312431591">Qo‘shish</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Shu varaqda davom etish}other{Shu varaqlarda davom etish}}</translation> <translation id="780301667611848630">Kerak emas</translation> <translation id="7804248752222191302">Sayt kameradan foydalanmoqda</translation> <translation id="7807060072011926525">Google taqdim qilgan</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb index a6ba687f..697f07c 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">限制使用第三方 Cookie</translation> <translation id="3008272652534848354">重設權限</translation> <translation id="301521992641321250">已自動封鎖</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">允許特定網站使用第三方登入功能。</translation> <translation id="3082992102194421695">{COUNT,plural, =1{明天到期}other{# 天後到期}}</translation> <translation id="310297983047869047">上一張投影片</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">已連線至 USB 裝置</translation> <translation id="4194328954146351878">在允許網站查看和變更 NFC 裝置上的資料前先詢問您 (建議)</translation> <translation id="4200726100658658164">開啟位置設定</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> 來自「<ph name="FROM_DEVICE" />」</translation> <translation id="4226663524361240545">裝置會在收到通知時震動</translation> <translation id="4259722352634471385">瀏覽網址被封鎖:<ph name="URL" /></translation> <translation id="4278390842282768270">已允許</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">隱藏「<ph name="TITLE_OF_MODULE" />」</translation> <translation id="7781829728241885113">昨天</translation> <translation id="7791543448312431591">新增</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{繼續使用此分頁}other{繼續使用這些分頁}}</translation> <translation id="780301667611848630">不用了,謝謝</translation> <translation id="7804248752222191302">有網站正在使用您的相機</translation> <translation id="7807060072011926525">由 Google 提供</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb index d040686..b490e662 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">限制使用第三方 Cookie</translation> <translation id="3008272652534848354">重設權限</translation> <translation id="301521992641321250">已自動封鎖</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">允許特定網站使用第三方登入功能。</translation> <translation id="3082992102194421695">{COUNT,plural, =1{明天到期}other{# 天後到期}}</translation> <translation id="310297983047869047">上一張投影片</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">已連接至 USB 裝置</translation> <translation id="4194328954146351878">系統必須先詢問你,才能允許網站在 NFC 裝置上查看和變更資訊 (建議設定)</translation> <translation id="4200726100658658164">開啟位置資訊設定</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> 來自「<ph name="FROM_DEVICE" />」</translation> <translation id="4226663524361240545">收到通知時裝置會震動</translation> <translation id="4259722352634471385">瀏覽的網址已封鎖:<ph name="URL" /></translation> <translation id="4278390842282768270">允許</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">隱藏「<ph name="TITLE_OF_MODULE" />」</translation> <translation id="7781829728241885113">昨天</translation> <translation id="7791543448312431591">新增</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{繼續使用這個分頁}other{繼續使用這些分頁}}</translation> <translation id="780301667611848630">不用了,謝謝</translation> <translation id="7804248752222191302">有網站正在使用你的攝影機</translation> <translation id="7807060072011926525">由 Google 提供</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb index a1124bd..a8eeb9af 100644 --- a/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb +++ b/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb
@@ -121,6 +121,7 @@ <translation id="2979365474350987274">Amakhukhi avela kwamanye amawebhusayithi alinganiselwe</translation> <translation id="3008272652534848354">Setha kabusha izimvume</translation> <translation id="301521992641321250">Kuvinjelwe ngokuzenzakalelayo</translation> +<translation id="3025010840409371499"><ph name="RECENCY" /> <ph name="SEPARATOR" /> <ph name="HOST_NAME" /></translation> <translation id="3069226013421428034">Vumela ukungena ngemvume kwenkampani yangaphandle kusayithi elithile.</translation> <translation id="3082992102194421695">{COUNT,plural, =1{Kuphelelwa yisikhathi kusasa}one{Kuphelelwa isikhathi ezinsukwini ezingu-#}other{Kuphelelwa isikhathi ezinsukwini ezingu-#}}</translation> <translation id="310297983047869047">Islayidi sangaphambilini</translation> @@ -190,6 +191,7 @@ <translation id="4169549551965910670">Ixhumeke kudivayisi ye-USB</translation> <translation id="4194328954146351878">Buza ngaphambi kokuvumela amasayithi ukuthi abone futhi aguqule ulwazi kumadivayisi e-NFC (kuyanconywa)</translation> <translation id="4200726100658658164">Vula Izilungiselelo zendawo</translation> +<translation id="4206661981211220935"><ph name="RECENCY" /> <ph name="SEPARATOR" /> Ukusuka ku-<ph name="FROM_DEVICE" /></translation> <translation id="4226663524361240545">Izaziso zingadlidliza idivayisi</translation> <translation id="4259722352634471385">Ukuzulazula kuvinjiwe: <ph name="URL" /></translation> <translation id="4278390842282768270">Kuvunyelwe</translation> @@ -403,6 +405,7 @@ <translation id="7770832849480336015">Fihla okuthi "<ph name="TITLE_OF_MODULE" />"</translation> <translation id="7781829728241885113">Izolo</translation> <translation id="7791543448312431591">Engeza</translation> +<translation id="7801888679188438140">{TILE_COUNT,plural, =1{Qhubeka nale thebhu}one{Qhubeka ngalawa mathebhu}other{Qhubeka ngalawa mathebhu}}</translation> <translation id="780301667611848630">Cha ngiyabonga</translation> <translation id="7804248752222191302">Isayithi lisebenzisa ikhamera yakho</translation> <translation id="7807060072011926525">Kuhlinzekwe yi-Google</translation>
diff --git a/components/browser_ui/webshare/DIR_METADATA b/components/browser_ui/webshare/DIR_METADATA index b5243d7..07d5c85e 100644 --- a/components/browser_ui/webshare/DIR_METADATA +++ b/components/browser_ui/webshare/DIR_METADATA
@@ -1,4 +1,6 @@ -monorail { +monorail: { component: "Blink>WebShare" } - +buganizer_public: { + component_id: 1456965 +}
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/image_tiles/DIR_METADATA b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/image_tiles/DIR_METADATA index 46d9513..283c2100 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/image_tiles/DIR_METADATA +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/image_tiles/DIR_METADATA
@@ -1,6 +1,7 @@ -monorail { +monorail: { component: "Upboarding>QueryTiles" } - team_email: "chrome-upboarding@google.com" - +buganizer_public: { + component_id: 1457082 +}
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index 689dd090..24b58e21 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -523,6 +523,7 @@ deps = [ ":cronet_api_java", + ":cronet_impl_common_java", "//build/android:build_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_core_core_java", @@ -1237,6 +1238,7 @@ "test/javatests/src/org/chromium/net/DiskStorageTest.java", "test/javatests/src/org/chromium/net/ExperimentalOptionsTest.java", "test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTest.java", + "test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTestUtil.java", "test/javatests/src/org/chromium/net/FileUtils.java", "test/javatests/src/org/chromium/net/GetStatusTest.java", "test/javatests/src/org/chromium/net/LogcatCapture.java", @@ -1258,6 +1260,7 @@ "test/javatests/src/org/chromium/net/httpflags/BaseFeatureTest.java", "test/javatests/src/org/chromium/net/httpflags/HttpFlagsLoaderTest.java", "test/javatests/src/org/chromium/net/httpflags/ResolvedFlagsTest.java", + "test/javatests/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapperTest.java", "test/javatests/src/org/chromium/net/impl/CronetLoggerTest.java", "test/javatests/src/org/chromium/net/impl/CronetManifestTest.java", "test/javatests/src/org/chromium/net/telemetry/CronetLoggerImplTest.java", @@ -1285,6 +1288,8 @@ "//third_party/android_deps:guava_android_java", "//third_party/android_deps:protobuf_lite_runtime_java", "//third_party/android_sdk:android_test_base_java", + "//third_party/androidx:androidx_annotation_annotation_java", + "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_ext_junit_java", "//third_party/androidx:androidx_test_runner_java", "//third_party/google-truth:google_truth_java",
diff --git a/components/cronet/android/api.txt b/components/cronet/android/api.txt index 11e5f27..2762af9 100644 --- a/components/cronet/android/api.txt +++ b/components/cronet/android/api.txt
@@ -62,7 +62,7 @@ } public interface org.chromium.net.ConnectionMigrationOptions$Experimental extends java.lang.annotation.Annotation { } -public class org.chromium.net.ConnectionMigrationOptions { +public final class org.chromium.net.ConnectionMigrationOptions { public java.lang.Boolean getEnableDefaultNetworkMigration(); public java.lang.Boolean getEnablePathDegradationMigration(); public java.lang.Boolean getAllowServerMigration(); @@ -73,7 +73,6 @@ public java.lang.Long getMaxTimeOnNonDefaultNetworkSeconds(); public java.lang.Integer getMaxWriteErrorEagerMigrationsCount(); public java.lang.Integer getMaxPathDegradingEagerMigrationsCount(); - public org.chromium.net.ConnectionMigrationOptions(org.chromium.net.ConnectionMigrationOptions$Builder); public static org.chromium.net.ConnectionMigrationOptions$Builder builder(); } public abstract class org.chromium.net.CronetEngine$Builder$LibraryLoader { @@ -633,4 +632,4 @@ public static org.chromium.net.apihelpers.JsonCronetCallback forJsonBody(org.chromium.net.apihelpers.RedirectHandler, org.chromium.net.apihelpers.CronetRequestCompletionListener<org.json.JSONObject>); public static org.chromium.net.apihelpers.UrlRequestCallbacks$CallbackAndResponseFuturePair<org.json.JSONObject, org.chromium.net.apihelpers.JsonCronetCallback> forJsonBody(org.chromium.net.apihelpers.RedirectHandler); } -Stamp: c70494071c55da3be9bb3f922762ba95 +Stamp: fb82aaef920d5db0ac22a2df3ddd26b4
diff --git a/components/cronet/android/api/src/org/chromium/net/ConnectionMigrationOptions.java b/components/cronet/android/api/src/org/chromium/net/ConnectionMigrationOptions.java index aed120b..697e94f 100644 --- a/components/cronet/android/api/src/org/chromium/net/ConnectionMigrationOptions.java +++ b/components/cronet/android/api/src/org/chromium/net/ConnectionMigrationOptions.java
@@ -10,22 +10,21 @@ /** * A class configuring Cronet's connection migration functionality. * - * <p>Connection migration stops open connections to servers from being destroyed when the - * client device switches its L4 connectivity (typically the IP address as a result of using - * a different network). This is particularly common with mobile devices losing - * wifi connectivity and switching to cellular data, or vice versa (a.k.a. the parking lot - * problem). QUIC uses connection identifiers which are independent of the underlying - * transport layer to make this possible. If the client connects to a new network and wants - * to preserve the existing connection, they can do so by using a connection identifier the server - * knows to be a continuation of the existing connection. + * <p>Connection migration stops open connections to servers from being destroyed when the client + * device switches its L4 connectivity (typically the IP address as a result of using a different + * network). This is particularly common with mobile devices losing wifi connectivity and switching + * to cellular data, or vice versa (a.k.a. the parking lot problem). QUIC uses connection + * identifiers which are independent of the underlying transport layer to make this possible. If the + * client connects to a new network and wants to preserve the existing connection, they can do so by + * using a connection identifier the server knows to be a continuation of the existing connection. * * <p>The features are only available for QUIC connections and the server needs to support * connection migration. * - * @see <a href="https://www.rfc-editor.org/rfc/rfc9000.html#section-9">Connection - * Migration specification</a> + * @see <a href="https://www.rfc-editor.org/rfc/rfc9000.html#section-9">Connection Migration + * specification</a> */ -public class ConnectionMigrationOptions { +public final class ConnectionMigrationOptions { @Nullable private final Boolean mEnableDefaultNetworkMigration; @Nullable private final Boolean mEnablePathDegradationMigration; @Nullable private final Boolean mAllowServerMigration; @@ -87,7 +86,7 @@ return mMaxPathDegradingEagerMigrationsCount; } - public ConnectionMigrationOptions(Builder builder) { + private ConnectionMigrationOptions(Builder builder) { this.mEnableDefaultNetworkMigration = builder.mEnableDefaultNetworkConnectionMigration; this.mEnablePathDegradationMigration = builder.mEnablePathDegradationMigration; this.mAllowServerMigration = builder.mAllowServerMigration; @@ -114,7 +113,7 @@ @Nullable private Integer mMaxWriteErrorEagerMigrationsCount; @Nullable private Integer mMaxPathDegradingEagerMigrationsCount; - Builder() {} + private Builder() {} /** * Enables the possibility of migrating connections on default network change. If enabled,
diff --git a/components/cronet/android/api/src/org/chromium/net/ExperimentalOptionsTranslatingCronetEngineBuilder.java b/components/cronet/android/api/src/org/chromium/net/ExperimentalOptionsTranslatingCronetEngineBuilder.java index 279fed1..b55a5e836 100644 --- a/components/cronet/android/api/src/org/chromium/net/ExperimentalOptionsTranslatingCronetEngineBuilder.java +++ b/components/cronet/android/api/src/org/chromium/net/ExperimentalOptionsTranslatingCronetEngineBuilder.java
@@ -284,8 +284,7 @@ } if (options.getEnablePathDegradationMigration() != null) { boolean pathDegradationValue = options.getEnablePathDegradationMigration(); - - boolean skipPortMigrationFlag = false; + quicOptions.put("allow_port_migration", pathDegradationValue); if (options.getAllowNonDefaultNetworkUsage() != null) { boolean nonDefaultNetworkValue = @@ -296,18 +295,16 @@ "Unable to turn on non-default network usage without path " + "degradation migration!"); } else if (pathDegradationValue && nonDefaultNetworkValue) { - // Both values being true results in the non-default network - // migration being enabled. quicOptions.put("migrate_sessions_early_v2", true); - skipPortMigrationFlag = true; + // To enable connection migration, + // migrate_sessions_on_network_change_v2 option needs to be set. + // See http://go/quic-cmv2-config-options or + // https://crsrc.org/c/net/quic/quic_session_pool.cc;l=1532;drc=4a6bf24b15fdb49a018a12af2025321691f87e1a?q=migrate_sessions_on_network_change + quicOptions.put("migrate_sessions_on_network_change_v2", true); } else { quicOptions.put("migrate_sessions_early_v2", false); } } - - if (!skipPortMigrationFlag) { - quicOptions.put("allow_port_migration", pathDegradationValue); - } } });
diff --git a/components/cronet/android/api_version.txt b/components/cronet/android/api_version.txt index 6f4247a..f64f5d8d 100644 --- a/components/cronet/android/api_version.txt +++ b/components/cronet/android/api_version.txt
@@ -1 +1 @@ -26 +27
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapper.java b/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapper.java index d1a17c7..ba31d0d 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapper.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapper.java
@@ -11,10 +11,13 @@ import android.util.Log; import androidx.annotation.RequiresExtension; +import androidx.annotation.VisibleForTesting; import org.chromium.net.CronetEngine; import org.chromium.net.ExperimentalCronetEngine; import org.chromium.net.ICronetEngineBuilder; +import org.chromium.net.telemetry.ExperimentalOptions; +import org.chromium.net.telemetry.OptionalBoolean; import java.util.Date; import java.util.Set; @@ -80,13 +83,6 @@ } @Override - public ICronetEngineBuilder setExperimentalOptions(String options) { - // TODO(danstahr): Hidden API. This should ideally extract values we know how to handle as a - // main API - return this; - } - - @Override public ICronetEngineBuilder enableHttpCache(int cacheMode, long maxSize) { mBackend.setEnableHttpCache(cacheMode, maxSize); return this; @@ -115,6 +111,14 @@ return this; } + @Override + public ICronetEngineBuilder setExperimentalOptions(String stringOptions) { + // This only translates known experimental options + ExperimentalOptions options = new ExperimentalOptions(stringOptions); + mBackend.setConnectionMigrationOptions(parseConnectionMigrationOptions(options)); + return this; + } + /** * Build a {@link CronetEngine} using this builder's configuration. * @@ -124,4 +128,40 @@ public ExperimentalCronetEngine build() { return new AndroidHttpEngineWrapper(mBackend.build()); } + + @VisibleForTesting + public static android.net.http.ConnectionMigrationOptions parseConnectionMigrationOptions( + ExperimentalOptions options) { + android.net.http.ConnectionMigrationOptions.Builder cmOptionsBuilder = + new android.net.http.ConnectionMigrationOptions.Builder(); + + cmOptionsBuilder.setDefaultNetworkMigration( + optionalBooleanToMigrationOptionState( + options.getMigrateSessionsOnNetworkChangeV2Option())); + cmOptionsBuilder.setPathDegradationMigration( + optionalBooleanToMigrationOptionState(options.getAllowPortMigration())); + + OptionalBoolean migrateSessionsEarly = options.getMigrateSessionsEarlyV2(); + cmOptionsBuilder.setAllowNonDefaultNetworkUsage( + optionalBooleanToMigrationOptionState(migrateSessionsEarly)); + if (migrateSessionsEarly == OptionalBoolean.TRUE) { + cmOptionsBuilder.setPathDegradationMigration( + optionalBooleanToMigrationOptionState(OptionalBoolean.TRUE)); + } + + return cmOptionsBuilder.build(); + } + + private static int optionalBooleanToMigrationOptionState(OptionalBoolean value) { + switch (value) { + case TRUE: + return android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_ENABLED; + case FALSE: + return android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_DISABLED; + case UNSET: + return android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_UNSPECIFIED; + } + + throw new AssertionError("Invalid OptionalBoolean value: " + value); + } }
diff --git a/components/cronet/android/java/src/org/chromium/net/telemetry/ExperimentalOptions.java b/components/cronet/android/java/src/org/chromium/net/telemetry/ExperimentalOptions.java index 352725c..bb97ba1b 100644 --- a/components/cronet/android/java/src/org/chromium/net/telemetry/ExperimentalOptions.java +++ b/components/cronet/android/java/src/org/chromium/net/telemetry/ExperimentalOptions.java
@@ -109,6 +109,11 @@ getOrDefault(QUIC, "enable_socket_recv_optimization", null, Boolean.class)); } + public OptionalBoolean getAllowPortMigration() { + return OptionalBoolean.fromBoolean( + getOrDefault(QUIC, "allow_port_migration", null, Boolean.class)); + } + public OptionalBoolean getAsyncDnsEnableOption() { return OptionalBoolean.fromBoolean(getOrDefault(ASYNC_DNS, "enable", null, Boolean.class)); }
diff --git a/components/cronet/android/java/src/org/chromium/net/telemetry/OptionalBoolean.java b/components/cronet/android/java/src/org/chromium/net/telemetry/OptionalBoolean.java index 8ab40c6..4bb8e3c 100644 --- a/components/cronet/android/java/src/org/chromium/net/telemetry/OptionalBoolean.java +++ b/components/cronet/android/java/src/org/chromium/net/telemetry/OptionalBoolean.java
@@ -10,7 +10,7 @@ * one of them and used it to create a private variable that we can use to make the code more * readable. */ -enum OptionalBoolean { +public enum OptionalBoolean { UNSET( CronetStatsLog .CRONET_ENGINE_CREATED__EXPERIMENTAL_OPTIONS_QUIC_STORE_SERVER_CONFIGS_IN_PROPERTIES__OPTIONAL_BOOLEAN_UNSET),
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTest.java index 9db1473..e3fc830 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTest.java
@@ -5,31 +5,23 @@ package org.chromium.net; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; +import static org.chromium.net.ExperimentalOptionsTranslationTestUtil.assertJsonEquals; +import static org.chromium.net.ExperimentalOptionsTranslationTestUtil.toTelephoneKeyboardSequence; + import androidx.annotation.OptIn; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.MediumTest; import org.jni_zero.JNINamespace; -import org.json.JSONException; -import org.json.JSONObject; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.test.util.Batch; import org.chromium.net.DnsOptions.StaleDnsOptions; - -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import org.chromium.net.ExperimentalOptionsTranslationTestUtil.MockCronetBuilderImpl; @RunWith(AndroidJUnit4.class) @Batch(Batch.UNIT_TESTS) @@ -143,7 +135,8 @@ assertThat(mockBuilderImpl.mConnectionMigrationOptions).isNull(); assertJsonEquals( - "{\"QUIC\":{\"migrate_sessions_early_v2\":true}}", + "{\"QUIC\":{\"migrate_sessions_early_v2\":true,\"allow_port_migration\":true," + + "\"migrate_sessions_on_network_change_v2\":true}}", mockBuilderImpl.mEffectiveExperimentalOptions); } @@ -285,15 +278,15 @@ + " \"allow_other_network\": true, \"delay_ms\": 373740587, " + " \"use_stale_on_name_not_resolved\": false, \"max_expired_time_ms\":" + " 629397243 }, \"QUIC\": { \"race_stale_dns_on_connection\": false, " - + " \"migrate_sessions_on_network_change_v2\": false, " + + " \"migrate_sessions_on_network_change_v2\": true, " + " \"allow_server_migration\": false, \"migrate_idle_sessions\": true, " + " \"idle_session_migration_period_seconds\": 435370463, " + " \"retry_on_alternate_network_before_handshake\": false, " + " \"max_time_on_non_default_network_seconds\": 629840858, " + " \"max_migrations_to_non_default_network_on_path_degrading\": 223720377, " + " \"max_migrations_to_non_default_network_on_write_error\": 7483377, " - + " \"migrate_sessions_early_v2\": true, \"host_whitelist\":" - + " \"quicHost1.com,quicHost2.com\", \"quic_version\":" + + " \"migrate_sessions_early_v2\": true, \"allow_port_migration\": true, " + + " \"host_whitelist\":\"quicHost1.com,quicHost2.com\", \"quic_version\":" + " \"quicVersion1,quicVersion2\", \"connection_options\":" + " \"connectionOption1,connectionOption2\", \"client_connection_options\": " + " \"clientConnectionOption1,clientConnectionOption2\", " @@ -330,194 +323,4 @@ "{\"QUIC\":{},\"AsyncDNS\":{},\"StaleDNS\":{}}", mockBuilderImpl.mEffectiveExperimentalOptions); } - - private static int toTelephoneKeyboardSequence(String string) { - int length = string.length(); - if (length > 9) { - return toTelephoneKeyboardSequence(string.substring(0, 5)) * 10000 - + toTelephoneKeyboardSequence(string.substring(length - 3, length)); - } - - // This could be optimized a lot but little inefficiency in tests doesn't matter all that - // much and readability benefits are quite significant. - Map<String, Integer> charMap = new HashMap<>(); - charMap.put("abc", 2); - charMap.put("def", 3); - charMap.put("ghi", 4); - charMap.put("jkl", 5); - charMap.put("mno", 6); - charMap.put("pqrs", 7); - charMap.put("tuv", 8); - charMap.put("xyz", 9); - - int result = 0; - for (int i = 0; i < length; i++) { - result *= 10; - for (Map.Entry<String, Integer> mapping : charMap.entrySet()) { - if (mapping.getKey() - .contains(string.substring(i, i + 1).toLowerCase(Locale.ROOT))) { - result += mapping.getValue(); - break; - } - } - } - return result; - } - - private static void assertJsonEquals(String expected, String actual) { - try { - JSONObject expectedJson = new JSONObject(expected); - JSONObject actualJson = new JSONObject(actual); - - assertJsonEquals(expectedJson, actualJson, ""); - } catch (JSONException e) { - throw new AssertionError(e); - } - } - - private static void assertJsonEquals(JSONObject expected, JSONObject actual, String currentPath) - throws JSONException { - assertThat(jsonKeys(actual)).isEqualTo(jsonKeys(expected)); - - for (String key : jsonKeys(expected)) { - Object expectedValue = expected.get(key); - Object actualValue = actual.get(key); - if (expectedValue == actualValue) { - continue; - } - String fullKey = currentPath.isEmpty() ? key : currentPath + "." + key; - if (expectedValue instanceof JSONObject) { - assertWithMessage("key is '" + fullKey + "'") - .that(actualValue) - .isInstanceOf(JSONObject.class); - assertJsonEquals((JSONObject) expectedValue, (JSONObject) actualValue, fullKey); - } else { - assertWithMessage("key is '" + fullKey + "'") - .that(actualValue) - .isEqualTo(expectedValue); - } - } - } - - private static Set<String> jsonKeys(JSONObject json) throws JSONException { - Set<String> result = new HashSet<>(); - - Iterator<String> keys = json.keys(); - - while (keys.hasNext()) { - String key = keys.next(); - result.add(key); - } - - return result; - } - - // Mocks make life downstream miserable so use a custom mock-like class. - private static class MockCronetBuilderImpl extends ICronetEngineBuilder { - private ConnectionMigrationOptions mConnectionMigrationOptions; - private String mTempExperimentalOptions; - private String mEffectiveExperimentalOptions; - - private final boolean mSupportsConnectionMigrationConfigOption; - - static MockCronetBuilderImpl withNativeSetterSupport() { - return new MockCronetBuilderImpl(true); - } - - static MockCronetBuilderImpl withoutNativeSetterSupport() { - return new MockCronetBuilderImpl(false); - } - - private MockCronetBuilderImpl(boolean supportsConnectionMigrationConfigOption) { - this.mSupportsConnectionMigrationConfigOption = supportsConnectionMigrationConfigOption; - } - - @Override - public ICronetEngineBuilder addPublicKeyPins( - String hostName, - Set<byte[]> pinsSha256, - boolean includeSubdomains, - Date expirationDate) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder addQuicHint(String host, int port, int alternatePort) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder enableHttp2(boolean value) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder enableHttpCache(int cacheMode, long maxSize) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder enablePublicKeyPinningBypassForLocalTrustAnchors( - boolean value) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder enableQuic(boolean value) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder enableSdch(boolean value) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder setExperimentalOptions(String options) { - mTempExperimentalOptions = options; - return this; - } - - @Override - public ICronetEngineBuilder setLibraryLoader(CronetEngine.Builder.LibraryLoader loader) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder setStoragePath(String value) { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder setUserAgent(String userAgent) { - throw new UnsupportedOperationException(); - } - - @Override - public String getDefaultUserAgent() { - throw new UnsupportedOperationException(); - } - - @Override - public ICronetEngineBuilder setConnectionMigrationOptions( - ConnectionMigrationOptions options) { - mConnectionMigrationOptions = options; - return this; - } - - @Override - public Set<Integer> getSupportedConfigOptions() { - if (mSupportsConnectionMigrationConfigOption) { - return Collections.singleton(ICronetEngineBuilder.CONNECTION_MIGRATION_OPTIONS); - } else { - return Collections.emptySet(); - } - } - - @Override - public ExperimentalCronetEngine build() { - mEffectiveExperimentalOptions = mTempExperimentalOptions; - return null; - } - } }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTestUtil.java b/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTestUtil.java new file mode 100644 index 0000000..a070ec4 --- /dev/null +++ b/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTranslationTestUtil.java
@@ -0,0 +1,215 @@ +// 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. +package org.chromium.net; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/* Utility class to be shared for ExperimentalOptions translation related tests. */ +public class ExperimentalOptionsTranslationTestUtil { + private ExperimentalOptionsTranslationTestUtil() {} + + static int toTelephoneKeyboardSequence(String string) { + int length = string.length(); + if (length > 9) { + return toTelephoneKeyboardSequence(string.substring(0, 5)) * 10000 + + toTelephoneKeyboardSequence(string.substring(length - 3, length)); + } + + // This could be optimized a lot but little inefficiency in tests doesn't matter all that + // much and readability benefits are quite significant. + Map<String, Integer> charMap = new HashMap<>(); + charMap.put("abc", 2); + charMap.put("def", 3); + charMap.put("ghi", 4); + charMap.put("jkl", 5); + charMap.put("mno", 6); + charMap.put("pqrs", 7); + charMap.put("tuv", 8); + charMap.put("xyz", 9); + + int result = 0; + for (int i = 0; i < length; i++) { + result *= 10; + for (Map.Entry<String, Integer> mapping : charMap.entrySet()) { + if (mapping.getKey() + .contains(string.substring(i, i + 1).toLowerCase(Locale.ROOT))) { + result += mapping.getValue(); + break; + } + } + } + return result; + } + + public static void assertJsonEquals(String expected, String actual) { + try { + JSONObject expectedJson = new JSONObject(expected); + JSONObject actualJson = new JSONObject(actual); + + assertJsonEquals(expectedJson, actualJson, ""); + } catch (JSONException e) { + throw new AssertionError(e); + } + } + + static void assertJsonEquals(JSONObject expected, JSONObject actual, String currentPath) + throws JSONException { + assertThat(jsonKeys(actual)).isEqualTo(jsonKeys(expected)); + + for (String key : jsonKeys(expected)) { + Object expectedValue = expected.get(key); + Object actualValue = actual.get(key); + if (expectedValue == actualValue) { + continue; + } + String fullKey = currentPath.isEmpty() ? key : currentPath + "." + key; + if (expectedValue instanceof JSONObject) { + assertWithMessage("key is '" + fullKey + "'") + .that(actualValue) + .isInstanceOf(JSONObject.class); + assertJsonEquals((JSONObject) expectedValue, (JSONObject) actualValue, fullKey); + } else { + assertWithMessage("key is '" + fullKey + "'") + .that(actualValue) + .isEqualTo(expectedValue); + } + } + } + + static Set<String> jsonKeys(JSONObject json) throws JSONException { + Set<String> result = new HashSet<>(); + + Iterator<String> keys = json.keys(); + + while (keys.hasNext()) { + String key = keys.next(); + result.add(key); + } + + return result; + } + + // Mocks make life downstream miserable so use a custom mock-like class. + public static class MockCronetBuilderImpl extends ICronetEngineBuilder { + public ConnectionMigrationOptions mConnectionMigrationOptions; + public String mEffectiveExperimentalOptions; + + private String mTempExperimentalOptions; + + private final boolean mSupportsConnectionMigrationConfigOption; + + static MockCronetBuilderImpl withNativeSetterSupport() { + return new MockCronetBuilderImpl(true); + } + + public static MockCronetBuilderImpl withoutNativeSetterSupport() { + return new MockCronetBuilderImpl(false); + } + + private MockCronetBuilderImpl(boolean supportsConnectionMigrationConfigOption) { + this.mSupportsConnectionMigrationConfigOption = supportsConnectionMigrationConfigOption; + } + + @Override + public ICronetEngineBuilder addPublicKeyPins( + String hostName, + Set<byte[]> pinsSha256, + boolean includeSubdomains, + Date expirationDate) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder addQuicHint(String host, int port, int alternatePort) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder enableHttp2(boolean value) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder enableHttpCache(int cacheMode, long maxSize) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder enablePublicKeyPinningBypassForLocalTrustAnchors( + boolean value) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder enableQuic(boolean value) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder enableSdch(boolean value) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder setExperimentalOptions(String options) { + mTempExperimentalOptions = options; + return this; + } + + @Override + public ICronetEngineBuilder setLibraryLoader(CronetEngine.Builder.LibraryLoader loader) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder setStoragePath(String value) { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder setUserAgent(String userAgent) { + throw new UnsupportedOperationException(); + } + + @Override + public String getDefaultUserAgent() { + throw new UnsupportedOperationException(); + } + + @Override + public ICronetEngineBuilder setConnectionMigrationOptions( + ConnectionMigrationOptions options) { + mConnectionMigrationOptions = options; + return this; + } + + @Override + public Set<Integer> getSupportedConfigOptions() { + if (mSupportsConnectionMigrationConfigOption) { + return Collections.singleton(ICronetEngineBuilder.CONNECTION_MIGRATION_OPTIONS); + } else { + return Collections.emptySet(); + } + } + + @Override + public ExperimentalCronetEngine build() { + mEffectiveExperimentalOptions = mTempExperimentalOptions; + return null; + } + } +}
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapperTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapperTest.java new file mode 100644 index 0000000..fbb0ccf --- /dev/null +++ b/components/cronet/android/test/javatests/src/org/chromium/net/impl/AndroidHttpEngineBuilderWrapperTest.java
@@ -0,0 +1,234 @@ +// 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. + +package org.chromium.net.impl; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.TruthJUnit.assume; + +import static org.chromium.net.ExperimentalOptionsTranslationTestUtil.assertJsonEquals; +import static org.chromium.net.impl.AndroidHttpEngineBuilderWrapper.parseConnectionMigrationOptions; + +import android.content.Context; +import android.net.http.HttpEngine; +import android.os.Build; + +import androidx.annotation.OptIn; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.Batch; +import org.chromium.net.CronetEngine; +import org.chromium.net.ExperimentalOptionsTranslationTestUtil.MockCronetBuilderImpl; +import org.chromium.net.telemetry.ExperimentalOptions; + +@Batch(Batch.UNIT_TESTS) +@RunWith(AndroidJUnit4.class) +@OptIn(markerClass = {org.chromium.net.ConnectionMigrationOptions.Experimental.class}) +public class AndroidHttpEngineBuilderWrapperTest { + private static final String EXPECTED_EARLY_MIGRATION_ENABLED_STRING = + "{\"QUIC\":{\"allow_port_migration\":true,\"migrate_sessions_early_v2\":true,\"migrate_" + + "sessions_on_network_change_v2\":true}}"; + + @Before + public void setUp() { + assume().that(Build.VERSION.SDK_INT).isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); + } + + // These options have a 1:1 mapping from the jsonOption to the ConnectionMigrationOption. So + // we are just testing that the values of ConnectionMigration are properly propagated. + + @Test + @SmallTest + public void testParseConnectionMigrationOptions_returnsCorrectValues() { + ExperimentalOptions options = + new ExperimentalOptions( + "{\"QUIC\":{\"migrate_sessions_on_network_change_v2\":true," + + " \"allow_port_migration\":false}}"); + + android.net.http.ConnectionMigrationOptions CMOptions = + parseConnectionMigrationOptions(options); + assertThat(CMOptions.getDefaultNetworkMigration()) + .isEqualTo(android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_ENABLED); + assertThat(CMOptions.getPathDegradationMigration()) + .isEqualTo(android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_DISABLED); + assertThat(CMOptions.getAllowNonDefaultNetworkUsage()) + .isEqualTo( + android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_UNSPECIFIED); + } + + // ----------------------------- + // ConnectionMigrationOptions configuration does not allow enabling early_migration without + // port_migration ie allowNonDefaultNetworkUsage requires PathDegradationMigration. So + // setting migrate_sessions_early_v2 also turns on port migration. These tests below confirm + // that + // both options are populated and being translated back to json correctly. + + @Test + @SmallTest + public void testSetExperimentalOption_connectionMigrationOptions_justEarlyMigration() { + MockCronetBuilderImpl mockBuilderImpl = MockCronetBuilderImpl.withoutNativeSetterSupport(); + AndroidHttpEngineBuilderWrapper httpEngineBuilder = + new AndroidHttpEngineBuilderWrapper( + new ApiHelper.MockHttpEngineBuilder( + ApplicationProvider.getApplicationContext(), + new CronetEngine.Builder(mockBuilderImpl))); + + httpEngineBuilder.setExperimentalOptions("{\"QUIC\":{\"migrate_sessions_early_v2\":true}}"); + httpEngineBuilder.build(); + + assertThat(mockBuilderImpl.mConnectionMigrationOptions).isNull(); + assertJsonEquals( + EXPECTED_EARLY_MIGRATION_ENABLED_STRING, + mockBuilderImpl.mEffectiveExperimentalOptions); + } + + @Test + @SmallTest + public void + testSetExperimentalOption_connectionMigrationOptions_bothPortAndEarlyMigrationTrue() { + MockCronetBuilderImpl mockBuilderImpl = MockCronetBuilderImpl.withoutNativeSetterSupport(); + AndroidHttpEngineBuilderWrapper httpEngineBuilder = + new AndroidHttpEngineBuilderWrapper( + new ApiHelper.MockHttpEngineBuilder( + ApplicationProvider.getApplicationContext(), + new CronetEngine.Builder(mockBuilderImpl))); + + httpEngineBuilder.setExperimentalOptions( + "{\"QUIC\":{\"allow_port_migration\":true, \"migrate_sessions_early_v2\":true}}"); + httpEngineBuilder.build(); + + assertThat(mockBuilderImpl.mConnectionMigrationOptions).isNull(); + assertJsonEquals( + EXPECTED_EARLY_MIGRATION_ENABLED_STRING, + mockBuilderImpl.mEffectiveExperimentalOptions); + } + + @Test + @SmallTest + public void + testSetExperimentalOption_connectionMigrationOptions_portAndEarlyMigrationFalseTrue() { + MockCronetBuilderImpl mockBuilderImpl = MockCronetBuilderImpl.withoutNativeSetterSupport(); + AndroidHttpEngineBuilderWrapper httpEngineBuilder = + new AndroidHttpEngineBuilderWrapper( + new ApiHelper.MockHttpEngineBuilder( + ApplicationProvider.getApplicationContext(), + new CronetEngine.Builder(mockBuilderImpl))); + + httpEngineBuilder.setExperimentalOptions( + "{\"QUIC\":{\"allow_port_migration\":false, \"migrate_sessions_early_v2\":true}}"); + httpEngineBuilder.build(); + + assertThat(mockBuilderImpl.mConnectionMigrationOptions).isNull(); + assertJsonEquals( + EXPECTED_EARLY_MIGRATION_ENABLED_STRING, + mockBuilderImpl.mEffectiveExperimentalOptions); + } + + @Test + @SmallTest + public void + testSetExperimentalOption_connectionMigrationOptions_bothPortAndEarlyMigrationFalse() { + MockCronetBuilderImpl mockBuilderImpl = MockCronetBuilderImpl.withoutNativeSetterSupport(); + AndroidHttpEngineBuilderWrapper httpEngineBuilder = + new AndroidHttpEngineBuilderWrapper( + new ApiHelper.MockHttpEngineBuilder( + ApplicationProvider.getApplicationContext(), + new CronetEngine.Builder(mockBuilderImpl))); + + httpEngineBuilder.setExperimentalOptions( + "{\"QUIC\":{\"allow_port_migration\":false, \"migrate_sessions_early_v2\":false}}"); + httpEngineBuilder.build(); + + assertThat(mockBuilderImpl.mConnectionMigrationOptions).isNull(); + assertJsonEquals( + "{\"QUIC\":{\"allow_port_migration\":false, \"migrate_sessions_early_v2\":false}}", + mockBuilderImpl.mEffectiveExperimentalOptions); + } + + @Test + @SmallTest + public void + testSetExperimentalOption_connectionMigrationOptions_portAndEarlyMigrationTrueFalse() { + MockCronetBuilderImpl mockBuilderImpl = MockCronetBuilderImpl.withoutNativeSetterSupport(); + AndroidHttpEngineBuilderWrapper httpEngineBuilder = + new AndroidHttpEngineBuilderWrapper( + new ApiHelper.MockHttpEngineBuilder( + ApplicationProvider.getApplicationContext(), + new CronetEngine.Builder(mockBuilderImpl))); + + httpEngineBuilder.setExperimentalOptions( + "{\"QUIC\":{\"allow_port_migration\":true, \"migrate_sessions_early_v2\":false}}"); + httpEngineBuilder.build(); + + assertThat(mockBuilderImpl.mConnectionMigrationOptions).isNull(); + assertJsonEquals( + "{\"QUIC\":{\"allow_port_migration\":true, \"migrate_sessions_early_v2\":false}}", + mockBuilderImpl.mEffectiveExperimentalOptions); + } + + // ------------ End migrate_sessions_early_v2 specific tests ------------------- + + /** + * JUnit uses reflection to fetch the TestClass's annotation and parameter types. Hence fails + * when it can't find android.net.http.* class for Android T- devices. This class abstracts the + * U+ methods away from JUnit, allowing us to compile. + */ + private static class ApiHelper { + public static class MockHttpEngineBuilder extends HttpEngine.Builder { + private final CronetEngine.Builder mBackend; + + public MockHttpEngineBuilder(Context context, CronetEngine.Builder backend) { + super(context); + mBackend = backend; + } + + @Override + public HttpEngine.Builder setConnectionMigrationOptions( + android.net.http.ConnectionMigrationOptions options) { + org.chromium.net.ConnectionMigrationOptions.Builder optionsBuilder = + org.chromium.net.ConnectionMigrationOptions.builder(); + + Boolean pathDegradationValue = + stateToBoolean(options.getPathDegradationMigration()); + if (pathDegradationValue != null) { + optionsBuilder.enablePathDegradationMigration(pathDegradationValue); + } + + Boolean allowNonDefaultNetworkUsage = + stateToBoolean(options.getAllowNonDefaultNetworkUsage()); + if (allowNonDefaultNetworkUsage != null) { + optionsBuilder.allowNonDefaultNetworkUsage(allowNonDefaultNetworkUsage); + } + + mBackend.setConnectionMigrationOptions(optionsBuilder.build()); + return this; + } + + @Override + public HttpEngine build() { + mBackend.build(); + return null; + } + + private static Boolean stateToBoolean(int optionState) { + switch (optionState) { + case android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_ENABLED: + return true; + case android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_DISABLED: + return false; + case android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_UNSPECIFIED: + return null; + default: + throw new AssertionError("Unknown state option"); + } + } + } + } +}
diff --git a/components/cronet/host_cache_persistence_manager_unittest.cc b/components/cronet/host_cache_persistence_manager_unittest.cc index 0c598d09..1eec3359 100644 --- a/components/cronet/host_cache_persistence_manager_unittest.cc +++ b/components/cronet/host_cache_persistence_manager_unittest.cc
@@ -22,7 +22,7 @@ class HostCachePersistenceManagerTest : public testing::Test { protected: void SetUp() override { - cache_ = net::HostCache::CreateDefaultCache(); + cache_ = std::make_unique<net::HostCache>(/*max_entries=*/1000); pref_service_ = std::make_unique<TestingPrefServiceSimple>(); pref_service_->registry()->RegisterListPref(kPrefName); }
diff --git a/components/enterprise/buildflags/BUILD.gn b/components/enterprise/buildflags/BUILD.gn index a61ff8b..86c2f18b 100644 --- a/components/enterprise/buildflags/BUILD.gn +++ b/components/enterprise/buildflags/BUILD.gn
@@ -14,5 +14,6 @@ "ENTERPRISE_CONTENT_ANALYSIS=$enterprise_content_analysis", "ENTERPRISE_DATA_CONTROLS=$enterprise_data_controls", "ENTERPRISE_CLIENT_CERTIFICATES=$enterprise_client_certificates", + "ENTERPRISE_WATERMARK=$enterprise_watermark", ] }
diff --git a/components/enterprise/buildflags/buildflags.gni b/components/enterprise/buildflags/buildflags.gni index cbfe329..7983af0e 100644 --- a/components/enterprise/buildflags/buildflags.gni +++ b/components/enterprise/buildflags/buildflags.gni
@@ -26,7 +26,8 @@ enterprise_client_certificates = is_win || is_mac # The watermark is currently implemented using the views framework - enterprise_watermark = toolkit_views + enterprise_watermark = + toolkit_views && (is_win || is_mac || is_linux || is_chromeos) } declare_args() {
diff --git a/components/enterprise/client_certificates/core/certificate_store.cc b/components/enterprise/client_certificates/core/certificate_store.cc index 31ad1d8..8814596 100644 --- a/components/enterprise/client_certificates/core/certificate_store.cc +++ b/components/enterprise/client_certificates/core/certificate_store.cc
@@ -71,6 +71,14 @@ std::move(callback).Run(std::nullopt); } +void SetCertificate(client_certificates_pb::ClientIdentity& proto_identity, + net::X509Certificate& certificate) { + base::Pickle pickle; + certificate.Persist(&pickle); + *proto_identity.mutable_certificate() = + std::string(pickle.data_as_char(), pickle.size()); +} + } // namespace class CertificateStoreImpl : public CertificateStore { @@ -90,6 +98,11 @@ const std::string& identity_name, scoped_refptr<net::X509Certificate> certificate, base::OnceCallback<void(std::optional<StoreError>)> callback) override; + void CommitIdentity( + const std::string& temporary_identity_name, + const std::string& final_identity_name, + scoped_refptr<net::X509Certificate> certificate, + base::OnceCallback<void(std::optional<StoreError>)> callback) override; void GetIdentity( const std::string& identity_name, base::OnceCallback<void(StoreErrorOr<std::optional<ClientIdentity>>)> @@ -143,6 +156,13 @@ base::OnceCallback<void(std::optional<StoreError>)> callback, StoreErrorOr<std::unique_ptr<client_certificates_pb::ClientIdentity>> proto_identity); + void CommitIdentityInner( + const std::string& temporary_identity_name, + const std::string& final_identity_name, + scoped_refptr<net::X509Certificate> certificate, + base::OnceCallback<void(std::optional<StoreError>)> callback, + StoreErrorOr<std::unique_ptr<client_certificates_pb::ClientIdentity>> + proto_identity); void GetIdentityInner( const std::string& identity_name, base::OnceCallback<void(StoreErrorOr<std::optional<ClientIdentity>>)> @@ -246,6 +266,19 @@ std::move(certificate), std::move(callback))); } +void CertificateStoreImpl::CommitIdentity( + const std::string& temporary_identity_name, + const std::string& final_identity_name, + scoped_refptr<net::X509Certificate> certificate, + base::OnceCallback<void(std::optional<StoreError>)> callback) { + WaitForInitializationAndGetIdentityProto( + temporary_identity_name, + base::BindOnce(&CertificateStoreImpl::CommitIdentityInner, + weak_factory_.GetWeakPtr(), temporary_identity_name, + final_identity_name, std::move(certificate), + std::move(callback))); +} + void CertificateStoreImpl::GetIdentity( const std::string& identity_name, base::OnceCallback<void(StoreErrorOr<std::optional<ClientIdentity>>)> @@ -412,10 +445,7 @@ } // Add cert to proto_identity, and save it to DB. - base::Pickle pickle; - certificate->Persist(&pickle); - *local_proto_identity->mutable_certificate() = - std::string(pickle.data_as_char(), pickle.size()); + SetCertificate(*local_proto_identity, *certificate); auto entries_to_save = std::make_unique<leveldb_proto::ProtoDatabase< client_certificates_pb::ClientIdentity>::KeyEntryVector>(); @@ -428,6 +458,48 @@ base::BindOnce(OnCertificateCommitted, std::move(callback))); } +void CertificateStoreImpl::CommitIdentityInner( + const std::string& temporary_identity_name, + const std::string& final_identity_name, + scoped_refptr<net::X509Certificate> certificate, + base::OnceCallback<void(std::optional<StoreError>)> callback, + StoreErrorOr<std::unique_ptr<client_certificates_pb::ClientIdentity>> + proto_identity) { + if (!proto_identity.has_value()) { + std::move(callback).Run(proto_identity.error()); + return; + } + + if (!certificate) { + std::move(callback).Run(StoreError::kInvalidCertificateInput); + return; + } + + if (final_identity_name.empty()) { + std::move(callback).Run(StoreError::kInvalidFinalIdentityName); + return; + } + + auto& local_proto_identity = proto_identity.value(); + if (!local_proto_identity) { + std::move(callback).Run(StoreError::kIdentityNotFound); + return; + } + + SetCertificate(*local_proto_identity, *certificate); + + auto entries_to_save = std::make_unique<leveldb_proto::ProtoDatabase< + client_certificates_pb::ClientIdentity>::KeyEntryVector>(); + entries_to_save->push_back({final_identity_name, *local_proto_identity}); + + auto entries_to_remove = std::make_unique<std::vector<std::string>>(); + entries_to_remove->push_back(temporary_identity_name); + + database_->UpdateEntries( + std::move(entries_to_save), std::move(entries_to_remove), + base::BindOnce(OnCertificateCommitted, std::move(callback))); +} + void CertificateStoreImpl::GetIdentityInner( const std::string& identity_name, base::OnceCallback<void(StoreErrorOr<std::optional<ClientIdentity>>)>
diff --git a/components/enterprise/client_certificates/core/certificate_store.h b/components/enterprise/client_certificates/core/certificate_store.h index 76708a4..64c5161 100644 --- a/components/enterprise/client_certificates/core/certificate_store.h +++ b/components/enterprise/client_certificates/core/certificate_store.h
@@ -68,11 +68,25 @@ // Will store the given `certificate` in the database under `identity_name`. // Will call `callback` with std::nullopt if successful, or an error if not. + // This API can be used to update an expired certificate without changing + // the existing private key. virtual void CommitCertificate( const std::string& identity_name, scoped_refptr<net::X509Certificate> certificate, base::OnceCallback<void(std::optional<StoreError>)> callback) = 0; + // Will move the private key with name `temporary_identity_name` and move + // it into `final_identity_name` alongside the given `certificate`. + // Will overwrite any pre-existing identity stored under + // `final_identity_name`. Will call `callback` with std::nullopt if + // successful, or an error if not. This API can be used as the last step in + // committing an updated identity when the private key needed to be rotated. + virtual void CommitIdentity( + const std::string& temporary_identity_name, + const std::string& final_identity_name, + scoped_refptr<net::X509Certificate> certificate, + base::OnceCallback<void(std::optional<StoreError>)> callback) = 0; + // Will attempt to retrieve an identity with name `identity_name` from the // database and load it into memory. Will return the loaded identity via // `callback`. Will invoke `callback` with std::nullopt if the identity
diff --git a/components/enterprise/client_certificates/core/certificate_store_unittest.cc b/components/enterprise/client_certificates/core/certificate_store_unittest.cc index b8f0cdb..4a8d90c 100644 --- a/components/enterprise/client_certificates/core/certificate_store_unittest.cc +++ b/components/enterprise/client_certificates/core/certificate_store_unittest.cc
@@ -41,7 +41,7 @@ namespace { constexpr char kTestIdentityName[] = "identity_name"; -// constexpr char kOtherTestIdentityName[] = "other_identity_name"; +constexpr char kOtherTestIdentityName[] = "other_identity_name"; constexpr char kFakeWrappedValue[] = "some_wrapped_value"; @@ -382,6 +382,154 @@ EXPECT_EQ(test_future.Get(), StoreError::kCertificateCommitFailed); } +// Tests that an existing private key is moved and a certificate can be saved +// to the database. +TEST_F(CertificateStoreTest, CommitIdentity_SuccessWithPrivateKey) { + client_certificates_pb::PrivateKey proto_key = CreateFakeProtoKey(); + client_certificates_pb::ClientIdentity proto_identity; + *proto_identity.mutable_private_key() = proto_key; + AddDatabaseEntry(kOtherTestIdentityName, proto_identity); + + auto test_cert = LoadTestCert(); + + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity(kOtherTestIdentityName, kTestIdentityName, test_cert, + test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kOK); + fake_db_->GetCallback(/*success=*/true); + fake_db_->UpdateCallback(/*success=*/true); + + EXPECT_EQ(test_future.Get(), std::nullopt); + + PersistCertificate(proto_identity, test_cert); + ExpectDatabaseEntry(kTestIdentityName, proto_identity); + ExpectNoDatabaseEntry(kOtherTestIdentityName); +} + +// Tests that a certificate cannot be saved to the database when the temporary +// identity does not already exist in the database. +TEST_F(CertificateStoreTest, CommitIdentity_FailWithoutIdentity) { + auto test_cert = LoadTestCert(); + + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity(kOtherTestIdentityName, kTestIdentityName, test_cert, + test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kOK); + fake_db_->GetCallback(/*success=*/true); + + EXPECT_EQ(test_future.Get(), StoreError::kIdentityNotFound); + + ExpectNoDatabaseEntry(kTestIdentityName); + ExpectNoDatabaseEntry(kOtherTestIdentityName); +} + +// Tests that a certificate won't be saved to the database when the temporary +// identity name is invalid. +TEST_F(CertificateStoreTest, CommitIdentity_InvalidTemporaryIdentityNameFail) { + auto test_cert = LoadTestCert(); + + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity("", kTestIdentityName, test_cert, + test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kOK); + + EXPECT_EQ(test_future.Get(), StoreError::kInvalidIdentityName); + ExpectNoDatabaseEntry(""); + ExpectNoDatabaseEntry(kTestIdentityName); +} + +// Tests that a certificate won't be saved to the database when the database +// initialization failed. +TEST_F(CertificateStoreTest, CommitIdentity_DatabaseInitFail) { + auto test_cert = LoadTestCert(); + + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity(kOtherTestIdentityName, kTestIdentityName, test_cert, + test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kCorrupt); + + EXPECT_EQ(test_future.Get(), StoreError::kInvalidDatabaseState); + ExpectNoDatabaseEntry(kOtherTestIdentityName); + ExpectNoDatabaseEntry(kTestIdentityName); +} + +// Tests that a certificate won't be saved to the database when failing to "get" +// from the database. +TEST_F(CertificateStoreTest, CommitIdentity_GetIdentityFail) { + auto test_cert = LoadTestCert(); + + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity(kOtherTestIdentityName, kTestIdentityName, test_cert, + test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kOK); + fake_db_->GetCallback(/*success=*/false); + + EXPECT_EQ(test_future.Get(), StoreError::kGetDatabaseEntryFailed); + ExpectNoDatabaseEntry(kOtherTestIdentityName); + ExpectNoDatabaseEntry(kTestIdentityName); +} + +// Tests that a certificate won't be saved to the database when the given +// certificate instance is invalid (nullptr). +TEST_F(CertificateStoreTest, CommitIdentity_InvalidCertificateFail) { + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity(kOtherTestIdentityName, kTestIdentityName, + /*certificate=*/nullptr, test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kOK); + fake_db_->GetCallback(/*success=*/true); + + EXPECT_EQ(test_future.Get(), StoreError::kInvalidCertificateInput); + ExpectNoDatabaseEntry(kOtherTestIdentityName); + ExpectNoDatabaseEntry(kTestIdentityName); +} + +// Tests that a certificate won't be saved to the database when the given +// certificate instance is invalid (nullptr). +TEST_F(CertificateStoreTest, CommitIdentity_InvalidFinalNameFail) { + auto test_cert = LoadTestCert(); + + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity(kOtherTestIdentityName, "", test_cert, + test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kOK); + fake_db_->GetCallback(/*success=*/true); + + EXPECT_EQ(test_future.Get(), StoreError::kInvalidFinalIdentityName); + ExpectNoDatabaseEntry(kOtherTestIdentityName); + ExpectNoDatabaseEntry(kTestIdentityName); +} + +// Tests that a certificate won't be saved to the database when failing to +// "update" the database. +TEST_F(CertificateStoreTest, CommitIdentity_UpdateFail) { + client_certificates_pb::PrivateKey proto_key = CreateFakeProtoKey(); + client_certificates_pb::ClientIdentity proto_identity; + *proto_identity.mutable_private_key() = proto_key; + AddDatabaseEntry(kOtherTestIdentityName, proto_identity); + + auto test_cert = LoadTestCert(); + + base::test::TestFuture<std::optional<StoreError>> test_future; + store_->CommitIdentity(kOtherTestIdentityName, kTestIdentityName, test_cert, + test_future.GetCallback()); + + fake_db_->InitStatusCallback(InitStatus::kOK); + fake_db_->GetCallback(/*success=*/true); + fake_db_->UpdateCallback(/*success=*/false); + + // Not checking the mocked database's state, as the mock behaves as if the + // update succeeded, but in this test case it was mocked to fail - so we can + // assume it failed. + EXPECT_EQ(test_future.Get(), StoreError::kCertificateCommitFailed); +} + // Tests that an identity stored in the database with a private key and // certificate can be properly loaded into memory and returned. TEST_F(CertificateStoreTest, GetIdentity_FullIdentitySuccess) {
diff --git a/components/enterprise/client_certificates/core/mock_certificate_store.h b/components/enterprise/client_certificates/core/mock_certificate_store.h index e1601b1b..42270aad 100644 --- a/components/enterprise/client_certificates/core/mock_certificate_store.h +++ b/components/enterprise/client_certificates/core/mock_certificate_store.h
@@ -32,6 +32,13 @@ scoped_refptr<net::X509Certificate>, base::OnceCallback<void(std::optional<StoreError>)>), (override)); + MOCK_METHOD(void, + CommitIdentity, + (const std::string&, + const std::string&, + scoped_refptr<net::X509Certificate>, + base::OnceCallback<void(std::optional<StoreError>)>), + (override)); MOCK_METHOD( void, GetIdentity,
diff --git a/components/enterprise/client_certificates/core/store_error.h b/components/enterprise/client_certificates/core/store_error.h index 4bb1667c..eb76f3d 100644 --- a/components/enterprise/client_certificates/core/store_error.h +++ b/components/enterprise/client_certificates/core/store_error.h
@@ -20,7 +20,9 @@ kInvalidCertificateInput = 7, kCertificateCommitFailed = 8, kLoadKeyFailed = 9, - kMaxValue = kLoadKeyFailed + kInvalidFinalIdentityName = 10, + kIdentityNotFound = 11, + kMaxValue = kIdentityNotFound }; template <class T>
diff --git a/components/facilitated_payments/content/renderer/BUILD.gn b/components/facilitated_payments/content/renderer/BUILD.gn index 4132934..3d511d3d 100644 --- a/components/facilitated_payments/content/renderer/BUILD.gn +++ b/components/facilitated_payments/content/renderer/BUILD.gn
@@ -11,6 +11,7 @@ deps = [ "//base", "//components/facilitated_payments/core/mojom", + "//components/facilitated_payments/core/util", "//content/public/renderer", "//third_party/blink/public:blink_headers", "//third_party/blink/public/common",
diff --git a/components/facilitated_payments/content/renderer/facilitated_payments_agent.cc b/components/facilitated_payments/content/renderer/facilitated_payments_agent.cc index 98c4647..04370943 100644 --- a/components/facilitated_payments/content/renderer/facilitated_payments_agent.cc +++ b/components/facilitated_payments/content/renderer/facilitated_payments_agent.cc
@@ -8,7 +8,9 @@ #include "base/location.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" +#include "components/facilitated_payments/core/util/pix_code_validator.h" #include "content/public/renderer/render_frame.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/platform/web_string.h" @@ -39,10 +41,10 @@ blink::WebString result = render_frame()->GetWebFrame()->GetDocument().FindTextInElementWith( blink::WebString(kPixCodeIdentifier)); - std::u16string trimmed = std::u16string( + std::string trimmed = base::UTF16ToUTF8( base::TrimWhitespace(result.Utf16(), base::TrimPositions::TRIM_ALL)); - std::move(callback).Run(/*found_pix_code=*/!trimmed.empty()); + std::move(callback).Run(/*found_pix_code=*/IsValidPixCode(trimmed)); } void FacilitatedPaymentsAgent::OnDestruct() {
diff --git a/components/facilitated_payments/content/renderer/facilitated_payments_agent_browsertest.cc b/components/facilitated_payments/content/renderer/facilitated_payments_agent_browsertest.cc index a2d785e..b94b34d 100644 --- a/components/facilitated_payments/content/renderer/facilitated_payments_agent_browsertest.cc +++ b/components/facilitated_payments/content/renderer/facilitated_payments_agent_browsertest.cc
@@ -50,7 +50,7 @@ EXPECT_TRUE(IsPixCodeFound(CreateAgentFor(R"( <body> <div> - ABC0014br.gov.bcb.pixXYZ + 00020126180014br.gov.bcb.pix63041D3D </div> </form> )").get())); @@ -61,7 +61,7 @@ std::unique_ptr<FacilitatedPaymentsAgent> agent = CreateAgentFor(R"( <body> <div> - ABC0014br.gov.bcb.pixXYZ + 00020126180014br.gov.bcb.pix63041D3D </div> </form> )");
diff --git a/components/facilitated_payments/core/util/BUILD.gn b/components/facilitated_payments/core/util/BUILD.gn new file mode 100644 index 0000000..4c709e1 --- /dev/null +++ b/components/facilitated_payments/core/util/BUILD.gn
@@ -0,0 +1,41 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/sanitizers/sanitizers.gni") +import("//testing/test.gni") + +static_library("util") { + sources = [ + "pix_code_validator.cc", + "pix_code_validator.h", + ] + + deps = [ + "//base", + "//third_party/re2", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "pix_code_validator_unittest.cc" ] + + deps = [ + ":util", + "//testing/gtest", + ] +} + +if (fuzztest_supported) { + test("pix_code_validator_fuzzer") { + sources = [ "pix_code_validator_fuzzer.cc" ] + + testonly = true + + deps = [ + ":util", + "//third_party/fuzztest:fuzztest_gtest_main", + ] + } +}
diff --git a/components/facilitated_payments/core/util/DEPS b/components/facilitated_payments/core/util/DEPS new file mode 100644 index 0000000..c6765d78 --- /dev/null +++ b/components/facilitated_payments/core/util/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+third_party/fuzztest", + "+third_party/re2", +]
diff --git a/components/facilitated_payments/core/util/pix_code_validator.cc b/components/facilitated_payments/core/util/pix_code_validator.cc new file mode 100644 index 0000000..1d486bff --- /dev/null +++ b/components/facilitated_payments/core/util/pix_code_validator.cc
@@ -0,0 +1,136 @@ +// 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 "components/facilitated_payments/core/util/pix_code_validator.h" + +#include "base/notreached.h" +#include "base/strings/string_number_conversions.h" +#include "third_party/re2/src/re2/re2.h" + +namespace payments::facilitated { +namespace { + +constexpr char kSectionIdAndSizePattern[] = "\\d\\d\\d\\d"; +constexpr char kPayloadFormatIndicatorFirstSectionId[] = "00"; +constexpr char kMerchantAccountInformationSectionId[] = "26"; +constexpr char kAdditionalDataFieldTemplateSectionId[] = "62"; +constexpr char kCrc16LastSectionId[] = "63"; +constexpr char kPixCodeIndicator[] = "0014br.gov.bcb.pix"; + +struct SectionInfo { + std::string_view section_id; + std::string_view section_value; + std::string::size_type section_end = 0; +}; + +// Returns true if there is a valid PIX `code` section at the given `position`. +// A valid PIX code section comprises: +// 1) Two digits of section ID. +// 2) Two digits of section size |N|. +// 3) Section value of length |N|. +bool ParseNextSection(std::string::size_type position, + std::string_view code, + SectionInfo* section_info) { + constexpr std::string::size_type kSectionIdAndSizeLength = 4; + if (position + kSectionIdAndSizeLength > code.length()) { + return false; + } + + if (!re2::RE2::FullMatch(code.substr(position, kSectionIdAndSizeLength), + kSectionIdAndSizePattern)) { + return false; + } + + constexpr std::string::size_type kSectionIdLength = 2; + section_info->section_id = code.substr(position, kSectionIdLength); + + constexpr std::string::size_type kSectionSizeLength = 2; + std::string::size_type section_size = 0; + if (!base::StringToSizeT( + code.substr(position + kSectionIdLength, kSectionSizeLength), + §ion_size)) { + // This number parsing is always successful because of the regex pattern + // check above. + NOTREACHED(); + return false; + } + + section_info->section_end = position + kSectionIdAndSizeLength + section_size; + if (section_info->section_end > code.length()) { + return false; + } + + section_info->section_value = + code.substr(position + kSectionIdAndSizeLength, section_size); + + return true; +} + +// Returns true if the `input` string consists of valid PIX code sections. +bool ContainsValidSections(std::string_view input) { + if (input.empty()) { + return false; + } + + SectionInfo section_info; + for (std::string::size_type position = 0; position < input.length(); + position = section_info.section_end) { + if (!ParseNextSection(position, input, §ion_info)) { + return false; + } + } + + return true; +} + +} // namespace + +bool IsValidPixCode(std::string_view code) { + if (code.empty()) { + return false; + } + + SectionInfo section_info; + bool is_first_section = true; + bool contains_pix_code_indicator = false; + + for (std::string::size_type position = 0; position < code.length(); + position = section_info.section_end) { + if (!ParseNextSection(position, code, §ion_info)) { + return false; + } + + if (is_first_section) { + is_first_section = false; + if (section_info.section_id != kPayloadFormatIndicatorFirstSectionId) { + return false; + } + } + + if (section_info.section_id == kMerchantAccountInformationSectionId) { + if (!ContainsValidSections(section_info.section_value)) { + return false; + } + if (section_info.section_value.find(kPixCodeIndicator) != 0) { + return false; + } + contains_pix_code_indicator = true; + } + + if (section_info.section_id == kAdditionalDataFieldTemplateSectionId) { + if (!ContainsValidSections(section_info.section_value)) { + return false; + } + } + + if (section_info.section_end == code.length() && + section_info.section_id != kCrc16LastSectionId) { + return false; + } + } + + return contains_pix_code_indicator; +} + +} // namespace payments::facilitated
diff --git a/components/facilitated_payments/core/util/pix_code_validator.h b/components/facilitated_payments/core/util/pix_code_validator.h new file mode 100644 index 0000000..8d8e27a --- /dev/null +++ b/components/facilitated_payments/core/util/pix_code_validator.h
@@ -0,0 +1,26 @@ +// 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 COMPONENTS_FACILITATED_PAYMENTS_CORE_UTIL_PIX_CODE_VALIDATOR_H_ +#define COMPONENTS_FACILITATED_PAYMENTS_CORE_UTIL_PIX_CODE_VALIDATOR_H_ + +#include <string> + +namespace payments::facilitated { + +// Returns true if the input `code` is a valid PIX code, i.e.: +// 1) It consists of valid PIX code sections. +// 2) The first section is the payload format indicator. +// 3) The last section is the CRC16. +// 4) The merchant account information section contains valid subsections, +// including the PIX code indicator as the first subsection. +// 5) The additional data field template section, if present, contains valid +// subsections. +// +// This function does not validate the value of the CRC16. +bool IsValidPixCode(std::string_view code); + +} // namespace payments::facilitated + +#endif // COMPONENTS_FACILITATED_PAYMENTS_CORE_UTIL_PIX_CODE_VALIDATOR_H_
diff --git a/components/facilitated_payments/core/util/pix_code_validator_fuzzer.cc b/components/facilitated_payments/core/util/pix_code_validator_fuzzer.cc new file mode 100644 index 0000000..c99715a --- /dev/null +++ b/components/facilitated_payments/core/util/pix_code_validator_fuzzer.cc
@@ -0,0 +1,33 @@ +// 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 <string> + +#include "components/facilitated_payments/core/util/pix_code_validator.h" +#include "third_party/fuzztest/src/fuzztest/fuzztest.h" + +namespace payments::facilitated { + +void IsValidPixCodeCanParseAnyString(const std::string& input) { + IsValidPixCode(input); +} + +FUZZ_TEST(IsValidPixCodeTest, IsValidPixCodeCanParseAnyString) + .WithDomains(fuzztest::Arbitrary<std::string>()) + .WithSeeds({{""}, + {"000201260063041D3D"}, + {"00020126030014br.gov.bcb.pix63041D3D"}, + {"00020126180014br.gov.bcb.pix620063041D3D"}, + {"00020126180014br.gov.bcb.pix630"}, + {"00020126180014br.gov.bcb.pix63041D3"}, + {"00020126180014br.gov.bcb.pix63041D3D"}, + {"00020126180014br.gov.bcb.PIX63041D3D"}, + {"00020126180014br.gov.bcb.pix63051D3D"}, + {"00020126180014br.gov.bcb.pix64041D3D"}, + {"000201261801020063041D3D"}, + {"00020163041D3D"}, + {"000A0126180014br.gov.bcb.pix63041D3D"}, + {"01020126180014br.gov.bcb.pix63041D3D"}}); + +} // namespace payments::facilitated
diff --git a/components/facilitated_payments/core/util/pix_code_validator_unittest.cc b/components/facilitated_payments/core/util/pix_code_validator_unittest.cc new file mode 100644 index 0000000..0954807d --- /dev/null +++ b/components/facilitated_payments/core/util/pix_code_validator_unittest.cc
@@ -0,0 +1,69 @@ +// 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 "components/facilitated_payments/core/util/pix_code_validator.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace payments::facilitated { +namespace { + +TEST(PixCodeValidatorTest, ValidCode) { + EXPECT_TRUE(IsValidPixCode("00020126180014br.gov.bcb.pix63041D3D")); +} + +TEST(PixCodeValidatorTest, EmptyStringNotValid) { + EXPECT_FALSE(IsValidPixCode("")); +} + +TEST(PixCodeValidatorTest, LastSectionLengthTooLong) { + EXPECT_FALSE(IsValidPixCode("00020126180014br.gov.bcb.pix63051D3D")); +} + +TEST(PixCodeValidatorTest, SectionHeaderIsNotADigit) { + EXPECT_FALSE(IsValidPixCode("000A0126180014br.gov.bcb.pix63041D3D")); +} + +TEST(PixCodeValidatorTest, SectionTruncatedTooShort) { + EXPECT_FALSE(IsValidPixCode("00020126180014br.gov.bcb.pix63041D3")); +} + +TEST(PixCodeValidatorTest, SectionHeaderTruncatedTooShort) { + EXPECT_FALSE(IsValidPixCode("00020126180014br.gov.bcb.pix630")); +} + +TEST(PixCodeValidatorTest, MerchantAccountInformationIsEmpty) { + EXPECT_FALSE(IsValidPixCode("000201260063041D3D")); +} + +TEST(PixCodeValidatorTest, MerchantAccountInformationIsNotValid) { + EXPECT_FALSE(IsValidPixCode("00020126030014br.gov.bcb.pix63041D3D")); +} + +TEST(PixCodeValidatorTest, InvalidPixCodeIndicator) { + EXPECT_FALSE(IsValidPixCode("00020126180014br.gov.bcb.PIX63041D3D")); +} + +TEST(PixCodeValidatorTest, EmptyAdditionalDataSection) { + EXPECT_FALSE(IsValidPixCode("00020126180014br.gov.bcb.pix620063041D3D")); +} + +TEST(PixCodeValidatorTest, LastSectionIdIsNotCrc16) { + EXPECT_FALSE(IsValidPixCode("00020126180014br.gov.bcb.pix64041D3D")); +} + +TEST(PixCodeValidatorTest, FirstSectionIsNotPayloadIndicator) { + EXPECT_FALSE(IsValidPixCode("01020126180014br.gov.bcb.pix63041D3D")); +} + +TEST(PixCodeValidatorTest, NoMerchantAccountInformationSection) { + EXPECT_FALSE(IsValidPixCode("00020163041D3D")); +} + +TEST(PixCodeValidatorTest, NoPixCodeIndicator) { + EXPECT_FALSE(IsValidPixCode("000201261801020063041D3D")); +} + +} // namespace +} // namespace payments::facilitated
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h index 5647c1e..78477e8 100644 --- a/components/feature_engagement/public/feature_list.h +++ b/components/feature_engagement/public/feature_list.h
@@ -260,7 +260,7 @@ DEFINE_VARIATION_PARAM(kIPHiOSShareToolbarItemFeature, "IPH_iOSShareToolbarItemFeature"); DEFINE_VARIATION_PARAM(kIPHiOSPromoPostRestoreDefaultBrowserFeature, - "IPH_iOSPromoPostDefaultBrowserRestore"); + "IPH_iOSPromoPostRestoreDefaultBrowser"); DEFINE_VARIATION_PARAM(kIPHiOSPromoPasswordManagerWidgetFeature, "IPH_iOSPromoPasswordManagerWidget"); DEFINE_VARIATION_PARAM(kIPHiOSChoiceScreenFeature,
diff --git a/components/history/core/browser/mojom/history_types.mojom b/components/history/core/browser/mojom/history_types.mojom index fa8b045..6da7e203 100644 --- a/components/history/core/browser/mojom/history_types.mojom +++ b/components/history/core/browser/mojom/history_types.mojom
@@ -22,9 +22,9 @@ // String to display. string title; - // Relative time in milliseconds. + // Time since tab was last active. mojo_base.mojom.TimeDelta relative_time; - // Relative time to display on UI (i.e. 2 hours ago) + // Relative time to display on UI (i.e. 2 hours ago). string relative_time_text; };
diff --git a/components/history_embeddings/BUILD.gn b/components/history_embeddings/BUILD.gn new file mode 100644 index 0000000..f66c1f44 --- /dev/null +++ b/components/history_embeddings/BUILD.gn
@@ -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. + +static_library("history_embeddings") { + sources = [ + "history_embeddings_features.cc", + "history_embeddings_features.h", + "history_embeddings_service.cc", + "history_embeddings_service.h", + ] + + deps = [ + "//base", + "//components/keyed_service/core", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "history_embeddings_service_unittest.cc" ] + deps = [ + ":history_embeddings", + "//base/test:test_support", + "//testing/gtest", + ] +}
diff --git a/components/history_embeddings/DEPS b/components/history_embeddings/DEPS new file mode 100644 index 0000000..f0bf3d9 --- /dev/null +++ b/components/history_embeddings/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/keyed_service/core", +]
diff --git a/components/history_embeddings/DIR_METADATA b/components/history_embeddings/DIR_METADATA new file mode 100644 index 0000000..328927d --- /dev/null +++ b/components/history_embeddings/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail { + component: "UI>Browser>HistoryEmbeddings" +}
diff --git a/components/history_embeddings/OWNERS b/components/history_embeddings/OWNERS new file mode 100644 index 0000000..634f10b --- /dev/null +++ b/components/history_embeddings/OWNERS
@@ -0,0 +1,3 @@ +mcrouse@chromium.org +tommycli@chromium.org +orinj@chromium.org
diff --git a/components/history_embeddings/README.md b/components/history_embeddings/README.md new file mode 100644 index 0000000..d84d744 --- /dev/null +++ b/components/history_embeddings/README.md
@@ -0,0 +1,3 @@ +# //components/history_embeddings + +Service implementation for history embeddings feature.
diff --git a/components/history_embeddings/history_embeddings_features.cc b/components/history_embeddings/history_embeddings_features.cc new file mode 100644 index 0000000..e6391c2 --- /dev/null +++ b/components/history_embeddings/history_embeddings_features.cc
@@ -0,0 +1,15 @@ +// 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 "components/history_embeddings/history_embeddings_features.h" + +#include "build/build_config.h" + +namespace history_embeddings { + +BASE_FEATURE(kHistoryEmbeddings, + "HistoryEmbeddings", + base::FEATURE_DISABLED_BY_DEFAULT); + +} // namespace history_embeddings
diff --git a/components/history_embeddings/history_embeddings_features.h b/components/history_embeddings/history_embeddings_features.h new file mode 100644 index 0000000..e5a1f25b --- /dev/null +++ b/components/history_embeddings/history_embeddings_features.h
@@ -0,0 +1,16 @@ +// 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 COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_FEATURES_H_ +#define COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_FEATURES_H_ + +#include "base/feature_list.h" + +namespace history_embeddings { + +BASE_DECLARE_FEATURE(kHistoryEmbeddings); + +} // namespace history_embeddings + +#endif // COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_FEATURES_H_
diff --git a/components/history_embeddings/history_embeddings_service.cc b/components/history_embeddings/history_embeddings_service.cc new file mode 100644 index 0000000..d4e5f36 --- /dev/null +++ b/components/history_embeddings/history_embeddings_service.cc
@@ -0,0 +1,14 @@ +// 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 "components/history_embeddings/history_embeddings_service.h" + +namespace history_embeddings { + +HistoryEmbeddingsService::HistoryEmbeddingsService() = default; +HistoryEmbeddingsService::~HistoryEmbeddingsService() = default; + +void HistoryEmbeddingsService::Shutdown() {} + +} // namespace history_embeddings
diff --git a/components/history_embeddings/history_embeddings_service.h b/components/history_embeddings/history_embeddings_service.h new file mode 100644 index 0000000..63e4df5c --- /dev/null +++ b/components/history_embeddings/history_embeddings_service.h
@@ -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. + +#ifndef COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_SERVICE_H_ +#define COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_SERVICE_H_ + +#include "components/keyed_service/core/keyed_service.h" + +namespace history_embeddings { + +class HistoryEmbeddingsService : public KeyedService { + public: + HistoryEmbeddingsService(); + HistoryEmbeddingsService(const HistoryEmbeddingsService&) = delete; + HistoryEmbeddingsService& operator=(const HistoryEmbeddingsService&) = delete; + ~HistoryEmbeddingsService() override; + + // KeyedService: + void Shutdown() override; +}; + +} // namespace history_embeddings + +#endif // COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_SERVICE_H_
diff --git a/components/history_embeddings/history_embeddings_service_unittest.cc b/components/history_embeddings/history_embeddings_service_unittest.cc new file mode 100644 index 0000000..6d224534 --- /dev/null +++ b/components/history_embeddings/history_embeddings_service_unittest.cc
@@ -0,0 +1,18 @@ +// 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 "components/history_embeddings/history_embeddings_service.h" + +#include <memory> + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace history_embeddings { + +TEST(HistoryEmbeddingsTest, Constructs) { + std::make_unique<HistoryEmbeddingsService>(); +} + +} // namespace history_embeddings
diff --git a/components/optimization_guide/core/model_execution/settings_enabled_observer.h b/components/optimization_guide/core/model_execution/settings_enabled_observer.h index 3e344a41..2728cb0 100644 --- a/components/optimization_guide/core/model_execution/settings_enabled_observer.h +++ b/components/optimization_guide/core/model_execution/settings_enabled_observer.h
@@ -22,7 +22,7 @@ // team should call `ShouldFeatureBeCurrentlyEnabledForUser` before displaying // any feature functionality. TODO(rajendrant): Remove this once all the // consumers stop using it. - virtual void PrepareToEnableOnRestart() = 0; + virtual void PrepareToEnableOnRestart() {} // Notifies the consumers whenever the feature enabled state is changed. // `is_now_enabled` indicates the current enabled state of the feature. This
diff --git a/components/password_manager/core/browser/features/password_manager_features_util.h b/components/password_manager/core/browser/features/password_manager_features_util.h index 3a0167a6..563136b 100644 --- a/components/password_manager/core/browser/features/password_manager_features_util.h +++ b/components/password_manager/core/browser/features/password_manager_features_util.h
@@ -78,7 +78,7 @@ // This doesn't necessarily mean the store is being used, e.g. this predicate // can return true for a signed-out user. For whether the store can be used, // see IsOptedInForAccountStorage() instead. -// TODO(crbug.com/1509058): Rename IsOptedInForAccountStorage() to +// TODO(b/324038136): Rename IsOptedInForAccountStorage() to // CanUseAccountStore() - there's no opt-in on mobile platforms anyway. Rename // CanAccountStorageBeEnabled() and IsUserEligibleForAccountStorage(). bool CanCreateAccountStore(const PrefService* pref_service);
diff --git a/components/password_manager/core/browser/features/password_manager_features_util_common.cc b/components/password_manager/core/browser/features/password_manager_features_util_common.cc index f7b884e..58b72e9 100644 --- a/components/password_manager/core/browser/features/password_manager_features_util_common.cc +++ b/components/password_manager/core/browser/features/password_manager_features_util_common.cc
@@ -24,8 +24,6 @@ const syncer::SyncService* sync_service) { CHECK(pref_service); - // TODO(crbug.com/1509058): Also, on Android the predicate should return true - // for syncing and false for signed-in non-syncing users. if (!CanCreateAccountStore(pref_service)) { return false; }
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index 5b4471ce..3a626f3 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -568,7 +568,6 @@ // fetch the actual password. See crbug.com/178358 for more context. bool item_uses_account_store = - popup_item_id == autofill::PopupItemId::kAccountStorageUsernameEntry || popup_item_id == autofill::PopupItemId::kAccountStoragePasswordEntry; // Look for any suitable matches to current field text.
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc index fb91f46..5e461a7 100644 --- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc +++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -482,9 +482,7 @@ ASSERT_GE(open_args.suggestions.size(), 1u); EXPECT_THAT( open_args.suggestions, - SuggestionVectorIdsAre(is_suggestion_on_password_field - ? autofill::PopupItemId::kPasswordEntry - : autofill::PopupItemId::kUsernameEntry, + SuggestionVectorIdsAre(autofill::PopupItemId::kPasswordEntry, #if !BUILDFLAG(IS_ANDROID) autofill::PopupItemId::kSeparator, #endif @@ -502,10 +500,7 @@ password_autofill_manager_->DidAcceptSuggestion( autofill::test::CreateAutofillSuggestion( - is_suggestion_on_password_field - ? autofill::PopupItemId::kPasswordEntry - : autofill::PopupItemId::kUsernameEntry, - test_username_), + autofill::PopupItemId::kPasswordEntry, test_username_), SuggestionPosition{.row = 1}); histograms.ExpectUniqueSample( @@ -563,12 +558,8 @@ ASSERT_GE(open_args.suggestions.size(), 2u); EXPECT_THAT(open_args.suggestions, SuggestionVectorIdsAre( - is_suggestion_on_password_field - ? autofill::PopupItemId::kPasswordEntry - : autofill::PopupItemId::kUsernameEntry, - is_suggestion_on_password_field - ? autofill::PopupItemId::kAccountStoragePasswordEntry - : autofill::PopupItemId::kAccountStorageUsernameEntry, + autofill::PopupItemId::kPasswordEntry, + autofill::PopupItemId::kAccountStoragePasswordEntry, #if !BUILDFLAG(IS_ANDROID) autofill::PopupItemId::kSeparator, #endif @@ -588,9 +579,7 @@ password_autofill_manager_->DidAcceptSuggestion( autofill::test::CreateAutofillSuggestion( - is_suggestion_on_password_field - ? autofill::PopupItemId::kAccountStoragePasswordEntry - : autofill::PopupItemId::kAccountStorageUsernameEntry, + autofill::PopupItemId::kAccountStoragePasswordEntry, test_username_), SuggestionPosition{.row = 0}); } @@ -1564,9 +1553,7 @@ ASSERT_GE(open_args.suggestions.size(), 1u); EXPECT_THAT( open_args.suggestions, - SuggestionVectorIdsAre(is_suggestion_on_password_field - ? autofill::PopupItemId::kPasswordEntry - : autofill::PopupItemId::kUsernameEntry, + SuggestionVectorIdsAre(autofill::PopupItemId::kPasswordEntry, #if !BUILDFLAG(IS_ANDROID) autofill::PopupItemId::kSeparator, #endif @@ -1627,9 +1614,7 @@ ASSERT_GE(open_args.suggestions.size(), 1u); EXPECT_THAT( open_args.suggestions, - SuggestionVectorIdsAre(is_suggestion_on_password_field - ? autofill::PopupItemId::kPasswordEntry - : autofill::PopupItemId::kUsernameEntry, + SuggestionVectorIdsAre(autofill::PopupItemId::kPasswordEntry, #if !BUILDFLAG(IS_ANDROID) autofill::PopupItemId::kSeparator, #endif @@ -1698,9 +1683,7 @@ ASSERT_GE(open_args.suggestions.size(), 1u); EXPECT_THAT( open_args.suggestions, - SuggestionVectorIdsAre(is_suggestion_on_password_field - ? autofill::PopupItemId::kPasswordEntry - : autofill::PopupItemId::kUsernameEntry, + SuggestionVectorIdsAre(autofill::PopupItemId::kPasswordEntry, #if !BUILDFLAG(IS_ANDROID) autofill::PopupItemId::kSeparator, #endif @@ -2045,7 +2028,7 @@ ASSERT_THAT(open_args.suggestions, SuggestionVectorIdsAre( autofill::PopupItemId::kWebauthnCredential, - autofill::PopupItemId::kUsernameEntry, + autofill::PopupItemId::kPasswordEntry, #if !BUILDFLAG(IS_ANDROID) autofill::PopupItemId::kWebauthnSignInWithAnotherDevice, autofill::PopupItemId::kSeparator, @@ -2120,7 +2103,7 @@ element_bounds); ASSERT_THAT(open_args.suggestions, SuggestionVectorIdsAre( - autofill::PopupItemId::kUsernameEntry, + autofill::PopupItemId::kPasswordEntry, autofill::PopupItemId::kWebauthnSignInWithAnotherDevice, autofill::PopupItemId::kSeparator, autofill::PopupItemId::kAllSavedPasswordsEntry)); @@ -2158,7 +2141,7 @@ element_bounds); ASSERT_THAT( open_args.suggestions, - SuggestionVectorIdsAre(autofill::PopupItemId::kUsernameEntry, + SuggestionVectorIdsAre(autofill::PopupItemId::kPasswordEntry, autofill::PopupItemId::kSeparator, autofill::PopupItemId::kAllSavedPasswordsEntry)); }
diff --git a/components/password_manager/core/browser/password_feature_manager_impl_unittest.cc b/components/password_manager/core/browser/password_feature_manager_impl_unittest.cc index 262750e..5dc5664 100644 --- a/components/password_manager/core/browser/password_feature_manager_impl_unittest.cc +++ b/components/password_manager/core/browser/password_feature_manager_impl_unittest.cc
@@ -148,8 +148,8 @@ #endif // BUILDFLAG(IS_ANDROID) TEST_F(PasswordFeatureManagerImplTest, GenerationDisabledIfSignedOut) { - // TODO(crbug.com/1509058): Extract this and similar combinations to helper - // methods, e.g. SetUpSignedOut(). + // TODO(b/324036646): Extract this and similar combinations to helper methods, + // e.g. SetUpSignedOut(). sync_service_.SetAccountInfo({}); sync_service_.SetHasSyncConsent(false); sync_service_.SetDisableReasons(
diff --git a/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h b/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h index 7e0063d..359a7ea 100644 --- a/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h +++ b/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h
@@ -48,8 +48,7 @@ PasswordStoreBackendMetricsRecorder( BackendInfix backend_name, MethodName method_name, - PasswordStoreAndroidBackendType store_type = - PasswordStoreAndroidBackendType::kNone); + PasswordStoreAndroidBackendType store_type); PasswordStoreBackendMetricsRecorder(PasswordStoreBackendMetricsRecorder&&); PasswordStoreBackendMetricsRecorder& operator=( PasswordStoreBackendMetricsRecorder&&);
diff --git a/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder_unittest.cc b/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder_unittest.cc index 918f9d9..ccc684c 100644 --- a/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder_unittest.cc +++ b/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder_unittest.cc
@@ -96,7 +96,9 @@ BackendInfix(kSomeBackend), MethodName(kSomeMethod), GetParam()); } else { metrics_recorder = PasswordStoreBackendMetricsRecorder( - BackendInfix(kSomeBackend), MethodName(kSomeMethod)); + BackendInfix(kSomeBackend), MethodName(kSomeMethod), + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kNone); } // Checking started requests in the overall and backend-specific histogram. @@ -175,7 +177,9 @@ BackendInfix(kSomeBackend), MethodName(kSomeMethod), GetParam()); } else { metrics_recorder = PasswordStoreBackendMetricsRecorder( - BackendInfix(kSomeBackend), MethodName(kSomeMethod)); + BackendInfix(kSomeBackend), MethodName(kSomeMethod), + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kNone); } AdvanceClock(kLatencyDelta); @@ -271,7 +275,9 @@ BackendInfix(kSomeBackend), MethodName(kSomeMethod), GetParam()); } else { metrics_recorder = PasswordStoreBackendMetricsRecorder( - BackendInfix(kSomeBackend), MethodName(kSomeMethod)); + BackendInfix(kSomeBackend), MethodName(kSomeMethod), + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kNone); } AdvanceClock(kLatencyDelta); @@ -366,7 +372,9 @@ BackendInfix(kSomeBackend), MethodName(kSomeMethod), GetParam()); } else { metrics_recorder = PasswordStoreBackendMetricsRecorder( - BackendInfix(kSomeBackend), MethodName(kSomeMethod)); + BackendInfix(kSomeBackend), MethodName(kSomeMethod), + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kNone); } AdvanceClock(kLatencyDelta); @@ -425,7 +433,9 @@ BackendInfix(kSomeBackend), MethodName(kSomeMethod), GetParam()); } else { metrics_recorder = PasswordStoreBackendMetricsRecorder( - BackendInfix(kSomeBackend), MethodName(kSomeMethod)); + BackendInfix(kSomeBackend), MethodName(kSomeMethod), + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kNone); } AdvanceClock(kLatencyDelta);
diff --git a/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc b/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc index 21dc0e8..7fd65ad 100644 --- a/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc +++ b/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc
@@ -31,7 +31,9 @@ base::OnceCallback<Result(Result)> ReportMetricsForResultCallback( MethodName method_name) { PasswordStoreBackendMetricsRecorder metrics_reporter( - BackendInfix("BuiltInBackend"), method_name); + BackendInfix("BuiltInBackend"), method_name, + PasswordStoreBackendMetricsRecorder::PasswordStoreAndroidBackendType:: + kNone); return base::BindOnce( [](PasswordStoreBackendMetricsRecorder reporter, Result result) -> Result {
diff --git a/components/password_manager/core/browser/password_suggestion_generator.cc b/components/password_manager/core/browser/password_suggestion_generator.cc index ddf6d20..18f4226c 100644 --- a/components/password_manager/core/browser/password_suggestion_generator.cc +++ b/components/password_manager/core/browser/password_suggestion_generator.cc
@@ -123,9 +123,7 @@ bool has_no_fillable_suggestions = base::ranges::none_of( *suggestions, [](autofill::PopupItemId id) { - return id == autofill::PopupItemId::kUsernameEntry || - id == autofill::PopupItemId::kPasswordEntry || - id == autofill::PopupItemId::kAccountStorageUsernameEntry || + return id == autofill::PopupItemId::kPasswordEntry || id == autofill::PopupItemId::kAccountStoragePasswordEntry || id == autofill::PopupItemId::kGeneratePasswordEntry || id == autofill::PopupItemId::kWebauthnCredential; @@ -196,16 +194,9 @@ *suggestion.voice_over += u", "; *suggestion.voice_over += suggestion.labels[0][0].value; } - if (from_account_store) { - suggestion.popup_item_id = - is_password_field - ? autofill::PopupItemId::kAccountStoragePasswordEntry - : autofill::PopupItemId::kAccountStorageUsernameEntry; - } else { - suggestion.popup_item_id = is_password_field - ? autofill::PopupItemId::kPasswordEntry - : autofill::PopupItemId::kUsernameEntry; - } + suggestion.popup_item_id = + from_account_store ? autofill::PopupItemId::kAccountStoragePasswordEntry + : autofill::PopupItemId::kPasswordEntry; suggestion.custom_icon = custom_icon; // The UI code will pick up an icon from the resources based on the string. suggestion.icon = autofill::Suggestion::Icon::kGlobe;
diff --git a/components/performance_manager/decorators/process_metrics_decorator.cc b/components/performance_manager/decorators/process_metrics_decorator.cc index 47161b8d..2aaf6f75 100644 --- a/components/performance_manager/decorators/process_metrics_decorator.cc +++ b/components/performance_manager/decorators/process_metrics_decorator.cc
@@ -148,7 +148,8 @@ } } -void ProcessMetricsDecorator::RequestImmediateMetrics() { +void ProcessMetricsDecorator::RequestImmediateMetrics( + base::OnceClosure on_metrics_received) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Callers should have an interest token before calling // RequestImmediateMetrics(). @@ -173,7 +174,8 @@ RequestProcessesMemoryMetrics( /*immediate_request=*/true, base::BindOnce(&ProcessMetricsDecorator::DidGetMemoryUsage, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr()) + .Then(std::move(on_metrics_received))); } void ProcessMetricsDecorator::StartTimer() {
diff --git a/components/performance_manager/public/decorators/process_metrics_decorator.h b/components/performance_manager/public/decorators/process_metrics_decorator.h index cb6c2ac..ba683f3 100644 --- a/components/performance_manager/public/decorators/process_metrics_decorator.h +++ b/components/performance_manager/public/decorators/process_metrics_decorator.h
@@ -73,7 +73,8 @@ // Immediately refreshes the metrics for all the process nodes. This will do // nothing if the last metric refresh was more recent than // `kMinImmediateRefreshDelay`, since a recent measurement already exists. - void RequestImmediateMetrics(); + void RequestImmediateMetrics( + base::OnceClosure on_metrics_received = base::DoNothing()); static constexpr base::TimeDelta kMinImmediateRefreshDelay = base::Seconds(2);
diff --git a/components/performance_manager/public/resource_attribution/queries.h b/components/performance_manager/public/resource_attribution/queries.h index a7a57a5..ba866ec 100644 --- a/components/performance_manager/public/resource_attribution/queries.h +++ b/components/performance_manager/public/resource_attribution/queries.h
@@ -11,6 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/scoped_refptr.h" #include "base/observer_list_threadsafe.h" +#include "base/scoped_observation.h" #include "base/sequence_checker.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" @@ -126,6 +127,11 @@ GUARDED_BY_CONTEXT(sequence_checker_); }; +// Convenience alias for a ScopedObservation that observes a +// ScopedResourceUsageQuery. +using ScopedQueryObservation = + base::ScopedObservation<ScopedResourceUsageQuery, QueryResultObserver>; + // Creates a query to request resource usage measurements on a schedule. // // Use CreateScopedQuery() to return an object that makes repeated measurements
diff --git a/components/permissions/features.cc b/components/permissions/features.cc index 575efba3..32e57a1 100644 --- a/components/permissions/features.cc +++ b/components/permissions/features.cc
@@ -40,10 +40,6 @@ "BlockRepeatedNotificationPermissionPrompts", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kNotificationInteractionHistory, - "NotificationInteractionHistory", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kOneTimePermission, "OneTimePermission", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/permissions/features.h b/components/permissions/features.h index 62d5ea3..62683449 100644 --- a/components/permissions/features.h +++ b/components/permissions/features.h
@@ -29,9 +29,6 @@ BASE_DECLARE_FEATURE(kBlockRepeatedNotificationPermissionPrompts); COMPONENT_EXPORT(PERMISSIONS_COMMON) -BASE_DECLARE_FEATURE(kNotificationInteractionHistory); - -COMPONENT_EXPORT(PERMISSIONS_COMMON) BASE_DECLARE_FEATURE(kOneTimePermission); COMPONENT_EXPORT(PERMISSIONS_COMMON)
diff --git a/components/policy/core/browser/configuration_policy_handler.cc b/components/policy/core/browser/configuration_policy_handler.cc index 401ab99..0a9e50a 100644 --- a/components/policy/core/browser/configuration_policy_handler.cc +++ b/components/policy/core/browser/configuration_policy_handler.cc
@@ -100,8 +100,10 @@ // It is safe to use `value_unsafe()` as multiple policy types are handled. *value = entry ? entry->value_unsafe() : nullptr; if (*value && (*value)->type() != value_type) { - errors->AddError(policy, IDS_POLICY_TYPE_ERROR, - base::Value::GetTypeName(value_type)); + if (errors) { + errors->AddError(policy, IDS_POLICY_TYPE_ERROR, + base::Value::GetTypeName(value_type)); + } return false; } return true; @@ -394,8 +396,10 @@ const base::Value* required_value = policies.GetValueUnsafe(required_policy_name_); if (!required_value) { - errors->AddError(policy_name(), IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE, - required_policy_name_); + if (errors) { + errors->AddError(policy_name(), IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE, + required_policy_name_); + } return false; } return handler_->CheckPolicySettings(policies, errors); @@ -758,7 +762,7 @@ const PolicyMap& policies, PolicyErrorMap* errors) { if (policies.Get(new_policy_handler_->policy_name())) { - if (policies.Get(legacy_policy_handler_->policy_name())) { + if (policies.Get(legacy_policy_handler_->policy_name()) && errors) { errors->AddError(legacy_policy_handler_->policy_name(), IDS_POLICY_OVERRIDDEN, new_policy_handler_->policy_name()); @@ -822,12 +826,16 @@ if (policy->source == policy::POLICY_SOURCE_MERGED) { for (const auto& conflict : policy->conflicts) { if (!IsCloudOnlyPolicy(conflict.entry())) { - errors->AddError(policy_name, IDS_POLICY_CLOUD_SOURCE_ONLY_ERROR); + if (errors) { + errors->AddError(policy_name, IDS_POLICY_CLOUD_SOURCE_ONLY_ERROR); + } return false; } } } else if (!IsCloudOnlyPolicy(*policy)) { - errors->AddError(policy_name, IDS_POLICY_CLOUD_SOURCE_ONLY_ERROR); + if (errors) { + errors->AddError(policy_name, IDS_POLICY_CLOUD_SOURCE_ONLY_ERROR); + } return false; }
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index 847b977..ec5df4b 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -912,6 +912,13 @@ // to new_public_key_verification_data_signature, but is computed over // DEPRECATEDPolicyPublicKeyAndDomain (which is equivalent to // PublicKeyVerificationData proto with version field unset). + // + // Do not remove this unless you know for sure that this is not required by + // managed devices any more, including devices that might be pinned to + // milestones older than current Stable. + // Note: As of February 2024, this is still strictly required by + // CloudPolicyValidator, see + // https://source.chromium.org/chromium/chromium/src/+/main:components/policy/core/common/cloud/cloud_policy_validator.cc;drc=08b91b49531894cbe9061a1148fd535155c2554b;l=407 optional bytes new_public_key_verification_signature_deprecated = 7 [deprecated = true];
diff --git a/components/policy/resources/policy_templates_de.xtb b/components/policy/resources/policy_templates_de.xtb index bf9e277..1ae901d7 100644 --- a/components/policy/resources/policy_templates_de.xtb +++ b/components/policy/resources/policy_templates_de.xtb
@@ -1371,7 +1371,7 @@ <translation id="2096932573113293941">Nutzer um Erlaubnis zum Ausführen von Plug-ins bitten, die eine Autorisierung erfordern</translation> <translation id="2098658257603918882">Berichte mit Nutzungs- und Absturzdaten erstellen</translation> <translation id="2099380339157427935">Schaltfläche „Abmelden“ nicht in der Taskleiste anzeigen</translation> -<translation id="2100630160869631650">Damit werden vorausgefüllte Kerberos-Konten hinzugefügt. Wenn die Kerberos-Anmeldedaten mit den für die Anmeldung verwendeten Daten übereinstimmen, kann ein Konto so konfiguriert werden, dass die Anmeldedaten wiederverwendet werden. Dazu müssen <ph name="LOGIN_EMAIL_PLACEHOLDER" /> und <ph name="PASSWORD_PLACEHOLDER" /> jeweils als Hauptkonto und Passwort festgelegt werden, sodass das Kerberos-Ticket automatisch abgerufen werden kann. Das ist jedoch nicht möglich, wenn die Bestätigung in zwei Schritten konfiguriert ist. Nutzer können über diese Richtlinie hinzugefügte Konten nicht ändern. +<translation id="2100630160869631650">Damit werden vorausgefüllte Kerberos-Konten hinzugefügt. Wenn die Kerberos-Anmeldedaten mit den für die Anmeldung verwendeten Daten übereinstimmen, kann ein Konto so konfiguriert werden, dass die Anmeldedaten wiederverwendet werden. Dazu müssen <ph name="LOGIN_EMAIL_PLACEHOLDER" /> und <ph name="PASSWORD_PLACEHOLDER" /> jeweils als Hauptkonto und Passwort festgelegt werden, sodass das Kerberos-Ticket automatisch abgerufen werden kann. Das ist jedoch nicht möglich, wenn die 2-Faktor-Authentifizierung konfiguriert ist. Nutzer können über diese Richtlinie hinzugefügte Konten nicht ändern. Ist die Richtlinie aktiviert, wird die Liste der Konten, die durch die Richtlinie definiert ist, den Einstellungen für Kerberos-Konten hinzugefügt.
diff --git a/components/policy/resources/policy_templates_id.xtb b/components/policy/resources/policy_templates_id.xtb index 0d65c6c..526804e 100644 --- a/components/policy/resources/policy_templates_id.xtb +++ b/components/policy/resources/policy_templates_id.xtb
@@ -1806,6 +1806,7 @@ Jika <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" /> (nilai 1) disetel, hanya variasi yang dianggap sebagai perbaikan keamanan atau stabilitas penting yang akan diterapkan ke <ph name="PRODUCT_NAME" />. Jika <ph name="VARIATIONS_DISABLED_OPTION_NAME" /> (nilai 2) disetel, semua variasi tidak akan dapat diterapkan ke browser. Perlu diketahui, mode ini tidak direkomendasikan karena berpotensi menyebabkan developer <ph name="PRODUCT_NAME" /> tidak dapat menyediakan perbaikan keamanan penting secara tepat waktu.</translation> +<translation id="2402537890732357732">Selalu tampilkan label pengelolaan</translation> <translation id="2402547085566757554">Jangan gunakan Halaman Tab Baru sebagai halaman beranda</translation> <translation id="240713331529749993">Jika kebijakan ini disetel, setiap asal bernama dalam daftar yang dipisahkan koma akan berjalan dalam proses khusus di Android. Setiap proses asal bernama hanya akan diizinkan untuk memuat dokumen dari asal tersebut dan subdomainnya. Misalnya, menentukan https://a1.example.com/ akan mengizinkan https://a2.a1.example.com/ dalam proses yang sama, tetapi tidak mengizinkan https://example.com atau https://b.example.com. Perlu diketahui bahwa Android akan mengisolasi situs sensitif tertentu secara default mulai <ph name="PRODUCT_NAME" /> versi 77, dan kebijakan ini memperluas mode tersebut untuk mengisolasi asal tambahan tertentu. @@ -4650,6 +4651,11 @@ Untuk perangkat yang tidak dikelola, pengguna dapat membuat keputusan untuk mengirim metrik.</translation> <translation id="4694138212536142867">Aktifkan pelaporan status hardware perangkat</translation> <translation id="4697581738794063407">Mengontrol fitur filter parameter URL</translation> +<translation id="4698147321113652592">Kebijakan ini menetapkan serangkaian interval mingguan untuk penjadwalan penangguhan otomatis. Saat interval dimulai, perangkat <ph name="PRODUCT_OS_NAME" /> akan memasuki mode ditangguhkan, dan akan aktif saat interval berakhir. + +Jadwal dengan interval yang tumpang tindih tidak didukung. Kebijakan ini tidak akan berpengaruh jika berisi dua interval yang tumpang-tindih. + +Perangkat <ph name="PRODUCT_OS_NAME" /> akan menggunakan zona waktu sistem untuk menerapkan interval ini.</translation> <translation id="4698895924806859508">Jangan laporkan peristiwa jaringan</translation> <translation id="4699172675775169585">Gambar dan file dalam cache</translation> <translation id="4699592681017489215">Kebijakan ini mengonfigurasi tombol lokal yang dapat digunakan untuk menonaktifkan pemeriksaan intersepsi DNS. Pemeriksaan ini berupaya mencari tahu apakah browser berada di balik proxy yang mengalihkan nama host tidak dikenal. @@ -6375,6 +6381,7 @@ <translation id="6181783961196084973">Nilai tombol alih pengumpulan data aktivitas aplikasi. Jika disetel ke benar (true), aktivitas aplikasi pengguna akan dilaporkan ke server dengan tujuan untuk ditampilkan di aplikasi <ph name="PRODUCT_NAME" /> anak dan orang tua. Jika disetel ke salah (false), fitur Batas waktu per aplikasi akan tetap berfungsi, tetapi tidak ada data yang akan dilaporkan ke server dan oleh karena itu, tidak ada data yang akan ditampilkan di <ph name="PRODUCT_NAME" />.</translation> <translation id="6182206125906000651">Nonaktifkan Upgrade HTTPS.</translation> <translation id="6182563940865917569">Izinkan Chrome memutar media secara otomatis</translation> +<translation id="6187632100458475876">Setelan label avatar toolbar terkelola</translation> <translation id="6190367314942602985">Laporkan informasi Identifikasi Pengguna</translation> <translation id="6191963383731098056">Kebijakan ini memungkinkan admin mengonfigurasi warna tema <ph name="PRODUCT_NAME" />. String input harus berupa string warna hex valid yang sesuai dengan format "#RRGGBB". @@ -7438,6 +7445,7 @@ Jika kebijakan disetel ke Nonaktif atau tidak disetel, perilaku default pemblokiran permintaan semacam itu akan diterapkan.</translation> +<translation id="6915524162137327111">Tampilkan label pengelolaan selama 30 detik</translation> <translation id="6919819553978815392">Jika kebijakan ini disetel ke benar (true) atau tidak dikonfigurasi, <ph name="PRODUCT_NAME" /> dan <ph name="LACROS_NAME" /> akan mengaktifkan login tamu. Login tamu adalah profil <ph name="PRODUCT_NAME" /> saat semua jendela berada dalam mode Samaran. Jika kebijakan ini disetel ke salah (false), <ph name="PRODUCT_NAME" /> dan <ph name="LACROS_NAME" /> tidak akan mengizinkan profil tamu dimulai. @@ -8711,6 +8719,11 @@ Kebijakan ini dihapus di Chrome 110. </translation> <translation id="7976157349247117979">Nama tujuan <ph name="PRODUCT_NAME" /></translation> +<translation id="797820628785995988">Jika kebijakan ini disetel, semua jenis data yang ditentukan akan dikecualikan dari sinkronisasi, baik untuk <ph name="CHROME_SYNC_NAME" /> maupun sinkronisasi profil roaming. Hal ini berguna untuk mengurangi ukuran profil roaming atau membatasi jenis data yang diupload ke Server <ph name="CHROME_SYNC_NAME" />. + + Jenis data saat ini untuk kebijakan ini adalah: "apps", "autofill", "bookmarks", "extensions", "preferences", "passwords", "payments", "readingList", "savedTabGroups", "tabs", "themes", "typedUrls", "wifiConfigurations". Nama-nama tersebut peka huruf besar/kecil. + + Catatan: Pembaruan Kebijakan Dinamis hanya didukung di <ph name="PRODUCT_NAME" /> versi 123 dan yang lebih baru. Menonaktifkan "autofill" juga akan menonaktifkan "payments". "typedUrls" merujuk pada semua histori penjelajahan.</translation> <translation id="7982057585796399404">Menyetel kebijakan akan menentukan daftar aplikasi dan ekstensi yang diinstal otomatis, tanpa interaksi pengguna, dan yang tidak dapat di-uninstal atau dinonaktifkan pengguna. Izin akan diberikan secara implisit, termasuk untuk API ekstensi enterprise.deviceAttributes dan enterprise.platformKeys. (Dua API ini tidak tersedia untuk aplikasi dan ekstensi yang tidak diinstal otomatis.) Jika kebijakan tidak disetel, tidak ada aplikasi atau ekstensi yang diinstal otomatis, dan pengguna dapat meng-uninstal aplikasi atau ekstensi apa pun di <ph name="PRODUCT_NAME" />. @@ -9004,6 +9017,10 @@ <translation id="8250048892729838843">Kebijakan ini tidak digunakan lagi. Jika kebijakan disetel ke Aktif atau tidak disetel, perangkat akan diizinkan menerima kontrol pelaporan terperinci. Jika kebijakan disetel ke Nonaktif, perangkat terdaftar tidak akan menerima kontrol pelaporan terperinci.</translation> <translation id="82530263956734297">ID Ekstensi yang dikeluarkan dari daftar yang tidak diizinkan</translation> +<translation id="8254792295762772851">Jika kebijakan ini tidak disetel atau disetel ke <ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" /> (nilai 0), label Kerja atau Sekolah akan ditampilkan di samping avatar toolbar. +Label ini hanya akan ditampilkan jika akun yang digunakan untuk login adalah akun terkelola. + +Jika kebijakan ini disetel ke <ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" /> (nilai 1), label Kerja atau Sekolah akan ditampilkan di samping avatar toolbar selama 30 detik setelah membuka profil.</translation> <translation id="8256006033157034334">Kebijakan ini tidak digunakan lagi dan tidak didukung. Sebagai gantinya, gunakan <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" />.</translation> <translation id="8256688113167012935">Mengontrol nama akun yang ditampilkan <ph name="PRODUCT_OS_NAME" /> di layar masuk untuk akun lokal perangkat yang sesuai. @@ -9622,6 +9639,7 @@ Jika Anda menyetel kebijakan, pengguna tidak dapat mengubah fungsi ini. Jika Anda tidak menyetelnya, pengguna akan diizinkan mengubah setelan.</translation> <translation id="8707790573162457301">Jalankan pembersihan disk otomatis selama login</translation> +<translation id="8712609946151927008">Menjadwalkan interval penangguhan mingguan</translation> <translation id="8713535263782304771">Nonaktifkan Safe Browsing</translation> <translation id="8714556680280715750">URL yang dapat dikunjungi pengguna untuk mempelajari lebih lanjut. Jika tidak disetel, tidak akan ada URL "pelajari lebih lanjut" di penginstal. Jika ada, URL harus menggunakan
diff --git a/components/policy/resources/policy_templates_ja.xtb b/components/policy/resources/policy_templates_ja.xtb index c7e60976..6748f666 100644 --- a/components/policy/resources/policy_templates_ja.xtb +++ b/components/policy/resources/policy_templates_ja.xtb
@@ -1691,6 +1691,7 @@ <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" />(値 1)に設定した場合は、セキュリティまたは安定性に関する重要な修正とみなされるバリエーションのみ <ph name="PRODUCT_NAME" /> に適用できます。 <ph name="VARIATIONS_DISABLED_OPTION_NAME" />(値 2)に設定した場合は、どのバリエーションもブラウザに適用できません。このモードは、<ph name="PRODUCT_NAME" /> のデベロッパーがセキュリティに関する重要な修正を適切なタイミングで適用できない場合があるため推奨されません。</translation> +<translation id="2402537890732357732">管理ラベルを常に表示する</translation> <translation id="2402547085566757554">新しいタブページをホームページとして使用しない</translation> <translation id="240713331529749993">このポリシーを設定した場合、カンマ区切りのリストで指定した発行元は、Android 上でそれぞれ独自のプロセスで実行されます。指定した発行元のプロセスで使用できるのは、発行元およびそのサブドメインのドキュメントだけです。たとえば、https://a1.example.com/ を指定した場合、https://a2.a1.example.com/ は同一のプロセスで実行されますが、https://example.com や https://b.example.com はこの限りではありません。Android では <ph name="PRODUCT_NAME" /> バージョン 77 以降、特定のデリケートなコンテンツを含むウェブサイトがデフォルトで分離されており、このポリシーによってデフォルトのサイト分離モードが特定の発行元にも適用されます。<ph name="PRODUCT_NAME" /> 77 以降であれば、ワイルドカードを使用し、分離する発行元の範囲を指定できます。たとえば、https://[*.]corp.example.com を指定した場合、https://corp.example.com 以下の発行元に対して同じ独自プロセスが適用されます。これには https://corp.example.com 自体が該当するほか、https://a1.corp.example.com や https://a2.a1.corp.example.com も含まれます。 @@ -4361,6 +4362,11 @@ 管理対象デバイス以外では、統計情報を送信するかどうかをユーザーが指定できます。</translation> <translation id="4694138212536142867">デバイスのハードウェア ステータスの報告を有効にする</translation> <translation id="4697581738794063407">URL パラメータ フィルタ機能を制御する</translation> +<translation id="4698147321113652592">このポリシーでは、自動停止期間を週単位で設定します。期間が開始すると、<ph name="PRODUCT_OS_NAME" /> デバイスは停止モードに入り、期間が終了すると復帰します。 + +重複する期間を設定することはできません。重複する 2 つの期間が設定されている場合、このポリシーは無視されます。 + +<ph name="PRODUCT_OS_NAME" /> デバイスでは、システムのタイムゾーンを使用してこれらの期間を適用します。</translation> <translation id="4698895924806859508">ネットワーク イベントを報告しない</translation> <translation id="4699172675775169585">キャッシュされた画像とファイル</translation> <translation id="4699592681017489215">このポリシーでは、DNS 傍受チェックの無効化に使用できるローカルのスイッチを設定します。DNS 傍受チェックは、ブラウザが不明なホスト名をリダイレクトするプロキシの背後にあるかどうかを検出するものです。 @@ -5940,6 +5946,7 @@ <translation id="6181783961196084973">アプリのアクティビティを収集するかどうかの切り替え値です。true に設定した場合、ユーザーによるアプリのアクティビティ レポートがサーバーに送信され、お子様と保護者の <ph name="PRODUCT_NAME" /> アプリに表示されます。false に設定した場合、アプリごとの利用時間の上限は引き続き有効ですが、レポートデータはサーバーに送信されず、<ph name="PRODUCT_NAME" /> にも表示されません。</translation> <translation id="6182206125906000651">HTTPS アップグレードを無効にする。</translation> <translation id="6182563940865917569">Chrome にメディアの自動再生を許可する</translation> +<translation id="6187632100458475876">管理対象のツールバー アバターラベル設定</translation> <translation id="6190367314942602985">ユーザー識別情報に関するレポートを作成</translation> <translation id="6191963383731098056">このポリシーにより、管理者は <ph name="PRODUCT_NAME" /> のテーマの色を設定できます。入力する文字列は「#RRGGBB」の形式に沿った有効な 16 進数色コードである必要があります。 @@ -6886,6 +6893,7 @@ <translation id="6908640907898649429">デフォルトの検索プロバイダを設定します。ユーザーが使用するデフォルトの検索プロバイダを指定するか、既定の検索を無効にすることができます。</translation> <translation id="6913068954484253496">すべての IP アドレスのキャスト デバイスに接続することを <ph name="PRODUCT_NAME" /> に許可する</translation> <translation id="6915493311660114995">有効に設定した場合、<ph name="PRODUCT_NAME" /> では、TLS 証明書にエラーがあるウェブサイト(ウェブサイトが安全でないと判断されるなど)でウェブ認証リクエストを許可します。このポリシーを無効に設定するか未設定のままにした場合、このようなリクエストをブロックするデフォルトの動作が適用されます。</translation> +<translation id="6915524162137327111">管理ラベルを 30 秒間表示する</translation> <translation id="6919819553978815392">このポリシーを true に設定するか未設定のままにした場合、<ph name="PRODUCT_NAME" /> と <ph name="LACROS_NAME" /> ではゲストモードでのログインが可能です。ゲストモードでのログインには、すべてのウィンドウをシークレット モードで表示する <ph name="PRODUCT_NAME" /> プロフィールが適用されます。 このポリシーを false に設定した場合、ゲストモードのプロフィールで <ph name="PRODUCT_NAME" /> と <ph name="LACROS_NAME" /> を使用することはできません。 @@ -8082,6 +8090,11 @@ このポリシーは Chrome 110 で削除されました。 </translation> <translation id="7976157349247117979"><ph name="PRODUCT_NAME" /> のレシーバー名</translation> +<translation id="797820628785995988">このポリシーを設定した場合、指定したすべてのデータタイプが <ph name="CHROME_SYNC_NAME" /> とローミング プロファイルの同期から除外されます。これにより、ローミング プロファイルのサイズを抑えたり、<ph name="CHROME_SYNC_NAME" /> サーバーにアップロードされるデータのタイプを制限したりできます。 + + 現在、このポリシーで指定できるデータタイプは次のとおりです: "apps"、"autofill"、"bookmarks"、"extensions"、"preferences"、"passwords"、"payments"、"readingList"、"savedTabGroups"、"tabs"、"themes"、"typedUrls"、"wifiConfigurations"。 データタイプの名前では大文字と小文字が区別されます。 + + 注: 動的なポリシー更新は <ph name="PRODUCT_NAME" /> バージョン 123 以降でのみサポートされます。"autofill" を無効にすると、"payments" も無効になります。"typedUrls" はすべての閲覧履歴を指します。</translation> <translation id="7982057585796399404">このポリシーを設定することで、ユーザーに操作を求めずにサイレント インストールするアプリと拡張機能のリストを指定します。ユーザーは、ここで指定されたアプリや拡張機能をアンインストールすることも無効化することもできません。権限は、enterprise.deviceAttributes 拡張機能 API と enterprise.platformKeys 拡張機能 API に対するものを含め、暗黙的に付与されます(これら 2 つの API は、自動インストールされたアプリや拡張機能以外には利用できません)。 このポリシーを未設定のままにした場合、どのアプリや拡張機能も自動的にインストールされることはなく、ユーザーは <ph name="PRODUCT_NAME" /> からアプリや拡張機能をアンインストールできます。 @@ -8348,6 +8361,10 @@ <translation id="824818544897669723">ブラウザとダウンロードの履歴の削除を無効にする</translation> <translation id="8250048892729838843">このポリシーはサポートを終了しました。このポリシーを有効に設定するか未設定のままにした場合、デバイスで詳細なレポート コントロールを受けることができます。このポリシーを無効に設定した場合、登録済みデバイスは詳細なレポート コントロールを受けません。</translation> <translation id="82530263956734297">拒否リストから除外する拡張機能 ID</translation> +<translation id="8254792295762772851">このポリシーを未設定のままにするか、<ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" />(値 0)に設定した場合、ツールバーのアバターの横に「職場」や「学校」のラベルが表示されます。 +これらのラベルは、ログインしているアカウントが管理対象である場合にのみ表示されます。 + +<ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" />(値 1)に設定した場合、プロフィールを開いてから 30 秒間、ツールバーのアバターの横に「職場」や「学校」のラベルが表示されます。</translation> <translation id="8256006033157034334">このポリシーは非推奨で、サポートされていません。代わりに <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" /> を使用してください。</translation> <translation id="8256688113167012935">対応するデバイスのローカル アカウントに対し、ログイン画面でアカウント名 <ph name="PRODUCT_OS_NAME" /> を表示するかどうかを指定します。 @@ -8941,6 +8958,7 @@ このポリシーを設定した場合、ユーザーはこの機能を変更できません。このポリシーを未設定のままにした場合、ユーザーは設定を変更できます。</translation> <translation id="8707790573162457301">ログイン中に自動ディスク クリーンアップを実行する</translation> +<translation id="8712609946151927008">週単位の停止期間を設定する</translation> <translation id="8713535263782304771">セーフ ブラウジングを無効にする</translation> <translation id="8714556680280715750">ユーザーがアクセスして詳細を確認するための URL。未設定のままにすると、インストーラに「詳細」URL は表示されません。URL を指定する場合は、https スキームを使用する必要があります。</translation> <translation id="8715885991031124968">異なる生成元のサブフレームからトリガーされた JavaScript ダイアログを許可します</translation>
diff --git a/components/policy/resources/policy_templates_ko.xtb b/components/policy/resources/policy_templates_ko.xtb index b26676c..3976363 100644 --- a/components/policy/resources/policy_templates_ko.xtb +++ b/components/policy/resources/policy_templates_ko.xtb
@@ -1766,6 +1766,7 @@ <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" /> 옵션을 설정하면(값 1) 중요한 보안 또는 안정성 관련 수정사항으로 간주되는 변형만 <ph name="PRODUCT_NAME" />에 적용 가능합니다. <ph name="VARIATIONS_DISABLED_OPTION_NAME" /> 옵션을 설정하면(값 2) 어떤 변형도 브라우저에 적용할 수 없습니다. 이 모드를 사용하면 <ph name="PRODUCT_NAME" /> 개발자가 중요한 보안 수정사항을 신속히 제공하지 못할 수 있으므로 권장되지 않습니다.</translation> +<translation id="2402537890732357732">관리 라벨 항상 표시</translation> <translation id="2402547085566757554">새 탭 페이지를 홈페이지로 사용 안함</translation> <translation id="240713331529749993">정책을 설정하면 쉼표로 구분된 목록의 이름이 지정된 각 출처가 Android에서 전용 프로세스로 실행됩니다. 이름이 지정된 각 출처의 프로세스에는 해당 출처와 하위 도메인의 문서만 포함될 수 있습니다. 예를 들어 https://a1.example.com/을 지정하면 동일한 프로세스에는 https://a2.a1.example.com/만 허용되며 https://example.com 또는 https://b.example.com은 허용되지 않습니다. Android에서는 <ph name="PRODUCT_NAME" /> 버전 77부터 기본적으로 민감한 특정 사이트가 격리됩니다. 이 정책을 설정하면 기본적인 격리 모드가 확장되어 특정 출처를 추가로 격리합니다. @@ -4510,6 +4511,11 @@ 관리되지 않는 기기의 경우 사용자가 측정항목 전송 여부를 결정할 수 있습니다.</translation> <translation id="4694138212536142867">기기 하드웨어 상태 보고 사용 설정</translation> <translation id="4697581738794063407">URL 매개변수 필터링 기능 제어</translation> +<translation id="4698147321113652592">이 정책은 자동 정지 일정의 주간 간격을 설정합니다. 간격이 시작되면 <ph name="PRODUCT_OS_NAME" /> 기기가 정지 모드로 전환되고, 간격이 끝나면 정지 모드가 해제됩니다. + +간격이 겹치는 일정은 지원되지 않습니다. 일정에 간격이 2개 이상 겹치는 경우 이 정책은 아무런 영향을 미치지 않습니다. + +<ph name="PRODUCT_OS_NAME" /> 기기에서 시스템 시간대를 사용하여 간격을 적용합니다.</translation> <translation id="4698895924806859508">네트워크 이벤트 보고 안 함</translation> <translation id="4699172675775169585">캐시된 이미지 및 파일</translation> <translation id="4699592681017489215">이 정책은 DNS 가로채기 검사를 사용 중지하는 데 이용할 수 있는 로컬 스위치를 구성합니다. DNS 가로채기 검사는 브라우저에서 알 수 없는 호스트 이름을 리디렉션하는 프록시를 사용 중인지 확인합니다. @@ -6213,6 +6219,7 @@ <translation id="6181783961196084973">앱 활동 모음 전환 버튼의 값입니다. True로 설정하면 자녀와 부모의 <ph name="PRODUCT_NAME" /> 앱에 표시될 수 있도록 사용자 앱 활동이 서버로 전송됩니다. False로 설정하면 앱별 시간제한 기능은 계속 작동되나 데이터가 서버로 전송되거나 <ph name="PRODUCT_NAME" />에 표시되지 않습니다.</translation> <translation id="6182206125906000651">HTTPS 업그레이드를 사용 중지합니다.</translation> <translation id="6182563940865917569">Chrome의 미디어 자동재생 허용</translation> +<translation id="6187632100458475876">관리 계정 툴바 아바타 라벨 설정</translation> <translation id="6190367314942602985">사용자 식별 정보 보고</translation> <translation id="6191963383731098056">이 정책으로 관리자는 <ph name="PRODUCT_NAME" />의 테마 색상을 구성할 수 있습니다. 입력 문자열은 '#RRGGBB' 형식의 유효한 16진수 색상이어야 합니다. @@ -7213,6 +7220,7 @@ <translation id="6915493311660114995">정책을 사용 설정하면 <ph name="PRODUCT_NAME" />에서 오류가 있는 TLS 인증서가 있는 웹사이트(안전하지 않은 것으로 간주되는 웹사이트)의 웹 인증 요청을 허용합니다. 정책을 사용 안함으로 설정하거나 설정하지 않으면 이러한 요청을 차단하는 기본 동작이 적용됩니다.</translation> +<translation id="6915524162137327111">관리 라벨 30초 동안 표시</translation> <translation id="6919819553978815392">정책을 true로 설정하거나 설정하지 않으면 <ph name="PRODUCT_NAME" /> 및 <ph name="LACROS_NAME" />가 게스트 로그인을 사용 설정합니다. 게스트 로그인은 모든 창이 시크릿 모드인 <ph name="PRODUCT_NAME" /> 프로필입니다. 정책을 false로 설정하면 <ph name="PRODUCT_NAME" /> 및 <ph name="LACROS_NAME" />가 게스트 프로필이 시작하도록 허용하지 않습니다. @@ -8480,6 +8488,11 @@ 이 정책은 Chrome 110에서 삭제되었습니다. </translation> <translation id="7976157349247117979"><ph name="PRODUCT_NAME" /> 전송 대상의 이름</translation> +<translation id="797820628785995988">정책을 설정하면, 지정된 모든 데이터 유형이 <ph name="CHROME_SYNC_NAME" /> 동기화와 로밍 프로필 동기화 모두에서 제외됩니다. 이렇게 하면 로밍 프로필의 크기를 줄이거나 <ph name="CHROME_SYNC_NAME" /> 서버에 업로드되는 데이터의 유형을 제한하는 데 도움이 될 수 있습니다. + + 정책의 현재 데이터 유형은 'apps', 'autofill', 'bookmarks', 'extensions', 'preferences', 'passwords', 'payments', 'readingList', 'savedTabGroups', 'tabs', 'themes', 'typedUrls', 'wifiConfigurations'입니다. 이름은 대소문자를 구분합니다. + + 참고로, 동적 정책 새로고침은 <ph name="PRODUCT_NAME" /> 버전 123 이상에서만 지원됩니다. 'autofill'을 사용 중지하면 'payments'도 사용 중지됩니다. 'typedUrls'는 모든 방문 기록을 의미합니다.</translation> <translation id="7982057585796399404">이 정책을 설정하면 사용자 상호작용 없이 자동으로 설치되는 앱 및 확장 프로그램 목록이 지정되며, 사용자가 제거하거나 사용 중지할 수 없습니다. enterprise.deviceAttributes 및 enterprise.platformKeys 확장 프로그램 API의 권한을 비롯한 권한은 암시적으로 부여됩니다. (이 2개의 API는 강제 설치되지 않은 앱과 확장 프로그램에서는 사용할 수 없습니다.) 정책을 설정하지 않으면 앱 또는 확장 프로그램이 자동 설치되지 않으며 사용자는 <ph name="PRODUCT_NAME" />에서 모든 앱 또는 확장 프로그램을 제거할 수 있습니다. @@ -8763,6 +8776,10 @@ <translation id="8250048892729838843">지원 중단된 정책입니다. 정책을 사용으로 설정하거나 설정하지 않은 채로 두면 기기가 상세 보고 제어 권한을 받을 수 있습니다. 정책을 사용 안함으로 설정하면 등록된 기기가 상세 보고 제어 권한을 받을 수 없습니다.</translation> <translation id="82530263956734297">차단 목록에서 제외할 확장 프로그램 ID</translation> +<translation id="8254792295762772851">정책을 설정하지 않거나 <ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" />(값 0)로 설정하면 툴바 아바타 옆에 직장 또는 학교 라벨이 표시됩니다. +이러한 라벨은 로그인한 계정이 관리 계정인 경우에만 표시됩니다. + +<ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" />(값 1)로 설정하면 프로필을 연 후 30초 동안 툴바 아바타 옆에 직장 또는 학교 라벨이 표시됩니다.</translation> <translation id="8256006033157034334">이 정책은 지원 중단되었으며 지원되지 않습니다. 대신 <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" /> 정책을 사용하세요.</translation> <translation id="8256688113167012935">계정 이름 <ph name="PRODUCT_OS_NAME" />을(를) 해당 기기 로컬 계정의 로그인 화면에 표시할 것인지 제어합니다. @@ -9377,6 +9394,7 @@ 정책을 설정하면 사용자가 이 기능을 변경할 수 없습니다. 설정하지 않으면 사용자가 설정을 변경할 수 있습니다.</translation> <translation id="8707790573162457301">로그인 중 자동 디스크 정리 실행</translation> +<translation id="8712609946151927008">주간 정지 간격 일정 예약</translation> <translation id="8713535263782304771">세이프 브라우징 사용 안함</translation> <translation id="8714556680280715750">사용자가 방문하여 자세히 알아볼 수 있는 URL입니다. 설정하지 않으면 설치 프로그램에 '자세히 알아보기' URL이 표시되지 않습니다. 설정된 경우 https 스키마를
diff --git a/components/policy/resources/policy_templates_nl.xtb b/components/policy/resources/policy_templates_nl.xtb index 96a7158f..5ba9df6f 100644 --- a/components/policy/resources/policy_templates_nl.xtb +++ b/components/policy/resources/policy_templates_nl.xtb
@@ -505,6 +505,15 @@ <translation id="1426170570389588560">De periode in dagen instellen voor het opslaan van metadata van afdruktaken</translation> <translation id="1426410128494586442">Ja</translation> <translation id="1427655258943162134">Adres of URL van proxyserver</translation> +<translation id="1430811977802269244">Toestaan dat geschikte apparaten die geen Android-ondersteuning meer krijgen, worden aangemeld voor uitgebreide automatische updates. + +Als je het beleid aanzet, worden apparaten aangemeld voor uitgebreide automatische updates. + +Als je het beleid uitzet of niet instelt, krijgen apparaten geen updates meer na de oorspronkelijke vervaldatum van automatische updates. + +Dit beleid is alleen relevant voor oudere modellen die niet automatisch uitgebreide updates krijgen. + +Ga voor meer informatie naar https://support.google.com/chrome/a/?p=extended_updates_support.</translation> <translation id="1432834104376790711">Met dit beleid kun je de instelling Batterijbesparing aan- of uitzetten. In Chrome wordt met deze instelling de framesnelheid beperkt voor een lager stroomverbruik. Als je dit beleid niet instelt, kan de eindgebruiker deze instelling beheren in chrome://settings/performance. In ChromeOS zorgt deze instelling ervoor dat de framesnelheid en CPU-frequentie worden beperkt, achtergrondverlichting wordt gedimd en Android in de modus Batterijbesparing wordt gezet. Op apparaten met meerdere CPU's worden sommige CPU's uitgezet. @@ -579,6 +588,7 @@ Als je dit beleid toepast of niet instelt, wordt op de webpagina naar specifieke tekstfragmenten scrollen via de URL aangezet. Als je dit beleid niet toepast, wordt op de webpagina naar specifieke tekstfragmenten scrollen via de URL uitgezet.</translation> +<translation id="1468702975912409463">Toestaan dat gebruikers met externe toegang URL's aan de hostzijde openen in hun lokale clientbrowser</translation> <translation id="1474273443907024088">TLS False Start uitzetten</translation> <translation id="1477934438414550161">TLS 1.2</translation> <translation id="1479427764273213107">Als je het beleid instelt, wordt de lijst met USB-apparaten gedefinieerd die door gebruikers mogen worden ontkoppeld van hun kernel-driver, zodat ze via de chrome.usb API rechtstreeks kunnen worden gebruikt in een web-app. Items zijn paren van de ID van de USB-leverancier en de ID van het product, zodat specifieke hardware kan worden geïdentificeerd. @@ -1752,6 +1762,7 @@ Als je <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" /> (waarde 1) instelt, mogen alleen varianten die worden beschouwd als essentiële beveiligings- of stabiliteitsoplossingen, worden toegepast op <ph name="PRODUCT_NAME" />. Als je <ph name="VARIATIONS_DISABLED_OPTION_NAME" /> (waarde 2) instelt, mag geen van de varianten worden toegepast op de browser. Deze modus kan er potentieel voor zorgen dat <ph name="PRODUCT_NAME" />-ontwikkelaars essentiële beveiligingsoplossingen niet tijdig kunnen leveren en wordt dus niet aanbevolen.</translation> +<translation id="2402537890732357732">Beheerlabel altijd tonen</translation> <translation id="2402547085566757554">Pagina Nieuw tabblad niet gebruiken als homepage</translation> <translation id="240713331529749993">Als je dit beleid toepast, wordt elk van de benoemde herkomsten in een door komma's gescheiden lijst op Android uitgevoerd in een eigen proces. Elk proces van een benoemde herkomst mag alleen documenten bevatten van de betreffende herkomst en de subdomeinen daarvan. Als je bijvoorbeeld https://a1.example.com/ opgeeft, is https://a2.a1.example.com/ toegestaan in hetzelfde proces, maar https://example.com of https://b.example.com niet. Vanaf <ph name="PRODUCT_NAME" /> versie 77 worden bepaalde gevoelige sites standaard geïsoleerd op Android. Dit beleid vormt daarvan een uitbreiding waarbij nog meer specifieke herkomsten worden geïsoleerd. @@ -2177,6 +2188,7 @@ <translation id="2755847332939882873">Verzameling van prestatietracering voor het hele systeem toestaan</translation> <translation id="2757054304033424106">Typen extensies/apps die mogen worden geïnstalleerd</translation> <translation id="2759224876420453487">Het gebruikersgedrag beheren in een multiprofielsessie</translation> +<translation id="2760947619380644513">Toestaan dat gebruikers met externe toegang URL's aan de hostzijde openen in hun lokale clientbrowser</translation> <translation id="2761483219396643566">Inactieve waarschuwingsvertraging wanneer op de batterij wordt gewerkt</translation> <translation id="2764750330785898947">Ondersteuning voor contentcodering met <ph name="ZSTANDARD_SHORTNAME" /> aanzetten</translation> <translation id="2764964245640818227">Beheert of er annotaties in pdf's kunnen worden gemaakt met de pdf-viewer in <ph name="PRODUCT_NAME" />. @@ -4461,6 +4473,11 @@ Voor onbeheerde apparaten kan de gebruiker ervoor kiezen om de statistieken te sturen.</translation> <translation id="4694138212536142867">Rapportage voor hardwarestatus van apparaat aanzetten</translation> <translation id="4697581738794063407">De filterfunctie voor URL-parameters beheren</translation> +<translation id="4698147321113652592">Met dit beleid stel je een reeks wekelijkse intervallen vast om automatische opschorting te plannen. Als een interval begint, wordt de opschortingsstand van het <ph name="PRODUCT_OS_NAME" />-apparaat geactiveerd. Het apparaat wordt weer geactiveerd als het interval voorbij is. + +Planningen met overlappende intervallen worden niet ondersteund. Dit beleid heeft geen effect als het 2 overlappende intervallen bevat. + +<ph name="PRODUCT_OS_NAME" />-apparaten gebruiken de tijdzone van het systeem om deze intervallen toe te passen.</translation> <translation id="4698895924806859508">Netwerkgebeurtenissen niet rapporteren</translation> <translation id="4699172675775169585">Gecachete afbeeldingen en bestanden</translation> <translation id="4699592681017489215">Met dit beleid wordt een lokale schakelaar ingesteld die kan worden gebruikt om controles voor DNS-onderschepping uit te zetten. Deze controles proberen te achterhalen of er een proxy achter de browser zit die als omleiding naar onbekende hostnamen dient. @@ -5032,6 +5049,13 @@ <translation id="5238275681097851753">Toestaan dat bepaalde <ph name="FLASH_PLUGIN_NAME" />-content wordt geblokkeerd</translation> <translation id="5238976843489093540">Snel koppelen (snelle bluetooth-koppeling) geforceerd aanzetten.</translation> <translation id="5239277956452384929">Toegang geven tot een lijst met URL's tijdens verificatie</translation> +<translation id="5242361766432467515">Als je het beleid aanzet of niet instelt, kunnen gebruikers die verbinding hebben met een host voor externe toegang, URL's aan de hostzijde openen in hun lokale clientbrowser. + +Als je het beleid uitzet, kan de host voor externe toegang geen URL's naar de client sturen. + +Deze instelling is niet van toepassing op verbindingen voor externe support, omdat de functie niet wordt ondersteund voor die verbindingsmodus. + +Opmerking: Deze functie is nog niet algemeen beschikbaar, dus als je deze aanzet, betekent dit niet dat de functie zichtbaar is in de client-UI.</translation> <translation id="5245647012663146075">Niet toestaan dat Telefoonhub wordt aangezet</translation> <translation id="5245671702326993331">Staat native meldingen toe</translation> <translation id="524637053580639111">Dit beleid is verwijderd in M82. Gebruik in plaats daarvan DeviceMinimumVersion. @@ -5568,6 +5592,7 @@ Dit beleid kan met de beleidsregels <ph name="CLIPBOARD_ALLOWED_FOR_URLS_POLICY_NAME" /> en <ph name="CLIPBOARD_BLOCKED_FOR_URLS_POLICY_NAME" /> worden overschreven voor specifieke URL-patronen. Dit beleid is alleen van toepassing op klembordbewerkingen die worden beheerd door het klembordrecht voor sites, niet op opgeschoonde klembordschrijfbewerkingen of vertrouwde kopieer-en-plakbewerkingen.</translation> +<translation id="5650256117857913687">Niet toestaan dat gebruikers met externe toegang URL's aan de hostzijde openen in hun lokale clientbrowser</translation> <translation id="5650716720715977549">Beperkingen toepassen op verzoeken naar netwerkeindpunten die meer privé zijn</translation> <translation id="5651538748810288218">Als je het beleid instelt op 1, hebben websites toegang tot sensoren, zoals bewegings- en lichtsensoren. Als je het beleid instelt op 2, wordt de toegang tot sensoren geblokkeerd. @@ -6132,6 +6157,7 @@ <translation id="6181783961196084973">De waarde van de schakelaar voor de verzameling van app-activiteit. Als de schakelaar is ingesteld op True, wordt app-activiteit gerapporteerd aan de server zodat het te zien is in de <ph name="PRODUCT_NAME" />-app van het kind en de ouder. Als ingesteld op False, werkt de functie voor tijdslimieten per app nog steeds, maar worden er geen gegevens gerapporteerd aan de server en getoond in <ph name="PRODUCT_NAME" />.</translation> <translation id="6182206125906000651">HTTPS-upgrades uitzetten.</translation> <translation id="6182563940865917569">Toestaan dat Chrome media automatisch afspeelt</translation> +<translation id="6187632100458475876">Labelinstelling voor beheerde werkbalkavatar</translation> <translation id="6190367314942602985">Gegevens over de identiteit van gebruikers rapporteren</translation> <translation id="6191963383731098056">Met dit beleid kunnen beheerders de kleur voor het thema van <ph name="PRODUCT_NAME" /> instellen. Je moet een geldige hexadecimale kleur opgeven in de vorm van een tekenreeks met de indeling #RRGGBB. @@ -7121,6 +7147,7 @@ <translation id="6915493311660114995">Als je dit beleid toepast, staat <ph name="PRODUCT_NAME" /> verzoeken voor webverificatie toe op websites met TLS-certificaten met fouten (dat wil zeggen, websites die niet als beveiligd worden beschouwd). Als je het beleid niet toepast of niet instelt, is het standaardgedrag van toepassing, waarbij dergelijke verzoeken worden geblokkeerd.</translation> +<translation id="6915524162137327111">Beheerlabels 30 seconden tonen</translation> <translation id="6919819553978815392">Als dit beleid is ingesteld op True of niet is ingesteld, zetten <ph name="PRODUCT_NAME" /> en<ph name="LACROS_NAME" /> gastlogins aan. Gastlogins zijn <ph name="PRODUCT_NAME" />-profielen waarbij alle vensters in de incognitomodus zijn. Als dit beleid is ingesteld op False, staan <ph name="PRODUCT_NAME" /> en <ph name="LACROS_NAME" /> niet toe dat er gastprofielen worden gestart. @@ -7614,6 +7641,7 @@ <translation id="7298197471363105063">First-Party Sets overschrijven.</translation> <translation id="7300320787419338290">F11-/F12-instellingen gebruiken de sneltoets met de functietoetsen Ctrl en Shift</translation> <translation id="7302043767260300182">Vertraging van schermvergrendeling wanneer op netstroom wordt gewerkt</translation> +<translation id="7302500623317853506">Uitgebreide automatische updates toestaan</translation> <translation id="7303655680460311843">Virtueel aanraaktoetsenbord aanzetten op het inlogscherm</translation> <translation id="7303902834678570827">Gebruikers van beheerde gastsessies kunnen geen weergave-eigenschappen voor het hele apparaat opslaan</translation> <translation id="7306926210354955892">Als je het beleid instelt, geef je de actie op die moet worden uitgevoerd als de ARC-gegevensdirectory van de gebruiker is gemaakt met virtio-fs. Tenzij virtio-fs-gegevens worden gemigreerd naar virtio-blk, worden Android-apps misschien langzamer uitgevoerd op ARC VM. @@ -8381,6 +8409,11 @@ Dit beleid is verwijderd in Chrome 110. </translation> <translation id="7976157349247117979">Naam van de bestemming van <ph name="PRODUCT_NAME" /></translation> +<translation id="797820628785995988">Als je het beleid instelt, worden alle aangegeven gegevenstypen uitgesloten van synchronisatie voor zowel <ph name="CHROME_SYNC_NAME" /> als synchronisatie van roamingprofielen. Dit kan handig zijn om het roamingprofiel te verkleinen of het type gegevens te beperken dat wordt geüpload naar de <ph name="CHROME_SYNC_NAME" />-servers. + + De huidige gegevenstypen voor dit beleid zijn: 'apps', 'autofill', 'bookmarks', 'extensions', 'preferences', 'passwords', 'payments', 'readingList', 'savedTabGroups', 'tabs', 'themes', 'typedUrls', 'wifiConfigurations'. Die namen zijn hoofdlettergevoelig. + + Opmerkingen: Beleid dynamisch vernieuwen wordt alleen ondersteund in <ph name="PRODUCT_NAME" /> versie 123 en hoger. Als je 'autofill' uitzet, wordt 'payments' ook uitgezet. 'typedUrls' verwijst naar de hele browsegeschiedenis.</translation> <translation id="7982057585796399404">Als je het beleid instelt, wordt een lijst met apps en extensies gespecificeerd die op de achtergrond worden geïnstalleerd zonder interactie met de gebruiker en die niet kunnen worden verwijderd of uitgezet door gebruikers. Rechten worden impliciet verleend, waaronder voor de extensie-API's enterprise.deviceAttributes en enterprise.platformKeys. (Deze 2 API's zijn niet beschikbaar voor apps en extensies die niet afgedwongen geïnstalleerd zijn.) Als je dit beleid niet instelt, worden apps of extensies niet automatisch geïnstalleerd en kunnen gebruikers elke app of extensie in <ph name="PRODUCT_NAME" /> verwijderen. @@ -8664,6 +8697,10 @@ <translation id="8250048892729838843">Dit beleid is beëindigd. Als je dit beleid toepast of niet instelt, kan het apparaat opties voor gedetailleerde rapportage krijgen. Als je het beleid niet toepast, kunnen ingeschreven apparaten geen opties voor gedetailleerde rapportage krijgen.</translation> <translation id="82530263956734297">Extensie-ID's die zijn vrijgesteld van de blokkeringslijst</translation> +<translation id="8254792295762772851">Als je dit beleid niet instelt of instelt op <ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" /> (waarde 0), wordt het label Werk of School naast de werkbalkavatar getoond. +Deze labels worden alleen getoond als het ingelogde account wordt beheerd. + +Als je dit beleid instelt op <ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" /> (waarde 1), wordt 30 seconden nadat je het profiel hebt geopend het label Werk of School naast de werkbalkavatar getoond.</translation> <translation id="8256006033157034334">Dit beleid is beëindigd en wordt niet ondersteund. Gebruik in plaats daarvan <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" />.</translation> <translation id="8256688113167012935">Hiermee wordt de weergave van de accountnaam in <ph name="PRODUCT_OS_NAME" /> op het aanmeldscherm beheerd voor het bijbehorende lokale account van het apparaat. @@ -9260,6 +9297,7 @@ Als je het beleid instelt, kunnen gebruikers deze functie niet wijzigen. Als je het niet instelt, kunnen ze de instelling wel wijzigen.</translation> <translation id="8707790573162457301">Automatische schijfopruiming uitvoeren tijdens inloggen</translation> +<translation id="8712609946151927008">Wekelijkse opschortingsintervallen plannen</translation> <translation id="8713535263782304771">Safe Browsing uitzetten</translation> <translation id="8714556680280715750">Een URL die gebruikers kunnen bezoeken voor meer informatie. Als je dit beleid niet instelt, bevat het installatieprogramma geen URL met meer informatie. Indien aanwezig moet dit het https-schema gebruiken.</translation> <translation id="8715885991031124968">JavaScript-dialoogvensters toestaan als deze worden geactiveerd vanaf een subframe met een andere oorsprong.</translation> @@ -9406,6 +9444,7 @@ <translation id="8862086508140571198">Met dit beleid kun je een lijst met DLC's (downloadbare content) instellen die zo snel mogelijk moeten worden gedownload. De gedownloade DLC's zijn dan beschikbaar voor alle gebruikers op het apparaat. Dit is handig als de beheerder weet dat de gebruikers van het apparaat een functie waarvoor de aanwezigheid van de DLC is vereist, waarschijnlijk gebruiken.</translation> +<translation id="8864727482158496280">Uitgebreide automatische updates niet toestaan</translation> <translation id="8864975621965365890">Hiermee onderdruk je de prompt die je ziet als een site wordt weergegeven door <ph name="PRODUCT_FRAME_NAME" />.</translation> <translation id="8865404058177794289">De standaardinstelling gebruiken voor controle van het RSA-sleutelgebruik</translation> <translation id="8866430022832109569">Rapportage van app-voorraad</translation>
diff --git a/components/policy/resources/policy_templates_pt-BR.xtb b/components/policy/resources/policy_templates_pt-BR.xtb index 2c6a5fa2..5f084e5 100644 --- a/components/policy/resources/policy_templates_pt-BR.xtb +++ b/components/policy/resources/policy_templates_pt-BR.xtb
@@ -1801,6 +1801,7 @@ Definir <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" /> (valor 1) permite que apenas as variações consideradas como correções críticas de segurança ou estabilidade sejam aplicadas ao <ph name="PRODUCT_NAME" />. Definir <ph name="VARIATIONS_DISABLED_OPTION_NAME" /> (valor 2) impede que qualquer variação seja aplicada ao navegador. Esse modo não é recomendado, porque pode impedir que os desenvolvedores do <ph name="PRODUCT_NAME" /> forneçam correções críticas de segurança de maneira rápida.</translation> +<translation id="2402537890732357732">Sempre mostrar o identificador de gerenciamento</translation> <translation id="2402547085566757554">Não usar a página Nova guia como página inicial</translation> <translation id="240713331529749993">Se a política for definida, cada uma das origens indicadas em uma lista separada por vírgulas será executada no próprio processo no Android. Cada processo de uma origem indicada só poderá conter documentos da origem em questão e dos subdomínios dela. Por exemplo, se https://a1.example.com/ for especificada, https://a2.a1.example.com/ será permitida no mesmo processo, mas https://example.com ou https://b.example.com não serão. Observe que o Android isola alguns sites confidenciais por padrão no <ph name="PRODUCT_NAME" /> 77 e em versões mais recentes, e esta política estende esse modo para isolar outras origens específicas. @@ -4641,6 +4642,11 @@ No caso de dispositivos não gerenciados, o usuário pode decidir enviar as métricas ou não.</translation> <translation id="4694138212536142867">Ativar relatórios sobre o status de hardware do dispositivo</translation> <translation id="4697581738794063407">Controlar o recurso de filtro do parâmetro de URL</translation> +<translation id="4698147321113652592">Esta política estabelece uma série de intervalos semanais para programar a suspensão automática. Quando um intervalo é iniciado, o dispositivo <ph name="PRODUCT_OS_NAME" /> entra no modo de suspensão e é ativado quando o intervalo termina. + +Não é possível usar programações com intervalos sobrepostos. Esta política não terá efeito se tiver dois intervalos sobrepostos. + +Os dispositivos <ph name="PRODUCT_OS_NAME" /> vão usar o fuso horário do sistema para aplicar esses intervalos.</translation> <translation id="4698895924806859508">Não informar eventos de rede</translation> <translation id="4699172675775169585">Imagens e arquivos armazenados em cache</translation> <translation id="4699592681017489215">Esta política configura um interruptor local que pode ser usado para desativar verificações de interceptação de DNS. As verificações tentam descobrir se o navegador está por trás de um proxy que redireciona nomes de host desconhecidos. @@ -6358,6 +6364,7 @@ <translation id="6181783961196084973">O valor da alternância da coleta de atividade em apps. Se ele for definido como verdadeiro, a atividade em apps será enviada ao servidor para ser exibida no app <ph name="PRODUCT_NAME" /> da criança e do familiar responsável. Se definido como falso o recurso de limites de tempo por app ainda funcionará, mas nenhum dado será enviado ao servidor ou exibido no <ph name="PRODUCT_NAME" />.</translation> <translation id="6182206125906000651">Desativar upgrades do HTTPS.</translation> <translation id="6182563940865917569">Permitir que o Chrome inicie mídia automaticamente</translation> +<translation id="6187632100458475876">Configuração do identificador do avatar na barra de ferramentas gerenciada</translation> <translation id="6190367314942602985">Reportar informações de identificação do usuário</translation> <translation id="6191963383731098056">Esta política permite que os administradores configurem a cor do tema do <ph name="PRODUCT_NAME" />. Para isso, a string de entrada precisa ser de uma cor hexadecimal válida compatível com o formato "#RRGGBB". @@ -7414,6 +7421,7 @@ Se ela for desativada ou deixada sem definição, o comportamento padrão de bloqueio dessas solicitações será aplicado.</translation> +<translation id="6915524162137327111">Mostrar identificadores de gerenciamento por 30 segundos</translation> <translation id="6919819553978815392">Se esta política for definida como verdadeira ou for deixada sem definição, o <ph name="PRODUCT_NAME" /> e o <ph name="LACROS_NAME" /> vão ativar os logins de visitantes. Esses são perfis do <ph name="PRODUCT_NAME" /> em que todas as janelas estão no modo de navegação anônima. Se esta política for definida como falsa, o <ph name="PRODUCT_NAME" /> e o <ph name="LACROS_NAME" /> não vão permitir que perfis de visitantes sejam iniciados. @@ -8688,6 +8696,11 @@ Esta política foi removida no Chrome 110. </translation> <translation id="7976157349247117979">Nome do destino do <ph name="PRODUCT_NAME" /></translation> +<translation id="797820628785995988">Se esta política for definida, todos os tipos de dados especificados serão excluídos da sincronização, tanto para a <ph name="CHROME_SYNC_NAME" /> quanto para a sincronização de perfil de roaming. Isso pode ajudar a reduzir o tamanho do perfil de roaming ou limitar o tipo de dado que será enviado por upload aos servidores da <ph name="CHROME_SYNC_NAME" />. + + Atualmente, os tipos de dados para esta política são: "apps", "autofill", "bookmarks", "extensions", "preferences", "passwords", "payments", "readingList", "savedTabGroups", "tabs", "themes", "typedUrls" e "wifiConfigurations". Esses nomes têm diferenciação entre letras maiúsculas e minúsculas. + + Observações: a atualização dinâmica de políticas está disponível apenas na versão 123 e mais recentes do <ph name="PRODUCT_NAME" />. Desativar a opção "autofill" também desativa "payments". "typedUrls" refere-se a todo o histórico de navegação.</translation> <translation id="7982057585796399404">Se definida, a política especificará uma lista de apps e extensões com instalação silenciosa, sem interação do usuário, e que não podem ser desinstalados ou desativados. As permissões são concedidas implicitamente, inclusive para as APIs de extensão enterprise.deviceAttributes e enterprise.platformKeys. Essas duas APIs não estão disponíveis para apps e extensões que não sejam de instalação forçada. Se a política não for definida, nenhum app ou extensão será instalado automaticamente e o usuário poderá desinstalar qualquer app ou extensão no <ph name="PRODUCT_NAME" />. @@ -8986,6 +8999,10 @@ <translation id="8250048892729838843">Esta política foi descontinuada. Se ela for ativada ou deixada sem definição, o dispositivo poderá receber controles de geração de relatórios granulares. Se ela for desativada, os dispositivos registrados não vão receber controles de geração de relatórios granulares.</translation> <translation id="82530263956734297">IDs de extensão que serão isentos da lista de bloqueio</translation> +<translation id="8254792295762772851">Se a política for deixada sem definição ou for definida como <ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" /> (valor 0), um identificador "Trabalho" ou "Escola" vai aparecer ao lado do avatar da barra de ferramentas. +Esses identificadores só aparecem se a conta conectada for gerenciada. + +Se a política for definida como <ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" /> (valor 1), um identificador "Trabalho" ou "Escola" vai aparecer ao lado do avatar da barra de ferramentas por 30 segundos após a abertura do perfil.</translation> <translation id="8256006033157034334">Essa política foi descontinuada e parou de ter suporte. Use a <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" />.</translation> <translation id="8256688113167012935">Controla o nome da conta que o <ph name="PRODUCT_OS_NAME" /> mostra na tela de login para a conta local de dispositivo correspondente. @@ -9605,6 +9622,7 @@ Se você definir a política, os usuários não poderão mudar essa função. Se ela não for definida, os usuários poderão mudar a configuração.</translation> <translation id="8707790573162457301">Executar a limpeza de disco automática durante o login</translation> +<translation id="8712609946151927008">Programar intervalos de suspensão semanais</translation> <translation id="8713535263782304771">Desativar o Navegação segura</translation> <translation id="8714556680280715750">Um URL que os usuários podem acessar para saber mais. Se essa propriedade não for configurada, não haverá um URL do tipo "saiba mais" no instalador. Se estiver presente, ela precisará usar
diff --git a/components/policy/resources/policy_templates_th.xtb b/components/policy/resources/policy_templates_th.xtb index dba22b53..ae5a2d0 100644 --- a/components/policy/resources/policy_templates_th.xtb +++ b/components/policy/resources/policy_templates_th.xtb
@@ -505,6 +505,15 @@ <translation id="1426170570389588560">กำหนดช่วงเวลาเป็นจำนวนวันในการจัดเก็บข้อมูลเมตาของงานพิมพ์</translation> <translation id="1426410128494586442">ยอมรับ</translation> <translation id="1427655258943162134">ที่อยู่หรือ URL ของพร็อกซีเซิร์ฟเวอร์</translation> +<translation id="1430811977802269244">อนุญาตให้อุปกรณ์ที่มีสิทธิ์ซึ่งจะสูญเสียการรองรับจาก Android เลือกรับการอัปเดตอัตโนมัติเพิ่มเติม + +หากเปิดใช้นโยบาย อุปกรณ์จะเลือกรับการอัปเดตอัตโนมัติเพิ่มเติม + +หากปิดใช้หรือไม่ได้ตั้งค่านโยบาย อุปกรณ์จะหยุดรับการอัปเดตหลังจากวันสิ้นสุดการอัปเดตอัตโนมัติเดิม + +นโยบายนี้มีไว้เฉพาะสำหรับรุ่นเก่าที่ไม่ได้รับการอัปเดตเพิ่มเติมโดยอัตโนมัติ + +ดูรายละเอียดเพิ่มเติมได้ที่ https://support.google.com/chrome/a/?p=extended_updates_support</translation> <translation id="1432834104376790711">นโยบายนี้จะเปิดใช้หรือปิดใช้การตั้งค่าโหมดประหยัดแบตเตอรี่ ใน Chrome การตั้งค่านี้จะช่วยให้ระบบควบคุมอัตราเฟรมให้ใช้พลังงานน้อยลงได้ หากไม่ได้ตั้งค่านโยบายนี้ ผู้ใช้ปลายทางจะควบคุมการตั้งค่านี้ได้ใน chrome://settings/performance ใน ChromeOS การตั้งค่านี้จะช่วยควบคุมอัตราเฟรมและความถี่ของ CPU, หรี่ไฟแบ็กไลต์ และให้ Android เข้าสู่โหมดประหยัดแบตเตอรี่ ในอุปกรณ์ที่มี CPU หลายตัว ระบบจะปิด CPU บางตัว @@ -579,6 +588,7 @@ หากเปิดใช้หรือไม่ได้กำหนดค่านโยบายนี้ ระบบจะเปิดใช้การเลื่อนหน้าเว็บไปยัง Fragment ของข้อความที่เจาะจงผ่าน URL หากคุณปิดใช้นโยบายนี้ ระบบจะปิดใช้การเลื่อนหน้าเว็บไปยัง Fragment ของข้อความที่เจาะจงผ่าน URL</translation> +<translation id="1468702975912409463">ให้ผู้ใช้ที่เข้าถึงจากระยะไกลเปิด URL ฝั่งโฮสต์ในเบราว์เซอร์ไคลเอ็นต์ในเครื่อง</translation> <translation id="1474273443907024088">ปิดใช้ TLS False Start</translation> <translation id="1477934438414550161">TLS 1.2</translation> <translation id="1479427764273213107">การตั้งค่านโยบายนี้จะกำหนดรายการอุปกรณ์ USB ที่ผู้ใช้จะปลดออกจากไดรเวอร์ Kernel เพื่อใช้งานผ่าน chrome.usb API ในเว็บแอปโดยตรงได้ รายการต่างๆ เป็นการจับคู่ระหว่างตัวระบุผู้ให้บริการ USB และตัวระบุผลิตภัณฑ์เพื่อที่จะระบุฮาร์ดแวร์ที่เจาะจง @@ -1752,6 +1762,7 @@ การตั้งค่า <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" /> (ค่า 1) จะอนุญาตให้ใช้เฉพาะรูปแบบที่ถือว่าเป็นการแก้ไขด้านความปลอดภัยที่สำคัญมากหรือการแก้ไขด้านความเสถียรกับ <ph name="PRODUCT_NAME" /> เท่านั้น การตั้งค่า <ph name="VARIATIONS_DISABLED_OPTION_NAME" /> (ค่า 2) จะไม่อนุญาตให้ใช้รูปแบบใดก็ตามกับเบราว์เซอร์ โปรดทราบว่าโหมดนี้อาจขัดขวางไม่ให้นักพัฒนาแอปของ <ph name="PRODUCT_NAME" /> ทำการแก้ไขด้านความปลอดภัยที่สำคัญมากได้อย่างทันท่วงที และด้วยเหตุนี้จึงไม่แนะนำให้ใช้โหมดนี้</translation> +<translation id="2402537890732357732">แสดงป้ายกำกับการจัดการเสมอ</translation> <translation id="2402547085566757554">ไม่ใช้หน้าแท็บใหม่เป็นหน้าแรก</translation> <translation id="240713331529749993">การตั้งค่านโยบายหมายความว่าต้นทางแต่ละแห่งที่มีชื่อในรายการที่คั่นด้วยคอมมาจะทำงานในกระบวนการเฉพาะบน Android กระบวนการของต้นทางแต่ละแห่งที่มีชื่อจะได้รับอนุญาตให้มีเอกสารจากต้นทางนั้นและโดเมนย่อยเท่านั้น ตัวอย่างเช่น การระบุ https://a1.example.com/ จะอนุญาต https://a2.a1.example.com/ ในกระบวนการเดียวกัน แต่ไม่อนุญาต https://example.com หรือ https://b.example.com โปรดทราบว่า Android จะแยกเว็บไซต์ที่มีความละเอียดอ่อนบางเว็บไซต์โดยค่าเริ่มต้นใน <ph name="PRODUCT_NAME" /> เวอร์ชัน 77 เป็นต้นไป และนโยบายนี้จะขยายการทำงานของโหมดดังกล่าวให้แยกต้นทางบางรายการเพิ่มเติม @@ -2176,6 +2187,7 @@ <translation id="2755847332939882873">อนุญาตให้รวบรวมการติดตามประสิทธิภาพทั้งระบบ</translation> <translation id="2757054304033424106">ประเภทของส่วนขยาย/แอปพลิเคชันที่ได้รับอนุญาตให้ติดตั้ง</translation> <translation id="2759224876420453487">ควบคุมพฤติกรรมผู้ใช้ในเซสชันหลายโปรไฟล์</translation> +<translation id="2760947619380644513">อนุญาตให้ผู้ใช้ที่เข้าถึงจากระยะไกลเปิด URL ฝั่งโฮสต์ในเบราว์เซอร์ไคลเอ็นต์ในเครื่องได้</translation> <translation id="2761483219396643566">คำเตือนการไม่ใช้งานล่าช้าเมื่อทำงานโดยใช้กำลังแบตเตอรี่</translation> <translation id="2764750330785898947">เปิดใช้การรองรับการเข้ารหัสเนื้อหาด้วย <ph name="ZSTANDARD_SHORTNAME" /></translation> <translation id="2764964245640818227">ควบคุมว่าโปรแกรมอ่าน PDF ใน <ph name="PRODUCT_NAME" /> จะใส่คำอธิบายประกอบใน PDF ได้หรือไม่ @@ -4472,6 +4484,11 @@ สำหรับอุปกรณ์ที่ไม่มีการจัดการ ผู้ใช้ตัดสินใจได้ว่าจะส่งเมตริกหรือไม่</translation> <translation id="4694138212536142867">เปิดใช้การรายงานสถานะของฮาร์ดแวร์อุปกรณ์</translation> <translation id="4697581738794063407">ควบคุมฟีเจอร์ตัวกรองพารามิเตอร์ของ URL</translation> +<translation id="4698147321113652592">นโยบายนี้จะกำหนดช่วงเวลารายสัปดาห์สำหรับการตั้งเวลาการระงับอัตโนมัติ เมื่อช่วงเวลาเริ่มต้นขึ้น อุปกรณ์ <ph name="PRODUCT_OS_NAME" /> จะเข้าสู่โหมดระงับและจะทำงานอีกครั้งเมื่อช่วงเวลาสิ้นสุดลง + +ไม่รองรับการตั้งเวลาที่มีช่วงเวลาทับซ้อนกัน นโยบายนี้จะไม่มีผลใดๆ หากมีช่วงเวลา 2 ช่วงทับซ้อนกัน + +อุปกรณ์ <ph name="PRODUCT_OS_NAME" /> จะใช้ช่วงเวลาเหล่านี้ตามเขตเวลาของระบบ</translation> <translation id="4698895924806859508">ไม่รายงานเหตุการณ์ในเครือข่าย</translation> <translation id="4699172675775169585">รูปภาพและไฟล์ที่แคชไว้</translation> <translation id="4699592681017489215">นโยบายนี้กำหนดค่าการสลับในเครื่องที่จะใช้สำหรับการปิดใช้การตรวจสอบการสกัดกั้น DNS ได้ การตรวจสอบจะพยายามหาว่าเบราว์เซอร์อยู่หลังพร็อกซีที่เปลี่ยนเส้นทางชื่อโฮสต์ที่ไม่รู้จักหรือไม่ @@ -5043,6 +5060,13 @@ <translation id="5238275681097851753">อนุญาตให้บล็อกนื้อหา "<ph name="FLASH_PLUGIN_NAME" />" บางรายการ</translation> <translation id="5238976843489093540">บังคับให้เปิดใช้การจับคู่ด่วน (การจับคู่บลูทูธด่วน)</translation> <translation id="5239277956452384929">อนุญาตให้เข้าถึงรายการ URL ในระหว่างการตรวจสอบสิทธิ์</translation> +<translation id="5242361766432467515">การตั้งค่านโยบายเป็น "เปิดใช้" หรือไม่ได้ตั้งค่าอาจทำให้ผู้ใช้ที่เชื่อมต่อกับโฮสต์การเข้าถึงระยะไกลเปิด URL ฝั่งโฮสต์ในเบราว์เซอร์ไคลเอ็นต์ในเครื่องได้ + +การตั้งค่านโยบายเป็น "ปิดใช้" จะป้องกันไม่ให้โฮสต์การเข้าถึงระยะไกลส่ง URL ไปยังไคลเอ็นต์ + +การตั้งค่านี้ไม่มีผลกับการเชื่อมต่อเพื่อรับความช่วยเหลือระยะไกล เนื่องจากโหมดการเชื่อมต่อดังกล่าวไม่รองรับฟีเจอร์นี้ + +หมายเหตุ: ฟีเจอร์นี้ยังไม่พร้อมใช้งานสำหรับผู้ใช้ทั่วไป การเปิดใช้จึงไม่ได้หมายความว่าฟีเจอร์จะปรากฏใน UI ของไคลเอ็นต์</translation> <translation id="5245647012663146075">ไม่อนุญาตให้เปิดใช้ฮับโทรศัพท์</translation> <translation id="5245671702326993331">อนุญาตการแจ้งเตือนดั้งเดิม</translation> <translation id="524637053580639111">เราจะนำนโยบายนี้ออกในเวอร์ชัน M82 โปรดใช้ DeviceMinimumVersion แทน @@ -5576,6 +5600,7 @@ นโยบายนี้ถูกลบล้างสำหรับ URL บางรูปแบบได้โดยใช้นโยบาย <ph name="CLIPBOARD_ALLOWED_FOR_URLS_POLICY_NAME" /> และ <ph name="CLIPBOARD_BLOCKED_FOR_URLS_POLICY_NAME" /> นโยบายนี้มีผลเฉพาะกับการดำเนินการเกี่ยวกับคลิปบอร์ดซึ่งควบคุมโดยสิทธิ์เข้าถึงคลิปบอร์ดสำหรับเว็บไซต์ และไม่มีผลกับการเขียนคลิปบอร์ดที่มีการปรับแต่งหรือการคัดลอกและวางที่เชื่อถือได้</translation> +<translation id="5650256117857913687">ไม่ให้ผู้ใช้ที่เข้าถึงจากระยะไกลเปิด URL ฝั่งโฮสต์ในเบราว์เซอร์ไคลเอ็นต์ในเครื่อง</translation> <translation id="5650716720715977549">ใช้ข้อจำกัดกับคำขอไปยังอุปกรณ์ปลายทางของเครือข่ายที่มีความเป็นส่วนตัวมากขึ้น</translation> <translation id="5651538748810288218">การตั้งค่านโยบายเป็น 1 จะให้เว็บไซต์เข้าถึงและใช้เซ็นเซอร์ เช่น เซ็นเซอร์ตรวจจับการเคลื่อนไหวและเซ็นเซอร์แสงได้ การตั้งค่านโยบายเป็น 2 จะทำให้ระบบปฏิเสธการเข้าถึงเซ็นเซอร์ @@ -6141,6 +6166,7 @@ <translation id="6181783961196084973">ปุ่มเปิด/ปิดค่าของการรวบรวมกิจกรรมบนแอป หากตั้งค่าเป็น "จริง" ระบบจะรายงานกิจกรรมบนแอปของผู้ใช้ไปยังเซิร์ฟเวอร์เพื่อแสดงในแอป <ph name="PRODUCT_NAME" /> ของบุตรหลานและผู้ปกครอง หากตั้งค่าเป็น "เท็จ" ฟีเจอร์การจำกัดเวลาต่อแอปจะยังทำงาน แต่จะไม่มีการรายงานข้อมูลไปยังเซิร์ฟเวอร์และจะไม่แสดงใน <ph name="PRODUCT_NAME" /></translation> <translation id="6182206125906000651">ปิดใช้การอัปเกรด HTTPS</translation> <translation id="6182563940865917569">อนุญาตให้ Chrome เล่นสื่อโดยอัตโนมัติ</translation> +<translation id="6187632100458475876">การตั้งค่าป้ายกำกับรูปโปรไฟล์ของแถบเครื่องมือที่มีการจัดการ</translation> <translation id="6190367314942602985">รายงานข้อมูลประจำตัวของผู้ใช้</translation> <translation id="6191963383731098056">นโยบายนี้ให้ผู้ดูแลระบบกำหนดค่าสีธีมของ <ph name="PRODUCT_NAME" /> สตริงอินพุตควรเป็นสตริงสีแบบเลขฐานสิบหกที่ถูกต้องซึ่งมีรูปแบบ "#RRGGBB" @@ -7131,6 +7157,7 @@ <translation id="6915493311660114995">หากตั้งค่าเป็นเปิดใช้ "<ph name="PRODUCT_NAME" />" จะอนุญาตคำขอการตรวจสอบสิทธิ์ผ่านเว็บในเว็บไซต์ที่มีใบรับรอง TLS ว่ามีข้อผิดพลาด (เช่น เว็บไซต์ที่ถือว่าไม่ปลอดภัย) หากตั้งค่านโยบายเป็นปิดใช้ หรือไม่ได้ตั้งค่า ระบบจะใช้ลักษณะการทำงานเริ่มต้นของการบล็อกคำขอดังกล่าว</translation> +<translation id="6915524162137327111">แสดงป้ายกำกับการจัดการเป็นเวลา 30 วินาที</translation> <translation id="6919819553978815392">หากตั้งค่านโยบายนี้เป็น "จริง" หรือไม่ได้กำหนดค่า <ph name="PRODUCT_NAME" /> และ <ph name="LACROS_NAME" /> จะเปิดใช้การเข้าสู่ระบบแบบผู้มาเยือน การเข้าสู่ระบบแบบผู้มาเยือนคือโปรไฟล์ <ph name="PRODUCT_NAME" /> ที่หน้าต่างทั้งหมดจะอยู่ในโหมดไม่ระบุตัวตน หากตั้งค่านโยบายนี้เป็น "เท็จ" <ph name="PRODUCT_NAME" /> และ <ph name="LACROS_NAME" /> จะไม่อนุญาตให้เริ่มโปรไฟล์ผู้มาเยือน @@ -7626,6 +7653,7 @@ <translation id="7298197471363105063">ลบล้างชุดบุคคลที่หนึ่ง</translation> <translation id="7300320787419338290">การตั้งค่า F11/F12 ใช้แป้นพิมพ์ลัดที่มีแป้นกดร่วม Ctrl และ Shift</translation> <translation id="7302043767260300182">ระยะหน่วงเวลาการล็อกหน้าจอเมื่อทำงานโดยใช้ไฟ AC</translation> +<translation id="7302500623317853506">อนุญาตการอัปเดตอัตโนมัติเพิ่มเติม</translation> <translation id="7303655680460311843">เปิดใช้ฟีเจอร์แป้นพิมพ์เสมือนแบบสัมผัสในหน้าจอการเข้าสู่ระบบ</translation> <translation id="7303902834678570827">ผู้ใช้เซสชันผู้เยี่ยมชมที่มีการจัดการจะจัดเก็บการตั้งค่าการแสดงผลแบบทั่วทั้งอุปกรณ์ไม่ได้</translation> <translation id="7306926210354955892">การตั้งค่านโยบายจะระบุการดำเนินการที่จะทำเมื่อมีการสร้างไดเรกทอรีข้อมูล ARC ของผู้ใช้ด้วย virtio-fs แอป Android อาจทำงานช้าลงใน VM ของ ARC เว้นแต่ว่าจะมีการย้ายข้อมูล virtio-fs ไปยัง virtio-blk @@ -8387,6 +8415,11 @@ เรานำนโยบายนี้ออกไปแล้วใน Chrome 110 </translation> <translation id="7976157349247117979">ชื่อของปลายทาง <ph name="PRODUCT_NAME" /></translation> +<translation id="797820628785995988">หากตั้งค่านโยบายนี้ ระบบจะยกเว้นประเภทข้อมูลที่ระบุไว้ทั้งหมดจากการซิงค์ข้อมูลทั้งสำหรับ<ph name="CHROME_SYNC_NAME" /> และการซิงค์ข้อมูลโปรไฟล์แบบโรมมิ่ง วิธีนี้อาจช่วยลดขนาดของโปรไฟล์แบบโรมมิ่งหรือจำกัดประเภทข้อมูลที่อัปโหลดไปยังเซิร์ฟเวอร์<ph name="CHROME_SYNC_NAME" /> + + ประเภทข้อมูลปัจจุบันของนโยบายนี้ ได้แก่ "apps", "autofill", "bookmarks", "extensions", "preferences", "passwords", "payments", "readingList", "savedTabGroups", "tabs", "themes", "typedUrls", "wifiConfigurations" โดยชื่อประเภทข้อมูลเหล่านี้จะคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ + + หมายเหตุ: การรีเฟรชนโยบายแบบไดนามิกรองรับเฉพาะใน <ph name="PRODUCT_NAME" /> เวอร์ชัน 123 ขึ้นไปเท่านั้น การปิดใช้ประเภทข้อมูล "autofill" จะเป็นการปิดใช้ "payments" ด้วย "typedUrls" หมายถึงประวัติการท่องเว็บทั้งหมด</translation> <translation id="7982057585796399404">การตั้งค่านโยบายนี้จะระบุรายชื่อแอปและส่วนขยายที่ติดตั้งแบบเงียบ (ไม่ต้องมีการโต้ตอบจากผู้ใช้) และผู้ใช้จะถอนการติดตั้งหรือปิดใช้ไม่ได้ ระบบจะให้สิทธิ์โดยปริยาย ซึ่งรวมถึงสิทธิ์การใช้ API ของส่วนขยาย enterprise.deviceAttributes และ enterprise.platformKeys (API ทั้งสองนี้ใช้ไม่ได้กับแอปและส่วนขยายที่ไม่ได้บังคับติดตั้ง) หากไม่ตั้งค่านโยบายนี้ จะไม่มีแอปหรือส่วนขยายใดที่ติดตั้งโดยอัตโนมัติ และผู้ใช้จะถอนการติดตั้งแอปหรือส่วนขยายใดก็ได้ใน <ph name="PRODUCT_NAME" /> @@ -8671,6 +8704,10 @@ <translation id="8250048892729838843">นโยบายนี้เลิกใช้งานแล้ว การตั้งค่านโยบายเป็น "เปิดใช้" หรือไม่ได้ตั้งค่าจะทำให้อุปกรณ์รับการควบคุมการรายงานแบบละเอียดได้ หากตั้งค่านโยบายเป็น "ปิดใช้" หมายความว่าอุปกรณ์ที่ลงทะเบียนไว้จะไม่ได้รับการควบคุมการรายงานแบบละเอียด</translation> <translation id="82530263956734297">รหัสส่วนขยายที่ได้รับการยกเว้นจากรายการที่บล็อก</translation> +<translation id="8254792295762772851">การไม่ตั้งค่านโยบายนี้หรือตั้งค่าเป็น <ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" /> (ค่า 0) จะแสดงป้ายกำกับ "ที่ทำงาน" หรือ "โรงเรียน" ข้างรูปโปรไฟล์ของแถบเครื่องมือ +ป้ายกำกับเหล่านี้จะแสดงก็ต่อเมื่อบัญชีที่ลงชื่อเข้าใช้มีการจัดการบัญชี + +การตั้งค่าเป็น <ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" /> (ค่า 1) จะแสดงป้ายกำกับ "ที่ทำงาน" หรือ "โรงเรียน" ข้างรูปโปรไฟล์ของแถบเครื่องมือเป็นเวลา 30 วินาทีหลังจากเปิดโปรไฟล์</translation> <translation id="8256006033157034334">เราเลิกใช้งานและไม่รองรับนโยบายนี้แล้ว โปรดใช้ <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" /> แทน</translation> <translation id="8256688113167012935">ควบคุมชื่อบัญชี <ph name="PRODUCT_OS_NAME" /> ที่แสดงในหน้าลงชื่อเข้าใช้สำหรับบัญชีภายในอุปกรณ์ที่เกี่ยวข้องกัน @@ -9271,6 +9308,7 @@ หากคุณตั้งค่านโยบายนี้ ผู้ใช้จะเปลี่ยนฟังก์ชันนี้ไม่ได้ การไม่ตั้งค่าจะให้ผู้ใช้เปลี่ยนการตั้งค่าได้</translation> <translation id="8707790573162457301">เรียกใช้การทำความสะอาดดิสก์อัตโนมัติในระหว่างเข้าสู่ระบบ</translation> +<translation id="8712609946151927008">กำหนดช่วงเวลาการระงับรายสัปดาห์</translation> <translation id="8713535263782304771">ปิดใช้ Google Safe Browsing</translation> <translation id="8714556680280715750">URL สำหรับให้ผู้ใช้เข้าชมเพื่อดูข้อมูลเพิ่มเติม หากไม่ได้ตั้งค่าไว้ จะไม่มี URL สำหรับ "ดูข้อมูลเพิ่มเติม" ในโปรแกรมติดตั้ง หากมี ก็ต้องใช้รูปแบบ HTTPS</translation> <translation id="8715885991031124968">อนุญาตกล่องโต้ตอบ JavaScript ที่เกิดจากเฟรมย่อยที่เป็นต้นทางเฟรมอื่น</translation> @@ -9415,6 +9453,7 @@ <translation id="8862086508140571198">นโยบายนี้ช่วยให้ตั้งค่ารายการ DLC (เนื้อหาที่ดาวน์โหลดได้) ให้ดาวน์โหลดโดยเร็วที่สุด จากนั้น DLC ที่ดาวน์โหลดมาจะพร้อมให้ผู้ใช้ทุกคนในอุปกรณ์ใช้งานได้ วิธีนี้มีประโยชน์เมื่อผู้ดูแลระบบทราบว่าผู้ใช้อุปกรณ์มีแนวโน้มที่จะใช้ฟีเจอร์ที่ต้องมี DLC</translation> +<translation id="8864727482158496280">ไม่อนุญาตการอัปเดตอัตโนมัติเพิ่มเติม</translation> <translation id="8864975621965365890">ระงับการแจ้งเรื่องการปฏิเสธ ซึ่งจะปรากฏขึ้นเมื่อไซต์แสดงผลโดย <ph name="PRODUCT_FRAME_NAME" /></translation> <translation id="8865404058177794289">ใช้การตั้งค่าเริ่มต้นสําหรับการตรวจสอบการใช้งานคีย์ RSA</translation> <translation id="8866430022832109569">การรายงานพื้นที่โฆษณาในแอป</translation>
diff --git a/components/policy/resources/policy_templates_uk.xtb b/components/policy/resources/policy_templates_uk.xtb index bb43a1462..87893fd0 100644 --- a/components/policy/resources/policy_templates_uk.xtb +++ b/components/policy/resources/policy_templates_uk.xtb
@@ -1772,6 +1772,7 @@ Якщо вибрано параметр <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" /> (значення 1), до <ph name="PRODUCT_NAME" /> можна застосовувати лише варіанти, які вважаються важливими виправленнями системи безпеки або стабільності. Якщо вибрано параметр <ph name="VARIATIONS_DISABLED_OPTION_NAME" /> (значення 2), жодний варіант не застосовуватиметься до веб-переглядача. Зауважте, що в цьому режимі розробники <ph name="PRODUCT_NAME" /> можуть не мати змоги вчасно надавати важливі виправлення системи безпеки, тому ми не радимо його вмикати.</translation> +<translation id="2402537890732357732">Завжди показувати мітку для керованого облікового запису</translation> <translation id="2402547085566757554">Не робити сторінку нової вкладки головною сторінкою</translation> <translation id="240713331529749993">Якщо це правило налаштувати, кожне джерело в списку значень, відокремлених комами, відкривається окремо в ОС Android. Кожний відповідний процес може містити лише документи з цього джерела та його субдоменів. Наприклад, якщо вказати https://a1.example.com/, то https://a2.a1.example.com/ зможе відкриватися в цьому ж процесі, а https://example.com чи https://b.example.com – ні. Зверніть увагу, що, починаючи з версії 77, Android за умовчанням ізолює в <ph name="PRODUCT_NAME" /> окремі сайти з чутливою інформацією, а це правило розширює цей режим та ізолює окремі додаткові джерела. @@ -4518,6 +4519,11 @@ Показники з некерованих пристроїв користувач може надсилати за бажанням.</translation> <translation id="4694138212536142867">Увімкнути звіти про статус апаратного забезпечення пристрою</translation> <translation id="4697581738794063407">Керувати функцією фільтрування за параметрами URL-адрес</translation> +<translation id="4698147321113652592">За допомогою цього правила можна вказати низку щотижневих інтервалів, щоб запланувати автоматичне призупинення роботи пристрою. Коли інтервал починатиметься, пристрій <ph name="PRODUCT_OS_NAME" /> призупинятиме роботу, а коли завершуватиметься – пристрій знов активуватиметься. + +Інтервали не можуть накладатись один на одного. Якщо таке станеться, правило не діятиме. + +На пристроях <ph name="PRODUCT_OS_NAME" /> інтервали застосовуються на основі часового поясу системи.</translation> <translation id="4698895924806859508">Не повідомляти про події в мережі</translation> <translation id="4699172675775169585">Кешовані зображення та файли</translation> <translation id="4699592681017489215">Це правило налаштовує локальний перемикач, за допомогою якого можна вимкнути перевірки перехоплення системи DNS. Ці перевірки виявляють, чи працює веб-переглядач через проксі-сервер, який переспрямовує невідомі імена хостів. @@ -6202,6 +6208,7 @@ <translation id="6181783961196084973">Значення для перемикача історії додатків. Якщо вибрано значення true, історія додатків користувача буде надсилатися на сервер і відображатися в додатку <ph name="PRODUCT_NAME" /> дитини та батьків. Якщо вибрано значення false, функція обмеження часу використання додатка все ще працюватиме, але дані не будуть повідомлятися на сервер і показуватися в додатку <ph name="PRODUCT_NAME" />.</translation> <translation id="6182206125906000651">Вимкнути перехід на HTTPS.</translation> <translation id="6182563940865917569">Дозволити Chrome автоматично відтворювати медіафайли</translation> +<translation id="6187632100458475876">Налаштування мітки аватара на панелі інструментів у керованому обліковому записі</translation> <translation id="6190367314942602985">Повідомляти ідентифікаційну інформацію користувачів</translation> <translation id="6191963383731098056">Це правило дає змогу адміністраторам налаштувати колір теми в <ph name="PRODUCT_NAME" />. Як вхідне значення потрібно задати дійсний шістнадцятковий код кольору, що відповідає формату "#RRGGBB". @@ -7227,6 +7234,7 @@ <translation id="6915493311660114995">Якщо це правило ввімкнути, <ph name="PRODUCT_NAME" /> дозволятиме запити на веб-автентифікацію на сайтах, які мають сертифікати TLS із помилками (тобто на сайтах, які вважаються ненадійними). Якщо його вимкнути або не налаштувати, такі запити за умовчанням блокуватимуться.</translation> +<translation id="6915524162137327111">Показувати мітку керованого облікового запису протягом 30 секунд</translation> <translation id="6919819553978815392">Якщо правило не налаштувати або вибрати для нього значення true, у <ph name="PRODUCT_NAME" /> і <ph name="LACROS_NAME" /> буде ввімкнено вхід у режимі гостя. Увійшовши як гість, користувач бачить усі вікна в <ph name="PRODUCT_NAME" /> у режимі анонімного перегляду. Якщо для правила вибрати значення false, у <ph name="PRODUCT_NAME" /> і <ph name="LACROS_NAME" /> буде заборонений запуск гостьових профілів. @@ -8486,6 +8494,11 @@ У Chrome 110 це правило вилучено. </translation> <translation id="7976157349247117979">Назва місця призначення <ph name="PRODUCT_NAME" /></translation> +<translation id="797820628785995988">Якщо це правило налаштувати, усі вказані типи даних не будуть синхронізуватися в сервісі <ph name="CHROME_SYNC_NAME" /> і в переміщуваному профілі. Це може допомогти зменшити розмір переміщуваного профілю або обмежити типи даних, які завантажуються на сервери сервісу <ph name="CHROME_SYNC_NAME" />. + + Поточні типи даних для цього правила: apps, autofill, bookmarks, extensions, preferences, passwords, payments, readingList, savedTabGroups, tabs, themes, typedUrls, wifiConfigurations. У назвах враховується регістр. + + Примітка. Динамічне оновлення правил підтримується лише в <ph name="PRODUCT_NAME" /> 123 й новіших версіях. Якщо вимкнути тип даних autofill, тип payments також буде вимкнено. Значення typedUrls означає всю історію веб-перегляду.</translation> <translation id="7982057585796399404">Налаштування цього правила визначають список додатків і розширень, які встановлюються автоматично без взаємодії з користувачем і які він не може видалити або вимкнути. Дозволи, зокрема для API розширень enterprise.deviceAttributes і enterprise.platformKeys, надаються непрямо. Ці 2 API доступні лише для примусово встановлених додатків і розширень. Якщо це правило не налаштувати, додатки й розширення не встановлюватимуться автоматично, а користувачі зможуть видаляти їх у <ph name="PRODUCT_NAME" />. @@ -8769,6 +8782,10 @@ <translation id="8250048892729838843">Це правило не підтримується. Якщо ввімкнути або не налаштувати це правило, на пристрої будуть доступні елементи керування докладними звітами. Якщо його вимкнути, таких елементів не буде на зареєстрованих пристроях.</translation> <translation id="82530263956734297">Ідентифікатори розширень-винятків із чорного списку</translation> +<translation id="8254792295762772851">Якщо це правило не налаштувати або вибрати для нього значення <ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" /> (0), поруч з аватаром на панелі інструментів відображатиметься мітка "Робочий профіль" або "Профіль закладу освіти". +Ці мітки показуються, лише якщо виконано вхід у керований обліковий запис. + +Якщо вибрати значення <ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" /> (1), мітка "Робочий профіль" або "Профіль закладу освіти" відображатиметься поруч з аватаром на панелі інструментів протягом 30 секунд після відкриття профілю.</translation> <translation id="8256006033157034334">Це правило більше не підтримується. Натомість використовуйте <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" />.</translation> <translation id="8256688113167012935">Контролюється, як <ph name="PRODUCT_OS_NAME" /> відображає ім’я облікового запису на екрані входу для відповідних локальних облікових записів у пристрої. @@ -9378,6 +9395,7 @@ Якщо його налаштовано, користувачі не зможуть змінювати цю функцію. Якщо правило не налаштовано, користувачі зможуть змінювати цей параметр.</translation> <translation id="8707790573162457301">Виконувати автоматичне очищення диска під час входу</translation> +<translation id="8712609946151927008">Розклад щотижневих інтервалів призупинення</translation> <translation id="8713535263782304771">Вимкнути Безпечний перегляд</translation> <translation id="8714556680280715750">URL-адреса, за якою користувачі можуть отримати більше інформації. Якщо властивість schema не налаштувати, у програмі встановлення не буде такої URL-адреси. У наявній адресі має використовуватися схема https.</translation>
diff --git a/components/policy/resources/policy_templates_vi.xtb b/components/policy/resources/policy_templates_vi.xtb index a08a237..9feba1b2 100644 --- a/components/policy/resources/policy_templates_vi.xtb +++ b/components/policy/resources/policy_templates_vi.xtb
@@ -548,7 +548,7 @@ Nếu bạn đặt chính sách này, thì người dùng sẽ không thể thay đổi được. Nếu bạn không đặt chính sách này, thì các tùy chọn hỗ trợ tiếp cận sẽ không xuất hiện trong trình đơn, nhưng người dùng có thể chọn hiển thị các tùy chọn này thông qua trang Cài đặt. Nếu bạn bật tính năng hỗ trợ tiếp cận bằng những phương thức khác (ví dụ: bằng tổ hợp phím), thì các tùy chọn hỗ trợ tiếp cận sẽ luôn xuất hiện trong trình đơn ở khay hệ thống.</translation> -<translation id="1449777485284610883">Cho phép cài đặt và cập nhật các tiện ích lưu trữ bên ngoài Chrome Web Store</translation> +<translation id="1449777485284610883">Cho phép cài đặt và cập nhật các tiện ích lưu trữ bên ngoài Cửa hàng Chrome trực tuyến</translation> <translation id="1451113827539677573">Kiểm soát cách <ph name="PRODUCT_NAME" /> in trên <ph name="MS_WIN_NAME" />. Khi in bằng một máy in không phải PostScript trên <ph name="MS_WIN_NAME" />, đôi khi, bạn cần tạo điểm ảnh cho các lệnh in để in một cách chính xác. @@ -1958,7 +1958,7 @@ Khi đặt cờ đề xuất thành True, người dùng có thể thay đổi độ phân giải và hệ số tỷ lệ của màn hình bất kỳ trên trang cài đặt. Tuy nhiên, tùy chọn cài đặt sẽ chuyển về như cũ vào lần khởi động lại tiếp theo. Khi bạn đặt cờ đề xuất thành False hoặc không đặt cờ này, người dùng không thể thay đổi các tùy chọn cài đặt màn hình. Lưu ý: Đặt <ph name="EXTERNAL_WIDTH" /> và <ph name="EXTERNAL_HEIGHT" /> bằng pixel và <ph name="EXTERNAL_SCALE_PERCENTAGE" /> và <ph name="INTERNAL_SCALE_PERCENTAGE" /> ở dạng tỷ lệ phần trăm.</translation> -<translation id="2548331788863219790">Ngăn việc cài đặt và cập nhật các tiện ích lưu trữ bên ngoài Chrome Web Store</translation> +<translation id="2548331788863219790">Ngăn việc cài đặt và cập nhật các tiện ích lưu trữ bên ngoài Cửa hàng Chrome trực tuyến</translation> <translation id="2548397295248733155">Lưu ý rằng chúng tôi không dùng chính sách này nữa và sẽ xóa khỏi <ph name="PRODUCT_OS_NAME" /> phiên bản 85. Thay vào đó, vui lòng sử dụng <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME" />. Chỉ định khoảng thời gian kể từ lần cuối cùng người dùng nhập cho đến thời điểm màn hình bị tắt khi chạy bằng pin. @@ -2185,7 +2185,7 @@ <translation id="273678600057164019">Quá trình phân giải DNS của hệ thống sẽ chạy trong quy trình mạng.</translation> <translation id="2737917415184832294">Sử dụng HTTPS cho các lượt tải bản cập nhật xuống</translation> <translation id="2739213523971537320">Tắt bàn phím ảo cảm ứng trên màn hình đăng nhập</translation> -<translation id="2742843273354638707">Ẩn ứng dụng Chrome Web Store và liên kết chân trang khỏi Trang thẻ mới và trình chạy ứng dụng <ph name="PRODUCT_OS_NAME" />. +<translation id="2742843273354638707">Ẩn ứng dụng Cửa hàng Chrome trực tuyến và liên kết chân trang khỏi Trang thẻ mới và trình chạy ứng dụng <ph name="PRODUCT_OS_NAME" />. Khi chính sách này được đặt thành true, các biểu tượng sẽ bị ẩn. @@ -3282,7 +3282,7 @@ Xin lưu ý rằng chúng tôi đã thông báo việc loại bỏ chính sách này trong <ph name="PRODUCT_NAME" /> phiên bản 82. Tuy nhiên, chính sách này sẽ bị loại bỏ trong phiên bản 84.</translation> <translation id="3606571057705314194">Tắt bộ chọn hồ sơ khi khởi động</translation> <translation id="3608206578291537084">Bật quy trình báo cáo đã mã hoá</translation> -<translation id="3608281460204780443">Hiển thị biểu tượng Chrome Web Store trong trình chạy <ph name="PRODUCT_OS_NAME" /> và trên trang thẻ mới</translation> +<translation id="3608281460204780443">Hiển thị biểu tượng Cửa hàng Chrome trực tuyến trong trình chạy <ph name="PRODUCT_OS_NAME" /> và trên trang thẻ mới</translation> <translation id="3616490235694929053">Chính sách này kiểm soát việc người dùng có thấy màn hình cài đặt kích thước trên màn hình trong lần đăng nhập đầu tiên hay không. Nếu bạn đặt chính sách này thành false (sai), thì màn hình cài đặt kích thước trên màn hình sẽ không hiển thị. Nếu bạn đặt chính sách này thành true (đúng), thì màn hình cài đặt kích thước trên màn hình sẽ hiển thị.</translation> @@ -3317,7 +3317,7 @@ <translation id="3652670852519271837">Cho phép các trang web yêu cầu người dùng cấp quyền đọc các tệp và thư mục qua API Hệ thống tệp</translation> <translation id="3653237928288822292">Biểu tượng nhà cung cấp dịch vụ tìm kiếm mặc định</translation> <translation id="3654906736796256792">Cho phép chạy hộp cát âm thanh</translation> -<translation id="3655710915351748191">Không hiển thị biểu tượng Chrome Web Store trong trình chạy <ph name="PRODUCT_OS_NAME" /> hoặc trên trang thẻ mới</translation> +<translation id="3655710915351748191">Không hiển thị biểu tượng Cửa hàng Chrome trực tuyến trong trình chạy <ph name="PRODUCT_OS_NAME" /> hoặc trên trang thẻ mới</translation> <translation id="3655885297177292093">API Event.path sẽ ở trạng thái mặc định: có ở các phiên bản trước M109 và không có ở các phiên bản từ M109 đến 114.</translation> <translation id="3659542706175323490">Khi bạn đặt chính sách này thành Bật, tính năng khởi động khi cắm nguồn AC sẽ bật liên tục nếu được hỗ trợ trên thiết bị này. Tính năng khởi động khi cắm nguồn AC cho phép hệ thống khởi động lại từ trạng thái Tắt hoặc Ngủ đông sau khi người dùng cắm dây nguồn. @@ -3897,15 +3897,15 @@ <translation id="4164511138197196839">Nếu bạn bật chính sách này thì các tiện ích chưa phát hành trên Cửa hàng Chrome trực tuyến sẽ bị vô hiệu hoá trong <ph name="PRODUCT_NAME" />. Chính sách này chỉ áp dụng cho các tiện ích được cài đặt và cập nhật từ -Chrome Web Store. +Cửa hàng Chrome trực tuyến. Tiện ích từ bên ngoài cửa hàng, chẳng hạn như tiện ích đã giải nén được cài đặt bằng chế độ nhà phát triển và tiện ích được cài đặt bằng nút chuyển dòng lệnh sẽ bị bỏ qua. Các tiện ích buộc cài đặt và tự lưu trữ sẽ bị bỏ qua. Tất cả các tiện ích cố định ở một phiên bản cũng bị bỏ qua. -Nếu bạn đặt chính sách này thành <ph name="ALLOW_UNPUBLISHED" /> (0) hoặc không đặt, các tiện ích chưa phát hành trên Chrome Web Store sẽ được cho phép. -Nếu bạn đặt chính sách này thành <ph name="DISABLE_UNPUBLISHED" /> (1) thì các tiện ích chưa phát hành trên Chrome Web Store sẽ bị vô hiệu hoá.</translation> +Nếu bạn đặt chính sách này thành <ph name="ALLOW_UNPUBLISHED" /> (0) hoặc không đặt, các tiện ích chưa phát hành trên Cửa hàng Chrome trực tuyến sẽ được cho phép. +Nếu bạn đặt chính sách này thành <ph name="DISABLE_UNPUBLISHED" /> (1) thì các tiện ích chưa phát hành trên Cửa hàng Chrome trực tuyến sẽ bị vô hiệu hoá.</translation> <translation id="4164866067069311355">Kiểm soát phím tắt dùng để kích hoạt chế độ cài đặt F11/F12</translation> <translation id="4165986682804962316">Chế độ cài đặt trang web</translation> <translation id="4166174702671320480">Nếu bạn đặt chính sách này thành Bật, các chính sách không có chung nguồn với các chính sách có độ ưu tiên cao nhất trong một nhóm không thể phân chia sẽ bị bỏ qua. @@ -4613,7 +4613,7 @@ Nếu bạn không đặt chính sách này, giá trị mặc định chung sẽ được dùng cho tất cả trang web (không có quyền truy cập tự động).</translation> <translation id="471360812659157054">window.webkitStorageInfo sẽ không được cung cấp.</translation> -<translation id="4715773950737036924">Kiểm soát việc cung cấp tiện ích chưa phát hành trên Chrome Web Store.</translation> +<translation id="4715773950737036924">Kiểm soát việc cung cấp tiện ích chưa phát hành trên Cửa hàng Chrome trực tuyến.</translation> <translation id="4722122254122249791">Bật chính sách Cô lập trang web cho các nguồn gốc đã xác định</translation> <translation id="4722761845551711583">Thiết lập khoảng thời gian hiển thị một hình ảnh (tính bằng giây) khi trình bảo vệ màn hình cho màn hình đăng nhập có nhiều hình ảnh cần hiển thị. @@ -4644,11 +4644,11 @@ Từ phiên bản 114 trở về sau, bạn không bắt buộc phải đặt <ph name="DOH_SALT_POLICY_NAME" /> nếu đã đặt chính sách này.</translation> <translation id="473673197014866318">Nếu bạn đặt chính sách này, hệ thống sẽ kiểm soát các chế độ cài đặt quản lý tiện ích cho <ph name="PRODUCT_NAME" />, bao gồm cả những chế độ cài đặt chịu sự kiểm soát của các chính sách hiện có liên quan đến tiện ích. Chính sách này sẽ thay thế mọi chính sách cũ mà bạn có thể đã đặt. -Chính sách này chỉ liên kết một mã tiện ích hoặc một URL cập nhật với chế độ cài đặt cụ thể tương ứng. Bạn có thể đặt cấu hình mặc định cho mã đặc biệt <ph name="DEFAULT_SCOPE" />. Cấu hình này sẽ áp dụng cho tất cả tiện ích chưa đặt cấu hình tuỳ chỉnh trong chính sách này. Với URL cập nhật, cấu hình sẽ áp dụng cho những tiện ích có URL cập nhật chính xác được nêu trong tệp kê khai của tiện ích đó (http://support.google.com/chrome/a?p=Configure_ExtensionSettings_policy). Nếu bạn đặt cờ "override_update_url" thành true, thì tiện ích đó sẽ được cài đặt và cập nhật bằng URL "cập nhật" được chỉ định trong chính sách <ph name="EXTENSION_INSTALL_FORCELIST_POLICY_NAME" /> hoặc trong trường "update_url" của chính sách này. Cờ "override_update_url" sẽ bị bỏ qua nếu "update_url" là một URL của Chrome Web Store. +Chính sách này chỉ liên kết một mã tiện ích hoặc một URL cập nhật với chế độ cài đặt cụ thể tương ứng. Bạn có thể đặt cấu hình mặc định cho mã đặc biệt <ph name="DEFAULT_SCOPE" />. Cấu hình này sẽ áp dụng cho tất cả tiện ích chưa đặt cấu hình tuỳ chỉnh trong chính sách này. Với URL cập nhật, cấu hình sẽ áp dụng cho những tiện ích có URL cập nhật chính xác được nêu trong tệp kê khai của tiện ích đó (http://support.google.com/chrome/a?p=Configure_ExtensionSettings_policy). Nếu bạn đặt cờ "override_update_url" thành true, thì tiện ích đó sẽ được cài đặt và cập nhật bằng URL "cập nhật" được chỉ định trong chính sách <ph name="EXTENSION_INSTALL_FORCELIST_POLICY_NAME" /> hoặc trong trường "update_url" của chính sách này. Cờ "override_update_url" sẽ bị bỏ qua nếu "update_url" là một URL của Cửa hàng Chrome trực tuyến. -Trên các phiên bản <ph name="MS_WIN_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Chrome Web Store nếu phiên bản đó đã liên kết với một miền <ph name="MS_AD_NAME" />, <ph name="MS_AAD_NAME" /> hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />. +Trên các phiên bản <ph name="MS_WIN_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Cửa hàng Chrome trực tuyến nếu phiên bản đó đã liên kết với một miền <ph name="MS_AD_NAME" />, <ph name="MS_AAD_NAME" /> hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />. -Trên các phiên bản <ph name="MAC_OS_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Chrome Web Store nếu phiên bản đó được quản lý qua MDM (Quản lý thiết bị di động), đã liên kết với một miền qua MCX hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />.</translation> +Trên các phiên bản <ph name="MAC_OS_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Cửa hàng Chrome trực tuyến nếu phiên bản đó được quản lý qua MDM (Quản lý thiết bị di động), đã liên kết với một miền qua MCX hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />.</translation> <translation id="4742973303930120836">Hạn chế chế độ in đồ họa nền</translation> <translation id="4744467872051608680">Kể từ M119, nếu bạn không đặt hoặc đặt chính sách này thành false thì WebSQL sẽ tắt, nhưng bạn có thể bật thông qua cờ Chrome "web-sql-access". Nếu bạn đặt chính sách này thành true, thì quyền truy cập vào WebSQL sẽ bật.</translation> <translation id="4745232963710538589">Bật tiện ích thông tin chi tiết để báo cáo các chỉ số về việc sử dụng</translation> @@ -6422,9 +6422,9 @@ Nếu một ứng dụng hoặc tiện ích bị buộc cài đặt trước đây và hiện đã bị xóa khỏi danh sách này, thì <ph name="PRODUCT_NAME" /> sẽ tự động gỡ cài đặt ứng dụng/tiện ích đó. - Mỗi mục danh sách của chính sách là một chuỗi chứa một mã tiện ích và một URL "cập nhật" (không bắt buộc) phân tách bằng dấu chấm phẩy (<ph name="SEMICOLON" />). Mã tiện ích là một chuỗi gồm 32 chữ cái, chẳng hạn như trên <ph name="CHROME_EXTENSIONS_LINK" /> khi ở chế độ nhà phát triển. URL "cập nhật", nếu được chỉ định, phải trỏ tới tài liệu XML của tệp kê khai cập nhật như mô tả tại <ph name="LINK_TO_EXTENSION_DOC1" />. Theo mặc định, URL cập nhật của Chrome Web Store sẽ được sử dụng (hiện là "https://clients2.google.com/service/update2/crx"). Xin lưu ý rằng URL "cập nhật" được đặt trong chính sách này chỉ dùng cho lần cài đặt ban đầu; các lần cập nhật tiện ích tiếp theo sẽ sử dụng URL cập nhật nêu trong tệp kê khai của tiện ích. + Mỗi mục danh sách của chính sách là một chuỗi chứa một mã tiện ích và một URL "cập nhật" (không bắt buộc) phân tách bằng dấu chấm phẩy (<ph name="SEMICOLON" />). Mã tiện ích là một chuỗi gồm 32 chữ cái, chẳng hạn như trên <ph name="CHROME_EXTENSIONS_LINK" /> khi ở chế độ nhà phát triển. URL "cập nhật", nếu được chỉ định, phải trỏ tới tài liệu XML của tệp kê khai cập nhật như mô tả tại <ph name="LINK_TO_EXTENSION_DOC1" />. Theo mặc định, URL cập nhật của Cửa hàng Chrome trực tuyến sẽ được sử dụng (hiện là "https://clients2.google.com/service/update2/crx"). Xin lưu ý rằng URL "cập nhật" được đặt trong chính sách này chỉ dùng cho lần cài đặt ban đầu; các lần cập nhật tiện ích tiếp theo sẽ sử dụng URL cập nhật nêu trong tệp kê khai của tiện ích. - Ví dụ: <ph name="LOGIN_SCREEN_EXTENSION_POLICY_EXAMPLE" /> cài đặt ứng dụng <ph name="SMART_CARD_CONNECTOR_APP_NAME" /> từ URL "cập nhật" tiêu chuẩn của Chrome Web Store. Để biết thêm thông tin về cách lưu trữ tiện ích, hãy xem: <ph name="LINK_TO_EXTENSION_DOC2" />.</translation> + Ví dụ: <ph name="LOGIN_SCREEN_EXTENSION_POLICY_EXAMPLE" /> cài đặt ứng dụng <ph name="SMART_CARD_CONNECTOR_APP_NAME" /> từ URL "cập nhật" tiêu chuẩn của Cửa hàng Chrome trực tuyến. Để biết thêm thông tin về cách lưu trữ tiện ích, hãy xem: <ph name="LINK_TO_EXTENSION_DOC2" />.</translation> <translation id="6273107124506133797">Chính sách này không còn được dùng nữa và không được hỗ trợ, vui lòng dùng <ph name="USB_DETACHABLE_ALLOWLIST_POLICY_NAME" />.</translation> <translation id="6274202259872570803">Screencast</translation> <translation id="6275497712828649588">Ẩn cảnh báo bảo mật khi cờ hiệu dòng lệnh có thể nguy hiểm được sử dụng</translation> @@ -7866,9 +7866,9 @@ <translation id="7325801934761922681">Không cho phép Chrome chặn các thao tác di chuyển đến những giao thức bên ngoài nằm bên trong iframe hộp cát</translation> <translation id="7326394567531622570">Tương tự như Wipe (giá trị 2) nhưng cố gắng giữ lại mã đăng nhập để người dùng không phải đăng nhập lại.</translation> <translation id="7331387825106440104">Không thực thi các quy tắc ràng buộc trong các neo tin cậy được thêm cục bộ</translation> -<translation id="7331962793961469250">Khi được đặt thành True, kết quả thăng hạng của các ứng dụng trong Chrome Web Store sẽ không xuất hiện trên trang thẻ mới. +<translation id="7331962793961469250">Khi được đặt thành True, kết quả thăng hạng của các ứng dụng trong Cửa hàng Chrome trực tuyến sẽ không xuất hiện trên trang thẻ mới. - Nếu đặt tùy chọn này thành False hoặc không đặt, các kết quả thăng hạng của các ứng dụng trong Chrome Web Store sẽ xuất hiện trên trang thẻ mới.</translation> + Nếu đặt tùy chọn này thành False hoặc không đặt, các kết quả thăng hạng của các ứng dụng trong Cửa hàng Chrome trực tuyến sẽ xuất hiện trên trang thẻ mới.</translation> <translation id="7332963785317884918">Chính sách này không còn được sử dụng. <ph name="PRODUCT_OS_NAME" /> sẽ luôn sử dụng chiến lược dọn sạch 'RemoveLRU'. Kiểm soát hoạt động dọn sạch tự động trên các thiết bị <ph name="PRODUCT_OS_NAME" />. Tính năng dọn sạch tự động được kích hoạt khi dung lượng đĩa trống đạt tới mức tới hạn để khôi phục một số dung lượng đĩa. @@ -8605,11 +8605,11 @@ Người dùng có thể thay đổi mã nguồn của mọi tiện ích thông qua các công cụ cho nhà phát triển (điều này có thể khiến tiện ích hoạt động không chính xác). Nếu bạn lo ngại về điều này, hãy đặt chính sách <ph name="DEVELOPER_TOOLS_DISABLED_POLICY_NAME" />. -Mỗi mục trong danh sách của chính sách này là một chuỗi chứa một mã tiện ích và một URL cập nhật (không bắt buộc) được phân tách bằng dấu chấm phẩy (;). Mã tiện ích là một chuỗi gồm 32 chữ cái, chẳng hạn như mã tiện ích trên chrome://extensions khi ở Chế độ nhà phát triển. Nếu được chỉ định, URL cập nhật phải trỏ đến tài liệu XML (Ngôn ngữ đánh dấu mở rộng) của Tệp kê khai cập nhật (https://developer.chrome.com/extensions/autoupdate). URL cập nhật phải sử dụng một trong các giao thức sau: <ph name="HTTP_SCHEME" />, <ph name="HTTPS_SCHEME" /> hoặc <ph name="FILE_SCHEME" />. Theo mặc định, URL cập nhật của Chrome Web Store sẽ được sử dụng. URL cập nhật được đặt trong chính sách này chỉ dùng cho lần cài đặt ban đầu. Các lần cập nhật tiện ích tiếp theo sẽ sử dụng URL cập nhật nêu trong tệp kê khai của tiện ích. Bạn có thể ghi đè url cập nhật cho những lần cập nhật tiếp theo bằng cách sử dụng chính sách <ph name="EXTENSION_SETTINGS_POLICY_NAME" />, hãy xem http://support.google.com/chrome/a?p=Configure_ExtensionSettings_policy. +Mỗi mục trong danh sách của chính sách này là một chuỗi chứa một mã tiện ích và một URL cập nhật (không bắt buộc) được phân tách bằng dấu chấm phẩy (;). Mã tiện ích là một chuỗi gồm 32 chữ cái, chẳng hạn như mã tiện ích trên chrome://extensions khi ở Chế độ nhà phát triển. Nếu được chỉ định, URL cập nhật phải trỏ đến tài liệu XML (Ngôn ngữ đánh dấu mở rộng) của Tệp kê khai cập nhật (https://developer.chrome.com/extensions/autoupdate). URL cập nhật phải sử dụng một trong các giao thức sau: <ph name="HTTP_SCHEME" />, <ph name="HTTPS_SCHEME" /> hoặc <ph name="FILE_SCHEME" />. Theo mặc định, URL cập nhật của Cửa hàng Chrome trực tuyến sẽ được sử dụng. URL cập nhật được đặt trong chính sách này chỉ dùng cho lần cài đặt ban đầu. Các lần cập nhật tiện ích tiếp theo sẽ sử dụng URL cập nhật nêu trong tệp kê khai của tiện ích. Bạn có thể ghi đè url cập nhật cho những lần cập nhật tiếp theo bằng cách sử dụng chính sách <ph name="EXTENSION_SETTINGS_POLICY_NAME" />, hãy xem http://support.google.com/chrome/a?p=Configure_ExtensionSettings_policy. -Trên các phiên bản <ph name="MS_WIN_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Chrome Web Store nếu phiên bản đó đã liên kết với một miền <ph name="MS_AD_NAME" />, <ph name="MS_AAD_NAME" /> hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />. +Trên các phiên bản <ph name="MS_WIN_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Cửa hàng Chrome trực tuyến nếu phiên bản đó đã liên kết với một miền <ph name="MS_AD_NAME" />, <ph name="MS_AAD_NAME" /> hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />. -Trên các phiên bản <ph name="MAC_OS_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Chrome Web Store nếu phiên bản đó được quản lý qua MDM, đã liên kết với một miền qua MCX hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />. +Trên các phiên bản <ph name="MAC_OS_NAME" />, bạn chỉ có thể buộc cài đặt các ứng dụng và tiện ích từ bên ngoài Cửa hàng Chrome trực tuyến nếu phiên bản đó được quản lý qua MDM, đã liên kết với một miền qua MCX hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />. Lưu ý: Chính sách này không áp dụng cho Chế độ ẩn danh. Tìm hiểu về việc lưu trữ các tiện ích (https://developer.chrome.com/extensions/hosting).</translation> <translation id="7985242821674907985"><ph name="PRODUCT_NAME" /></translation> @@ -10127,7 +10127,7 @@ Nếu bạn đặt chính sách này thành false hoặc không đặt chính sách này, thì AppCache sẽ tuân theo các tùy chọn mặc định của Chrome.</translation> <translation id="930930237275114205">Thiết lập thư mục dữ liệu người dùng <ph name="PRODUCT_FRAME_NAME" /></translation> <translation id="935779984563655842">Báo cáo thông tin về Bluetooth</translation> -<translation id="936188865879911137">Nếu bạn đặt chính sách này thành Bật, thì <ph name="PRODUCT_NAME" /> sẽ cho phép cài đặt và cập nhật các tiện ích lưu trữ bên ngoài Chrome Web Store. Bạn chỉ có thể bảo vệ nội dung của những tiện ích này ở mức tối thiểu. +<translation id="936188865879911137">Nếu bạn đặt chính sách này thành Bật, thì <ph name="PRODUCT_NAME" /> sẽ cho phép cài đặt và cập nhật các tiện ích lưu trữ bên ngoài Cửa hàng Chrome trực tuyến. Bạn chỉ có thể bảo vệ nội dung của những tiện ích này ở mức tối thiểu. Nếu bạn đặt chính sách này thành Tắt, thì <ph name="PRODUCT_NAME" /> sẽ không cho phép cài đặt (và cập nhật) các tiện ích đó. Chính sách này không ảnh hưởng đến <ph name="PRODUCT_NAME" /> 78 trở lên.
diff --git a/components/policy/resources/policy_templates_zh-TW.xtb b/components/policy/resources/policy_templates_zh-TW.xtb index cd40bef..1fee5e9 100644 --- a/components/policy/resources/policy_templates_zh-TW.xtb +++ b/components/policy/resources/policy_templates_zh-TW.xtb
@@ -491,6 +491,15 @@ <translation id="1426170570389588560">設定儲存列印工作中繼資料的時間範圍 (以天為單位)</translation> <translation id="1426410128494586442">是</translation> <translation id="1427655258943162134">Proxy 伺服器的地址或網址</translation> +<translation id="1430811977802269244">允許適用裝置在 Android 停止支援後啟用延長自動更新。 + +如果將這項政策設為啟用,裝置將啟用延長自動更新。 + +如果將這項政策設為停用或未設定,裝置會在自動更新期限過後停止接收更新。 + +這項政策僅適用於不會自動接收延長更新的舊機型。 + +詳情請參閱 https://support.google.com/chrome/a/?p=extended_updates_support。</translation> <translation id="1432834104376790711">這項政策會啟用或停用省電模式設定。 如果是 Chrome,啟用這項設定會限制畫面更新率,以降低耗電量。如果不設定這項政策,使用者可前往 chrome://settings/performance 控管這項設定。 如果是 ChromeOS,啟用這項設定會限制畫面更新率和 CPU 頻率、調暗背光。如果是 Android,啟用這項設定會進入省電模式。如果是搭載多個 CPU 的裝置,系統會關閉部分 CPU。 @@ -565,6 +574,7 @@ 如果啟用或不設定這項政策,系統會啟用透過網址將網頁捲動至特定文字片段的功能。 如果停用這項政策,系統會停用透過網址將網頁捲動至特定文字片段的功能。</translation> +<translation id="1468702975912409463">允許遠端存取使用者在本機用戶端瀏覽器中開啟主機端網址</translation> <translation id="1474273443907024088">停用 TLS False Start</translation> <translation id="1477934438414550161">TLS 1.2</translation> <translation id="1479427764273213107">你可以透過這項政策來定義 USB 裝置清單,使用者可以從核心驅動程式中卸除這份清單中的 USB 裝置,並且直接透過 chrome.usb API 在網頁應用程式中使用。輸入項目為可識別特定硬體的 USB 供應商 ID 和產品 ID 組合。 @@ -1724,6 +1734,7 @@ 如果設為 <ph name="CRITICAL_VARIATIONS_ONLY_OPTION_NAME" /> (值為 1),使用者只能將修正重大安全性或穩定性問題的變化版本套用到 <ph name="PRODUCT_NAME" />。 如果設為 <ph name="VARIATIONS_DISABLED_OPTION_NAME" /> (值為 2),使用者無法將任何變化版本套用到瀏覽器。請注意,這個模式可能會讓 <ph name="PRODUCT_NAME" /> 開發人員無法及時提供重大安全性修正項目,因此不建議使用。</translation> +<translation id="2402537890732357732">一律顯示管理標籤</translation> <translation id="2402547085566757554">不要將新分頁設為首頁</translation> <translation id="240713331529749993">如果設定這項政策,那麼在 Android 裝置上,逗號分隔清單中指定的每個來源就會在獨立程序中執行。每個指定來源的程序都只能容納來自相同來源及其子網域的文件。舉例來說,如果指定 https://a1.example.com/,https://a2.a1.example.com/ 就能使用同一個程序,但是 https://example.com 和 https://b.example.com 並不能使用同一個程序。請注意,自 <ph name="PRODUCT_NAME" /> 第 77 版起,Android 平台預設會隔離某些敏感網站,而這項政策會將這個模式擴大應用至隔離其他特定來源。 @@ -2144,6 +2155,7 @@ <translation id="2755847332939882873">允許收集整個系統的效能追蹤記錄</translation> <translation id="2757054304033424106">允許安裝的擴充功能/應用程式類型</translation> <translation id="2759224876420453487">控制使用者在多重設定檔工作階段中的行為</translation> +<translation id="2760947619380644513">允許遠端存取使用者在本機用戶端瀏覽器中開啟主機端網址</translation> <translation id="2761483219396643566">在電池供電環境下執行時的閒置警告延遲時間</translation> <translation id="2764750330785898947">支援 <ph name="ZSTANDARD_SHORTNAME" /> 內容編碼功能</translation> <translation id="2764964245640818227">控管 <ph name="PRODUCT_NAME" /> 中的 PDF 檢視器是否能為 PDF 加註。 @@ -4388,6 +4400,11 @@ 如果是未受管理的裝置,使用者可以決定是否要傳送指標。</translation> <translation id="4694138212536142867">啟用裝置硬體狀態回報功能</translation> <translation id="4697581738794063407">控管網址參數篩選器功能</translation> +<translation id="4698147321113652592">這項政策會建立一系列每週時段,用以安排自動暫停時間表。時段開始時,<ph name="PRODUCT_OS_NAME" /> 裝置會進入暫停模式,時段結束後就會醒來。 + +系統不支援時段重疊的時間表。如果有任何兩個時段重疊,這項政策將不會有任何作用。 + +<ph name="PRODUCT_OS_NAME" /> 裝置會使用系統時區套用這些時段。</translation> <translation id="4698895924806859508">不要回報網路事件</translation> <translation id="4699172675775169585">快取的圖片和檔案</translation> <translation id="4699592681017489215">這項政策會設定可用於停用 DNS 攔截檢查功能的本機切換鈕。這些檢查機制會嘗試偵測瀏覽器是否透過 Proxy,將使用者重新導向未知的主機名稱。 @@ -4955,6 +4972,13 @@ <translation id="5238275681097851753">允許封鎖特定的 <ph name="FLASH_PLUGIN_NAME" /> 內容</translation> <translation id="5238976843489093540">強制啟用快速配對功能 (快速藍牙配對)。</translation> <translation id="5239277956452384929">允許在驗證期間存取網址清單</translation> +<translation id="5242361766432467515">如果將這項政策設為啟用或未設定,使用者或許可在連上遠端存取主機後,使用本機用戶端瀏覽器開啟主機端網址。 + +如果將這項政策設為停用,遠端存取主機就無法將網址傳送至用戶端。 + +這項設定不適用於遠端協助連線,原因在於該連線模式不支援這項功能。 + +注意:這項功能尚未正式發布,因此即使啟用,也不表示用戶端使用者介面會顯示這項功能。</translation> <translation id="5245647012663146075">不允許啟用 Phone Hub</translation> <translation id="5245671702326993331">允許原生通知</translation> <translation id="524637053580639111">這項政策已在 M82 版中移除,請改用 DeviceMinimumVersion。 @@ -5486,6 +5510,7 @@ 你可以將特定網址模式列於 <ph name="CLIPBOARD_ALLOWED_FOR_URLS_POLICY_NAME" /> 和 <ph name="CLIPBOARD_BLOCKED_FOR_URLS_POLICY_NAME" /> 政策中,藉此覆寫這項政策。 這項政策只會影響由剪貼簿網站權限控管的剪貼簿作業,不會對經過處理的剪貼簿寫入作業或信任的複製及貼上作業造成影響。</translation> +<translation id="5650256117857913687">禁止遠端存取使用者在本機用戶端瀏覽器中開啟主機端網址</translation> <translation id="5650716720715977549">將限制套用到更私人的網路端點</translation> <translation id="5651538748810288218">如果將這項政策設為 1,網站就能存取及使用感應器 (例如動作感應器和光度感應器)。如果將這項政策設為 2,系統會拒絕授予感應器存取權。 @@ -6041,6 +6066,7 @@ <translation id="6181783961196084973">用於切換應用程式活動收集功能的值。如果設為 True,系統會將使用者的應用程式活動回報給伺服器,以便在兒童和家長的 <ph name="PRODUCT_NAME" /> 應用程式中顯示這些資訊。如果設為 False,個別應用程式的時間限制功能仍可正常運作,但系統不會將任何資料回報給伺服器,因此 <ph name="PRODUCT_NAME" /> 也不會顯示相關資訊。</translation> <translation id="6182206125906000651">停用 HTTPS 升級功能。</translation> <translation id="6182563940865917569">允許 Chrome 自動播放媒體</translation> +<translation id="6187632100458475876">受管理的工具列顯示圖片標籤設定</translation> <translation id="6190367314942602985">回報使用者身分識別資訊</translation> <translation id="6191963383731098056">管理員可以透過這項政策設定 <ph name="PRODUCT_NAME" /> 主題的顏色。輸入的字串應為有效的十六進位顏色字串,格式為「#RRGGBB」。 @@ -7018,6 +7044,7 @@ <translation id="6913068954484253496">允許 <ph name="PRODUCT_NAME" /> 連線至所有 IP 位址上的 Cast 裝置。</translation> <translation id="6915493311660114995">如果設為啟用,即使網站的 TLS 憑證有問題 (即系統認定網站不安全),<ph name="PRODUCT_NAME" /> 仍允許來自這類網站的網路驗證要求。 如果將這項政策設為停用或不設定,系統將套用封鎖這類要求的預設行為。</translation> +<translation id="6915524162137327111">顯示管理標籤 30 秒</translation> <translation id="6919819553978815392">如果將這項政策設為 True 或不設定,<ph name="PRODUCT_NAME" /> 和 <ph name="LACROS_NAME" /> 將啟用訪客登入。訪客可以登入 <ph name="PRODUCT_NAME" /> 設定檔,登入後,所有視窗都會以無痕模式開啟。 如果將這項政策設為 False,<ph name="PRODUCT_NAME" /> 和 <ph name="LACROS_NAME" /> 將不允許啟用訪客設定檔。 @@ -7507,6 +7534,7 @@ <translation id="7298197471363105063">覆寫 First-Party Sets 功能。</translation> <translation id="7300320787419338290">使用含有 ctrl 和 shift 輔助鍵的快速鍵觸發 F11/F12 設定</translation> <translation id="7302043767260300182">在 AC 供電環境下執行時的螢幕鎖定延遲時間</translation> +<translation id="7302500623317853506">允許延長自動更新</translation> <translation id="7303655680460311843">登入畫面上啟用觸控虛擬鍵盤</translation> <translation id="7303902834678570827">受管理訪客工作階段的使用者無法儲存整部裝置的顯示設定</translation> <translation id="7306926210354955892">你可以透過這項政策指定當使用者使用 virtio-fs 建立 ARC 資料目錄時,系統要採取的動作。除非 virtio-fs 資料遷移至 virtio-blk,否則 ARC VM 上的 Android 應用程式執行速度可能會較慢。 @@ -8253,6 +8281,11 @@ 這項政策已在 Chrome 110 版中移除。 </translation> <translation id="7976157349247117979">「<ph name="PRODUCT_NAME" />」目的地名稱</translation> +<translation id="797820628785995988">如果設定這項政策,所有指定的資料類型都會從同步處理作業 (包含 <ph name="CHROME_SYNC_NAME" />和漫遊設定檔的同步處理作業) 中排除。這有助於縮減漫遊設定檔的大小,或限制上傳到 <ph name="CHROME_SYNC_NAME" />伺服器的資料類型。 + + 這項政策目前的資料類型為:「apps」、「autofill」、「bookmarks」、「extensions」、「preferences」、「passwords」、「payments」、「readingList」、「savedTabGroups」、「tabs」、「themes」、「typedUrls」和「wifiConfigurations」。這些名稱有大小寫之分! + + 注意:動態政策重新整理功能僅適用於 <ph name="PRODUCT_NAME" /> 123 以上版本。停用「autofill」也會一併停用「payments」。「typedUrls」是指所有的瀏覽記錄。</translation> <translation id="7982057585796399404">你可以透過這項政策,指定要以無訊息方式 (使用者不用操作) 安裝的應用程式和擴充功能清單,使用者無法解除安裝或停用這些應用程式和擴充功能。系統會直接授予權限給 enterprise.deviceAttributes 和 enterprise.platformKeys 擴充功能 API 等項目 (非強制安裝的應用程式和擴充功能無法取得這 2 個 API 的權限)。 如果未設定這項政策,系統不會自動安裝任何應用程式或擴充功能,且使用者可以在 <ph name="PRODUCT_NAME" /> 中解除安裝任何應用程式或擴充功能。 @@ -8528,6 +8561,10 @@ <translation id="8250048892729838843">這項政策已淘汰。如果將這項政策設為 Enabled 或不設定,裝置就能取得精細回報控制項。 如果將這項政策設為 Disabled,表示已註冊的裝置不會取得精細回報控制項。</translation> <translation id="82530263956734297">要從封鎖清單中排除的擴充功能 ID</translation> +<translation id="8254792295762772851">如果不設定這項政策或設為 <ph name="DISPLAY_MANAGEMENT_LABEL_PERMAMENT_VALUE" /> (值 0),工具列顯示圖片旁會顯示「公司」或「學校」的標籤。 +只有登入受管理的帳戶時,系統才會顯示這些標籤。 + +如果設為 <ph name="DISPLAY_MANAGEMENT_LABEL_TRANSIENT_VALUE" /> (值 1),開啟設定檔後,工具列顯示圖片旁會顯示「工作」或「學校」標籤 30 秒。</translation> <translation id="8256006033157034334">這項政策已淘汰,因此系統不再支援,請改用 <ph name="PRINTERS_BULK_ACCESS_MODE_POLICY_NAME_POLICY_NAME" />。</translation> <translation id="8256688113167012935">控制 <ph name="PRODUCT_OS_NAME" /> 在登入畫面上顯示的帳戶名稱,以表示相對應的裝置本機帳戶。 @@ -9116,6 +9153,7 @@ 如果設定這項政策,使用者將無法變更此功能。如果不設定,使用者將可變更這項設定。</translation> <translation id="8707790573162457301">在登入期間執行自動清理磁碟作業</translation> +<translation id="8712609946151927008">安排每週暫停時段</translation> <translation id="8713535263782304771">停用安全瀏覽功能</translation> <translation id="8714556680280715750">此網址可讓使用者點選以瞭解詳情。如果未設定,安裝程式中就不會顯示「瞭解詳情」網址。如果有顯示網址,則必須使用 https 配置。</translation> <translation id="8715885991031124968">允許從不同來源子頁框觸發的 JavaScript 對話方塊。</translation> @@ -9258,6 +9296,7 @@ <translation id="8862086508140571198">這項政策允許設定要盡快下載的可下載內容 (DLC) 清單。下載之後,裝置的所有使用者都使用 DLC。 如果系統管理員知道裝置使用者可能會使用需要 DLC 的功能,這項政策就非常實用。</translation> +<translation id="8864727482158496280">不允許延長自動更新</translation> <translation id="8864975621965365890">瀏覽使用 <ph name="PRODUCT_FRAME_NAME" />轉譯的網站時,隱藏停止支援提示。</translation> <translation id="8865404058177794289">使用 RSA 金鑰用途檢查的預設設定</translation> <translation id="8866430022832109569">應用程式廣告空間報表</translation>
diff --git a/components/policy/resources/templates/policies.yaml b/components/policy/resources/templates/policies.yaml index f71acbb..b227187 100644 --- a/components/policy/resources/templates/policies.yaml +++ b/components/policy/resources/templates/policies.yaml
@@ -1209,6 +1209,8 @@ 1208: ToolbarAvatarLabelSettings 1209: DeviceWeeklyScheduledSuspend 1210: RemoteAccessHostAllowUrlForwarding + 1211: ScreenCaptureLocation + 1212: AllowedDomainsForAppsList atomic_groups: 1: Homepage 2: RemoteAccess
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowedDomainsForApps.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowedDomainsForApps.yaml index 2f8d8df..09f42d4c 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowedDomainsForApps.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowedDomainsForApps.yaml
@@ -1,7 +1,9 @@ caption: Define domains allowed to access <ph name="GOOGLE_WORKSPACE_PRODUCT_NAME">Google Workspace</ph> desc: |- - Setting the policy turns on Chrome's restricted sign-in feature in <ph name="GOOGLE_WORKSPACE_PRODUCT_NAME">Google Workspace</ph> and prevents users from changing this setting. Users can only access Google tools using accounts from the specified domains (to allow gmail or googlemail accounts, add consumer_accounts to the list of domains). This setting prevents users from signing in and adding a Secondary Account on a managed device that requires Google authentication, if that account doesn't belong to one of the explicitly allowed domains. + This policy is deprecated since <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> version 122, please use the AllowedDomainsForAppsList policy instead. + + Setting the policy turns on Chrome's restricted sign-in feature in <ph name="GOOGLE_WORKSPACE_PRODUCT_NAME">Google Workspace</ph> and prevents users from changing this setting. Users can only access Google tools using accounts from the specified domains (to allow gmail or googlemail accounts, add consumer_accounts to the list of domains). This setting prevents users from signing in and adding a Secondary Account on a managed device that requires Google authentication, if that account doesn't belong to one of the explicitly allowed domains. Leaving this setting empty or unset means users can access <ph name="GOOGLE_WORKSPACE_PRODUCT_NAME">Google Workspace</ph> with any account. @@ -13,8 +15,6 @@ can_be_recommended: false dynamic_refresh: true per_profile: true -future_on: -- fuchsia owners: - igorcov@chromium.org - atwilson@chromium.org @@ -24,6 +24,7 @@ - chrome.*:51- - chrome_os:51- - android:51- +deprecated: true tags: - filtering type: string
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowedDomainsForAppsList.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowedDomainsForAppsList.yaml new file mode 100644 index 0000000..e11ac27 --- /dev/null +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowedDomainsForAppsList.yaml
@@ -0,0 +1,33 @@ +caption: Define domains allowed to access <ph name="GOOGLE_WORKSPACE_PRODUCT_NAME">Google + Workspace</ph> +desc: |- + Setting the policy turns on Chrome's restricted sign-in feature in <ph name="GOOGLE_WORKSPACE_PRODUCT_NAME">Google Workspace</ph> and prevents users from changing this setting. Users can only access Google tools using accounts from the specified domains (to allow gmail or googlemail accounts, add consumer_accounts to the list of domains). This setting prevents users from signing in and adding a Secondary Account on a managed device that requires Google authentication, if that account doesn't belong to one of the explicitly allowed domains. + + Leaving this setting empty or unset means users can access <ph name="GOOGLE_WORKSPACE_PRODUCT_NAME">Google Workspace</ph> with any account. + + Users cannot change or override this setting. + + Note: This policy causes the X-GoogApps-Allowed-Domains header to be appended to all HTTP and HTTPS requests to all google.com domains, as described in https://support.google.com/a/answer/1668854. +example_value: +- managedchrome.com +- example.com +features: + can_be_recommended: false + dynamic_refresh: true + per_profile: true +owners: +- igorcov@chromium.org +- pastarmovj@chromium.org +schema: + items: + type: string + type: array +supported_on: +- chrome.*:123- +- chrome_os:123- +- android:123- +future_on: +- fuchsia +tags: +- filtering +type: list \ No newline at end of file
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/ScreenCaptureLocation.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/ScreenCaptureLocation.yaml new file mode 100644 index 0000000..66af7f19 --- /dev/null +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/ScreenCaptureLocation.yaml
@@ -0,0 +1,27 @@ +caption: Set location to store screen captures +desc: |- + Sets the directory where Screen Captures (both screenshot and screen recordings) are being saved. + If the policy is set as recommended, the value will be used by default, but user will be able to change it. + Otherwise the user can't change it and the captures are always saved to the defined directory. + + The policy uses same format as <ph name="DOWNLOAD_DIRECTORY_POLICY_NAME">DownloadDirectory</ph> policy + The location could be set to either local filesystem or <ph name="GOOGLE_DRIVE_NAME">Google Drive</ph> (with '${google_drive}' prefix) or <ph name="MICROSOFT_ONE_DRIVE_NAME">Microsoft OneDrive</ph> (with '${onedrive}' prefix). + If the policy is set to empty string, it'll force the screen captures to be stored in the local "Downloads" directory. + See a list of variables you can use ( https://www.chromium.org/administrators/policy-list-3/user-data-directory-variables ). + + Leaving the policy unset means <ph name="PRODUCT_OS_NAME">$2<ex>Google ChromeOS</ex></ph> uses the default "Downloads" directory to store screen captures, and users can change it. +example_value: ${google_drive}/ScreenCapture +features: + can_be_recommended: true + dynamic_refresh: true + per_profile: false +owners: +- file://components/policy/OWNERS +- poromov@chromium.org +schema: + type: string +future_on: +- chrome_os +tags: +- local-data-access +type: string
diff --git a/components/policy/test/data/pref_mapping/AllowedDomainsForAppsList.json b/components/policy/test/data/pref_mapping/AllowedDomainsForAppsList.json new file mode 100644 index 0000000..5cbcb2f23 --- /dev/null +++ b/components/policy/test/data/pref_mapping/AllowedDomainsForAppsList.json
@@ -0,0 +1,33 @@ +[ + { + "os": [ + "win", + "linux", + "mac", + "chromeos_ash", + "chromeos_lacros", + "android", + "fuchsia" + ], + "policy_pref_mapping_tests": [ + { + "policies": { + "AllowedDomainsForAppsList": ["google.com","mit.edu"] + }, + "prefs": { + "settings.allowed_domains_for_apps": { + "value": "google.com,mit.edu" + } + } + }, + { + "policies": {}, + "prefs": { + "settings.allowed_domains_for_apps": { + "default_value": "" + } + } + } + ] + } +]
diff --git a/components/policy/test/data/pref_mapping/ScreenCaptureLocation.json b/components/policy/test/data/pref_mapping/ScreenCaptureLocation.json new file mode 100644 index 0000000..5470de3b --- /dev/null +++ b/components/policy/test/data/pref_mapping/ScreenCaptureLocation.json
@@ -0,0 +1,5 @@ +[ + { + "reason_for_missing_test": "Mapping not yet implemented. b/323146997" + } +] \ No newline at end of file
diff --git a/components/policy/test_support/fake_dmserver.cc b/components/policy/test_support/fake_dmserver.cc index 452606b..7cd2e11 100644 --- a/components/policy/test_support/fake_dmserver.cc +++ b/components/policy/test_support/fake_dmserver.cc
@@ -23,6 +23,11 @@ #include "components/policy/test_support/request_handler_for_policy.h" #include "components/policy/test_support/test_server_helpers.h" +#define RETURN_IF_FALSE(expr) \ + if (!expr) { \ + return false; \ + } + namespace fakedms { namespace { @@ -79,6 +84,193 @@ return resp; } +void ParsePolicyUser(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const std::string* policy_user = dict->FindString(kPolicyUserKey); + if (policy_user) { + LOG(INFO) << "Adding " << *policy_user << " as a policy user"; + policy_storage->set_policy_user(*policy_user); + } else { + LOG(INFO) << "The policy_user key isn't found and the default policy " + "user " + << policy::kDefaultUsername << " will be used"; + } +} + +void ParseManagedUsers(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const base::Value::List* managed_users = dict->FindList(kManagedUsersKey); + if (managed_users) { + for (const base::Value& managed_user : *managed_users) { + const std::string* managed_val = managed_user.GetIfString(); + if (managed_val) { + LOG(INFO) << "Adding " << *managed_val << " as a managed user"; + policy_storage->add_managed_user(*managed_val); + } + } + } +} + +void ParseDeviceAffiliationIds(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const base::Value::List* device_affiliation_ids = + dict->FindList(kDeviceAffiliationIdsKey); + if (device_affiliation_ids) { + for (const base::Value& device_affiliation_id : *device_affiliation_ids) { + const std::string* device_affiliation_id_val = + device_affiliation_id.GetIfString(); + if (device_affiliation_id_val) { + LOG(INFO) << "Adding " << *device_affiliation_id_val + << " as a device affiliation id"; + policy_storage->add_device_affiliation_id(*device_affiliation_id_val); + } + } + } +} + +void ParseUserAffiliationIds(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const base::Value::List* user_affiliation_ids = + dict->FindList(kUserAffiliationIdsKey); + if (user_affiliation_ids) { + for (const base::Value& user_affiliation_id : *user_affiliation_ids) { + const std::string* user_affiliation_id_val = + user_affiliation_id.GetIfString(); + if (user_affiliation_id_val) { + LOG(INFO) << "Adding " << *user_affiliation_id_val + << " as a user affiliation id"; + policy_storage->add_user_affiliation_id(*user_affiliation_id_val); + } + } + } +} + +void ParseDirectoryApiId(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const std::string* directory_api_id = dict->FindString(kDirectoryApiIdKey); + if (directory_api_id) { + LOG(INFO) << "Adding " << *directory_api_id << " as a directory API ID"; + policy_storage->set_directory_api_id(*directory_api_id); + } +} + +bool ParseAllowSetDeviceAttributes(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + if (const base::Value* v = dict->Find(kAllowSetDeviceAttributesKey); v) { + std::optional<bool> allow_set_device_attributes = v->GetIfBool(); + if (!allow_set_device_attributes.has_value()) { + LOG(ERROR) + << "The allow_set_device_attributes key isn't a bool, found type " + << v->type() << ", found value " << *v; + return false; + } + policy_storage->set_allow_set_device_attributes( + allow_set_device_attributes.value()); + } + return true; +} + +bool ParseUseUniversalSigningKeys(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const base::Value* use_universal_signing_keys = + dict->Find(kUseUniversalSigningKeysKey); + if (use_universal_signing_keys) { + std::optional<bool> maybe_value = use_universal_signing_keys->GetIfBool(); + if (!maybe_value.has_value()) { + LOG(ERROR) + << "The use_universal_signing_keys key isn't a bool, found type " + << use_universal_signing_keys->type() << ", found value " + << *use_universal_signing_keys; + return false; + } + if (maybe_value.value()) { + policy_storage->signature_provider()->SetUniversalSigningKeys(); + } + } + return true; +} + +void ParseRobotApiAuthCode(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const std::string* robot_api_auth_code = + dict->FindString(kRobotApiAuthCodeKey); + if (robot_api_auth_code) { + LOG(INFO) << "Adding " << *robot_api_auth_code + << " as a robot api auth code"; + policy_storage->set_robot_api_auth_code(*robot_api_auth_code); + } +} + +bool ParseRequestErrors(const base::Value::Dict* dict, + FakeDMServer* fake_dmserver) { + const base::Value::Dict* request_errors = dict->FindDict(kRequestErrorsKey); + if (request_errors) { + for (auto request_error : *request_errors) { + std::optional<int> net_error_code = request_error.second.GetIfInt(); + if (!net_error_code.has_value()) { + LOG(ERROR) << "The error code isn't an int"; + return false; + } + LOG(INFO) << "Configuring request " << request_error.first << " to error " + << net_error_code.value(); + fake_dmserver->ConfigureRequestError( + request_error.first, + static_cast<net::HttpStatusCode>(net_error_code.value())); + } + } + return true; +} + +bool ParseInitialEnrollmentState(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + const base::Value::Dict* initial_enrollment_state = + dict->FindDict(kInitialEnrollmentStateKey); + if (initial_enrollment_state) { + for (auto state : *initial_enrollment_state) { + const base::Value::Dict* state_val = state.second.GetIfDict(); + if (!state_val) { + LOG(ERROR) << "The current state value for key " << state.first + << " isn't a dict"; + return false; + } + const std::string* management_domain = + state_val->FindString(kManagementDomainKey); + if (!management_domain) { + LOG(ERROR) << "The management_domain key isn't a string"; + return false; + } + std::optional<int> initial_enrollment_mode = + state_val->FindInt(kInitialEnrollmentModeKey); + if (!initial_enrollment_mode.has_value()) { + LOG(ERROR) << "The initial_enrollment_mode key isn't an int"; + return false; + } + policy::PolicyStorage::InitialEnrollmentState initial_value; + initial_value.management_domain = *management_domain; + initial_value.initial_enrollment_mode = static_cast< + enterprise_management::DeviceInitialEnrollmentStateResponse:: + InitialEnrollmentMode>(initial_enrollment_mode.value()); + policy_storage->SetInitialEnrollmentState(state.first, initial_value); + } + } + return true; +} + +bool ParseCurrentKeyIndex(const base::Value::Dict* dict, + policy::PolicyStorage* policy_storage) { + if (const base::Value* v = dict->Find(kCurrentKeyIndexKey); v) { + std::optional<int> current_key_index = v->GetIfInt(); + if (!current_key_index.has_value()) { + LOG(ERROR) << "The current_key_index key isn't an int, found type " + << v->type() << ", found value " << *v; + return false; + } + policy_storage->signature_provider()->set_current_key_version( + current_key_index.value()); + } + return true; +} + } // namespace void InitLogging(const std::optional<std::string>& log_path, @@ -543,178 +735,7 @@ return true; } -bool FakeDMServer::ReadPolicyBlobFile() { - DCHECK_CALLED_ON_VALID_SEQUENCE(embedded_server_sequence_checker_); - if (!base::PathExists(policy_blob_path_)) { - LOG(INFO) << "Policy blob file doesn't exist yet."; - return true; - } - JSONFileValueDeserializer deserializer(policy_blob_path_); - int error_code = 0; - std::string error_msg; - std::unique_ptr<base::Value> value = - deserializer.Deserialize(&error_code, &error_msg); - if (!value) { - LOG(ERROR) << "Failed to read the policy blob file " << policy_blob_path_ - << ": " << error_msg; - return false; - } - LOG(INFO) << "Deserialized value of the policy blob: " << *value; - const base::Value::Dict* dict = value->GetIfDict(); - if (!dict) { - LOG(ERROR) << "Policy blob isn't a dict"; - return false; - } - - const std::string* policy_user = dict->FindString(kPolicyUserKey); - if (policy_user) { - LOG(INFO) << "Adding " << *policy_user << " as a policy user"; - policy_storage()->set_policy_user(*policy_user); - } else { - LOG(INFO) << "The policy_user key isn't found and the default policy " - "user " - << policy::kDefaultUsername << " will be used"; - } - - const base::Value::List* managed_users = dict->FindList(kManagedUsersKey); - if (managed_users) { - for (const base::Value& managed_user : *managed_users) { - const std::string* managed_val = managed_user.GetIfString(); - if (managed_val) { - LOG(INFO) << "Adding " << *managed_val << " as a managed user"; - policy_storage()->add_managed_user(*managed_val); - } - } - } - - const base::Value::List* device_affiliation_ids = - dict->FindList(kDeviceAffiliationIdsKey); - if (device_affiliation_ids) { - for (const base::Value& device_affiliation_id : *device_affiliation_ids) { - const std::string* device_affiliation_id_val = - device_affiliation_id.GetIfString(); - if (device_affiliation_id_val) { - LOG(INFO) << "Adding " << *device_affiliation_id_val - << " as a device affiliation id"; - policy_storage()->add_device_affiliation_id(*device_affiliation_id_val); - } - } - } - - const base::Value::List* user_affiliation_ids = - dict->FindList(kUserAffiliationIdsKey); - if (user_affiliation_ids) { - for (const base::Value& user_affiliation_id : *user_affiliation_ids) { - const std::string* user_affiliation_id_val = - user_affiliation_id.GetIfString(); - if (user_affiliation_id_val) { - LOG(INFO) << "Adding " << *user_affiliation_id_val - << " as a user affiliation id"; - policy_storage()->add_user_affiliation_id(*user_affiliation_id_val); - } - } - } - - const std::string* directory_api_id = dict->FindString(kDirectoryApiIdKey); - if (directory_api_id) { - LOG(INFO) << "Adding " << *directory_api_id << " as a directory API ID"; - policy_storage()->set_directory_api_id(*directory_api_id); - } - - if (const base::Value* v = dict->Find(kAllowSetDeviceAttributesKey); v) { - std::optional<bool> allow_set_device_attributes = v->GetIfBool(); - if (!allow_set_device_attributes.has_value()) { - LOG(ERROR) - << "The allow_set_device_attributes key isn't a bool, found type " - << v->type() << ", found value " << *v; - return false; - } - policy_storage()->set_allow_set_device_attributes( - allow_set_device_attributes.value()); - } - - const base::Value* use_universal_signing_keys = - dict->Find(kUseUniversalSigningKeysKey); - if (use_universal_signing_keys) { - std::optional<bool> maybe_value = use_universal_signing_keys->GetIfBool(); - if (!maybe_value.has_value()) { - LOG(ERROR) - << "The use_universal_signing_keys key isn't a bool, found type " - << use_universal_signing_keys->type() << ", found value " - << *use_universal_signing_keys; - return false; - } - if (maybe_value.value()) { - policy_storage()->signature_provider()->SetUniversalSigningKeys(); - } - } - - const std::string* robot_api_auth_code = - dict->FindString(kRobotApiAuthCodeKey); - if (robot_api_auth_code) { - LOG(INFO) << "Adding " << *robot_api_auth_code - << " as a robot api auth code"; - policy_storage()->set_robot_api_auth_code(*robot_api_auth_code); - } - - const base::Value::Dict* request_errors = dict->FindDict(kRequestErrorsKey); - if (request_errors) { - for (auto request_error : *request_errors) { - std::optional<int> net_error_code = request_error.second.GetIfInt(); - if (!net_error_code.has_value()) { - LOG(ERROR) << "The error code isn't an int"; - return false; - } - LOG(INFO) << "Configuring request " << request_error.first << " to error " - << net_error_code.value(); - EmbeddedPolicyTestServer::ConfigureRequestError( - request_error.first, - static_cast<net::HttpStatusCode>(net_error_code.value())); - } - } - - const base::Value::Dict* initial_enrollment_state = - dict->FindDict(kInitialEnrollmentStateKey); - if (initial_enrollment_state) { - for (auto state : *initial_enrollment_state) { - const base::Value::Dict* state_val = state.second.GetIfDict(); - if (!state_val) { - LOG(ERROR) << "The current state value for key " << state.first - << " isn't a dict"; - return false; - } - const std::string* management_domain = - state_val->FindString(kManagementDomainKey); - if (!management_domain) { - LOG(ERROR) << "The management_domain key isn't a string"; - return false; - } - std::optional<int> initial_enrollment_mode = - state_val->FindInt(kInitialEnrollmentModeKey); - if (!initial_enrollment_mode.has_value()) { - LOG(ERROR) << "The initial_enrollment_mode key isn't an int"; - return false; - } - policy::PolicyStorage::InitialEnrollmentState initial_value; - initial_value.management_domain = *management_domain; - initial_value.initial_enrollment_mode = static_cast< - enterprise_management::DeviceInitialEnrollmentStateResponse:: - InitialEnrollmentMode>(initial_enrollment_mode.value()); - policy_storage()->SetInitialEnrollmentState(state.first, initial_value); - } - } - - if (const base::Value* v = dict->Find(kCurrentKeyIndexKey); v) { - std::optional<int> current_key_index = v->GetIfInt(); - if (!current_key_index.has_value()) { - LOG(ERROR) << "The current_key_index key isn't an int, found type " - << v->type() << ", found value " << *v; - return false; - } - policy_storage()->signature_provider()->set_current_key_version( - current_key_index.value()); - } - +bool FakeDMServer::ParsePolicies(const base::Value::Dict* dict) { const base::Value::List* policies = dict->FindList(kPoliciesKey); if (policies) { for (const base::Value& policy : *policies) { @@ -754,6 +775,45 @@ return true; } +bool FakeDMServer::ReadPolicyBlobFile() { + DCHECK_CALLED_ON_VALID_SEQUENCE(embedded_server_sequence_checker_); + if (!base::PathExists(policy_blob_path_)) { + LOG(INFO) << "Policy blob file doesn't exist yet."; + return true; + } + JSONFileValueDeserializer deserializer(policy_blob_path_); + int error_code = 0; + std::string error_msg; + std::unique_ptr<base::Value> value = + deserializer.Deserialize(&error_code, &error_msg); + if (!value) { + LOG(ERROR) << "Failed to read the policy blob file " << policy_blob_path_ + << ": " << error_msg; + return false; + } + LOG(INFO) << "Deserialized value of the policy blob: " << *value; + const base::Value::Dict* dict = value->GetIfDict(); + if (!dict) { + LOG(ERROR) << "Policy blob isn't a dict"; + return false; + } + + ParsePolicyUser(dict, policy_storage()); + ParseManagedUsers(dict, policy_storage()); + ParseDeviceAffiliationIds(dict, policy_storage()); + ParseUserAffiliationIds(dict, policy_storage()); + ParseDirectoryApiId(dict, policy_storage()); + ParseRobotApiAuthCode(dict, policy_storage()); + RETURN_IF_FALSE(ParseAllowSetDeviceAttributes(dict, policy_storage())); + RETURN_IF_FALSE(ParseUseUniversalSigningKeys(dict, policy_storage())); + RETURN_IF_FALSE(ParseRequestErrors(dict, this)); + RETURN_IF_FALSE(ParseInitialEnrollmentState(dict, policy_storage())); + RETURN_IF_FALSE(ParseCurrentKeyIndex(dict, policy_storage())); + RETURN_IF_FALSE(ParsePolicies(dict)); + + return true; +} + base::Value::Dict FakeDMServer::GetValueFromClient( const policy::ClientStorage::ClientInfo& c) { base::Value::Dict dict;
diff --git a/components/policy/test_support/fake_dmserver.h b/components/policy/test_support/fake_dmserver.h index ae452fc..cdbf986 100644 --- a/components/policy/test_support/fake_dmserver.h +++ b/components/policy/test_support/fake_dmserver.h
@@ -147,6 +147,10 @@ bool SetExternalPolicyPayload(const std::string* policy_type, const std::string* entity_id, const std::string* serialized_raw_policy); + + // Parses regular and external policy from the JSON dict. + bool ParsePolicies(const base::Value::Dict* dict); + // Reads and sets the values in the policy blob file, it will return true if // the policy blob file doesn't exist yet or all the values are read // correctly, and false otherwise.
diff --git a/components/policy/test_support/fake_dmserver_unittest.cc b/components/policy/test_support/fake_dmserver_unittest.cc index 1f8071c..924e835 100644 --- a/components/policy/test_support/fake_dmserver_unittest.cc +++ b/components/policy/test_support/fake_dmserver_unittest.cc
@@ -140,6 +140,8 @@ if (response_body) { LOG(INFO) << "Response body: " << *response_body; } + LOG(INFO) << "Response headers: " + << url_loader->ResponseInfo()->headers->raw_headers(); return url_loader->ResponseInfo()->headers->response_code(); }
diff --git a/components/power_bookmarks/core/bookmark_client_base_unittest.cc b/components/power_bookmarks/core/bookmark_client_base_unittest.cc index be245bf6..4d9ec85 100644 --- a/components/power_bookmarks/core/bookmark_client_base_unittest.cc +++ b/components/power_bookmarks/core/bookmark_client_base_unittest.cc
@@ -51,9 +51,17 @@ return false; } - std::string EncodeBookmarkSyncMetadata() override { return ""; } + std::string EncodeLocalOrSyncableBookmarkSyncMetadata() override { + return ""; + } - void DecodeBookmarkSyncMetadata( + std::string EncodeAccountBookmarkSyncMetadata() override { return ""; } + + void DecodeLocalOrSyncableBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) override {} + + void DecodeAccountBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) override {}
diff --git a/components/power_bookmarks/storage/power_bookmark_backend.cc b/components/power_bookmarks/storage/power_bookmark_backend.cc index f6db588b..c49f1ee 100644 --- a/components/power_bookmarks/storage/power_bookmark_backend.cc +++ b/components/power_bookmarks/storage/power_bookmark_backend.cc
@@ -36,7 +36,8 @@ db_.reset(); - // Substitute a dummy implementation when the feature is disabled. + // Substitute a dummy implementation when the feature is disabled. Note that + // `use_database` is the PowerBookmarkBackend feature toggle on the call site. if (use_database) { db_ = std::make_unique<PowerBookmarkDatabaseImpl>(database_dir_); bool success = db_->Init(); @@ -64,9 +65,10 @@ base::WeakPtr<syncer::ModelTypeControllerDelegate> PowerBookmarkBackend::GetSyncControllerDelegate() { - if (!bridge_ && bridge_->initialized()) { - return nullptr; - } + // When the current method is called, the bridge is expected to exist + // (`use_database` in the Init() method is set iff the PowerBookmarkBackend + // feature toggle is enabled). + CHECK(bridge_); return bridge_->change_processor()->GetControllerDelegate(); }
diff --git a/components/reading_list/core/dual_reading_list_model_unittest.cc b/components/reading_list/core/dual_reading_list_model_unittest.cc index dc898ef..8bb75ef3df 100644 --- a/components/reading_list/core/dual_reading_list_model_unittest.cc +++ b/components/reading_list/core/dual_reading_list_model_unittest.cc
@@ -2607,6 +2607,119 @@ } TEST_F(DualReadingListModelTest, + ShouldMaintainCountsWhenRemoveLocalUnreadEntryFromTheLocalModel) { + ASSERT_TRUE(ResetStorageAndMimicSignedInSyncDisabled( + /*initial_local_entries_builders=*/{ + TestEntryBuilder(kUrl, clock_.Now())})); + ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInLocalOrSyncableModelOnly); + + ASSERT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul)); + + EXPECT_CALL(observer_, ReadingListWillRemoveEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul), + _)); + EXPECT_CALL(observer_, ReadingListDidRemoveEntry( + HasCountersEqual(/*size=*/0ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + + dual_model_->GetLocalOrSyncableModel()->RemoveEntryByURL(kUrl); + + EXPECT_THAT(dual_model_, HasCountersEqual(/*size=*/0ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); +} + +TEST_F(DualReadingListModelTest, + ShouldMaintainCountsWhenRemoveLocalReadEntryFromTheLocalModel) { + ASSERT_TRUE(ResetStorageAndMimicSignedInSyncDisabled( + /*initial_local_entries_builders=*/{ + TestEntryBuilder(kUrl, clock_.Now()).SetRead()})); + ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInLocalOrSyncableModelOnly); + + ASSERT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); + + EXPECT_CALL(observer_, ReadingListWillRemoveEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + EXPECT_CALL(observer_, ReadingListDidRemoveEntry( + HasCountersEqual(/*size=*/0ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + + dual_model_->GetLocalOrSyncableModel()->RemoveEntryByURL(kUrl); + + EXPECT_THAT(dual_model_, HasCountersEqual(/*size=*/0ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); +} + +TEST_F(DualReadingListModelTest, + ShouldMaintainCountsWhenRemoveCommonUnreadEntryFromTheLocalModel) { + ASSERT_TRUE(ResetStorageAndMimicSignedInSyncDisabled( + /*initial_local_entries_builders=*/{TestEntryBuilder( + kUrl, clock_.Now() + base::Seconds(1))}, + /*initial_account_entries_builders=*/{ + TestEntryBuilder(kUrl, clock_.Now()).SetRead()})); + ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInBothModels); + + ASSERT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul)); + + EXPECT_CALL(observer_, ReadingListWillUpdateEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul), + _)); + EXPECT_CALL(observer_, ReadingListDidUpdateEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + + dual_model_->GetLocalOrSyncableModel()->RemoveEntryByURL(kUrl); + + EXPECT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); + EXPECT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInAccountModelOnly); +} + +TEST_F(DualReadingListModelTest, + ShouldMaintainCountsWhenRemoveCommonReadEntryFromTheLocalModel) { + ASSERT_TRUE(ResetStorageAndMimicSignedInSyncDisabled( + /*initial_local_entries_builders=*/{TestEntryBuilder(kUrl, clock_.Now()) + .SetRead(clock_.Now() + + base::Seconds(1))}, + /*initial_account_entries_builders=*/{ + TestEntryBuilder(kUrl, clock_.Now())})); + ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInBothModels); + + ASSERT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); + + EXPECT_CALL(observer_, ReadingListWillUpdateEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + EXPECT_CALL(observer_, ReadingListDidUpdateEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul), + _)); + + dual_model_->GetLocalOrSyncableModel()->RemoveEntryByURL(kUrl); + + EXPECT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul)); + EXPECT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInAccountModelOnly); +} + +TEST_F(DualReadingListModelTest, ShouldMaintainCountsWhenAddEntryWhenSignedOut) { ASSERT_TRUE(ResetStorageAndMimicSignedOut()); ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), @@ -3157,6 +3270,95 @@ } TEST_F(DualReadingListModelTest, + ShouldMaintainCountsWhenAddLocalEntryFromTheLocalModel) { + ASSERT_TRUE(ResetStorageAndMimicSignedInSyncDisabled()); + ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kNotFound); + + ASSERT_THAT(dual_model_, HasCountersEqual(/*size=*/0ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); + + EXPECT_CALL(observer_, ReadingListWillAddEntry( + HasCountersEqual(/*size=*/0ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + EXPECT_CALL(observer_, ReadingListDidAddEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul), + _, _)); + + dual_model_->GetLocalOrSyncableModel()->AddOrReplaceEntry( + kUrl, "entry_title", reading_list::ADDED_VIA_CURRENT_APP, + /*estimated_read_time=*/base::TimeDelta()); + + EXPECT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul)); + EXPECT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInLocalOrSyncableModelOnly); +} + +TEST_F(DualReadingListModelTest, + ShouldMaintainCountsWhenAddLocalExistingEntryFromTheLocalModel) { + ASSERT_TRUE(ResetStorageAndMimicSignedInSyncDisabled( + /*initial_local_entries_builders=*/{ + TestEntryBuilder(kUrl, clock_.Now()).SetRead()})); + ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInLocalOrSyncableModelOnly); + + ASSERT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); + + EXPECT_CALL(observer_, ReadingListWillAddEntry( + HasCountersEqual(/*size=*/0ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + EXPECT_CALL(observer_, ReadingListDidAddEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul), + _, _)); + + dual_model_->GetLocalOrSyncableModel()->AddOrReplaceEntry( + kUrl, "entry_title", reading_list::ADDED_VIA_CURRENT_APP, + /*estimated_read_time=*/base::TimeDelta()); + + EXPECT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul)); + EXPECT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInLocalOrSyncableModelOnly); +} + +TEST_F(DualReadingListModelTest, + ShouldMaintainCountsWhenAddAccountExistingEntryFromTheLocalModel) { + ASSERT_TRUE(ResetStorageAndMimicSignedInSyncDisabled( + /*initial_local_entries_builders=*/{}, + /*initial_account_entries_builders*/ { + TestEntryBuilder(kUrl, clock_.Now() - base::Seconds(1)).SetRead()})); + ASSERT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInAccountModelOnly); + + ASSERT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul)); + + EXPECT_CALL(observer_, ReadingListWillUpdateEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/0ul, + /*unread_size=*/0ul), + _)); + EXPECT_CALL(observer_, ReadingListDidUpdateEntry( + HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul), + _)); + + dual_model_->GetLocalOrSyncableModel()->AddOrReplaceEntry( + kUrl, "entry_title", reading_list::ADDED_VIA_CURRENT_APP, + /*estimated_read_time=*/base::TimeDelta()); + + EXPECT_THAT(dual_model_, HasCountersEqual(/*size=*/1ul, /*unseen_size=*/1ul, + /*unread_size=*/1ul)); + EXPECT_EQ(dual_model_->GetStorageStateForURLForTesting(kUrl), + StorageStateForTesting::kExistsInBothModels); +} + +TEST_F(DualReadingListModelTest, ShouldMaintainCountsWhenSetLocalUnreadEntryUnread) { ASSERT_TRUE(ResetStorageAndTriggerLoadCompletion( /*initial_local_or_syncable_entries_builders=*/{
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.cc b/components/safe_browsing/content/browser/client_side_detection_service.cc index 3373a67..5462d46 100644 --- a/components/safe_browsing/content/browser/client_side_detection_service.cc +++ b/components/safe_browsing/content/browser/client_side_detection_service.cc
@@ -220,7 +220,11 @@ for (content::RenderProcessHost::iterator it( content::RenderProcessHost::AllHostsIterator()); !it.IsAtEnd(); it.Advance()) { - SetPhishingModel(it.GetCurrentValue(), /*new_renderer_process_host=*/false); + if (delegate_->ShouldSendModelToBrowserContext( + it.GetCurrentValue()->GetBrowserContext())) { + SetPhishingModel(it.GetCurrentValue(), + /*new_renderer_process_host=*/false); + } } if (client_side_phishing_model_) { trigger_model_version_ = @@ -507,7 +511,9 @@ void ClientSideDetectionService::OnRenderProcessHostCreated( content::RenderProcessHost* rph) { - SetPhishingModel(rph, /*new_renderer_process_host=*/true); + if (delegate_->ShouldSendModelToBrowserContext(rph->GetBrowserContext())) { + SetPhishingModel(rph, /*new_renderer_process_host=*/true); + } } void ClientSideDetectionService::SetPhishingModel(
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.h b/components/safe_browsing/content/browser/client_side_detection_service.h index 4977c87..8b26d03 100644 --- a/components/safe_browsing/content/browser/client_side_detection_service.h +++ b/components/safe_browsing/content/browser/client_side_detection_service.h
@@ -33,6 +33,7 @@ #include "components/prefs/pref_change_registrar.h" #include "components/safe_browsing/content/browser/client_side_phishing_model.h" #include "components/safe_browsing/core/common/proto/csd.pb.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host_creation_observer.h" #include "net/base/ip_address.h" @@ -80,6 +81,8 @@ GetURLLoaderFactory() = 0; virtual scoped_refptr<network::SharedURLLoaderFactory> GetSafeBrowsingURLLoaderFactory() = 0; + virtual bool ShouldSendModelToBrowserContext( + content::BrowserContext* context) = 0; }; ClientSideDetectionService(
diff --git a/components/safe_browsing/core/common/proto/csd.proto b/components/safe_browsing/core/common/proto/csd.proto index eec27ba..6398d9c 100644 --- a/components/safe_browsing/core/common/proto/csd.proto +++ b/components/safe_browsing/core/common/proto/csd.proto
@@ -2358,6 +2358,8 @@ // The telemetry configuration version used to generate this report. // This field is not present if the default configuration is used. optional uint32 configuration_version = 3; + // Tracks the current setting of developer mode in chrome://extensions page. + optional bool developer_mode_enabled = 4; } message ExtensionTelemetryReportResponse {
diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc index 02c07889..5d9a53f8 100644 --- a/components/search/ntp_features.cc +++ b/components/search/ntp_features.cc
@@ -392,6 +392,7 @@ "HistoryClustersModuleEnableContentClustering", base::FEATURE_DISABLED_BY_DEFAULT); +// If enabled, the Tab Resumption module will be shown. BASE_FEATURE(kNtpTabResumptionModule, "NtpTabResumptionModule", base::FEATURE_DISABLED_BY_DEFAULT); @@ -400,6 +401,11 @@ "NtpTabResumptionModuleCategories", base::FEATURE_DISABLED_BY_DEFAULT); +// Dummy feature to set how recent tabs must be to be shown. +BASE_FEATURE(kNtpTabResumptionModuleTimeLimit, + "NtpTabResumptionModuleTimeLimit", + base::FEATURE_DISABLED_BY_DEFAULT); + const char kNtpModuleIgnoredCriteriaThreshold[] = "NtpModuleIgnoredCriteriaThreshold"; const char kNtpModuleIgnoredHaTSDelayTimeParam[] = @@ -475,6 +481,8 @@ "NtpTabResumptionModuleCategoriesBlocklistParam"; const char kNtpTabResumptionModuleDataParam[] = "NtpTabResumptionModuleDataParam"; +const char kNtpTabResumptionModuleTimeLimitParam[] = + "NtpTabResumptionModuleTimeLimitParam"; const char kNtpTabResumptionModuleVisibilityThresholdDataParam[] = "NtpTabResumptionModuleVisibilityThresholdDataParam"; const char kWallpaperSearchHatsDelayParam[] = "WallpaperSearchHatsDelayParam";
diff --git a/components/search/ntp_features.h b/components/search/ntp_features.h index 410d9bf..163e285 100644 --- a/components/search/ntp_features.h +++ b/components/search/ntp_features.h
@@ -96,6 +96,7 @@ BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleEnableContentClustering); BASE_DECLARE_FEATURE(kNtpTabResumptionModule); BASE_DECLARE_FEATURE(kNtpTabResumptionModuleCategories); +BASE_DECLARE_FEATURE(kNtpTabResumptionModuleTimeLimit); // Parameter for controlling the luminosity difference for NTP elements on light // backgrounds. @@ -208,6 +209,8 @@ // to be shown. extern const char kNtpTabResumptionModuleCategoriesBlocklistParam[]; extern const char kNtpTabResumptionModuleDataParam[]; +// Parameter determining the recency of tabs in the Tab Resumption module. +extern const char kNtpTabResumptionModuleTimeLimitParam[]; extern const char kNtpTabResumptionModuleVisibilityThresholdDataParam[]; // Parameter determining the trigger delay of the Wallpaper Search HaTS survey. extern const char kWallpaperSearchHatsDelayParam[];
diff --git a/components/services/app_service/public/cpp/app_launch_util.cc b/components/services/app_service/public/cpp/app_launch_util.cc index 6838aad..1a75bb0 100644 --- a/components/services/app_service/public/cpp/app_launch_util.cc +++ b/components/services/app_service/public/cpp/app_launch_util.cc
@@ -97,6 +97,8 @@ APPLICATION_LAUNCH_SOURCE_SYSTEM_TRAY_CALENDAR; case LaunchSource::kFromInstaller: return ApplicationLaunchSource::APPLICATION_LAUNCH_SOURCE_INSTALLER; + case LaunchSource::kFromFirstRun: + return ApplicationLaunchSource::APPLICATION_LAUNCH_SOURCE_FIRST_RUN; } }
diff --git a/components/services/app_service/public/cpp/app_launch_util.h b/components/services/app_service/public/cpp/app_launch_util.h index f6487847..5e3e4a1c 100644 --- a/components/services/app_service/public/cpp/app_launch_util.h +++ b/components/services/app_service/public/cpp/app_launch_util.h
@@ -67,10 +67,11 @@ 35, // Profile menu of installable chrome://password-manager WebUI. kFromSysTrayCalendar = 36, // Launches from the system tray Calendar. kFromInstaller = 37, // Installation UI + kFromFirstRun = 38, // First Run. // Add any new values above this one, and update kMaxValue to the highest // enumerator value. - kMaxValue = kFromInstaller, + kMaxValue = kFromFirstRun, }; // Don't remove items or change the order of this enum. It's used in
diff --git a/components/services/app_service/public/cpp/types_util.cc b/components/services/app_service/public/cpp/types_util.cc index 22e6b5d..33d6e12 100644 --- a/components/services/app_service/public/cpp/types_util.cc +++ b/components/services/app_service/public/cpp/types_util.cc
@@ -64,6 +64,7 @@ case apps::LaunchSource::kFromOsLogin: case apps::LaunchSource::kFromProtocolHandler: case apps::LaunchSource::kFromUrlHandler: + case apps::LaunchSource::kFromFirstRun: return false; } NOTREACHED();
diff --git a/components/services/app_service/public/protos/app_types.proto b/components/services/app_service/public/protos/app_types.proto index 24d98a8c..685e0f62 100644 --- a/components/services/app_service/public/protos/app_types.proto +++ b/components/services/app_service/public/protos/app_types.proto
@@ -108,6 +108,7 @@ APPLICATION_LAUNCH_SOURCE_PROFILE_MENU = 35; APPLICATION_LAUNCH_SOURCE_SYSTEM_TRAY_CALENDAR = 36; APPLICATION_LAUNCH_SOURCE_INSTALLER = 37; + APPLICATION_LAUNCH_SOURCE_FIRST_RUN = 38; } // Describes the app uninstall source. Should be kept in sync with
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn index 8023bd5a..35913e8 100644 --- a/components/signin/core/browser/BUILD.gn +++ b/components/signin/core/browser/BUILD.gn
@@ -165,6 +165,10 @@ "mirror_landing_account_reconcilor_delegate_unittest.cc", ] } + + if (enable_dice_support) { + sources += [ "dice_account_reconcilor_delegate_unittest.cc" ] + } } if (is_android) {
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc index a417222..ada6c17 100644 --- a/components/signin/core/browser/account_reconcilor.cc +++ b/components/signin/core/browser/account_reconcilor.cc
@@ -596,7 +596,15 @@ // completely remove them from Chrome. // Revoking the token for the primary account is not supported (it should be // signed out or put to auth error state instead). - delegate_->RevokeSecondaryTokensBeforeReconcileIfNeeded(); + delegate_->RevokeSecondaryTokensForReconcileIfNeeded(verified_gaia_accounts); + if (!delegate_->IsUpdateCookieAllowed()) { + // TODO(b/320279580): Record reconcilor operation if tokens were revoked to + // match cookies. + error_during_last_reconcile_ = GoogleServiceAuthError::AuthErrorNone(); + CalculateIfMultiloginReconcileIsDone(); + ScheduleStartReconcileIfChromeAccountsChanged(); + return; + } std::vector<CoreAccountId> chrome_accounts = LoadValidAccountsFromTokenService();
diff --git a/components/signin/core/browser/account_reconcilor_delegate.cc b/components/signin/core/browser/account_reconcilor_delegate.cc index 4b58001..b046242 100644 --- a/components/signin/core/browser/account_reconcilor_delegate.cc +++ b/components/signin/core/browser/account_reconcilor_delegate.cc
@@ -22,6 +22,10 @@ return false; } +bool AccountReconcilorDelegate::IsUpdateCookieAllowed() const { + return true; +} + gaia::GaiaSource AccountReconcilorDelegate::GetGaiaApiSource() const { NOTREACHED() << "Reconcile is not enabled, no Gaia API calls should be made."; return gaia::GaiaSource::kChrome; @@ -175,8 +179,8 @@ return std::vector<CoreAccountId>(); } -void AccountReconcilorDelegate::RevokeSecondaryTokensBeforeReconcileIfNeeded() { -} +void AccountReconcilorDelegate::RevokeSecondaryTokensForReconcileIfNeeded( + const std::vector<gaia::ListedAccount>& gaia_accounts) {} void AccountReconcilorDelegate::OnAccountsCookieDeletedByUserAction( bool synced_data_deletion_in_progress) {}
diff --git a/components/signin/core/browser/account_reconcilor_delegate.h b/components/signin/core/browser/account_reconcilor_delegate.h index 777778a..a8eb9ba 100644 --- a/components/signin/core/browser/account_reconcilor_delegate.h +++ b/components/signin/core/browser/account_reconcilor_delegate.h
@@ -29,6 +29,11 @@ // false. virtual bool IsReconcileEnabled() const; + // Returns true if calling `OAuthMultiLogin` to update cookies to match + // refresh tokens is allowed. Used in Dice to disable updating cookies when + // the user is not signed in to chrome. + virtual bool IsUpdateCookieAllowed() const; + // Returns the value to set in the "source" parameter for Gaia API calls. virtual gaia::GaiaSource GetGaiaApiSource() const; @@ -55,8 +60,14 @@ const std::vector<gaia::ListedAccount>& gaia_accounts, bool first_execution); - // Revokes secondary accounts if needed. - virtual void RevokeSecondaryTokensBeforeReconcileIfNeeded(); + // On Dice platforms: + // - Revokes tokens in error state except the primary account with consent + // level `GetConsentLevelForPrimaryAccount()`. + // - If `IsUpdateCookieAllowed()` returns false, it also revokes tokens not + // present in the gaia cookies to maintain account consistency. + // On other platforms, this is no-op. + virtual void RevokeSecondaryTokensForReconcileIfNeeded( + const std::vector<gaia::ListedAccount>& gaia_accounts); // Called when cookies are deleted by user action. // This might be a no-op or signout the profile or lead to a sync paused state
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index d26877c3..961caf1 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_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 "components/signin/core/browser/account_reconcilor.h" + #include <cstring> #include <map> #include <memory> @@ -10,6 +12,7 @@ #include <vector> #include "base/containers/contains.h" +#include "base/feature_list.h" #include "base/ranges/algorithm.h" #include "base/run_loop.h" #include "base/scoped_observation.h" @@ -25,7 +28,6 @@ #include "components/content_settings/core/browser/content_settings_observer.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/prefs/pref_service.h" -#include "components/signin/core/browser/account_reconcilor.h" #include "components/signin/core/browser/mirror_account_reconcilor_delegate.h" #include "components/signin/public/base/account_consistency_method.h" #include "components/signin/public/base/consent_level.h" @@ -1571,6 +1573,40 @@ account_info.account_id)); } +const std::vector<AccountReconcilorTestTableParam> + kDiceParamsUnoPreChromeSignIn = { + // clang-format off + // See `kDiceParams` above for detailed params format. + { "", "A", IsFirstReconcile::kBoth, "", "", "A" }, + { "AB", "", IsFirstReconcile::kBoth, "", "" , "" }, + { "AB", "A", IsFirstReconcile::kBoth, "", "A", "A" }, + { "A", "B", IsFirstReconcile::kBoth, "", "" , "B" }, + { "xA", "A", IsFirstReconcile::kBoth, "", "", "A" }, + { "xAB", "A", IsFirstReconcile::kBoth, "", "", "A" }, + + // Account marked as invalid in cookies. + { "A", "xA", IsFirstReconcile::kBoth, "", "", "xA" }, + { "AB", "AxB", IsFirstReconcile::kBoth, "", "A", "AxB" }, + { "xA", "xA", IsFirstReconcile::kBoth, "", "", "xA" }, + // clang-format on +}; +class AccountReconcilorTestDiceWithUnoPreChromeSignIn + : public AccountReconcilorTestTable { + private: + base::test::ScopedFeatureList scoped_feature_list_{switches::kUnoDesktop}; +}; + +// Checks one row of the `kDiceParamsUnoPreChromeSignIn` table above. +TEST_P(AccountReconcilorTestDiceWithUnoPreChromeSignIn, TableRowTest) { + SetAccountConsistency(signin::AccountConsistencyMethod::kDice); + RunRowTest(GetParam()); +} + +INSTANTIATE_TEST_SUITE_P(, + AccountReconcilorTestDiceWithUnoPreChromeSignIn, + ::testing::ValuesIn(GenerateTestCasesFromParams( + kDiceParamsUnoPreChromeSignIn))); + #endif // BUILDFLAG(ENABLE_DICE_SUPPORT) // clang-format off
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.cc b/components/signin/core/browser/dice_account_reconcilor_delegate.cc index 586a50f..d7135d3 100644 --- a/components/signin/core/browser/dice_account_reconcilor_delegate.cc +++ b/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -17,6 +17,7 @@ #include "components/signin/public/base/signin_metrics.h" #include "components/signin/public/base/signin_pref_names.h" #include "components/signin/public/base/signin_switches.h" +#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" #include "components/signin/public/identity_manager/accounts_mutator.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/primary_account_mutator.h" @@ -35,7 +36,7 @@ } // namespace #endif -// Revokes tokens for all accounts in chrome_accounts but the primary account. +// Revokes tokens for all accounts in `chrome_accounts` but the primary account. void RevokeAllSecondaryTokens( IdentityManager* identity_manager, ConsentLevel consent_level, @@ -97,6 +98,40 @@ return true; } +bool DiceAccountReconcilorDelegate::IsUpdateCookieAllowed() const { + CHECK(IsReconcileEnabled()); + if (switches::IsExplicitBrowserSigninUIOnDesktopEnabled( + switches::ExplicitBrowserSigninPhase::kExperimental)) { + // If the user is not signed in to chrome, cookie updates (OAuthMultiLogin) + // is not allowed. In this mode, cookies are the source of truth. + return identity_manager_->HasPrimaryAccount( + GetConsentLevelForPrimaryAccount()); + } + return true; +} + +void DiceAccountReconcilorDelegate::MatchTokensWithAccountsInCookie( + const std::vector<gaia::ListedAccount>& gaia_accounts) { + CHECK(!IsUpdateCookieAllowed()); + const signin_metrics::SourceForRefreshTokenOperation source = + signin_metrics::SourceForRefreshTokenOperation:: + kAccountReconcilor_RevokeTokensNotInCookies; + auto* accounts_mutator = identity_manager_->GetAccountsMutator(); + for (const CoreAccountInfo& account_info : + identity_manager_->GetAccountsWithRefreshTokens()) { + auto it = base::ranges::find(gaia_accounts, account_info.account_id, + &gaia::ListedAccount::id); + if (it == gaia_accounts.end() || !it->valid) { + // Account not in the cookie or the account is not valid (session + // expired) and requires the user to reauth. + accounts_mutator->RemoveAccount(account_info.account_id, source); + } + } + // TODO(b/320279580): Record a histogram with the number of valid signed in + // accounts in the cookie but doesn't have a refresh token (aka Chrome + // account). +} + DiceAccountReconcilorDelegate::InconsistencyReason DiceAccountReconcilorDelegate::GetInconsistencyReason( const CoreAccountId& primary_account, @@ -331,14 +366,18 @@ : gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER; } -void DiceAccountReconcilorDelegate:: - RevokeSecondaryTokensBeforeReconcileIfNeeded() { +void DiceAccountReconcilorDelegate::RevokeSecondaryTokensForReconcileIfNeeded( + const std::vector<gaia::ListedAccount>& gaia_accounts) { RevokeAllSecondaryTokens(identity_manager_, GetConsentLevelForPrimaryAccount(), signin_metrics::SourceForRefreshTokenOperation:: kAccountReconcilor_GaiaCookiesUpdated, signin_metrics::ProfileSignout::kGaiaCookieUpdated, /*revoke_only_if_in_error=*/true); + if (!IsUpdateCookieAllowed()) { + // Cookie update not enabled, match tokens with Gaia accounts. + MatchTokensWithAccountsInCookie(gaia_accounts); + } } void DiceAccountReconcilorDelegate::OnAccountsCookieDeletedByUserAction(
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.h b/components/signin/core/browser/dice_account_reconcilor_delegate.h index 33ac57a..fea1581 100644 --- a/components/signin/core/browser/dice_account_reconcilor_delegate.h +++ b/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -28,8 +28,10 @@ // AccountReconcilorDelegate: bool IsReconcileEnabled() const override; + bool IsUpdateCookieAllowed() const override; gaia::GaiaSource GetGaiaApiSource() const override; - void RevokeSecondaryTokensBeforeReconcileIfNeeded() override; + void RevokeSecondaryTokensForReconcileIfNeeded( + const std::vector<gaia::ListedAccount>& gaia_accounts) override; void OnReconcileFinished(const CoreAccountId& first_account) override; void OnAccountsCookieDeletedByUserAction( bool synced_data_deletion_in_progress) override; @@ -57,6 +59,12 @@ kMaxValue = kSyncCookieNotFirst }; + // Used when update cookies to match refresh tokens is not allowed, see + // `IsUpdateCookieAllowed()`. In this mode, refresh tokens are updated to + // match accounts in the Gaia cookies to maintain consistency. + void MatchTokensWithAccountsInCookie( + const std::vector<gaia::ListedAccount>& gaia_accounts); + // Computes inconsistency reason between tokens and gaia cookies. InconsistencyReason GetInconsistencyReason( const CoreAccountId& primary_account,
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc new file mode 100644 index 0000000..8039cd2 --- /dev/null +++ b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
@@ -0,0 +1,165 @@ +// 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 "components/signin/core/browser/dice_account_reconcilor_delegate.h" + +#include <optional> + +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "components/signin/public/base/consent_level.h" +#include "components/signin/public/base/signin_client.h" +#include "components/signin/public/base/signin_switches.h" +#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/signin/public/identity_manager/identity_test_utils.h" +#include "google_apis/gaia/gaia_auth_util.h" +#include "google_apis/gaia/gaia_constants.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace signin { +namespace { +constexpr char kPrimaryAccountEmail[] = "primary@gmail.com "; + +gaia::ListedAccount GetListedAccountFromAccountInfo( + const AccountInfo& account_info, + bool valid = true) { + gaia::ListedAccount gaia_account; + gaia_account.id = account_info.account_id; + gaia_account.email = account_info.email; + gaia_account.gaia_id = account_info.gaia; + gaia_account.valid = valid; + return gaia_account; +} + +class DiceAccountReconcilorDelegateTest : public testing::Test { + public: + DiceAccountReconcilorDelegateTest() + : delegate_(identity_manager(), + identity_test_environment_.signin_client()) {} + + DiceAccountReconcilorDelegate& delegate() { return delegate_; } + + IdentityTestEnvironment& identity_test_environment() { + return identity_test_environment_; + } + + IdentityManager* identity_manager() { + return identity_test_environment().identity_manager(); + } + + private: + base::test::SingleThreadTaskEnvironment task_environment_; + base::test::ScopedFeatureList scoped_feature_list_{switches::kUnoDesktop}; + IdentityTestEnvironment identity_test_environment_; + DiceAccountReconcilorDelegate delegate_; +}; + +TEST_F(DiceAccountReconcilorDelegateTest, GetConsentLevelForPrimaryAccount) { + // Uno enabled. + EXPECT_EQ(delegate().GetConsentLevelForPrimaryAccount(), + ConsentLevel::kSignin); +} + +TEST_F(DiceAccountReconcilorDelegateTest, + IsUpdateCookieAllowedPreChromeSignIn) { + EXPECT_FALSE(delegate().IsUpdateCookieAllowed()); +} + +TEST_F(DiceAccountReconcilorDelegateTest, + IsUpdateCookieAllowedPostChromeSignIn) { + identity_test_environment().MakePrimaryAccountAvailable( + kPrimaryAccountEmail, ConsentLevel::kSignin); + ASSERT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin)); + EXPECT_TRUE(delegate().IsUpdateCookieAllowed()); +} + +TEST_F(DiceAccountReconcilorDelegateTest, + RevokeSecondaryTokensForReconcileIfNeededPreChromeSignIn) { + AccountInfo valid_account = + identity_test_environment().MakeAccountAvailable("account@gmail.com"); + + // Accounts with invalid refresh token should be revoked. + AccountInfo account_with_invalid_refresh_token = + identity_test_environment().MakeAccountAvailable( + AccountAvailabilityOptionsBuilder() + .WithRefreshToken(GaiaConstants::kInvalidRefreshToken) + .Build("invalid_refresh_token@gmail.com")); + + // Accounts not in the gaia cookie should be revoked. + AccountInfo no_cookie_account = + identity_test_environment().MakeAccountAvailable("no_cookie@gmail.com"); + AccountInfo cookie_no_refresh_token_account = + identity_test_environment().MakeAccountAvailable( + AccountAvailabilityOptionsBuilder().WithoutRefreshToken().Build( + "no_refresh_token_with_cookie@gmail.com")); + + // Setup account with refresh token and invalid cookie account. + // The refresh token should be revoked + AccountInfo invalid_cookie_account = + identity_test_environment().MakeAccountAvailable( + "invalid_cookie@gmail.com"); + + // Verify the test setup. + EXPECT_THAT(identity_manager()->GetAccountsWithRefreshTokens(), + ::testing::UnorderedElementsAre( + valid_account, account_with_invalid_refresh_token, + no_cookie_account, invalid_cookie_account)); + ASSERT_FALSE(delegate().IsUpdateCookieAllowed()); + + const std::vector<gaia::ListedAccount> gaia_signed_in_accounts{ + GetListedAccountFromAccountInfo(valid_account), + GetListedAccountFromAccountInfo(cookie_no_refresh_token_account), + GetListedAccountFromAccountInfo(invalid_cookie_account, /*valid=*/false)}; + + delegate().RevokeSecondaryTokensForReconcileIfNeeded(gaia_signed_in_accounts); + std::vector<CoreAccountInfo> chrome_accounts = + identity_manager()->GetAccountsWithRefreshTokens(); + ASSERT_EQ(chrome_accounts.size(), 1u); + EXPECT_THAT(chrome_accounts[0], ::testing::Eq(valid_account)); +} + +TEST(DiceAccountReconcilorDelegateTestUnoDisabled, + RevokeSecondaryTokensForReconcile) { + base::test::SingleThreadTaskEnvironment task_environment; + base::test::ScopedFeatureList scoped_feature_list; + IdentityTestEnvironment identity_test_environment; + IdentityManager* identity_manager = + identity_test_environment.identity_manager(); + DiceAccountReconcilorDelegate delegate( + identity_manager, identity_test_environment.signin_client()); + + EXPECT_TRUE(delegate.IsUpdateCookieAllowed()); + + scoped_feature_list.InitAndDisableFeature(switches::kUnoDesktop); + + AccountInfo valid_account = + identity_test_environment.MakeAccountAvailable("account@gmail.com"); + + // Accounts with invalid refresh token should be revoked. + AccountInfo account_with_invalid_refresh_token = + identity_test_environment.MakeAccountAvailable( + AccountAvailabilityOptionsBuilder() + .WithRefreshToken(GaiaConstants::kInvalidRefreshToken) + .Build("invalid_refresh_token@gmail.com")); + + // Uno disabled, only accounts with invalid refresh tokens should be revoked. + AccountInfo no_cookie_account = + identity_test_environment.MakeAccountAvailable("no_cookie@gmail.com"); + EXPECT_EQ(identity_manager->GetAccountsWithRefreshTokens().size(), 3u); + + const std::vector<gaia::ListedAccount> gaia_signed_in_accounts{ + GetListedAccountFromAccountInfo(valid_account), + GetListedAccountFromAccountInfo(account_with_invalid_refresh_token)}; + delegate.RevokeSecondaryTokensForReconcileIfNeeded(gaia_signed_in_accounts); + EXPECT_THAT( + identity_manager->GetAccountsWithRefreshTokens(), + ::testing::UnorderedElementsAre(valid_account, no_cookie_account)); +} + +} // namespace +} // namespace signin
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc index 72a6b85..1ba0a8d 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc +++ b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
@@ -23,6 +23,10 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/cookie_manager.mojom.h" +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +#include "components/signin/public/base/bound_session_oauth_multilogin_delegate.h" +#endif + namespace signin { namespace { @@ -75,6 +79,11 @@ DCHECK(!accounts_.empty()); DCHECK(callback_); +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + bound_session_delegate_ = + signin_client_->CreateBoundSessionOAuthMultiloginDelegate(); +#endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + #ifndef NDEBUG // Check that there is no duplicate accounts. std::set<AccountIdGaiaIdPair> accounts_no_duplicates(accounts_.begin(), @@ -148,6 +157,12 @@ VLOG(1) << "Multilogin successful accounts=" << base::JoinString(account_ids, " "); } +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + if (bound_session_delegate_) { + bound_session_delegate_->BeforeSetCookies(result); + } +#endif + StartSettingCookies(result); return; } @@ -229,8 +244,14 @@ << " for domain=" << cookie_domain << "."; } UMA_HISTOGRAM_BOOLEAN("Signin.SetCookieSuccess", success); - if (cookies_to_set_.empty()) + if (cookies_to_set_.empty()) { +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + if (bound_session_delegate_) { + bound_session_delegate_->OnCookiesSet(); + } +#endif std::move(callback_).Run(SetAccountsInCookieResult::kSuccess); + } // Do not add anything below this line, because this may be deleted. }
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper.h b/components/signin/internal/identity_manager/oauth_multilogin_helper.h index a8470f1..19f331b 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_helper.h +++ b/components/signin/internal/identity_manager/oauth_multilogin_helper.h
@@ -14,6 +14,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h" +#include "components/signin/public/base/signin_buildflags.h" #include "components/signin/public/identity_manager/accounts_cookie_mutator.h" #include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/gaia_auth_consumer.h" @@ -28,6 +29,10 @@ enum class SetAccountsInCookieResult; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +class BoundSessionOAuthMultiLoginDelegate; +#endif + // This is a helper class that drives the OAuth multilogin process. // The main steps are: // - fetch access tokens with login scope, @@ -81,6 +86,10 @@ raw_ptr<AccountsCookieMutator::PartitionDelegate> partition_delegate_; raw_ptr<ProfileOAuth2TokenService> token_service_; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + std::unique_ptr<BoundSessionOAuthMultiLoginDelegate> bound_session_delegate_; +#endif + int fetcher_retries_ = 0; gaia::MultiloginMode mode_;
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc index 07506220..a2b19b4 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc +++ b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
@@ -4,17 +4,22 @@ #include "components/signin/internal/identity_manager/oauth_multilogin_helper.h" +#include <memory> + #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "components/prefs/testing_pref_service.h" #include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h" +#include "components/signin/public/base/bound_session_oauth_multilogin_delegate.h" #include "components/signin/public/base/test_signin_client.h" #include "components/signin/public/identity_manager/accounts_cookie_mutator.h" #include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h" #include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/gaia_urls.h" +#include "google_apis/gaia/oauth_multilogin_result.h" #include "services/network/test/test_cookie_manager.h" #include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" @@ -166,6 +171,17 @@ void(const CoreAccountId& account_id, const std::string& token)); }; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +class MockBoundSessionOAuthMultiLoginDelegate + : public ::testing::StrictMock<BoundSessionOAuthMultiLoginDelegate> { + public: + MOCK_METHOD(void, + BeforeSetCookies, + (const OAuthMultiloginResult&), + (override)); + MOCK_METHOD(void, OnCookiesSet, (), (override)); +}; +#endif } // namespace class OAuthMultiloginHelperTest @@ -176,30 +192,48 @@ : kAccountId(CoreAccountId::FromGaiaId(kGaiaId)), kAccountId2(CoreAccountId::FromGaiaId(kGaiaId2)), test_signin_client_(&pref_service_), - mock_token_service_(&pref_service_) {} + mock_token_service_(&pref_service_) { +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + test_signin_client_.SetBoundSessionOauthMultiloginDelegateFactory( + base::BindRepeating(&OAuthMultiloginHelperTest:: + CreateMockBoundSessionOAuthMultiLoginDelegate, + base::Unretained(this))); +#endif + } ~OAuthMultiloginHelperTest() override = default; - std::unique_ptr<OAuthMultiloginHelper> CreateHelper( - const std::vector<OAuthMultiloginHelper::AccountIdGaiaIdPair> accounts) { - return std::make_unique<OAuthMultiloginHelper>( + OAuthMultiloginHelper* CreateHelper( + const std::vector<OAuthMultiloginHelper::AccountIdGaiaIdPair> accounts, + bool set_external_cc_result = false) { +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + // `bound_session_delegate_` is owned by `OAuthMultiloginHelper`, ensures it + // resets before creating a new helper to avoid dangling pointers. + bound_session_delegate_ = nullptr; +#endif + helper_ = std::make_unique<OAuthMultiloginHelper>( &test_signin_client_, this, token_service(), gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, accounts, - std::string(), gaia::GaiaSource::kChrome, + set_external_cc_result ? kExternalCcResult : std::string(), + gaia::GaiaSource::kChrome, base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished, base::Unretained(this))); + return helper_.get(); } - std::unique_ptr<OAuthMultiloginHelper> CreateHelperWithExternalCcResult( - const std::vector<OAuthMultiloginHelper::AccountIdGaiaIdPair> accounts) { - return std::make_unique<OAuthMultiloginHelper>( - &test_signin_client_, this, token_service(), - gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, accounts, - kExternalCcResult, gaia::GaiaSource::kChrome, - base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished, - base::Unretained(this))); +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + std::unique_ptr<BoundSessionOAuthMultiLoginDelegate> + CreateMockBoundSessionOAuthMultiLoginDelegate() { + auto delegate = std::make_unique<MockBoundSessionOAuthMultiLoginDelegate>(); + bound_session_delegate_ = delegate.get(); + return delegate; } + MockBoundSessionOAuthMultiLoginDelegate* bound_session_delegate() { + return bound_session_delegate_; + } +#endif + network::TestURLLoaderFactory* url_loader() { return test_signin_client_.GetTestURLLoaderFactory(); } @@ -247,13 +281,17 @@ MockCookieManager mock_cookie_manager_; TestSigninClient test_signin_client_; MockTokenService mock_token_service_; + std::unique_ptr<OAuthMultiloginHelper> helper_; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + raw_ptr<MockBoundSessionOAuthMultiLoginDelegate> bound_session_delegate_ = + nullptr; +#endif }; // Everything succeeds. TEST_F(OAuthMultiloginHelperTest, Success) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}}); + CreateHelper({{kAccountId, kGaiaId}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -272,6 +310,10 @@ // Multilogin call. EXPECT_FALSE(callback_called_); EXPECT_TRUE(url_loader()->IsPending(multilogin_url())); +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + EXPECT_CALL(*bound_session_delegate(), BeforeSetCookies); + EXPECT_CALL(*bound_session_delegate(), OnCookiesSet); +#endif url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse); EXPECT_FALSE(url_loader()->IsPending(multilogin_url())); EXPECT_TRUE(callback_called_); @@ -281,8 +323,7 @@ // Multiple cookies in the multilogin response. TEST_F(OAuthMultiloginHelperTest, MultipleCookies) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}}); + CreateHelper({{kAccountId, kGaiaId}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -306,6 +347,10 @@ // Multilogin call. EXPECT_FALSE(callback_called_); EXPECT_TRUE(url_loader()->IsPending(multilogin_url())); +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + EXPECT_CALL(*bound_session_delegate(), BeforeSetCookies); + EXPECT_CALL(*bound_session_delegate(), OnCookiesSet); +#endif url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponseTwoCookies); EXPECT_FALSE(url_loader()->IsPending(multilogin_url())); @@ -316,8 +361,7 @@ // Multiple cookies in the multilogin response. TEST_F(OAuthMultiloginHelperTest, SuccessWithExternalCcResult) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelperWithExternalCcResult({{kAccountId, kGaiaId}}); + CreateHelper({{kAccountId, kGaiaId}}, /*set_external_cc_result=*/true); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -342,6 +386,10 @@ EXPECT_FALSE(callback_called_); EXPECT_TRUE( url_loader()->IsPending(multilogin_url_with_external_cc_result())); +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + EXPECT_CALL(*bound_session_delegate(), BeforeSetCookies); + EXPECT_CALL(*bound_session_delegate(), OnCookiesSet); +#endif url_loader()->AddResponse(multilogin_url_with_external_cc_result(), kMultiloginSuccessResponseWithSecondaryDomain); EXPECT_FALSE( @@ -353,8 +401,7 @@ // Failure to get the access token. TEST_F(OAuthMultiloginHelperTest, OneAccountAccessTokenFailure) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}}); + CreateHelper({{kAccountId, kGaiaId}}); token_service()->IssueErrorForAllPendingRequestsForAccount( kAccountId, @@ -366,8 +413,7 @@ // Retry on transient errors in the multilogin call. TEST_F(OAuthMultiloginHelperTest, OneAccountTransientMultiloginError) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}}); + CreateHelper({{kAccountId, kGaiaId}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -393,6 +439,10 @@ token_service()->IssueAllTokensForAccount(kAccountId, success_response); EXPECT_FALSE(callback_called_); EXPECT_TRUE(url_loader()->IsPending(multilogin_url())); +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + EXPECT_CALL(*bound_session_delegate(), BeforeSetCookies); + EXPECT_CALL(*bound_session_delegate(), OnCookiesSet); +#endif url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse); EXPECT_FALSE(url_loader()->IsPending(multilogin_url())); EXPECT_TRUE(callback_called_); @@ -403,8 +453,7 @@ TEST_F(OAuthMultiloginHelperTest, OneAccountTransientMultiloginErrorMaxRetries) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}}); + CreateHelper({{kAccountId, kGaiaId}}); // Issue access token. OAuth2AccessTokenConsumer::TokenResponse success_response; @@ -427,8 +476,7 @@ // Persistent error in the multilogin call. TEST_F(OAuthMultiloginHelperTest, OneAccountPersistentMultiloginError) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}}); + CreateHelper({{kAccountId, kGaiaId}}); // Issue access token. OAuth2AccessTokenConsumer::TokenResponse success_response; @@ -448,17 +496,7 @@ TEST_F(OAuthMultiloginHelperTest, InvalidTokenError) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); token_service()->UpdateCredentials(kAccountId2, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}}); - - // Configure mock cookie manager: - // - check that the cookie is the expected one - // - immediately invoke the callback - EXPECT_CALL(*cookie_manager(), - SetCanonicalCookie( - CookieMatcher("SID", "SID_value", ".google.fr"), - CookieSourceMatcher("google.fr"), testing::_, testing::_)) - .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess)); + CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}}); // The failed access token should be invalidated. EXPECT_CALL(*token_service(), @@ -486,6 +524,17 @@ // Multilogin succeeds the second time. EXPECT_FALSE(callback_called_); EXPECT_TRUE(url_loader()->IsPending(multilogin_url())); +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + EXPECT_CALL(*bound_session_delegate(), BeforeSetCookies); + EXPECT_CALL(*bound_session_delegate(), OnCookiesSet); +#endif + // Configure mock cookie manager: check that the cookie is the expected one. + EXPECT_CALL(*cookie_manager(), + SetCanonicalCookie( + CookieMatcher("SID", "SID_value", ".google.fr"), + CookieSourceMatcher("google.fr"), testing::_, testing::_)) + .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess)); + url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse); EXPECT_FALSE(url_loader()->IsPending(multilogin_url())); EXPECT_TRUE(callback_called_); @@ -496,8 +545,7 @@ TEST_F(OAuthMultiloginHelperTest, InvalidTokenErrorMaxRetries) { token_service()->UpdateCredentials(kAccountId, "refresh_token"); token_service()->UpdateCredentials(kAccountId2, "refresh_token"); - std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}}); + CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}}); // The failed access token should be invalidated. EXPECT_CALL(*token_service(), @@ -529,4 +577,39 @@ EXPECT_EQ(SetAccountsInCookieResult::kTransientError, result_); } +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +TEST_F(OAuthMultiloginHelperTest, BoundSessionHelperCalled) { + token_service()->UpdateCredentials(kAccountId, "refresh_token"); + CreateHelper({{kAccountId, kGaiaId}}); + + { + testing::InSequence seq; + + EXPECT_CALL(*bound_session_delegate(), BeforeSetCookies(testing::_)); + EXPECT_CALL(*cookie_manager(), + SetCanonicalCookie( + CookieMatcher("SID", "SID_value", ".google.fr"), + CookieSourceMatcher("google.fr"), testing::_, testing::_)); + EXPECT_CALL(*cookie_manager(), + SetCanonicalCookie( + CookieMatcher("FOO", "FOO_value", ".google.com"), + CookieSourceMatcher("google.com"), testing::_, testing::_)); + EXPECT_CALL(*bound_session_delegate(), OnCookiesSet()); + } + + // Issue access token. + OAuth2AccessTokenConsumer::TokenResponse success_response; + success_response.access_token = kAccessToken; + token_service()->IssueAllTokensForAccount(kAccountId, success_response); + + // Multilogin call. + EXPECT_TRUE(url_loader()->IsPending(multilogin_url())); + url_loader()->AddResponse(multilogin_url(), + kMultiloginSuccessResponseTwoCookies); + // All set cookie calls must be sent before adding any mock expectation, + // otherwise the test will fail. + task_environment_.RunUntilIdle(); + EXPECT_EQ(SetAccountsInCookieResult::kSuccess, result_); +} +#endif } // namespace signin
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc index dc5d3e9b..aaed39d 100644 --- a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc +++ b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
@@ -12,6 +12,7 @@ #include "components/prefs/pref_registry_simple.h" #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h" #include "components/signin/public/base/device_id_helper.h" +#include "components/signin/public/base/signin_metrics.h" #include "components/signin/public/base/signin_pref_names.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/google_service_auth_error.h" @@ -63,6 +64,9 @@ return "LogoutTabHelper::PrimaryPageChanged"; case SourceForRefreshTokenOperation::kForceSigninReauthWithDifferentAccount: return "ForceSigninReauthWithDifferentAccount"; + case SourceForRefreshTokenOperation:: + kAccountReconcilor_RevokeTokensNotInCookies: + return "AccountReconcilor::RevokeTokensNotInCookies"; } } } // namespace
diff --git a/components/signin/public/base/BUILD.gn b/components/signin/public/base/BUILD.gn index 7e50941..218fca0 100644 --- a/components/signin/public/base/BUILD.gn +++ b/components/signin/public/base/BUILD.gn
@@ -73,6 +73,10 @@ if (is_chromeos_lacros) { public_deps += [ "//components/account_manager_core" ] } + + if (enable_bound_session_credentials) { + sources += [ "bound_session_oauth_multilogin_delegate.h" ] + } } if (is_android) {
diff --git a/components/signin/public/base/bound_session_oauth_multilogin_delegate.h b/components/signin/public/base/bound_session_oauth_multilogin_delegate.h new file mode 100644 index 0000000..a1f450a --- /dev/null +++ b/components/signin/public/base/bound_session_oauth_multilogin_delegate.h
@@ -0,0 +1,31 @@ +// 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 COMPONENTS_SIGNIN_PUBLIC_BASE_BOUND_SESSION_OAUTH_MULTILOGIN_DELEGATE_H_ +#define COMPONENTS_SIGNIN_PUBLIC_BASE_BOUND_SESSION_OAUTH_MULTILOGIN_DELEGATE_H_ + +class OAuthMultiloginResult; + +namespace signin { + +// Handles cookie binding during OAuthMultiLogin request. +// OAuthMultiLogin can start a bound session or override an existing one. +// If cookies from OAuthMultiLogin are bound, it would be to the refresh token's +// binding key. +// There should be one delegate instance per `OAuthMultiloginHelper`. +class BoundSessionOAuthMultiLoginDelegate { + public: + virtual ~BoundSessionOAuthMultiLoginDelegate() = default; + // Processes `DbscMetaData` if available in `result`. + // Called before setting cookies to avoid any possible race condition where + // bound cookies are overridden by in-flight cookie rotation request. + // Bound sessions impacted by OAuthMultiLogin would have cookie rotation + // paused till `OnCookiesSet()` is called. + virtual void BeforeSetCookies(const OAuthMultiloginResult& result) = 0; + + // Resumes cookie rotation and overrides the existing sessions if needed. + virtual void OnCookiesSet() = 0; +}; +} // namespace signin +#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_BOUND_SESSION_OAUTH_MULTILOGIN_DELEGATE_H_
diff --git a/components/signin/public/base/signin_client.cc b/components/signin/public/base/signin_client.cc index 219c3e7..b433ed64 100644 --- a/components/signin/public/base/signin_client.cc +++ b/components/signin/public/base/signin_client.cc
@@ -27,4 +27,4 @@ bool SigninClient::is_clear_primary_account_allowed_for_testing() const { return is_clear_primary_account_allowed_for_testing_ == SignoutDecision::ALLOW; -} \ No newline at end of file +}
diff --git a/components/signin/public/base/signin_client.h b/components/signin/public/base/signin_client.h index 3c79a903..c5fef82 100644 --- a/components/signin/public/base/signin_client.h +++ b/components/signin/public/base/signin_client.h
@@ -16,6 +16,7 @@ #include "components/keyed_service/core/keyed_service.h" #include "components/signin/public/base/account_consistency_method.h" #include "components/signin/public/base/consent_level.h" +#include "components/signin/public/base/signin_buildflags.h" #include "components/signin/public/base/signin_metrics.h" #include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/gaia_auth_fetcher.h" @@ -26,6 +27,12 @@ #include "components/account_manager_core/account.h" #endif +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +namespace signin { +class BoundSessionOAuthMultiLoginDelegate; +} +#endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + class PrefService; namespace content_settings { @@ -152,6 +159,11 @@ absl::variant<signin_metrics::AccessPoint, signin_metrics::ProfileSignout> event_source) = 0; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + virtual std::unique_ptr<signin::BoundSessionOAuthMultiLoginDelegate> + CreateBoundSessionOAuthMultiloginDelegate() const = 0; +#endif + protected: std::optional<SignoutDecision> is_clear_primary_account_allowed_for_testing_; };
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h index 63c03e4..1e9e913 100644 --- a/components/signin/public/base/signin_metrics.h +++ b/components/signin/public/base/signin_metrics.h
@@ -438,8 +438,9 @@ // kAccountReconcilor_RevokeTokensNotInCookies = 18, kLogoutTabHelper_PrimaryPageChanged = 19, kForceSigninReauthWithDifferentAccount = 20, + kAccountReconcilor_RevokeTokensNotInCookies = 21, - kMaxValue = kForceSigninReauthWithDifferentAccount, + kMaxValue = kAccountReconcilor_RevokeTokensNotInCookies, }; // Different types of reporting. This is used as a histogram suffix.
diff --git a/components/signin/public/base/test_signin_client.cc b/components/signin/public/base/test_signin_client.cc index df5f3dc..62f2f9db 100644 --- a/components/signin/public/base/test_signin_client.cc +++ b/components/signin/public/base/test_signin_client.cc
@@ -139,6 +139,19 @@ absl::variant<signin_metrics::AccessPoint, signin_metrics::ProfileSignout> event_source) {} +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +std::unique_ptr<signin::BoundSessionOAuthMultiLoginDelegate> +TestSigninClient::CreateBoundSessionOAuthMultiloginDelegate() const { + return bound_session_delegate_factory_ ? bound_session_delegate_factory_.Run() + : nullptr; +} + +void TestSigninClient::SetBoundSessionOauthMultiloginDelegateFactory( + BoundSessionOauthMultiloginDelegateFactory factory) { + bound_session_delegate_factory_ = std::move(factory); +} +#endif + #if BUILDFLAG(IS_CHROMEOS_LACROS) std::optional<account_manager::Account> TestSigninClient::GetInitialPrimaryAccount() {
diff --git a/components/signin/public/base/test_signin_client.h b/components/signin/public/base/test_signin_client.h index e26a4b987..7b75951 100644 --- a/components/signin/public/base/test_signin_client.h +++ b/components/signin/public/base/test_signin_client.h
@@ -15,6 +15,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "build/chromeos_buildflags.h" +#include "components/signin/public/base/signin_buildflags.h" #include "components/signin/public/base/signin_client.h" #include "components/signin/public/base/wait_for_network_callback_helper.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -28,6 +29,10 @@ #include "components/account_manager_core/account.h" #endif +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +#include "components/signin/public/base/bound_session_oauth_multilogin_delegate.h" +#endif + class PrefService; namespace version_info { @@ -117,6 +122,16 @@ absl::variant<signin_metrics::AccessPoint, signin_metrics::ProfileSignout> event_source) override; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + std::unique_ptr<signin::BoundSessionOAuthMultiLoginDelegate> + CreateBoundSessionOAuthMultiloginDelegate() const override; + + void SetBoundSessionOauthMultiloginDelegateFactory( + base::RepeatingCallback< + std::unique_ptr<signin::BoundSessionOAuthMultiLoginDelegate>()> + factory); +#endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + #if BUILDFLAG(IS_CHROMEOS_LACROS) std::optional<account_manager::Account> GetInitialPrimaryAccount() override; std::optional<bool> IsInitialPrimaryAccountChild() const override; @@ -129,6 +144,11 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) private: +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + using BoundSessionOauthMultiloginDelegateFactory = base::RepeatingCallback< + std::unique_ptr<signin::BoundSessionOAuthMultiLoginDelegate>()>; +#endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + std::unique_ptr<TestWaitForNetworkCallbackHelper> test_wait_for_network_callback_helper_; std::unique_ptr<network::TestURLLoaderFactory> @@ -139,6 +159,10 @@ std::unique_ptr<network::mojom::CookieManager> cookie_manager_; bool are_signin_cookies_allowed_; +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + BoundSessionOauthMultiloginDelegateFactory bound_session_delegate_factory_; +#endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) + #if BUILDFLAG(IS_CHROMEOS_LACROS) std::optional<account_manager::Account> initial_primary_account_; std::optional<bool> is_initial_primary_account_child_;
diff --git a/components/spellcheck/browser/spellcheck_host_metrics.cc b/components/spellcheck/browser/spellcheck_host_metrics.cc index acda1d5..bf68628 100644 --- a/components/spellcheck/browser/spellcheck_host_metrics.cc +++ b/components/spellcheck/browser/spellcheck_host_metrics.cc
@@ -6,6 +6,7 @@ #include <stdint.h> +#include "base/containers/span.h" #include "base/hash/md5.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -51,8 +52,7 @@ // Collects actual number of checked words, excluding duplication. base::MD5Digest digest; - base::MD5Sum(reinterpret_cast<const unsigned char*>(word.c_str()), - word.size() * sizeof(char16_t), &digest); + base::MD5Sum(base::as_byte_span(word), &digest); checked_word_hashes_.insert(base::MD5DigestToBase16(digest)); RecordWordCounts();
diff --git a/components/strings/components_strings_ca.xtb b/components/strings/components_strings_ca.xtb index 2096c21..d8d7f6c 100644 --- a/components/strings/components_strings_ca.xtb +++ b/components/strings/components_strings_ca.xtb
@@ -3003,7 +3003,7 @@ <translation id="6934672428414710184">Aquest nom prové del teu Compte de Google</translation> <translation id="6935082727755903526">Feines del sector financer i de comptabilitat</translation> <translation id="6935179587384421592"><ph name="SIZE" />. És possible que alguns llocs web es carreguin més a poc a poc la propera vegada que els visitis.</translation> -<translation id="6936976777388162184">Aquest és un dispositiu agrupat i no es pot inscriure amb la Llicència de Kiosk i Signage.</translation> +<translation id="6936976777388162184">Aquest és un dispositiu amb llicència integrada i no es pot inscriure amb la Llicència de Kiosk i Signage.</translation> <translation id="6939469646605424232">Sèries dramàtiques de televisió</translation> <translation id="6944692733090228304">Has introduït la contrasenya en un lloc web que no està gestionat per <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Per protegir el teu compte, no facis servir la mateixa contrasenya en altres aplicacions ni llocs web.</translation> <translation id="6945221475159498467">Selecciona</translation>
diff --git a/components/strings/components_strings_fi.xtb b/components/strings/components_strings_fi.xtb index 6883f3d7..925945f5 100644 --- a/components/strings/components_strings_fi.xtb +++ b/components/strings/components_strings_fi.xtb
@@ -1577,6 +1577,7 @@ <translation id="4089152113577680600">Lokero 14</translation> <translation id="4092349052316400070">Täytä osoite</translation> <translation id="4096237801206588987">11 x 15 tuumaa</translation> +<translation id="4098306082496067348">Lisää virtuaalikortin tiedot kassalle napauttamalla niitä.</translation> <translation id="4098354747657067197">Seuraava sivusto on petollinen</translation> <translation id="4099048595830172239">Järjestelmänvalvojakäytännössä ei suositella näytön jakamista (<ph name="APPLICATION_TITLE" />) luottamuksellisen sisällön ollessa näkyvissä:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, muokkaa fonttien kokoja ja kirjasimia Chromessa painamalla sarkainta ja sitten Enter</translation>
diff --git a/components/strings/components_strings_it.xtb b/components/strings/components_strings_it.xtb index d872f23..79b5ddf 100644 --- a/components/strings/components_strings_it.xtb +++ b/components/strings/components_strings_it.xtb
@@ -1573,6 +1573,7 @@ <translation id="4089152113577680600">Vassoio 14</translation> <translation id="4092349052316400070">Inserisci l'indirizzo</translation> <translation id="4096237801206588987">11 x 15 in</translation> +<translation id="4098306082496067348">Tocca i dati della carta virtuale per aggiungerli al pagamento.</translation> <translation id="4098354747657067197">Sito ingannevole in vista</translation> <translation id="4099048595830172239">Il criterio dell'amministratore sconsiglia la condivisione dello schermo con <ph name="APPLICATION_TITLE" /> quando sono visibili contenuti riservati:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, premi Tab e poi Invio per personalizzare le dimensioni dei caratteri e i caratteri tipografici in Chrome</translation>
diff --git a/components/strings/components_strings_iw.xtb b/components/strings/components_strings_iw.xtb index 819c2d2a..47fc0aad 100644 --- a/components/strings/components_strings_iw.xtb +++ b/components/strings/components_strings_iw.xtb
@@ -1576,6 +1576,7 @@ <translation id="4089152113577680600">מגש 14</translation> <translation id="4092349052316400070">אפשר למלא את הכתובת</translation> <translation id="4096237801206588987">11x15 אינץ'</translation> +<translation id="4098306082496067348">מקישים על פרטי הכרטיס הווירטואלי כדי להוסיף אותם לתשלום.</translation> <translation id="4098354747657067197">זהירות, אתר מטעה</translation> <translation id="4099048595830172239">לפי המדיניות של מנהל המערכת, לא מומלץ לשתף את המסך עם <ph name="APPLICATION_TITLE" /> כשמופיע בו תוכן סודי גלוי:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, מקישים על Tab ואז על Enter כדי להתאים אישית את הגופנים וגודל הטקסט ב-Chrome</translation>
diff --git a/components/strings/components_strings_km.xtb b/components/strings/components_strings_km.xtb index ef94ecf..f2ae60a 100644 --- a/components/strings/components_strings_km.xtb +++ b/components/strings/components_strings_km.xtb
@@ -1579,6 +1579,7 @@ <translation id="4089152113577680600">ទម្រទី 14</translation> <translation id="4092349052316400070">បំពេញអាសយដ្ឋាន</translation> <translation id="4096237801206588987">11 x 15 in</translation> +<translation id="4098306082496067348">ចុច "ព័ត៌មានលម្អិតអំពីកាតនិម្មិត" ដើម្បីបញ្ចូលព័ត៌មានលម្អិតទាំងនេះទៅក្នុងការបង់ប្រាក់ចេញ។</translation> <translation id="4098354747657067197">មានគេហទំព័រឆបោកនៅខាងមុខ</translation> <translation id="4099048595830172239">គោលការណ៍របស់អ្នកគ្រប់គ្រងមិនណែនាំឱ្យចែករំលែកអេក្រង់របស់អ្នកជាមួយ <ph name="APPLICATION_TITLE" /> នៅពេលដែលអាចមើលឃើញខ្លឹមសារសម្ងាត់ទេ៖</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ចុច "tab" រួចចុច "Enter" ដើម្បីប្ដូរទំហំពុម្ពអក្សរ និងពុម្ពអក្សរតាមបំណងនៅក្នុង Chrome</translation>
diff --git a/components/strings/components_strings_lo.xtb b/components/strings/components_strings_lo.xtb index 725d1142..d0899aa 100644 --- a/components/strings/components_strings_lo.xtb +++ b/components/strings/components_strings_lo.xtb
@@ -1576,6 +1576,7 @@ <translation id="4089152113577680600">ຖາດ 14</translation> <translation id="4092349052316400070">ຕື່ມຂໍ້ມູນທີ່ຢູ່</translation> <translation id="4096237801206588987">11 x 15 ນິ້ວ</translation> +<translation id="4098306082496067348">ແຕະລາຍລະອຽດບັດສະເໝືອນເພື່ອເພີ່ມພວກມັນໃສ່ການຈ່າຍເງິນ.</translation> <translation id="4098354747657067197">ເວັບໄຊທ໌ຫຼອກລວງຢູ່ຂ້າງໜ້າ</translation> <translation id="4099048595830172239">ນະໂຍບາຍຜູ້ເບິ່ງແຍງລະບົບບໍ່ແນະນຳໃຫ້ແບ່ງປັນໜ້າຈໍຂອງທ່ານກັບ <ph name="APPLICATION_TITLE" /> ເມື່ອປາກົດມີເນື້ອຫາທີ່ເປັນຄວາມລັບ:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ກົດ tab ຈາກນັ້ນກົດ Enter ເພື່ອປັບແຕ່ງຂະໜາດຟອນ ແລະ ແບບອັກສອນໃນ Chrome</translation>
diff --git a/components/strings/components_strings_lt.xtb b/components/strings/components_strings_lt.xtb index a8cbab03..e6cf005 100644 --- a/components/strings/components_strings_lt.xtb +++ b/components/strings/components_strings_lt.xtb
@@ -1577,6 +1577,7 @@ <translation id="4089152113577680600">Keturioliktas dėklas</translation> <translation id="4092349052316400070">Užpildyti adresą</translation> <translation id="4096237801206588987">11 x 15 col.</translation> +<translation id="4098306082496067348">Palieskite išsamią virtualiosios kortelės informaciją, jei norite ją pridėti prie atsiskaitymo.</translation> <translation id="4098354747657067197">Ketinate apsilankyti apgaulingoje svetainėje</translation> <translation id="4099048595830172239">Pagal administratoriaus politiką nerekomenduojama bendrinti ekrano su <ph name="APPLICATION_TITLE" />, kai matomas konfidencialus turinys.</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, paspauskite tabuliavimo klavišą, tada – „Enter“, kad galėtumėte tinkinti šriftų dydį ir šriftų šeimas naršyklėje „Chrome“.</translation>
diff --git a/components/strings/components_strings_ml.xtb b/components/strings/components_strings_ml.xtb index 7196cb7e..e35d118 100644 --- a/components/strings/components_strings_ml.xtb +++ b/components/strings/components_strings_ml.xtb
@@ -1575,6 +1575,7 @@ <translation id="4089152113577680600">ട്രേ 14</translation> <translation id="4092349052316400070">വിലാസം പൂരിപ്പിക്കുക</translation> <translation id="4096237801206588987">11 x 15 ഇഞ്ച്</translation> +<translation id="4098306082496067348">ചെക്ക്ഔട്ടിലേക്ക് ചേർക്കാൻ വെച്വൽ കാർഡ് വിശദാംശങ്ങൾ ടാപ്പ് ചെയ്യുക.</translation> <translation id="4098354747657067197">വഞ്ചനാപരമായ സൈറ്റ് ഉണ്ട്</translation> <translation id="4099048595830172239">രഹസ്യാത്മകമായ ഉള്ളടക്കം ദൃശ്യമാകുമ്പോൾ, <ph name="APPLICATION_TITLE" /> എന്നതുമായി നിങ്ങളുടെ സ്ക്രീൻ പങ്കിടാൻ അഡ്മിൻ നയം നിർദ്ദേശിക്കുന്നില്ല:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome-ൽ ഫോണ്ട് വലുപ്പങ്ങളും ടൈപ്പ്ഫേസുകളും ഇഷ്ടാനുസൃതമാക്കാൻ Tab അമർത്തുക, തുടർന്ന് Enter അമർത്തുക</translation>
diff --git a/components/strings/components_strings_mr.xtb b/components/strings/components_strings_mr.xtb index ab109b0..51c6b22a 100644 --- a/components/strings/components_strings_mr.xtb +++ b/components/strings/components_strings_mr.xtb
@@ -831,7 +831,7 @@ <translation id="2552246211866555379">हगाकी</translation> <translation id="2552295903035773204">यापुढे कार्डे निश्चित करण्यासाठी स्क्रीन लॉक वापरा</translation> <translation id="2552532158894206888">राइट की</translation> -<translation id="2553853292994445426">तुमची सुरक्षित DNS सेटिंग्ज तपासा. तुम्ही कदाचित कनेक्ट करता येत नसलेला एखादा सुरक्षित DNS सर्व्हर कॉंफिगर केला आहे.</translation> +<translation id="2553853292994445426">तुमची सुरक्षित DNS सेटिंग्ज तपासा. तुम्ही कदाचित कनेक्ट करता येत नसलेला एखादा सुरक्षित DNS सर्व्हर कॉन्फिगर केला आहे.</translation> <translation id="255497580849974774">अपडेटदरम्यान कृपया तुमचे डिव्हाइस चार्जरशी कनेक्ट केलेले ठेवा.</translation> <translation id="2556876185419854533">& संपादित करा पूर्ववत करा</translation> <translation id="2557417190997681027">व्यवसायासाठी प्रवास</translation> @@ -1350,7 +1350,7 @@ <translation id="3630155396527302611">नेटवर्क ॲक्सेस करण्यासाठी परवानगी दिलेला प्रोग्राम म्हणून तो आधीपासून सूचीबद्ध केला असल्यास तो सूचीमधून काढा आणि पुन्हा जोडून पहा.</translation> <translation id="3630426379756188722">Find My Device बटण, Google खाते मध्ये तुमचे डिव्हाइस शोधा ला भेट देण्यासाठी ॲक्टिव्हेट करा</translation> -<translation id="3630699740441428070">या डिव्हाइसच्या अॅडमिनिस्ट्रेटरनी तुमचे नेटवर्क कनेक्शन कॉंफिगर केले आहे, ज्यामुळे त्यांना तुम्ही भेट देत असलेल्या वेबसाइटसह, तुमचे नेटवर्क ट्रॅफिक पाहता येते.</translation> +<translation id="3630699740441428070">या डिव्हाइसच्या अॅडमिनिस्ट्रेटरनी तुमचे नेटवर्क कनेक्शन कॉन्फिगर केले आहे, ज्यामुळे त्यांना तुम्ही भेट देत असलेल्या वेबसाइटसह, तुमचे नेटवर्क ट्रॅफिक पाहता येते.</translation> <translation id="3631244953324577188">बायोमेट्रिक</translation> <translation id="3632503704576938756">स्क्रीन शेअर करणे पुन्हा सुरू केले</translation> <translation id="3632892046558972264">स्क्रीन शेअर करणे थांबवले आहे</translation> @@ -3599,7 +3599,7 @@ <translation id="8046360364391076336">औद्योगिक साहित्य आणि उपकरणे</translation> <translation id="8052898407431791827">क्लिपबोर्डवर कॉपी केले</translation> <translation id="8055534648776115597">व्यावसायिक आणि प्रौढ शिक्षण</translation> -<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" योग्य रीतीने कॉंफिगर केलेले नाही. "<ph name="SOFTWARE_NAME" />" अनइंस्टॉल केल्याने सहसा समस्या सुटते. <ph name="FURTHER_EXPLANATION" /></translation> +<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" योग्य रीतीने कॉन्फिगर केलेले नाही. "<ph name="SOFTWARE_NAME" />" अनइंस्टॉल केल्याने सहसा समस्या सुटते. <ph name="FURTHER_EXPLANATION" /></translation> <translation id="8058009102480785916">खाद्यपदार्थाचे उत्पादन</translation> <translation id="8058603697124206642">आवश्यक नाही</translation> <translation id="8063875539456488183">किंमत सेव्ह करून तिचा माग ठेवा</translation>
diff --git a/components/strings/components_strings_nl.xtb b/components/strings/components_strings_nl.xtb index 2e9b89b..dc00cd34 100644 --- a/components/strings/components_strings_nl.xtb +++ b/components/strings/components_strings_nl.xtb
@@ -1571,6 +1571,7 @@ <translation id="4089152113577680600">Lade 14</translation> <translation id="4092349052316400070">Adres invullen</translation> <translation id="4096237801206588987">11 x 15 inch</translation> +<translation id="4098306082496067348">Tik op Gegevens van virtuele kaart om deze toe te voegen aan het betaalproces.</translation> <translation id="4098354747657067197">Misleidende site gedetecteerd</translation> <translation id="4099048595830172239">Op basis van het beheerdersbeleid wordt afgeraden dat je je scherm met <ph name="APPLICATION_TITLE" /> deelt als er vertrouwelijke content zichtbaar is:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, druk op Tab en daarna op Enter om je lettertypen en lettergrootten aan te passen in Chrome</translation>
diff --git a/components/strings/components_strings_pl.xtb b/components/strings/components_strings_pl.xtb index 60c1af4..a8e2394 100644 --- a/components/strings/components_strings_pl.xtb +++ b/components/strings/components_strings_pl.xtb
@@ -1576,6 +1576,7 @@ <translation id="4089152113577680600">Taca 14</translation> <translation id="4092349052316400070">Uzupełnij adres</translation> <translation id="4096237801206588987">11 x 15 cali</translation> +<translation id="4098306082496067348">Kliknij dane karty wirtualnej, aby dodać je do płatności.</translation> <translation id="4098354747657067197">Wchodzisz na stronę wprowadzającą w błąd</translation> <translation id="4099048595830172239">Zgodnie z zasadą administratora nie zaleca się udostępniania ekranu za pomocą aplikacji <ph name="APPLICATION_TITLE" />, gdy są widoczne treści poufne:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />; aby dostosować rozmiary i kroje czcionek w Chrome, naciśnij Tab, a potem Enter</translation>
diff --git a/components/strings/components_strings_sl.xtb b/components/strings/components_strings_sl.xtb index d9d82dd5..477fc54 100644 --- a/components/strings/components_strings_sl.xtb +++ b/components/strings/components_strings_sl.xtb
@@ -1576,6 +1576,7 @@ <translation id="4089152113577680600">Pladenj 14</translation> <translation id="4092349052316400070">Izpolni naslov</translation> <translation id="4096237801206588987">11 x 15 palcev</translation> +<translation id="4098306082496067348">Dotaknite se podrobnosti navidezne kartice, da jih dodate v zaključek nakupa.</translation> <translation id="4098354747657067197">Zavajajoče spletno mesto</translation> <translation id="4099048595830172239">Pravilnik skrbnika ne priporoča deljenja zaslona z aplikacijo <ph name="APPLICATION_TITLE" />, kadar je vidna zaupna vsebina:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite tabulatorko, nato Enter, če želite prilagoditi velikost pisav in tipografije v Chromu</translation>
diff --git a/components/strings/components_strings_sr-Latn.xtb b/components/strings/components_strings_sr-Latn.xtb index 5a02a09..9da40b9 100644 --- a/components/strings/components_strings_sr-Latn.xtb +++ b/components/strings/components_strings_sr-Latn.xtb
@@ -1576,6 +1576,7 @@ <translation id="4089152113577680600">14. fioka</translation> <translation id="4092349052316400070">Popunite polje za adresu</translation> <translation id="4096237801206588987">11×15 in</translation> +<translation id="4098306082496067348">Dodirnite detalje o virtuelnoj kartici da biste ih dodali u plaćanje.</translation> <translation id="4098354747657067197">Pred vama je obmanjujući sajt</translation> <translation id="4099048595830172239">Smernice administratora ne preporučuju deljenje ekrana sa <ph name="APPLICATION_TITLE" /> kada se vidi poverljiv sadržaj:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, pa Enter da biste prilagodili veličine i izgled fontova u Chrome-u</translation>
diff --git a/components/strings/components_strings_sr.xtb b/components/strings/components_strings_sr.xtb index ec656ce..e23fb3c6 100644 --- a/components/strings/components_strings_sr.xtb +++ b/components/strings/components_strings_sr.xtb
@@ -1576,6 +1576,7 @@ <translation id="4089152113577680600">14. фиока</translation> <translation id="4092349052316400070">Попуните поље за адресу</translation> <translation id="4096237801206588987">11×15 in</translation> +<translation id="4098306082496067348">Додирните детаље о виртуелној картици да бисте их додали у плаћање.</translation> <translation id="4098354747657067197">Пред вама је обмањујући сајт</translation> <translation id="4099048595830172239">Смернице администратора не препоручују дељење екрана са <ph name="APPLICATION_TITLE" /> када се види поверљив садржај:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />, притисните Tab, па Enter да бисте прилагодили величине и изглед фонтова у Chrome-у</translation>
diff --git a/components/strings/components_strings_sv.xtb b/components/strings/components_strings_sv.xtb index ef24bef..6822676 100644 --- a/components/strings/components_strings_sv.xtb +++ b/components/strings/components_strings_sv.xtb
@@ -1576,6 +1576,7 @@ <translation id="4089152113577680600">Fack 14</translation> <translation id="4092349052316400070">Fyll i adress</translation> <translation id="4096237801206588987">11 x 15 tum</translation> +<translation id="4098306082496067348">Tryck på de virtuella kortuppgifterna för att lägga till dem i kassan.</translation> <translation id="4098354747657067197">Webbplatsen som öppnas är bedräglig</translation> <translation id="4099048595830172239">Enligt administratörspolicyn är det inte rekommenderat att dela skärmen med <ph name="APPLICATION_TITLE" /> när konfidentiellt innehåll är synligt:</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" />: tryck på Tabb och sedan på Retur om du vill anpassa teckenstorlekar och teckensnitt i Chrome</translation>
diff --git a/components/strings/components_strings_th.xtb b/components/strings/components_strings_th.xtb index 342bdd5..18d42d95 100644 --- a/components/strings/components_strings_th.xtb +++ b/components/strings/components_strings_th.xtb
@@ -1575,6 +1575,7 @@ <translation id="4089152113577680600">ถาด 14</translation> <translation id="4092349052316400070">กรอกที่อยู่</translation> <translation id="4096237801206588987">11 x 15 นิ้ว</translation> +<translation id="4098306082496067348">แตะรายละเอียดบัตรเสมือน (Virtual Card) เพื่อเพิ่มลงในการชำระเงิน</translation> <translation id="4098354747657067197">เว็บไซต์ที่กำลังจะเข้าชมไม่ปลอดภัย</translation> <translation id="4099048595830172239">นโยบายของผู้ดูแลระบบไม่แนะนำให้แชร์หน้าจอกับ <ph name="APPLICATION_TITLE" /> เมื่อมีเนื้อหาที่เป็นความลับแสดงอยู่</translation> <translation id="4099391883283080991"><ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT" /> กด Tab ตามด้วย Enter เพื่อปรับแต่งขนาดแบบอักษรและลักษณะแบบอักษรใน Chrome</translation>
diff --git a/components/strings/components_strings_uz.xtb b/components/strings/components_strings_uz.xtb index d23089f4..a12ce292 100644 --- a/components/strings/components_strings_uz.xtb +++ b/components/strings/components_strings_uz.xtb
@@ -4072,7 +4072,7 @@ <translation id="9005998258318286617">PDF hujjat yuklanmadi.</translation> <translation id="9008178007718859630">Uy va interyer dekori</translation> <translation id="9008201768610948239">Tashlab ketish</translation> -<translation id="9014705027639070815">Ochilgan saytlar oʻz reklamalari unumdorligini oʻlchash maqsadida Chromedan axborot soʻrashi mumkin. Chrome saytlarga tashrifdan keyingi xaridlar kabi cheklangan turdagi axborotlarni jamlashiga ruxsat beradi.</translation> +<translation id="9014705027639070815">Ochilgan saytlar oʻz reklamalari unumdorligini oʻlchash maqsadida Chromedan axborot soʻrashi mumkin. Chrome saytlarga tashrifdan keyingi xaridlar kabi cheklangan turdagi axborotlarni jamlashga ruxsat beradi.</translation> <translation id="9018120810758822233"><ph name="CREDIT_CARD" /> kartangiz himoya kodini kiriting</translation> <translation id="901834265349196618">e-pochta</translation> <translation id="9020542370529661692">Bu sahifa <ph name="TARGET_LANGUAGE" /> tiliga o‘girildi.</translation>
diff --git a/components/strings/components_strings_vi.xtb b/components/strings/components_strings_vi.xtb index 7c67575c..6935fa6 100644 --- a/components/strings/components_strings_vi.xtb +++ b/components/strings/components_strings_vi.xtb
@@ -1731,7 +1731,7 @@ <translation id="4336913590841287350">Chính sách này chưa được hỗ trợ làm chính sách người dùng trên iOS.</translation> <translation id="4340575312453649552">Chrome đã xóa quảng cáo này vì quảng cáo sử dụng quá nhiều tài nguyên của thiết bị.</translation> <translation id="4340810192899866471">Nhập từ JSON</translation> -<translation id="4340982228985273705">Máy tính này không được coi là máy tính do doanh nghiệp quản lý, vì vậy, chính sách này chỉ có thể tự động cài đặt các tiện ích được lưu trữ trên Chrome Web Store. URL cập nhật Chrome Web Store là "<ph name="CWS_UPDATE_URL" />".</translation> +<translation id="4340982228985273705">Máy tính này không được coi là máy tính do doanh nghiệp quản lý, vì vậy, chính sách này chỉ có thể tự động cài đặt các tiện ích được lưu trữ trên Cửa hàng Chrome trực tuyến. URL cập nhật Cửa hàng Chrome trực tuyến là "<ph name="CWS_UPDATE_URL" />".</translation> <translation id="4348834659292907206">Kết nối đến <ph name="SITE" /> không an toàn</translation> <translation id="4349365535725594680">Không thể chia sẻ nội dung bảo mật</translation> <translation id="4349810866125026513">Vẫn tải lên</translation>
diff --git a/components/strings/components_strings_zh-HK.xtb b/components/strings/components_strings_zh-HK.xtb index 596e1ef..38cfbc5 100644 --- a/components/strings/components_strings_zh-HK.xtb +++ b/components/strings/components_strings_zh-HK.xtb
@@ -398,7 +398,7 @@ <translation id="1711528724596764268">機器學習和人工智能</translation> <translation id="1712552549805331520"><ph name="URL" /> 要求在您的本機電腦上永久儲存數據</translation> <translation id="1713628304598226412">紙匣 2</translation> -<translation id="1713819065634160212">將地址儲存到 Google 帳戶並自動填入</translation> +<translation id="1713819065634160212">將地址儲存至 Google 帳戶並自動填入</translation> <translation id="1714807406136741351">瀏覽模式,改成「表格」模式之後,用向左/向右箭咀就可以喺圖表上面睇到價格變動</translation> <translation id="1717218214683051432">動作感應器</translation> <translation id="1717494416764505390">出紙槽 3</translation> @@ -1089,7 +1089,7 @@ <translation id="3120807611504813890">信封 (輕量)</translation> <translation id="3121994479408824897">前往 <ph name="DOMAIN" /></translation> <translation id="3126023634486644099">標籤 (永久)</translation> -<translation id="3133565499688974786"><ph name="SEARCH_ENGINE_NAME" /> 已設為預設搜尋引擎</translation> +<translation id="3133565499688974786"><ph name="SEARCH_ENGINE_NAME" /> 已設定為預設搜尋引擎</translation> <translation id="3140646734028448730">商業服務</translation> <translation id="3141093262818886744">仍要開啟</translation> <translation id="3141641372357166056">沒有同意書決定</translation> @@ -1510,7 +1510,7 @@ <translation id="3943857333388298514">貼上</translation> <translation id="3946209740501886391">在此網站上一律詢問</translation> <translation id="3948588869002647271">此應用程式遺失或已毀損</translation> -<translation id="3949297482798028668">系統管理員已禁止在此貼上這項內容。</translation> +<translation id="3949297482798028668">管理員已禁止在此貼上這項內容。</translation> <translation id="3949571496842715403">此伺服器無法證明所屬網域為 <ph name="DOMAIN" />;其安全性憑證沒有指定主體替代名稱。這可能是因為設定錯誤,或有攻擊者攔截您的連線。</translation> <translation id="3949601375789751990">您的瀏覽記錄會在這裡顯示</translation> <translation id="3949790930165450333"><ph name="DEVICE_NAME" /> (<ph name="DEVICE_ID" />)</translation> @@ -2454,7 +2454,7 @@ <translation id="5838732667866024867">你可以用向左/向右箭咀睇到圖表嘅價格變化</translation> <translation id="5840318881868981258">更新 Google 帳戶 (<ph name="ACCOUNT" />) 中的密碼</translation> <translation id="5841338463993781099">要儲存在帳戶中嗎?</translation> -<translation id="5843987376989109187">目前尚不支援這個語言。 +<translation id="5843987376989109187">目前不支援此語言。 <ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation> <translation id="5847181246682413476">電力供應</translation> <translation id="5851548754964597211">分頁清單</translation> @@ -4100,7 +4100,7 @@ <translation id="9049981332609050619">您嘗試連線至 <ph name="DOMAIN" />,但伺服器提供的憑證無效。</translation> <translation id="9050666287014529139">複雜密碼</translation> <translation id="9051072642122229460">咖啡及濃縮咖啡機</translation> -<translation id="9051260467258969162">請重新<ph name="BEGIN_LINK" />登入<ph name="END_LINK" />,再返回這個分頁取得寫入協助</translation> +<translation id="9051260467258969162">請重新<ph name="BEGIN_LINK" />登入<ph name="END_LINK" />並返回此分頁,才能取得撰寫協助</translation> <translation id="9053840549256861041">我們即將推出名為「廣告成效評估」的全新廣告私隱功能。Chrome 只會在網站間分享非常有限的資料 (例如向使用者放送廣告的時段),以協助網站評估廣告成效。</translation> <translation id="9056953843249698117">商店</translation> <translation id="9062620674789239642">此檔案可能已被移動、編輯或刪除。</translation>
diff --git a/components/sync/service/sync_prefs.cc b/components/sync/service/sync_prefs.cc index 5c1afd4..d272367 100644 --- a/components/sync/service/sync_prefs.cc +++ b/components/sync/service/sync_prefs.cc
@@ -599,6 +599,18 @@ } } +void SyncPrefs::ClearEncryptionBootstrapTokenForAccount( + const signin::GaiaIdHash& gaia_id_hash) { + CHECK(gaia_id_hash.IsValid()); + { + ScopedDictPrefUpdate update_account_passphrase_dict( + pref_service_, + prefs::internal::kSyncEncryptionBootstrapTokenPerAccount); + base::Value::Dict& all_accounts = update_account_passphrase_dict.Get(); + all_accounts.Remove(gaia_id_hash.ToBase64()); + } +} + // static const char* SyncPrefs::GetPrefNameForTypeForTesting(UserSelectableType type) { return GetPrefNameForType(type);
diff --git a/components/sync/service/sync_prefs.h b/components/sync/service/sync_prefs.h index d872ffdd..96aec15 100644 --- a/components/sync/service/sync_prefs.h +++ b/components/sync/service/sync_prefs.h
@@ -222,6 +222,8 @@ void SetEncryptionBootstrapTokenForAccount( const std::string& token, const signin::GaiaIdHash& gaia_id_hash); + void ClearEncryptionBootstrapTokenForAccount( + const signin::GaiaIdHash& gaia_id_hash); // Muting mechanism for passphrase prompts, used on Android. int GetPassphrasePromptMutedProductVersion() const;
diff --git a/components/sync/service/sync_service_impl.cc b/components/sync/service/sync_service_impl.cc index dc301dd..66f7bba 100644 --- a/components/sync/service/sync_service_impl.cc +++ b/components/sync/service/sync_service_impl.cc
@@ -1092,6 +1092,14 @@ "Sync.PassphraseTypeUponNotMyBirthdayOrEncryptionObsolete", crypto_.GetPassphraseType().value_or( PassphraseType::kImplicitPassphrase)); + // Account passphrase pref should be cleared when sync is reset from the + // dashboard because then the cached passphrase wouldn't be useful + // anymore. + if (GetSyncAccountStateForPrefs() == + SyncPrefs::SyncAccountState::kSignedInNotSyncing) { + sync_prefs_.ClearEncryptionBootstrapTokenForAccount( + signin::GaiaIdHash::FromGaiaId(GetAccountInfo().gaia)); + } } // Security domain state might be reset, reset local state as well.
diff --git a/components/sync/service/sync_service_impl_unittest.cc b/components/sync/service/sync_service_impl_unittest.cc index ffb4b1a..7c828c6 100644 --- a/components/sync/service/sync_service_impl_unittest.cc +++ b/components/sync/service/sync_service_impl_unittest.cc
@@ -1365,6 +1365,70 @@ /*expected_bucket_count=*/1); } +TEST_F(SyncServiceImplTest, DisableSyncOnClientClearsPassphrasePrefForAccount) { + const PassphraseType kPassphraseType = PassphraseType::kCustomPassphrase; + + SignInWithoutSyncConsent(); + InitializeService({{AUTOFILL, false}, {AUTOFILL_WALLET_DATA, false}}); + base::RunLoop().RunUntilIdle(); + + // This call represents the initial passphrase type coming in from the server. + service()->PassphraseTypeChanged(kPassphraseType); + ASSERT_EQ(kPassphraseType, service()->GetUserSettings()->GetPassphraseType()); + + // Set the passphrase. + SyncPrefs sync_prefs(prefs()); + signin::GaiaIdHash gaia_id_hash = signin::GaiaIdHash::FromGaiaId( + identity_manager() + ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin) + .gaia); + sync_prefs.SetEncryptionBootstrapTokenForAccount("token", gaia_id_hash); + ASSERT_EQ("token", + sync_prefs.GetEncryptionBootstrapTokenForAccount(gaia_id_hash)); + + // Clear sync from the dashboard. + SyncProtocolError client_cmd; + client_cmd.action = DISABLE_SYNC_ON_CLIENT; + client_cmd.error_type = NOT_MY_BIRTHDAY; + service()->OnActionableProtocolError(client_cmd); + + // The passphrase for account pref cleared when sync is cleared from + // dashboard. + EXPECT_TRUE( + sync_prefs.GetEncryptionBootstrapTokenForAccount(gaia_id_hash).empty()); +} + +TEST_F(SyncServiceImplTest, EncryptionObsoleteClearsPassphrasePrefForAccount) { + const PassphraseType kPassphraseType = PassphraseType::kCustomPassphrase; + + SignInWithoutSyncConsent(); + InitializeService({{AUTOFILL, false}, {AUTOFILL_WALLET_DATA, false}}); + base::RunLoop().RunUntilIdle(); + + // This call represents the initial passphrase type coming in from the server. + service()->PassphraseTypeChanged(kPassphraseType); + ASSERT_EQ(kPassphraseType, service()->GetUserSettings()->GetPassphraseType()); + + // Set the passphrase. + SyncPrefs sync_prefs(prefs()); + signin::GaiaIdHash gaia_id_hash = signin::GaiaIdHash::FromGaiaId( + identity_manager() + ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin) + .gaia); + sync_prefs.SetEncryptionBootstrapTokenForAccount("token", gaia_id_hash); + ASSERT_EQ("token", + sync_prefs.GetEncryptionBootstrapTokenForAccount(gaia_id_hash)); + + SyncProtocolError client_cmd; + client_cmd.action = DISABLE_SYNC_ON_CLIENT; + client_cmd.error_type = ENCRYPTION_OBSOLETE; + service()->OnActionableProtocolError(client_cmd); + + // The passphrase for account pref should be cleared. + EXPECT_TRUE( + sync_prefs.GetEncryptionBootstrapTokenForAccount(gaia_id_hash).empty()); +} + // Verify a that local sync mode isn't impacted by sync being disabled. TEST_F(SyncServiceImplTest, LocalBackendUnimpactedByPolicy) { prefs()->SetManagedPref(prefs::internal::kSyncManaged, base::Value(false));
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc index 2bafc30e..e89e884 100644 --- a/components/sync_bookmarks/bookmark_model_type_processor.cc +++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -376,16 +376,26 @@ } } - if (!bookmark_tracker_ && - wipe_model_upon_sync_disabled_behavior_ == - syncer::WipeModelUponSyncDisabledBehavior::kOnceIfTrackingMetadata) { - // Since the model isn't initially tracking metadata, move away from - // kOnceIfTrackingMetadata so the behavior doesn't kick in, in case sync is - // turned on later and back to off. This should be practically unreachable - // because usually ClearMetadataIfStopped() would be invoked earlier, - // but let's be extra safe and avoid relying on this behavior. - wipe_model_upon_sync_disabled_behavior_ = - syncer::WipeModelUponSyncDisabledBehavior::kNever; + if (!bookmark_tracker_) { + switch (wipe_model_upon_sync_disabled_behavior_) { + case syncer::WipeModelUponSyncDisabledBehavior::kNever: + // Nothing to do. + break; + case syncer::WipeModelUponSyncDisabledBehavior::kOnceIfTrackingMetadata: + // Since the model isn't initially tracking metadata, move away from + // kOnceIfTrackingMetadata so the behavior doesn't kick in, in case sync + // is turned on later and back to off. This should be practically + // unreachable because usually ClearMetadataIfStopped() would be invoked + // earlier, but let's be extra safe and avoid relying on this behavior. + wipe_model_upon_sync_disabled_behavior_ = + syncer::WipeModelUponSyncDisabledBehavior::kNever; + break; + case syncer::WipeModelUponSyncDisabledBehavior::kAlways: + // Remove any previous data that may exist, if its lifetime is strongly + // coupled with the tracker's (sync metadata's). + bookmark_model_->RemoveAllSyncableNodes(); + break; + } } ConnectIfReady();
diff --git a/components/variations/field_trial_config/field_trial_util_unittest.cc b/components/variations/field_trial_config/field_trial_util_unittest.cc index 4c720eb..a297d59 100644 --- a/components/variations/field_trial_config/field_trial_util_unittest.cc +++ b/components/variations/field_trial_config/field_trial_util_unittest.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/command_line.h" +#include "base/containers/span.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" #include "base/strings/utf_string_conversions.h" @@ -26,6 +27,43 @@ namespace variations { namespace { +class ExperimentBuilder { + public: + ExperimentBuilder() {} + + FieldTrialTestingExperiment Build() const { + return { + name, + platforms.data(), + platforms.size(), + form_factors.data(), + form_factors.size(), + is_low_end_device, + min_os_version, + params.data(), + params.size(), + enable_features.data(), + enable_features.size(), + disable_features.data(), + disable_features.size(), + forcing_flag, + override_ui_string.data(), + override_ui_string.size(), + }; + } + + const char* name = nullptr; + base::span<const Study::Platform> platforms = {}; + base::span<const Study::FormFactor> form_factors = {}; + std::optional<bool> is_low_end_device = std::nullopt; + const char* min_os_version = nullptr; + base::span<const FieldTrialTestingExperimentParams> params = {}; + base::span<const char*> enable_features = {}; + base::span<const char*> disable_features = {}; + const char* forcing_flag = nullptr; + base::span<const OverrideUIString> override_ui_string = {}; +}; + class TestOverrideStringCallback { public: typedef std::map<uint32_t, std::u16string> OverrideMap; @@ -136,59 +174,26 @@ const Study::Platform platform = Study::PLATFORM_LINUX; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_0[] = {{"x", "1"}, {"y", "2"}}; + ExperimentBuilder study_0_experiment_0_builder; + study_0_experiment_0_builder.name = "TestGroup1"; + study_0_experiment_0_builder.platforms = base::make_span(&platform, 1u); + study_0_experiment_0_builder.params = array_kFieldTrialConfig_params_0; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { - {"TestGroup1", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - array_kFieldTrialConfig_params_0, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, + study_0_experiment_0_builder.Build(), }; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_1[] = {{"x", "3"}, {"y", "4"}}; + ExperimentBuilder study_1_experiment_0_builder; + study_1_experiment_0_builder.name = "TestGroup2"; + study_1_experiment_0_builder.platforms = base::make_span(&platform, 1u); + study_1_experiment_0_builder.params = array_kFieldTrialConfig_params_0; + ExperimentBuilder study_1_experiment_1_builder; + study_1_experiment_1_builder.name = "TestGroup2-2"; + study_1_experiment_1_builder.platforms = base::make_span(&platform, 1u); + study_1_experiment_1_builder.params = array_kFieldTrialConfig_params_1; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { - {"TestGroup2", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - array_kFieldTrialConfig_params_0, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, - {"TestGroup2-2", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - array_kFieldTrialConfig_params_1, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, + study_1_experiment_0_builder.Build(), + study_1_experiment_1_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial1", array_kFieldTrialConfig_experiments_0, 1}, @@ -259,64 +264,32 @@ const Study::Platform platform = Study::PLATFORM_LINUX; const char* enable_features_0[] = {"A"}; + ExperimentBuilder experiment_0_builder; + experiment_0_builder.name = "TestGroup0"; + experiment_0_builder.platforms = base::make_span(&platform, 1u); + experiment_0_builder.enable_features = enable_features_0; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { - {/*name=*/"TestGroup0", - /*platforms=*/&platform, - /*platforms_size=*/1, - /*form_factors=*/{}, - /*form_factors_size=*/0, - /*is_low_end_device=*/std::nullopt, - /*min_os_version=*/nullptr, - /*params=*/nullptr, - /*params_size=*/0, - /*enable_features=*/enable_features_0, - /*enable_features_size=*/1, - /*disable_features=*/nullptr, - /*disable_features_size=*/0, - /*forcing_flag=*/nullptr, - /*override_ui_string=*/nullptr, - /*override_ui_string_size=*/0}, + experiment_0_builder.Build(), }; const char* disable_features_1[] = {"B"}; + ExperimentBuilder experiment_1_builder; + experiment_1_builder.name = "TestGroup1"; + experiment_1_builder.platforms = base::make_span(&platform, 1u); + experiment_1_builder.disable_features = disable_features_1; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { - {/*name=*/"TestGroup1", - /*platforms=*/&platform, - /*platforms_size=*/1, - /*form_factors=*/{}, - /*form_factors_size=*/0, - /*is_low_end_device=*/std::nullopt, - /*min_os_version=*/nullptr, - /*params=*/nullptr, - /*params_size=*/0, - /*enable_features=*/nullptr, - /*enable_features_size=*/0, - /*disable_features=*/disable_features_1, - /*disable_features_size=*/1, - /*forcing_flag=*/nullptr, - /*override_ui_string=*/nullptr, - /*override_ui_string_size=*/0}, + experiment_1_builder.Build(), }; const char* enable_features2[] = {"C"}; const char* disable_features_2[] = {"D"}; + ExperimentBuilder experiment_2_builder; + experiment_2_builder.name = "TestGroup2"; + experiment_2_builder.platforms = base::make_span(&platform, 1u); + experiment_0_builder.enable_features = enable_features2; + experiment_2_builder.disable_features = disable_features_2; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { - {/*name=*/"TestGroup2", - /*platforms=*/&platform, - /*platforms_size=*/1, - /*form_factors=*/{}, - /*form_factors_size=*/0, - /*is_low_end_device=*/std::nullopt, - /*min_os_version=*/nullptr, - /*params=*/nullptr, - /*params_size=*/0, - /*enable_features=*/enable_features2, - /*enable_features_size=*/1, - /*disable_features=*/disable_features_2, - /*disable_features_size=*/1, - /*forcing_flag=*/nullptr, - /*override_ui_string=*/nullptr, - /*override_ui_string_size=*/0}, + experiment_2_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { @@ -377,23 +350,12 @@ for (size_t i = 0; i < std::size(all_platforms); ++i) { const Study::Platform platform = all_platforms[i]; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - array_kFieldTrialConfig_params, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial", array_kFieldTrialConfig_experiments, 1} @@ -425,23 +387,12 @@ const Study::Platform platform = Study::PLATFORM_ANDROID; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {{"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - array_kFieldTrialConfig_params, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -469,23 +420,12 @@ {Study::PLATFORM_ANDROID, Study::PLATFORM_ANDROID_WEBVIEW}; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {{"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = platforms; + experiment_builder.params = array_kFieldTrialConfig_params; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", - platforms, - 2, - {}, - 0, - std::nullopt, - nullptr, - array_kFieldTrialConfig_params, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -522,10 +462,13 @@ }; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {{"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.form_factors = form_factors; + experiment_builder.params = array_kFieldTrialConfig_params; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", &platform, 1, form_factors, std::size(form_factors), - std::nullopt, nullptr, array_kFieldTrialConfig_params, 2, nullptr, 0, - nullptr, 0, nullptr, nullptr, 0}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -557,10 +500,13 @@ variation_service_client_.GetCurrentFormFactor(); const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {{"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.form_factors = base::make_span(&form_factor, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", &platform, 1, &form_factor, 1, std::nullopt, nullptr, - array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr, - nullptr, 0}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial", array_kFieldTrialConfig_experiments, 1} @@ -603,10 +549,13 @@ continue; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {{"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.form_factors = base::make_span(&form_factor, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", &platform, 1, &form_factor, 1, std::nullopt, nullptr, - array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr, - nullptr, 0}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -639,57 +588,23 @@ const char* disable_features[] = {"C", "D"}; const Study::Platform platform = Study::PLATFORM_LINUX; + ExperimentBuilder study_0_experiment_0_builder; + study_0_experiment_0_builder.name = "TestGroup1"; + study_0_experiment_0_builder.platforms = base::make_span(&platform, 1u); + study_0_experiment_0_builder.enable_features = enable_features; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { - {"TestGroup1", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - enable_features, - 2, - nullptr, - 0, - nullptr, - nullptr, - 0}, + study_0_experiment_0_builder.Build(), }; + ExperimentBuilder study_1_experiment_0_builder; + study_1_experiment_0_builder.name = "TestGroup2"; + study_1_experiment_0_builder.platforms = base::make_span(&platform, 1u); + study_1_experiment_0_builder.disable_features = disable_features; + ExperimentBuilder study_1_experiment_1_builder; + study_1_experiment_1_builder.name = "TestGroup2-2"; + study_1_experiment_1_builder.platforms = base::make_span(&platform, 1u); const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { - {"TestGroup2", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - disable_features, - 2, - nullptr, - nullptr, - 0}, - {"TestGroup2-2", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, + study_1_experiment_0_builder.Build(), + study_1_experiment_1_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { @@ -723,106 +638,38 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) { const Study::Platform platform = Study::PLATFORM_LINUX; + ExperimentBuilder study_0_experiment_0_builder; + study_0_experiment_0_builder.name = "TestGroup1"; + study_0_experiment_0_builder.platforms = base::make_span(&platform, 1u); const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { - {"TestGroup1", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}}; - const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { - {"TestGroup2", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, - {"ForcedGroup2", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - "flag-2", - nullptr, - 0}, + study_0_experiment_0_builder.Build(), }; + ExperimentBuilder study_1_experiment_0_builder; + study_1_experiment_0_builder.name = "TestGroup2"; + study_1_experiment_0_builder.platforms = base::make_span(&platform, 1u); + ExperimentBuilder study_1_experiment_1_builder; + study_1_experiment_1_builder.name = "ForcedGroup2"; + study_1_experiment_1_builder.platforms = base::make_span(&platform, 1u); + study_1_experiment_1_builder.forcing_flag = "flag-2"; + const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { + study_1_experiment_0_builder.Build(), + study_1_experiment_1_builder.Build(), + }; + ExperimentBuilder study_2_experiment_0_builder; + study_2_experiment_0_builder.name = "TestGroup3"; + study_2_experiment_0_builder.platforms = base::make_span(&platform, 1u); + ExperimentBuilder study_2_experiment_1_builder; + study_2_experiment_1_builder.name = "ForcedGroup3"; + study_2_experiment_1_builder.platforms = base::make_span(&platform, 1u); + study_2_experiment_1_builder.forcing_flag = "flag-3"; + ExperimentBuilder study_2_experiment_2_builder; + study_2_experiment_2_builder.name = "ForcedGroup3-2"; + study_2_experiment_2_builder.platforms = base::make_span(&platform, 1u); + study_2_experiment_2_builder.forcing_flag = "flag-3-2"; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { - {"TestGroup3", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - nullptr, - nullptr, - 0}, - {"ForcedGroup3", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - "flag-3", - nullptr, - 0}, - {"ForcedGroup3-2", - &platform, - 1, - {}, - 0, - std::nullopt, - nullptr, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - "flag-3-2", - nullptr, - 0}, + study_2_experiment_0_builder.Build(), + study_2_experiment_1_builder.Build(), + study_2_experiment_2_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial1", array_kFieldTrialConfig_experiments_0, 1}, @@ -853,10 +700,14 @@ {{"x", "1"}, {"y", "2"}}; const OverrideUIString array_kFieldTrialConfig_override_ui_string[] = {{1234, "test1"}, {5678, "test2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; + experiment_builder.override_ui_string = + array_kFieldTrialConfig_override_ui_string; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", &platform, 1, nullptr, 0, std::nullopt, nullptr, - array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr, - array_kFieldTrialConfig_override_ui_string, 2}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial", array_kFieldTrialConfig_experiments, 1} @@ -895,21 +746,13 @@ const Study::Platform platform = Study::PLATFORM_WINDOWS; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { {"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; + experiment_builder.is_low_end_device = base::SysInfo::IsLowEndDevice(); const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", - &platform, - 1, - {}, - 0, - base::SysInfo::IsLowEndDevice(), - nullptr, - array_kFieldTrialConfig_params, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -938,21 +781,13 @@ const Study::Platform platform = Study::PLATFORM_WINDOWS; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { {"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; + experiment_builder.is_low_end_device = !base::SysInfo::IsLowEndDevice(); const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", - &platform, - 1, - {}, - 0, - !base::SysInfo::IsLowEndDevice(), - nullptr, - array_kFieldTrialConfig_params, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -980,21 +815,13 @@ const Study::Platform platform = Study::PLATFORM_WINDOWS; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { {"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; + experiment_builder.min_os_version = min_os_version.c_str(); const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", - &platform, - 1, - {}, - 0, - std::nullopt, - min_os_version.c_str(), - array_kFieldTrialConfig_params, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -1027,21 +854,13 @@ const Study::Platform platform = Study::PLATFORM_WINDOWS; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { {"x", "1"}, {"y", "2"}}; + ExperimentBuilder experiment_builder; + experiment_builder.name = "TestGroup"; + experiment_builder.platforms = base::make_span(&platform, 1u); + experiment_builder.params = array_kFieldTrialConfig_params; + experiment_builder.min_os_version = min_os_version.c_str(); const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", - &platform, - 1, - {}, - 0, - std::nullopt, - min_os_version.c_str(), - array_kFieldTrialConfig_params, - 2, - nullptr, - 0, - nullptr, - 0, - nullptr}, + experiment_builder.Build(), }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial", array_kFieldTrialConfig_experiments, 1}};
diff --git a/components/webapps/browser/installable/installable_metrics.h b/components/webapps/browser/installable/installable_metrics.h index 9451de6..df1155a 100644 --- a/components/webapps/browser/installable/installable_metrics.h +++ b/components/webapps/browser/installable/installable_metrics.h
@@ -214,8 +214,11 @@ // sessions. kHealthcareUserInstallCleanup = 21, + // Isolated Web App Enterprise policy. + kIwaEnterprisePolicy = 22, + // Add any new values above this one. - kMaxValue = kHealthcareUserInstallCleanup, + kMaxValue = kIwaEnterprisePolicy, }; // This is the result of the promotability check that is recorded in the
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 86b88e2..f3989b3 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -195,6 +195,7 @@ "//services/data_decoder/public/mojom", "//services/device:lib", "//services/device/public/cpp:device_features", + "//services/device/public/cpp/generic_sensor", "//services/device/public/cpp/geolocation", "//services/device/public/mojom", "//services/device/public/mojom:device_service", @@ -313,6 +314,8 @@ "$target_gen_dir/devtools/protocol/browser.h", "$target_gen_dir/devtools/protocol/device_access.cc", "$target_gen_dir/devtools/protocol/device_access.h", + "$target_gen_dir/devtools/protocol/device_orientation.cc", + "$target_gen_dir/devtools/protocol/device_orientation.h", "$target_gen_dir/devtools/protocol/dom.cc", "$target_gen_dir/devtools/protocol/dom.h", "$target_gen_dir/devtools/protocol/emulation.cc", @@ -833,6 +836,8 @@ "devtools/protocol/browser_handler.h", "devtools/protocol/device_access_handler.cc", "devtools/protocol/device_access_handler.h", + "devtools/protocol/device_orientation_handler.cc", + "devtools/protocol/device_orientation_handler.h", "devtools/protocol/devtools_domain_handler.cc", "devtools/protocol/devtools_domain_handler.h", "devtools/protocol/devtools_download_manager_delegate.cc",
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index 87fb9be9..49dbd33 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -76,6 +76,7 @@ #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/common/device_memory/approximated_device_memory.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/features_generated.h" #include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h" #include "third_party/blink/public/common/switches.h" #include "third_party/blink/public/mojom/frame/frame.mojom.h" @@ -2771,7 +2772,7 @@ class BackForwardCacheBrowserUnloadHandlerTest : public BackForwardCacheBrowserTest, public ::testing::WithParamInterface< - std::tuple<bool, bool, TestFrameType>> { + std::tuple<bool, bool, bool, TestFrameType>> { public: void SetUpCommandLine(base::CommandLine* command_line) override { if (IsUnloadAllowed()) { @@ -2784,20 +2785,28 @@ } else { DisableFeature(blink::features::kUnloadBlocklisted); } + if (IsUnloadDeprecationOptedOut()) { + EnableFeatureAndSetParams(blink::features::kDeprecateUnloadOptOut, "", + ""); + } else { + DisableFeature(blink::features::kDeprecateUnloadOptOut); + } + BackForwardCacheBrowserTest::SetUpCommandLine(command_line); } bool IsUnloadAllowed() { return std::get<0>(GetParam()); } bool IsUnloadBlocklisted() { return std::get<1>(GetParam()); } + bool IsUnloadDeprecationOptedOut() { return std::get<2>(GetParam()); } - TestFrameType GetTestFrameType() { return std::get<2>(GetParam()); } + TestFrameType GetTestFrameType() { return std::get<3>(GetParam()); } private: base::test::ScopedFeatureList scoped_feature_list_; }; -// Ensure that unload handlers in main frames and subframes block caching or -// not, depending on the flag setting. +// Ensure that unload handlers in main frames and subframes block caching, +// depending on unload deprecation status and OS. IN_PROC_BROWSER_TEST_P(BackForwardCacheBrowserUnloadHandlerTest, UnloadHandlerPresent) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -2808,17 +2817,28 @@ // 1) Navigate to A. EXPECT_TRUE(NavigateToURL(shell(), url_a)); - BackForwardCacheMetrics::NotRestoredReason expected_blocking_reason; + std::vector<BackForwardCacheMetrics::NotRestoredReason> + expected_blocking_reasons; + std::vector<blink::scheduler::WebSchedulerTrackedFeature> + expected_blocklisted_reason; + if (IsUnloadBlocklisted()) { + expected_blocking_reasons.push_back( + BackForwardCacheMetrics::NotRestoredReason::kBlocklistedFeatures); + expected_blocklisted_reason.push_back( + blink::scheduler::WebSchedulerTrackedFeature::kUnloadHandler); + } switch (GetTestFrameType()) { case content::TestFrameType::kMainFrame: InstallUnloadHandlerOnMainFrame(); - expected_blocking_reason = BackForwardCacheMetrics::NotRestoredReason:: - kUnloadHandlerExistsInMainFrame; + expected_blocking_reasons.push_back( + BackForwardCacheMetrics::NotRestoredReason:: + kUnloadHandlerExistsInMainFrame); break; case content::TestFrameType::kSubFrame: InstallUnloadHandlerOnSubFrame(); - expected_blocking_reason = BackForwardCacheMetrics::NotRestoredReason:: - kUnloadHandlerExistsInSubFrame; + expected_blocking_reasons.push_back( + BackForwardCacheMetrics::NotRestoredReason:: + kUnloadHandlerExistsInSubFrame); break; default: NOTREACHED(); @@ -2830,48 +2850,33 @@ // 3) Go back. ASSERT_TRUE(HistoryGoBack(web_contents())); - if (IsUnloadBlocklisted()) { + bool unload_never_blocks = IsUnloadAllowed(); + bool unload_deprecated_and_not_opted_out = + (base::FeatureList::IsEnabled(blink::features::kDeprecateUnload) && + !IsUnloadDeprecationOptedOut()); + if (unload_never_blocks || unload_deprecated_and_not_opted_out) { // Pages with unload handlers are eligible for bfcache only if it is - // specifically allowed (happens on Android), or when unload handlers are - // deprecated. - if (BackForwardCacheImpl::IsUnloadAllowed() || - base::FeatureList::IsEnabled(blink::features::kDeprecateUnload)) { - ExpectRestored(FROM_HERE); - EXPECT_EQ("0", GetUnloadRunCount()); - } else { - // If unload handlers are a blocklisted feature, the blocklisted feature - // gets reported in addition to the not restored reason. - ExpectNotRestored( - {expected_blocking_reason, - BackForwardCacheMetrics::NotRestoredReason::kBlocklistedFeatures}, - {blink::scheduler::WebSchedulerTrackedFeature::kUnloadHandler}, {}, - {}, {}, FROM_HERE); - EXPECT_EQ("1", GetUnloadRunCount()); - } + // specifically allowed (happens on Android). Also, when unload is + // deprecated and `kDeprecateUnloadOptOut` doesn't override it, unload + // handlers cannot be installed so there should be no blocker for BFCache. + ExpectRestored(FROM_HERE); + EXPECT_EQ("0", GetUnloadRunCount()); } else { - if (BackForwardCacheImpl::IsUnloadAllowed() || - base::FeatureList::IsEnabled(blink::features::kDeprecateUnload)) { - ExpectRestored(FROM_HERE); - EXPECT_EQ("0", GetUnloadRunCount()); - } else { - ExpectNotRestored({expected_blocking_reason}, {}, {}, {}, {}, FROM_HERE); - EXPECT_EQ("1", GetUnloadRunCount()); - } + ExpectNotRestored(expected_blocking_reasons, expected_blocklisted_reason, + {}, {}, {}, FROM_HERE); + EXPECT_EQ("1", GetUnloadRunCount()); } - - // 4) Go forward. - ASSERT_TRUE(HistoryGoForward(web_contents())); - - ExpectRestored(FROM_HERE); } -// The first param is to check if unload is allowed, and the second one is to -// check if unload is a blocklisted feature. +// First param: whether unload is allowed or not. +// Second one: whether unload is blocklisted or not. +// Third one: whether it's opted out from unload deprecation or not. INSTANTIATE_TEST_SUITE_P( All, BackForwardCacheBrowserUnloadHandlerTest, ::testing::Combine(::testing::Bool(), ::testing::Bool(), + ::testing::Bool(), ::testing::Values(TestFrameType::kMainFrame, TestFrameType::kSubFrame)));
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index 72b1e46..89d22d8 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc
@@ -1218,8 +1218,6 @@ // requestable by any child process. Also, this case covers // <javascript:...>, which should be handled internally by the process and // not kicked up to the browser. - // TODO(dcheng): Figure out why this check is different from CanCommitURL, - // which checks for direct equality with kAboutBlankURL. if (IsPseudoScheme(scheme)) return url.IsAboutBlank() || url.IsAboutSrcdoc();
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn index d9812e6..cb78e03 100644 --- a/content/browser/devtools/BUILD.gn +++ b/content/browser/devtools/BUILD.gn
@@ -106,6 +106,8 @@ "protocol/browser.h", "protocol/device_access.cc", "protocol/device_access.h", + "protocol/device_orientation.cc", + "protocol/device_orientation.h", "protocol/dom.cc", "protocol/dom.h", "protocol/emulation.cc",
diff --git a/content/browser/devtools/devtools_session.h b/content/browser/devtools/devtools_session.h index b8bb0a5..ece3305 100644 --- a/content/browser/devtools/devtools_session.h +++ b/content/browser/devtools/devtools_session.h
@@ -33,6 +33,7 @@ class DevToolsDomainHandler; class AuditsHandler; class DOMHandler; +class DeviceOrientationHandler; class EmulationHandler; class InputHandler; class InspectorHandler; @@ -190,21 +191,23 @@ template <typename T> bool IsDomainAvailableToUntrustedClient() { - return std::disjunction_v<std::is_same<T, protocol::AuditsHandler>, - std::is_same<T, protocol::DOMHandler>, - std::is_same<T, protocol::EmulationHandler>, - std::is_same<T, protocol::InputHandler>, - std::is_same<T, protocol::InspectorHandler>, - std::is_same<T, protocol::IOHandler>, - std::is_same<T, protocol::OverlayHandler>, - std::is_same<T, protocol::NetworkHandler>, - std::is_same<T, protocol::FetchHandler>, - std::is_same<T, protocol::StorageHandler>, - std::is_same<T, protocol::TargetHandler>, - std::is_same<T, protocol::PageHandler>, - std::is_same<T, protocol::TracingHandler>, - std::is_same<T, protocol::LogHandler>, - std::is_same<T, protocol::WebAuthnHandler>>; + return std::disjunction_v< + std::is_same<T, protocol::AuditsHandler>, + std::is_same<T, protocol::DOMHandler>, + std::is_same<T, protocol::DeviceOrientationHandler>, + std::is_same<T, protocol::EmulationHandler>, + std::is_same<T, protocol::InputHandler>, + std::is_same<T, protocol::InspectorHandler>, + std::is_same<T, protocol::IOHandler>, + std::is_same<T, protocol::OverlayHandler>, + std::is_same<T, protocol::NetworkHandler>, + std::is_same<T, protocol::FetchHandler>, + std::is_same<T, protocol::StorageHandler>, + std::is_same<T, protocol::TargetHandler>, + std::is_same<T, protocol::PageHandler>, + std::is_same<T, protocol::TracingHandler>, + std::is_same<T, protocol::LogHandler>, + std::is_same<T, protocol::WebAuthnHandler>>; } void AddHandler(std::unique_ptr<protocol::DevToolsDomainHandler> handler);
diff --git a/content/browser/devtools/protocol/device_orientation_handler.cc b/content/browser/devtools/protocol/device_orientation_handler.cc new file mode 100644 index 0000000..dab1eb0 --- /dev/null +++ b/content/browser/devtools/protocol/device_orientation_handler.cc
@@ -0,0 +1,101 @@ +// 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 "content/browser/devtools/protocol/device_orientation_handler.h" + +#include "base/functional/bind.h" +#include "content/browser/devtools/protocol/emulation.h" +#include "content/browser/devtools/protocol/emulation_handler.h" +#include "content/browser/devtools/protocol/protocol.h" +#include "content/browser/generic_sensor/web_contents_sensor_provider_proxy.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "services/device/public/cpp/generic_sensor/orientation_util.h" +#include "services/device/public/mojom/sensor_provider.mojom.h" + +namespace content { +namespace protocol { + +DeviceOrientationHandler::DeviceOrientationHandler() + : DevToolsDomainHandler(DeviceOrientation::Metainfo::domainName) {} + +DeviceOrientationHandler::~DeviceOrientationHandler() = default; + +void DeviceOrientationHandler::Wire(UberDispatcher* dispatcher) { + DeviceOrientation::Dispatcher::wire(dispatcher, this); +} + +void DeviceOrientationHandler::SetRenderer(int process_host_id, + RenderFrameHostImpl* frame_host) { + if (!frame_host) { + Disable(); + } + frame_host_ = frame_host; +} + +Response DeviceOrientationHandler::Disable() { + return ClearDeviceOrientationOverride(); +} + +Response DeviceOrientationHandler::ClearDeviceOrientationOverride() { + virtual_sensor_.reset(); + return Response::FallThrough(); +} + +void DeviceOrientationHandler::SetDeviceOrientationOverride( + double alpha, + double beta, + double gamma, + std::unique_ptr<SetDeviceOrientationOverrideCallback> callback) { + if (!frame_host_) { + callback->sendFailure(Response::InternalError()); + return; + } + if (!frame_host_->IsOutermostMainFrame()) { + // Virtual sensors are handled at the WebContents level, so there is no need + // to try to run the code below if we are not the outermost frame -- it will + // just result in CreateVirtualSensorForDevTools() returning nullptr. + callback->fallThrough(); + return; + } + + device::SensorReading quaternion_readings; + if (!device::ComputeQuaternionFromEulerAngles(alpha, beta, gamma, + &quaternion_readings)) { + callback->sendFailure(Response::InvalidParams( + "Failed to convert Euler angles to quaternions. Invalid alpha, beta, " + "or gamma value.")); + return; + } + quaternion_readings.raw.timestamp = + (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); + + if (!virtual_sensor_) { + virtual_sensor_ = + WebContentsSensorProviderProxy::GetOrCreate(GetWebContents()) + ->CreateVirtualSensorForDevTools( + device::mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION, + device::mojom::VirtualSensorMetadata::New()); + if (!virtual_sensor_) { + // Already overridden elsewhere (e.g. EmulationHandler). + callback->sendFailure(Response::InvalidParams( + "The 'relative-orientation' sensor type is already overridden, " + "possibly by the Emulation domain.")); + return; + } + } + + virtual_sensor_->UpdateVirtualSensor(quaternion_readings, + base::NullCallback()); + callback->fallThrough(); +} + +WebContentsImpl* DeviceOrientationHandler::GetWebContents() { + CHECK(frame_host_); // Only call if |frame_host_| is set. + return static_cast<WebContentsImpl*>( + WebContents::FromRenderFrameHost(frame_host_)); +} + +} // namespace protocol +} // namespace content
diff --git a/content/browser/devtools/protocol/device_orientation_handler.h b/content/browser/devtools/protocol/device_orientation_handler.h new file mode 100644 index 0000000..ef34333 --- /dev/null +++ b/content/browser/devtools/protocol/device_orientation_handler.h
@@ -0,0 +1,59 @@ +// 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVICE_ORIENTATION_HANDLER_H_ +#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVICE_ORIENTATION_HANDLER_H_ + +#include <memory> + +#include "base/memory/raw_ptr.h" +#include "content/browser/devtools/protocol/device_orientation.h" +#include "content/browser/devtools/protocol/devtools_domain_handler.h" + +namespace content { + +class RenderFrameHostImpl; +class ScopedVirtualSensorForDevTools; +class WebContentsImpl; + +namespace protocol { + +// Handling of this CDP domain is also partially implemented in Blink. See +// DeviceOrientationInspectorAgent. +class DeviceOrientationHandler : public DevToolsDomainHandler, + public DeviceOrientation::Backend { + public: + DeviceOrientationHandler(); + + DeviceOrientationHandler(const DeviceOrientationHandler&) = delete; + DeviceOrientationHandler& operator=(const DeviceOrientationHandler&) = delete; + + ~DeviceOrientationHandler() override; + + private: + WebContentsImpl* GetWebContents(); + + // DevToolsDomainHandler overrides. + void Wire(UberDispatcher* dispatcher) override; + void SetRenderer(int process_host_id, + RenderFrameHostImpl* frame_host) override; + Response Disable() override; + + // DeviceOrientation::Backend overrides. + Response ClearDeviceOrientationOverride() override; + void SetDeviceOrientationOverride( + double alpha, + double beta, + double gamma, + std::unique_ptr<SetDeviceOrientationOverrideCallback> callback) override; + + raw_ptr<RenderFrameHostImpl> frame_host_ = nullptr; + + std::unique_ptr<ScopedVirtualSensorForDevTools> virtual_sensor_; +}; + +} // namespace protocol +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVICE_ORIENTATION_HANDLER_H_
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index 2fbae0d4..db9c1e3 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -27,6 +27,12 @@ "include_events": [] }, { + "domain": "DeviceOrientation", + "async": [ + "setDeviceOrientationOverride" + ] + }, + { "domain": "Emulation", "include": [ "getOverriddenSensorInformation",
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 2465f80..dd029fe 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -28,6 +28,7 @@ #include "content/browser/devtools/protocol/background_service_handler.h" #include "content/browser/devtools/protocol/browser_handler.h" #include "content/browser/devtools/protocol/device_access_handler.h" +#include "content/browser/devtools/protocol/device_orientation_handler.h" #include "content/browser/devtools/protocol/dom_handler.h" #include "content/browser/devtools/protocol/emulation_handler.h" #include "content/browser/devtools/protocol/fedcm_handler.h" @@ -337,6 +338,7 @@ session->CreateAndAddHandler<protocol::BrowserHandler>( session->GetClient()->MayWriteLocalFiles()); session->CreateAndAddHandler<protocol::DeviceAccessHandler>(); + session->CreateAndAddHandler<protocol::DeviceOrientationHandler>(); session->CreateAndAddHandler<protocol::DOMHandler>( session->GetClient()->MayReadLocalFiles()); auto* emulation_handler =
diff --git a/content/browser/fenced_frame/fenced_frame_browsertest.cc b/content/browser/fenced_frame/fenced_frame_browsertest.cc index d7584ed..23ab3ebf 100644 --- a/content/browser/fenced_frame/fenced_frame_browsertest.cc +++ b/content/browser/fenced_frame/fenced_frame_browsertest.cc
@@ -1613,6 +1613,44 @@ ff_rfh->GetSiteInstance()->GetBrowsingInstanceId()); } +// A test to confirm that a FencedFrame fails to create inside a CSP sandbox +// frame without allow-same-origin. This test should fail regardless of the +// state of kIsolateSandboxedIframes or kIsolateFencedFrames. +IN_PROC_BROWSER_TEST_P(FencedFrameIsolatedSandboxedIframesBrowserTest, + NoFencedFramesInIsolatedSandboxedIframes) { + IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess()); + ASSERT_TRUE(AreAllSitesIsolatedForTesting()); + ASSERT_TRUE(https_server()->Start()); + + // Load CSP sandboxed frame as mainframe. + const GURL main_url = + https_server()->GetURL("a.test", "/fenced_frames/sandbox_flags.html"); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + EXPECT_TRUE(primary_main_frame_host() + ->GetSiteInstance() + ->GetSiteInfo() + .is_sandboxed()); + + // Try to load FencedFrame inside the CSP sandboxed frame. + const GURL fenced_frame_url = + https_server()->GetURL("a.test", "/fenced_frames/title1.html"); + // Extracted from CreateFencedFrame, which doesn't expect to fail. + constexpr char kAddFencedFrameScript[] = R"({ + const fenced_frame = document.createElement('fencedframe'); + document.body.appendChild(fenced_frame); + })"; + size_t previous_fenced_frame_count = + primary_main_frame_host()->GetFencedFrames().size(); + EXPECT_EQ(0U, previous_fenced_frame_count); + // The following attempt to create a fenced frame is expected to fail since + // it would otherwise be contained in a sandbox that doesn't have the + // allow-same-origin attribute. See kFencedFrameMandatoryUnsandboxedFlags. + EXPECT_FALSE(ExecJs(primary_main_frame_host(), kAddFencedFrameScript, + EvalJsOptions::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ(previous_fenced_frame_count, + primary_main_frame_host()->GetFencedFrames().size()); +} + class FencedFrameProcessIsolationBrowserTest : public FencedFrameMPArchBrowserTest { public:
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index 4fa857fe..ab25311 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -578,6 +578,12 @@ BUILDFLAG(IS_CHROMEOS_ASH) CHECK(false) << "GPU acceleration is required on certain platforms!"; #endif + } else if (features::IsSkiaGraphiteEnabled(command_line)) { + // If Graphite is enabled, do not add modes to fall back to Ganesh. Instead, + // fall back directly to software. + // TODO(crbug.com/1507801): Add fallback to Ganesh/GL on platforms that + // don't support software compositing (Android and ChromeOS). + fallback_modes_.push_back(gpu::GpuMode::HARDWARE_GRAPHITE); } else { // On Fuchsia Vulkan must be used when it's enabled by the WebEngine // embedder. Falling back to SW compositing in that case is not supported. @@ -625,6 +631,7 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed(std::string* reason) const { switch (gpu_mode_) { case gpu::GpuMode::HARDWARE_GL: + case gpu::GpuMode::HARDWARE_GRAPHITE: case gpu::GpuMode::HARDWARE_VULKAN: return true; case gpu::GpuMode::SWIFTSHADER: @@ -1385,6 +1392,7 @@ std::string use_gl; switch (gpu_mode_) { case gpu::GpuMode::HARDWARE_GL: + case gpu::GpuMode::HARDWARE_GRAPHITE: case gpu::GpuMode::HARDWARE_VULKAN: use_gl = browser_command_line->GetSwitchValueASCII(switches::kUseGL); break; @@ -1449,6 +1457,16 @@ if (gpu_mode_ != gpu::GpuMode::HARDWARE_VULKAN) gpu_preferences->use_vulkan = gpu::VulkanImplementationName::kNone; #endif + + if (gpu_mode_ != gpu::GpuMode::HARDWARE_GRAPHITE) { + // Recompute the `gr_context_type` pref with Graphite explicitly disabled, + // as it may currently be set to Graphite. + auto command_line_with_graphite_disabled(*command_line); + command_line_with_graphite_disabled.AppendSwitch( + switches::kDisableSkiaGraphite); + gpu_preferences->gr_context_type = + gpu::gles2::ParseGrContextType(&command_line_with_graphite_disabled); + } } void GpuDataManagerImplPrivate::DisableHardwareAcceleration() { @@ -1460,6 +1478,7 @@ bool GpuDataManagerImplPrivate::HardwareAccelerationEnabled() const { switch (gpu_mode_) { case gpu::GpuMode::HARDWARE_GL: + case gpu::GpuMode::HARDWARE_GRAPHITE: case gpu::GpuMode::HARDWARE_VULKAN: return true; default:
diff --git a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc index 57e4137f..f792986 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
@@ -458,6 +458,14 @@ ::testing::Values(gpu::DomainGuilt::kKnown, gpu::DomainGuilt::kUnknown)); +TEST_F(GpuDataManagerImplPrivateTest, GpuStartsWithGraphiteFeatureFlag) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableSkiaGraphite); + + ScopedGpuDataManagerImplPrivate manager; + EXPECT_EQ(gpu::GpuMode::HARDWARE_GRAPHITE, manager->GetGpuMode()); +} + // Android and Chrome OS do not support software compositing, while Fuchsia does // not support falling back to software from Vulkan. #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_IOS) @@ -480,6 +488,32 @@ gpu::GpuMode expected_mode = gpu::GpuMode::DISPLAY_COMPOSITOR; EXPECT_EQ(expected_mode, manager->GetGpuMode()); } + +TEST_F(GpuDataManagerImplPrivateTest, FallbackFromGraphiteToSwiftShader) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableSkiaGraphite); + + ScopedGpuDataManagerImplPrivate manager; + EXPECT_EQ(gpu::GpuMode::HARDWARE_GRAPHITE, manager->GetGpuMode()); + + manager->FallBackToNextGpuMode(); + EXPECT_EQ(gpu::GpuMode::SWIFTSHADER, manager->GetGpuMode()); +} + +TEST_F(GpuDataManagerImplPrivateTest, + FallbackFromGraphiteWithSwiftShaderDisabled) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableSkiaGraphite); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisableSoftwareRasterizer); + + ScopedGpuDataManagerImplPrivate manager; + EXPECT_EQ(gpu::GpuMode::HARDWARE_GRAPHITE, manager->GetGpuMode()); + + manager->FallBackToNextGpuMode(); + gpu::GpuMode expected_mode = gpu::GpuMode::DISPLAY_COMPOSITOR; + EXPECT_EQ(expected_mode, manager->GetGpuMode()); +} #endif // !BUILDFLAG(IS_FUCHSIA) #if !defined(CAST_AUDIO_ONLY)
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index c8ec221..9f6e63a 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -151,6 +151,7 @@ NOTREACHED(); return nullptr; case gpu::GpuMode::HARDWARE_GL: + case gpu::GpuMode::HARDWARE_GRAPHITE: case gpu::GpuMode::HARDWARE_VULKAN: return kProcessLifetimeEventsHardwareAccelerated; case gpu::GpuMode::SWIFTSHADER: @@ -1162,14 +1163,14 @@ if (!version) { continue; } - if (token.GetAs<blink::ServiceWorkerToken>() != - version->embedded_worker()->token().value()) { - continue; - } ServiceWorkerHost* service_worker_host = version->worker_host(); if (!service_worker_host) { continue; } + if (service_worker_host->token() != + token.GetAs<blink::ServiceWorkerToken>()) { + continue; + } auto isolation_key = service_worker_host->GetNetworkIsolationKey().ToCacheKeyString(); return isolation_key ? *isolation_key : "";
diff --git a/content/browser/interest_group/interest_group_storage.cc b/content/browser/interest_group/interest_group_storage.cc index d72b364..4c1fcbe 100644 --- a/content/browser/interest_group/interest_group_storage.cc +++ b/content/browser/interest_group/interest_group_storage.cc
@@ -693,9 +693,7 @@ "LIMIT 1")); // We can get any previously added row for a k_anon key because the same data // is duplicated for each row of the same key. - if (!get_previous_kanon_val.is_valid()) { - return false; - } + CHECK(get_previous_kanon_val.is_valid()) << db.GetErrorMessage(); get_previous_kanon_val.BindString(0, key); @@ -732,9 +730,7 @@ db.GetCachedStatement(SQL_FROM_HERE, query.c_str())); } - if (!maybe_insert_kanon.is_valid()) { - return false; - } + CHECK(maybe_insert_kanon.is_valid()) << db.GetErrorMessage(); maybe_insert_kanon.Reset(true); maybe_insert_kanon.BindTime(0, last_referenced_time); @@ -2161,9 +2157,7 @@ db.GetCachedStatement(SQL_FROM_HERE, "DELETE FROM join_history " "WHERE owner=? AND name=?")); - if (!remove_join_history.is_valid()) { - return false; - } + CHECK(remove_join_history.is_valid()) << db.GetErrorMessage(); remove_join_history.Reset(true); remove_join_history.BindString(0, Serialize(group_key.owner)); @@ -2177,9 +2171,7 @@ db.GetCachedStatement(SQL_FROM_HERE, "DELETE FROM bid_history " "WHERE owner=? AND name=?")); - if (!remove_bid_history.is_valid()) { - return false; - } + CHECK(remove_bid_history.is_valid()) << db.GetErrorMessage(); remove_bid_history.Reset(true); remove_bid_history.BindString(0, Serialize(group_key.owner)); @@ -2193,9 +2185,7 @@ db.GetCachedStatement(SQL_FROM_HERE, "DELETE FROM win_history " "WHERE owner=? AND name=?")); - if (!remove_win_history.is_valid()) { - return false; - } + CHECK(remove_win_history.is_valid()) << db.GetErrorMessage(); remove_win_history.Reset(true); remove_win_history.BindString(0, Serialize(group_key.owner)); @@ -2225,9 +2215,7 @@ db.GetCachedStatement(SQL_FROM_HERE, "DELETE FROM interest_groups " "WHERE owner=? AND name=?")); - if (!remove_group.is_valid()) { - return false; - } + CHECK(remove_group.is_valid()) << db.GetErrorMessage(); remove_group.Reset(true); remove_group.BindString(0, Serialize(group_key.owner)); @@ -2251,9 +2239,7 @@ "WHERE owner = ? AND joining_origin = ? AND execution_mode = ?")); // clang-format on - if (!same_cluster_groups.is_valid()) { - return false; - } + CHECK(same_cluster_groups.is_valid()) << db.GetErrorMessage(); same_cluster_groups.Reset(true); same_cluster_groups.BindString(0, Serialize(owner)); @@ -2297,9 +2283,7 @@ "WHERE owner = ? AND joining_origin = ?")); // clang-format on - if (!same_cluster_groups.is_valid()) { - return std::nullopt; - } + CHECK(same_cluster_groups.is_valid()) << db.GetErrorMessage(); same_cluster_groups.Reset(true); same_cluster_groups.BindString(0, Serialize(owner)); @@ -2363,9 +2347,7 @@ "WHERE owner = ? AND name = ? ")); // clang-format on - if (!load.is_valid()) { - return false; - } + CHECK(load.is_valid()) << db.GetErrorMessage(); load.Reset(true); load.BindString(0, Serialize(group_key.owner)); @@ -2446,9 +2428,7 @@ "INSERT OR IGNORE INTO join_history(owner,name,join_time,count) " "VALUES(?,?,?,1)")); // clang-format on - if (!insert_join_hist.is_valid()) { - return false; - } + CHECK(insert_join_hist.is_valid()) << db.GetErrorMessage(); insert_join_hist.Reset(true); insert_join_hist.BindString(0, Serialize(owner)); @@ -2470,9 +2450,7 @@ "SET count=count+1 " "WHERE owner=? AND name=? AND join_time=?")); // clang-format on - if (!update_join_hist.is_valid()) { - return false; - } + CHECK(update_join_hist.is_valid()) << db.GetErrorMessage(); update_join_hist.Reset(true); update_join_hist.BindString(0, Serialize(owner)); @@ -2561,9 +2539,7 @@ )); // clang-format on - if (!join_group.is_valid()) { - return false; - } + CHECK(join_group.is_valid()) << db.GetErrorMessage(); join_group.Reset(true); join_group.BindTime(0, data.expiry); join_group.BindTime(1, last_updated); @@ -2656,9 +2632,7 @@ "WHERE owner=? AND name=?")); // clang-format on - if (!store_group.is_valid()) { - return false; - } + CHECK(store_group.is_valid()) << db.GetErrorMessage(); store_group.Reset(true); store_group.BindTime(0, now); @@ -2835,9 +2809,7 @@ next_update_after=? WHERE owner=? AND name=?)")); - if (!update_group.is_valid()) { - return false; - } + CHECK(update_group.is_valid()) << db.GetErrorMessage(); update_group.Reset(true); if (parse_failure) { @@ -2873,9 +2845,7 @@ "INSERT OR IGNORE INTO bid_history(owner,name,bid_time,count) " "VALUES(?,?,?,1)")); // clang-format on - if (!insert_bid_hist.is_valid()) { - return false; - } + CHECK(insert_bid_hist.is_valid()) << db.GetErrorMessage(); insert_bid_hist.Reset(true); insert_bid_hist.BindString(0, Serialize(group_key.owner)); @@ -2897,9 +2867,7 @@ "SET count=count+1 " "WHERE owner=? AND name=? AND bid_time=?")); // clang-format on - if (!update_bid_hist.is_valid()) { - return false; - } + CHECK(update_bid_hist.is_valid()) << db.GetErrorMessage(); update_bid_hist.Reset(true); update_bid_hist.BindString(0, Serialize(group_key.owner)); @@ -2937,9 +2905,7 @@ "INSERT INTO win_history(owner,name,win_time,ad) " "VALUES(?,?,?,?)")); // clang-format on - if (!win_hist.is_valid()) { - return false; - } + CHECK(win_hist.is_valid()) << db.GetErrorMessage(); win_hist.Reset(true); win_hist.BindString(0, Serialize(group_key.owner)); @@ -2956,9 +2922,7 @@ "INSERT OR REPLACE " "INTO lockout_debugging_only_report(id, last_report_sent_time) " "VALUES(1, ?)")); - if (!debug_lockout.is_valid()) { - return false; - } + CHECK(debug_lockout.is_valid()) << db.GetErrorMessage(); debug_lockout.Reset(true); // Ceil to nearest hour to be stored in DB. @@ -2978,9 +2942,7 @@ "INSERT OR REPLACE " "INTO cooldown_debugging_only_report(origin, starting_time, type) " "VALUES(?, ?, ?)")); - if (!debug_cooldown.is_valid()) { - return false; - } + CHECK(debug_cooldown.is_valid()) << db.GetErrorMessage(); debug_cooldown.Reset(true); debug_cooldown.BindString(0, Serialize(origin)); @@ -3010,9 +2972,7 @@ "last_referenced_time=? " "WHERE key=?")); // clang-format on - if (!update.is_valid()) { - return false; - } + CHECK(update.is_valid()) << db.GetErrorMessage(); update.Reset(true); update.BindInt(0, data.is_k_anonymous); @@ -3034,11 +2994,8 @@ db.GetCachedStatement(SQL_FROM_HERE, "SELECT last_reported_to_anon_server_time FROM " "k_anon WHERE key=? LIMIT 1")); - if (!get_reported.is_valid()) { - DLOG(ERROR) << "GetLastKAnonymityReported SQL statement did not compile: " - << db.GetErrorMessage(); - return std::nullopt; - } + CHECK(get_reported.is_valid()) << db.GetErrorMessage(); + get_reported.Reset(true); get_reported.BindString(0, key); if (!get_reported.Step()) { @@ -3066,12 +3023,8 @@ "last_referenced_time=? " "WHERE key=?")); // clang-format on - if (!set_reported.is_valid()) { - DLOG(ERROR) - << "DoUpdateLastKAnonymityReported SQL statement did not compile: " - << db.GetErrorMessage(); - return; - } + CHECK(set_reported.is_valid()) << db.GetErrorMessage(); + set_reported.Reset(true); set_reported.BindTime(0, now); set_reported.BindTime(1, now); @@ -3094,8 +3047,8 @@ // interest group with this key. // clang-format off - sql::Statement insert_entry_for_empty_ig( - db.GetCachedStatement(SQL_FROM_HERE, + sql::Statement insert_entry_for_empty_ig( + db.GetCachedStatement(SQL_FROM_HERE, "INSERT INTO k_anon(" "last_referenced_time," "key," @@ -3107,9 +3060,7 @@ "VALUES(?,?,'','',0,?,?)")); // clang-format on - if (!insert_entry_for_empty_ig.is_valid()) { - return; - } + CHECK(insert_entry_for_empty_ig.is_valid()) << db.GetErrorMessage(); insert_entry_for_empty_ig.Reset(true); insert_entry_for_empty_ig.BindTime(0, base::Time::Min()); @@ -3133,11 +3084,8 @@ "FROM interest_groups " "WHERE expiration>? " "ORDER BY expiration DESC")); - if (!load.is_valid()) { - DLOG(ERROR) << "LoadAllInterestGroups SQL statement did not compile: " - << db.GetErrorMessage(); - return std::nullopt; - } + CHECK(load.is_valid()) << db.GetErrorMessage(); + load.Reset(true); load.BindTime(0, expiring_after); while (load.Step()) { @@ -3157,12 +3105,8 @@ "SELECT DISTINCT joining_origin " "FROM interest_groups " "WHERE expiration>?")); - if (!load.is_valid()) { - DLOG(ERROR) << "LoadAllInterestGroupJoiningOrigins SQL statement did not " - "compile: " - << db.GetErrorMessage(); - return std::nullopt; - } + CHECK(load.is_valid()) << db.GetErrorMessage(); + load.Reset(true); load.BindTime(0, expiring_after); while (load.Step()) { @@ -3190,9 +3134,7 @@ "FROM interest_groups " "WHERE owner=? AND joining_origin=? AND expiration>?")); - if (!load.is_valid()) { - return false; - } + CHECK(load.is_valid()) << db.GetErrorMessage(); load.Reset(true); load.BindString(0, owner.Serialize()); @@ -3221,12 +3163,8 @@ "SELECT DISTINCT owner,joining_origin " "FROM interest_groups " "WHERE expiration>?")); - if (!load.is_valid()) { - DLOG(ERROR) << "LoadAllInterestGroupOwnerJoinerPairs SQL statement did not " - "compile: " - << db.GetErrorMessage(); - return std::nullopt; - } + CHECK(load.is_valid()) << db.GetErrorMessage(); + load.Reset(true); load.BindTime(0, expiring_after); while (load.Step()) { @@ -3251,12 +3189,8 @@ "WHERE owner = ? AND name = ? AND win_time >= ? " "ORDER BY win_time DESC")); // clang-format on - if (!prev_wins.is_valid()) { - DLOG(ERROR) << "GetInterestGroupsForOwner win_history SQL statement did " - "not compile: " - << db.GetErrorMessage(); - return false; - } + CHECK(prev_wins.is_valid()) << db.GetErrorMessage(); + prev_wins.Reset(true); prev_wins.BindString(0, Serialize(group_key.owner)); prev_wins.BindString(1, group_key.name); @@ -3281,11 +3215,8 @@ "FROM join_history " "WHERE owner = ? AND name = ? AND join_time >=?")); // clang-format on - if (!join_count.is_valid()) { - DLOG(ERROR) << "GetJoinCount SQL statement did not compile: " - << db.GetErrorMessage(); - return false; - } + CHECK(join_count.is_valid()) << db.GetErrorMessage(); + join_count.Reset(true); join_count.BindString(0, Serialize(group_key.owner)); join_count.BindString(1, group_key.name); @@ -3307,11 +3238,8 @@ "FROM bid_history " "WHERE owner = ? AND name = ? AND bid_time >= ?")); // clang-format on - if (!bid_count.is_valid()) { - DLOG(ERROR) << "GetBidCount SQL statement did not compile: " - << db.GetErrorMessage(); - return false; - } + CHECK(bid_count.is_valid()) << db.GetErrorMessage(); + bid_count.Reset(true); bid_count.BindString(0, Serialize(group_key.owner)); bid_count.BindString(1, group_key.name); @@ -3331,11 +3259,7 @@ "SELECT last_report_sent_time " "FROM lockout_debugging_only_report " "WHERE last_report_sent_time > ?")); - if (!sent_time.is_valid()) { - DLOG(ERROR) << "GetLastDebugReportSentDate SQL statement did not compile: " - << db.GetErrorMessage(); - return; - } + CHECK(sent_time.is_valid()) << db.GetErrorMessage(); sent_time.BindTime(0, ignore_before.value_or(base::Time::Min())); if (sent_time.Step()) { debug_report_lockout_and_cooldowns.last_report_sent_time = @@ -3352,11 +3276,7 @@ "SELECT starting_time, type " "FROM cooldown_debugging_only_report " "WHERE origin = ? AND starting_time > ?")); - if (!cooldown_debugging_only_report.is_valid()) { - DLOG(ERROR) << "GetDebugReportCooldown SQL statement did not compile: " - << db.GetErrorMessage(); - return std::nullopt; - } + CHECK(cooldown_debugging_only_report.is_valid()) << db.GetErrorMessage(); cooldown_debugging_only_report.BindString(0, Serialize(origin)); cooldown_debugging_only_report.BindTime( 1, ignore_before.value_or(base::Time::Min())); @@ -3397,9 +3317,7 @@ "ORDER BY expiration DESC")); // clang-format on - if (!get_names.is_valid()) { - return std::nullopt; - } + CHECK(get_names.is_valid()) << db.GetErrorMessage(); get_names.Reset(true); get_names.BindString(0, Serialize(owner)); @@ -3428,9 +3346,7 @@ "ORDER BY expiration DESC")); // clang-format on - if (!get_names.is_valid()) { - return std::nullopt; - } + CHECK(get_names.is_valid()) << db.GetErrorMessage(); get_names.Reset(true); get_names.BindString(0, Serialize(owner)); @@ -3458,9 +3374,7 @@ "ORDER BY expiration DESC")); // clang-format on - if (!get_names.is_valid()) { - return std::nullopt; - } + CHECK(get_names.is_valid()) << db.GetErrorMessage(); get_names.Reset(true); get_names.BindString(0, Serialize(owner)); @@ -3485,9 +3399,7 @@ "FROM k_anon " "WHERE owner = ? AND name = ?")); - if (!interest_group_kanon_query.is_valid()) { - return std::nullopt; - } + CHECK(interest_group_kanon_query.is_valid()) << db.GetErrorMessage(); interest_group_kanon_query.BindString(0, Serialize(group_key.owner)); interest_group_kanon_query.BindString(1, group_key.name); @@ -3577,9 +3489,8 @@ "ORDER BY joining_origin, RANDOM() " "LIMIT ?")); - if (!get_interest_group_update_parameters.is_valid()) { - return std::nullopt; - } + CHECK(get_interest_group_update_parameters.is_valid()) + << db.GetErrorMessage(); get_interest_group_update_parameters.Reset(true); get_interest_group_update_parameters.BindString(0, Serialize(owner)); @@ -3658,12 +3569,7 @@ "WHERE joining_origin=? AND expiration>?")); // clang-format on - if (!load.is_valid()) { - DLOG(ERROR) << "GetInterestGroupNamesForJoiningOrigin SQL statement did " - "not compile: " - << db.GetErrorMessage(); - return std::nullopt; - } + CHECK(load.is_valid()) << db.GetErrorMessage(); load.Reset(true); load.BindString(0, Serialize(joining_origin)); @@ -3755,10 +3661,8 @@ "SET priority=? " "WHERE owner=? AND name=?")); // clang-format on - if (!set_priority_sql.is_valid()) { - DLOG(ERROR) << "SetPriority SQL statement did not compile."; - return false; - } + CHECK(set_priority_sql.is_valid()) << db.GetErrorMessage(); + set_priority_sql.Reset(true); set_priority_sql.BindDouble(0, priority); set_priority_sql.BindString(1, Serialize(group_key.owner)); @@ -3778,10 +3682,9 @@ "SET priority_signals_overrides=? " "WHERE owner=? AND name=?")); // clang-format on - if (!update_priority_signals_overrides_sql.is_valid()) { - DLOG(ERROR) << "SetPrioritySignalsOverrides SQL statement did not compile."; - return false; - } + CHECK(update_priority_signals_overrides_sql.is_valid()) + << db.GetErrorMessage(); + update_priority_signals_overrides_sql.Reset(true); update_priority_signals_overrides_sql.BindString( 0, Serialize(priority_signals_overrides)); @@ -3794,10 +3697,8 @@ bool DeleteOldJoins(sql::Database& db, base::Time cutoff) { sql::Statement del_join_history(db.GetCachedStatement( SQL_FROM_HERE, "DELETE FROM join_history WHERE join_time <= ?")); - if (!del_join_history.is_valid()) { - DLOG(ERROR) << "DeleteOldJoins SQL statement did not compile."; - return false; - } + CHECK(del_join_history.is_valid()) << db.GetErrorMessage(); + del_join_history.Reset(true); del_join_history.BindTime(0, cutoff); if (!del_join_history.Run()) { @@ -3810,10 +3711,8 @@ bool DeleteOldBids(sql::Database& db, base::Time cutoff) { sql::Statement del_bid_history(db.GetCachedStatement( SQL_FROM_HERE, "DELETE FROM bid_history WHERE bid_time <= ?")); - if (!del_bid_history.is_valid()) { - DLOG(ERROR) << "DeleteOldBids SQL statement did not compile."; - return false; - } + CHECK(del_bid_history.is_valid()) << db.GetErrorMessage(); + del_bid_history.Reset(true); del_bid_history.BindTime(0, cutoff); if (!del_bid_history.Run()) { @@ -3826,10 +3725,8 @@ bool DeleteOldWins(sql::Database& db, base::Time cutoff) { sql::Statement del_win_history(db.GetCachedStatement( SQL_FROM_HERE, "DELETE FROM win_history WHERE win_time <= ?")); - if (!del_win_history.is_valid()) { - DLOG(ERROR) << "DeleteOldWins SQL statement did not compile."; - return false; - } + CHECK(del_win_history.is_valid()) << db.GetErrorMessage(); + del_win_history.Reset(true); del_win_history.BindTime(0, cutoff); if (!del_win_history.Run()) { @@ -3900,10 +3797,7 @@ "SELECT owner, name " "FROM interest_groups " "WHERE expiration<=?")); - if (!expired_interest_group.is_valid()) { - DLOG(ERROR) << "ClearExpiredInterestGroups SQL statement did not compile."; - return false; - } + CHECK(expired_interest_group.is_valid()) << db.GetErrorMessage(); expired_interest_group.Reset(true); expired_interest_group.BindTime(0, expiration_before); @@ -3948,9 +3842,7 @@ "ORDER BY owner, expiration DESC" )); // clang-format on - if (!excessive_storage_groups.is_valid()) { - return false; - } + CHECK(excessive_storage_groups.is_valid()) << db.GetErrorMessage(); excessive_storage_groups.Reset(true); std::vector<blink::InterestGroupKey> groups_to_remove; @@ -4000,10 +3892,7 @@ "OR ig.last_updated > k.last_referenced_time) " "AND k.last_reported_to_anon_server_time < ?)")); // clang-format on - if (!expired_k_anon.is_valid()) { - DLOG(ERROR) << "ClearExpiredKAnon SQL statement did not compile."; - return false; - } + CHECK(expired_k_anon.is_valid()) << db.GetErrorMessage(); expired_k_anon.Reset(true); expired_k_anon.BindTime(0, cutoff); @@ -4018,11 +3907,7 @@ "WHERE (type==? AND starting_time<?) OR " "(type==? AND starting_time<?)")); // clang-format on - if (!delete_cooldown.is_valid()) { - DLOG(ERROR) - << "DeleteExpiredDebugReportCooldown SQL statement did not compile."; - return false; - } + CHECK(delete_cooldown.is_valid()) << db.GetErrorMessage(); delete_cooldown.Reset(true); std::optional<base::TimeDelta> short_duration = @@ -4090,11 +3975,7 @@ "SELECT keys " "FROM bidding_and_auction_server_keys " "WHERE coordinator = ? AND expiration>?")); - if (!keys_statement.is_valid()) { - DLOG(ERROR) - << "DoGetBiddingAndAuctionServerKeys SQL statement did not compile."; - return {}; - } + CHECK(keys_statement.is_valid()) << db.GetErrorMessage(); keys_statement.Reset(true); keys_statement.BindString(0, Serialize(coordinator));
diff --git a/content/browser/media/captured_surface_controller.cc b/content/browser/media/captured_surface_controller.cc index 6bcc94e..62d2877 100644 --- a/content/browser/media/captured_surface_controller.cc +++ b/content/browser/media/captured_surface_controller.cc
@@ -222,43 +222,6 @@ return CapturedSurfaceControlResult::kSuccess; } -// Get the zoom level of the tab indicated by `captured_wc`. -// -// Return the zoom_level if successful or nullopt otherwise. -std::pair<std::optional<int>, CapturedSurfaceControlResult> DoGetZoomLevel( - GlobalRenderFrameHostId capturer_rfh_id, - base::WeakPtr<WebContents> captured_wc) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - WebContentsImpl* const capturer_wc = WebContentsImpl::FromRenderFrameHostImpl( - RenderFrameHostImpl::FromID(capturer_rfh_id)); - if (!capturer_wc) { - // The capturing frame or tab appears to have closed asynchronously. - return std::make_pair(std::nullopt, - CapturedSurfaceControlResult::kCapturerNotFoundError); - } - - if (!captured_wc) { - return std::make_pair( - std::nullopt, - CapturedSurfaceControlResult::kCapturedSurfaceNotFoundError); - } - - if (capturer_wc == captured_wc.get()) { - return std::make_pair( - std::nullopt, - CapturedSurfaceControlResult::kDisallowedForSelfCaptureError); - } - - // The requirement that the capturer be focused does not apply here - // as it does for SendWheel() and SetZoomLevel(). - - const double zoom_level = blink::PageZoomLevelToZoomFactor( - HostZoomMap::GetZoomLevel(captured_wc.get())); - return std::make_pair(std::round(100 * zoom_level), - CapturedSurfaceControlResult::kSuccess); -} - void OnPermissionCheckResult( base::OnceCallback<CapturedSurfaceControlResult()> action_callback, base::OnceCallback<void(CapturedSurfaceControlResult)> reply_callback, @@ -392,29 +355,6 @@ ComposeCallbacks(std::move(action_callback), std::move(reply_callback))); } -void CapturedSurfaceController::GetZoomLevel( - GetZoomLevelReplyCallback reply_callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (!captured_wc_.has_value()) { - std::move(reply_callback) - .Run(std::nullopt, - CapturedSurfaceControlResult::kCapturedSurfaceNotFoundError); - return; - } - - GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&DoGetZoomLevel, capturer_rfh_id_, captured_wc_.value()), - base::BindOnce( - [](GetZoomLevelReplyCallback reply_callback, - std::pair<std::optional<int>, CapturedSurfaceControlResult> - result) { - std::move(reply_callback).Run(result.first, result.second); - }, - std::move(reply_callback))); -} - void CapturedSurfaceController::SetZoomLevel( int zoom_level, base::OnceCallback<void(CapturedSurfaceControlResult)> reply_callback) {
diff --git a/content/browser/media/captured_surface_controller.h b/content/browser/media/captured_surface_controller.h index 641c70b..2db7be4 100644 --- a/content/browser/media/captured_surface_controller.h +++ b/content/browser/media/captured_surface_controller.h
@@ -61,14 +61,6 @@ blink::mojom::CapturedWheelActionPtr action, base::OnceCallback<void(CapturedSurfaceControlResult)> reply_callback); - // Get the zoom level of the captured tab. - // TODO(crbug.com/1466247): Remove this function when GetZoomLevel in the - // JavaScript API has been made synhronous. - virtual void GetZoomLevel( - base::OnceCallback<void( - std::optional<int> zoom_level, - blink::mojom::CapturedSurfaceControlResult result)> reply_callback); - // Set the zoom level of the captured tab. virtual void SetZoomLevel( int zoom_level,
diff --git a/content/browser/media/captured_surface_controller_unittest.cc b/content/browser/media/captured_surface_controller_unittest.cc index 667a17b..9265a015 100644 --- a/content/browser/media/captured_surface_controller_unittest.cc +++ b/content/browser/media/captured_surface_controller_unittest.cc
@@ -208,36 +208,6 @@ run_loop, expected_result); } -// Equivalent to MakeCallbackExpectingResult, but for GetZoomLevel(). -base::OnceCallback<void(std::optional<int>, CSCResult)> -MakeGetZoomCallbackExpectingResult(base::RunLoop* run_loop, - CSCResult expected_result) { - return base::BindOnce( - [](base::RunLoop* run_loop, CSCResult expected_result, - std::optional<int> zoom_level, CSCResult result) { - EXPECT_EQ(result, expected_result); - // `zoom_level` intentionally ignored. - run_loop->Quit(); - }, - run_loop, expected_result); -} - -// Make a callback that expects `result` and then unblock `run_loop`. -base::OnceCallback<void(std::optional<int>, CSCResult)> -MakeGetZoomLevelCallbackExpectingResult(base::RunLoop* run_loop, - std::optional<int> expected_zoom_level, - CSCResult expected_result) { - return base::BindOnce( - [](base::RunLoop* run_loop, std::optional<int> expected_zoom_level, - CSCResult expected_result, std::optional<int> zoom_level, - CSCResult result) { - EXPECT_EQ(zoom_level, expected_zoom_level); - EXPECT_EQ(result, expected_result); - run_loop->Quit(); - }, - run_loop, expected_zoom_level, expected_result); -} - class CapturedSurfaceControllerTestBase : public RenderViewHostTestHarness { public: ~CapturedSurfaceControllerTestBase() override = default; @@ -430,31 +400,6 @@ run_loop.Run(); } -// TODO(crbug.com/1466247): Remove this test suite after the getZoomLevel() API -// is made synchronous. -class CapturedSurfaceControllerGetZoomLevelTest - : public CapturedSurfaceControllerTestBase { - public: - ~CapturedSurfaceControllerGetZoomLevelTest() override = default; -}; - -TEST_F(CapturedSurfaceControllerGetZoomLevelTest, GetZoomLevelSuccess) { - HostZoomMap::SetZoomLevel(capturee_->web_contents(), - blink::PageZoomFactorToZoomLevel(0.9)); - base::RunLoop run_loop; - controller_->GetZoomLevel(MakeGetZoomLevelCallbackExpectingResult( - &run_loop, 90, CSCResult::kSuccess)); - run_loop.Run(); -} - -TEST_F(CapturedSurfaceControllerGetZoomLevelTest, GetZoomLevelUnknownError) { - base::RunLoop run_loop; - capturee_.reset(); - controller_->GetZoomLevel(MakeGetZoomLevelCallbackExpectingResult( - &run_loop, std::nullopt, CSCResult::kCapturedSurfaceNotFoundError)); - run_loop.Run(); -} - class CapturedSurfaceControllerZoomEventTest : public CapturedSurfaceControllerTestBase { public: @@ -532,8 +477,6 @@ enum class CapturedSurfaceControlAPI { kSendWheel, kSetZoomLevel, - // TODO(crbug.com/1466247): Remove kGetZoomLevel after making that API sync. - kGetZoomLevel, }; class CapturedSurfaceControllerInterfaceTestBase @@ -557,10 +500,6 @@ /*zoom_level=*/100, MakeCallbackExpectingResult(run_loop, expected_result)); return; - case CapturedSurfaceControlAPI::kGetZoomLevel: - controller_->GetZoomLevel( - MakeGetZoomCallbackExpectingResult(run_loop, expected_result)); - return; } NOTREACHED_NORETURN(); } @@ -583,8 +522,7 @@ , CapturedSurfaceControllerInterfaceTest, ::testing::Values(CapturedSurfaceControlAPI::kSendWheel, - CapturedSurfaceControlAPI::kSetZoomLevel, - CapturedSurfaceControlAPI::kGetZoomLevel)); + CapturedSurfaceControlAPI::kSetZoomLevel)); TEST_P(CapturedSurfaceControllerInterfaceTest, SuccessReportedIfPermitted) { base::RunLoop run_loop; @@ -594,9 +532,6 @@ } TEST_P(CapturedSurfaceControllerInterfaceTest, NoPermissionReportedIfDenied) { - if (tested_interface_ == CapturedSurfaceControlAPI::kGetZoomLevel) { - GTEST_SKIP() << "No permission check required for getZoomLevel()."; - } base::RunLoop run_loop; permission_manager_->SetPermissionResult(CSCPermissionResult::kDenied); RunTestedActionAndExpect(&run_loop, CSCResult::kNoPermissionError); @@ -605,9 +540,6 @@ TEST_P(CapturedSurfaceControllerInterfaceTest, UnknownErrorReportedIfPermissionError) { - if (tested_interface_ == CapturedSurfaceControlAPI::kGetZoomLevel) { - GTEST_SKIP() << "No permission check required for getZoomLevel()."; - } base::RunLoop run_loop; permission_manager_->SetPermissionResult(CSCPermissionResult::kError); RunTestedActionAndExpect(&run_loop, CSCResult::kUnknownError); @@ -677,8 +609,7 @@ , CapturedSurfaceControllerWebContentsResolutionTest, ::testing::Values(CapturedSurfaceControlAPI::kSendWheel, - CapturedSurfaceControlAPI::kSetZoomLevel, - CapturedSurfaceControlAPI::kGetZoomLevel)); + CapturedSurfaceControlAPI::kSetZoomLevel)); TEST_P(CapturedSurfaceControllerWebContentsResolutionTest, ApiInvocationAfterWebContentsResolutionSucceeds) { @@ -794,8 +725,7 @@ , CapturedSurfaceControllerWebContentsResolutionOfUpdatesTest, ::testing::Values(CapturedSurfaceControlAPI::kSendWheel, - CapturedSurfaceControlAPI::kSetZoomLevel, - CapturedSurfaceControlAPI::kGetZoomLevel)); + CapturedSurfaceControlAPI::kSetZoomLevel)); TEST_P( CapturedSurfaceControllerWebContentsResolutionOfUpdatesTest, @@ -847,8 +777,7 @@ , CapturedSurfaceControllerSelfCaptureTest, ::testing::Values(CapturedSurfaceControlAPI::kSendWheel, - CapturedSurfaceControlAPI::kSetZoomLevel, - CapturedSurfaceControlAPI::kGetZoomLevel)); + CapturedSurfaceControlAPI::kSetZoomLevel)); TEST_P(CapturedSurfaceControllerSelfCaptureTest, SelfCaptureDisallowed) { StartCaptureOf(*capturer_); @@ -918,8 +847,7 @@ , CapturedSurfaceControllerFocusRequirementTest, ::testing::Values(CapturedSurfaceControlAPI::kSendWheel, - CapturedSurfaceControlAPI::kSetZoomLevel, - CapturedSurfaceControlAPI::kGetZoomLevel)); + CapturedSurfaceControlAPI::kSetZoomLevel)); TEST_P(CapturedSurfaceControllerFocusRequirementTest, CallSucceedsIfCapturerFocused) { @@ -932,9 +860,6 @@ TEST_P(CapturedSurfaceControllerFocusRequirementTest, CallsFailsIfCapturerUnfocused) { - if (tested_interface_ == CapturedSurfaceControlAPI::kGetZoomLevel) { - GTEST_SKIP() << "The focus requirement does not apply to getZoomLevel()."; - } base::RunLoop run_loop; permission_manager_->SetPermissionResult(CSCPermissionResult::kGranted); // Note absence of call to `capturer_->Focus()`.
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index 33d8211..9499be2f 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -490,8 +490,7 @@ } result.PutAll(non_sticky); } - if (IsUnloadAllowed() || - base::FeatureList::IsEnabled(blink::features::kDeprecateUnload)) { + if (IsUnloadAllowed()) { result.Put(WebSchedulerTrackedFeature::kUnloadHandler); } // When not under "Cache-Control: no-store" context, the features listed in @@ -517,8 +516,7 @@ // Remove all non-sticky features from |result|. result = Intersection(result, blink::scheduler::StickyFeatures()); } - if (IsUnloadAllowed() || - base::FeatureList::IsEnabled(blink::features::kDeprecateUnload)) { + if (IsUnloadAllowed()) { result.Remove(WebSchedulerTrackedFeature::kUnloadHandler); } // When under "Cache-Control: no-store" context, the features listed in
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc index 176cf22e..fda42b2 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -736,22 +736,6 @@ std::move(action), std::move(callback)); } -void MediaStreamDispatcherHost::GetZoomLevel( - const base::UnguessableToken& device_id, - GetZoomLevelCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (!base::FeatureList::IsEnabled( - features::kCapturedSurfaceControlKillswitch)) { - std::move(callback).Run(std::nullopt, - CapturedSurfaceControlResult::kUnknownError); - return; - } - - media_stream_manager_->GetZoomLevel(render_frame_host_id_, device_id, - std::move(callback)); -} - void MediaStreamDispatcherHost::SetZoomLevel( const base::UnguessableToken& device_id, int32_t zoom_level,
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h index 122db23..4b60a401 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -137,8 +137,6 @@ void SendWheel(const base::UnguessableToken& device_id, blink::mojom::CapturedWheelActionPtr action, SendWheelCallback callback) override; - void GetZoomLevel(const base::UnguessableToken& device_id, - GetZoomLevelCallback callback) override; void SetZoomLevel(const base::UnguessableToken& device_id, int32_t zoom_level, SetZoomLevelCallback callback) override;
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index dee9a9b..8298cc2a 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -4265,25 +4265,6 @@ controller->SendWheel(std::move(action), std::move(callback)); } -void MediaStreamManager::GetZoomLevel( - GlobalRenderFrameHostId capturer_rfh_id, - const base::UnguessableToken& session_id, - base::OnceCallback<void(std::optional<int> zoom_level, - blink::mojom::CapturedSurfaceControlResult result)> - callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - CapturedSurfaceControlResult result; - CapturedSurfaceController* const controller = - GetCapturedSurfaceController(capturer_rfh_id, session_id, result); - if (!controller) { - std::move(callback).Run(std::nullopt, result); - return; - } - - controller->GetZoomLevel(std::move(callback)); -} - void MediaStreamManager::SetZoomLevel( GlobalRenderFrameHostId capturer_rfh_id, const base::UnguessableToken& session_id,
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 2ec6c1c..d06054d8 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -434,13 +434,6 @@ base::OnceCallback<void(blink::mojom::CapturedSurfaceControlResult)> callback); - void GetZoomLevel( - GlobalRenderFrameHostId capturer_rfh_id, - const base::UnguessableToken& session_id, - base::OnceCallback< - void(std::optional<int> zoom_level, - blink::mojom::CapturedSurfaceControlResult result)> callback); - void SetZoomLevel( GlobalRenderFrameHostId capturer_rfh_id, const base::UnguessableToken& session_id,
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index 957b4657..e689351 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -316,8 +316,6 @@ void SendWheel(const base::UnguessableToken& device_id, blink::mojom::CapturedWheelActionPtr action, SendWheelCallback callback) override {} - void GetZoomLevel(const base::UnguessableToken& device_id, - GetZoomLevelCallback callback) override {} void SetZoomLevel(const base::UnguessableToken& device_id, int32_t zoom_level, SetZoomLevelCallback callback) override {} @@ -380,10 +378,8 @@ } #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -// TODO(crbug.com/1466247): Add other APIs (setZoomLevel, getZoomLevel). enum class CapturedSurfaceControlAPI { kSendWheel, - kGetZoomLevel, kSetZoomLevel, }; @@ -1941,14 +1937,6 @@ &result_); } - void GetZoomLevel( - GlobalRenderFrameHostId gdm_rfhid, - std::optional<base::UnguessableToken> session_id = std::nullopt) { - media_stream_manager_->GetZoomLevel( - gdm_rfhid, session_id.value_or(video_device_.session_id()), - MakeGetZoomLevelCallback()); - } - void SetZoomLevel( GlobalRenderFrameHostId gdm_rfhid, std::optional<base::UnguessableToken> session_id = std::nullopt) { @@ -1994,10 +1982,6 @@ SendWheel(gdm_rfhid, session_id); return; } - case CapturedSurfaceControlAPI::kGetZoomLevel: { - GetZoomLevel(gdm_rfhid, session_id); - return; - } case CapturedSurfaceControlAPI::kSetZoomLevel: { SetZoomLevel(gdm_rfhid, session_id); return; @@ -2013,7 +1997,6 @@ , MediaStreamManagerCapturedSurfaceControlActionTest, testing::Values(CapturedSurfaceControlAPI::kSendWheel, - CapturedSurfaceControlAPI::kGetZoomLevel, CapturedSurfaceControlAPI::kSetZoomLevel)); TEST_P(MediaStreamManagerCapturedSurfaceControlActionTest, SuccessfulIfValid) {
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index bcdcd1d7..63bd067d 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3120,12 +3120,17 @@ } // static -RenderProcessHost* RenderProcessHost::GetSpareRenderProcessHostForTesting() { +RenderProcessHost* RenderProcessHost::GetSpareRenderProcessHost() { return SpareRenderProcessHostManager::GetInstance() .spare_render_process_host(); } // static +RenderProcessHost* RenderProcessHost::GetSpareRenderProcessHostForTesting() { + return GetSpareRenderProcessHost(); +} + +// static base::CallbackListSubscription RenderProcessHost::RegisterSpareRenderProcessHostChangedCallback( const base::RepeatingCallback<void(RenderProcessHost*)>& cb) {
diff --git a/content/browser/service_process_host_impl.cc b/content/browser/service_process_host_impl.cc index 97cda5e..7c9548b 100644 --- a/content/browser/service_process_host_impl.cc +++ b/content/browser/service_process_host_impl.cc
@@ -13,7 +13,6 @@ #include "base/process/process.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" -#include "build/chromecast_buildflags.h" #include "content/browser/utility_process_host.h" #include "content/common/child_process.mojom.h" #include "content/public/browser/browser_task_traits.h" @@ -26,10 +25,6 @@ #include "mojo/public/cpp/bindings/remote.h" #include "sandbox/policy/mojom/sandbox.mojom.h" -#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID) -#include "base/process/process_handle.h" -#endif - namespace content { namespace { @@ -243,28 +238,4 @@ } } -// TODO(crbug.com/1328879): Remove this method when fixing the bug. -#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID) -void LaunchUtilityProcessServiceDeprecated( - const std::string& service_name, - const std::u16string& display_name, - sandbox::mojom::Sandbox sandbox_type, - mojo::ScopedMessagePipeHandle service_pipe, - base::OnceCallback<void(base::ProcessId)> callback) { - UtilityProcessHost* host = new UtilityProcessHost(); - host->SetName(display_name); - host->SetMetricsName(service_name); - host->SetSandboxType(sandbox_type); - host->Start(); - host->RunServiceDeprecated( - service_name, std::move(service_pipe), - base::BindOnce( - [](base::OnceCallback<void(base::ProcessId)> callback, - const std::optional<base::ProcessId> pid) { - std::move(callback).Run(pid.value_or(base::kNullProcessId)); - }, - std::move(callback))); -} -#endif - } // namespace content
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 268a141..90255ce 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -245,7 +245,6 @@ status_ = blink::EmbeddedWorkerStatus::kStarting; starting_phase_ = ALLOCATING_PROCESS; network_accessed_for_script_ = false; - token_ = blink::ServiceWorkerToken(); for (auto& observer : listener_list_) observer.OnStarting(); @@ -255,7 +254,6 @@ params->wait_for_debugger = false; params->subresource_loader_updater = subresource_loader_updater_.BindNewPipeAndPassReceiver(); - params->service_worker_token = token_.value(); // TODO(https://crbug.com/978694): Consider a reset flow since new mojo types // check is_bound strictly. @@ -1035,7 +1033,6 @@ status_ = blink::EmbeddedWorkerStatus::kStopped; starting_phase_ = NOT_STARTING; thread_id_ = ServiceWorkerConsts::kInvalidEmbeddedWorkerThreadId; - token_ = std::nullopt; DCHECK(!foreground_notified_); }
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h index bd778cf..aedd37f 100644 --- a/content/browser/service_worker/embedded_worker_instance.h +++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -266,13 +266,6 @@ ContentBrowserClient::URLLoaderFactoryType factory_type, const std::string& devtools_worker_token); - // Returns the unique token that has been generated to identify this worker - // instance, and its corresponding GlobalScope in the renderer process. If the - // service worker is not currently running, this is std::nullopt. - const std::optional<blink::ServiceWorkerToken>& token() const { - return token_; - } - private: typedef base::ObserverList<Listener>::Unchecked ListenerList; struct StartInfo; @@ -418,12 +411,6 @@ // thread, and |coep_reporter_| has the ownership of the impl instance. std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter_; - // A unique identifier for this service worker instance. This is unique across - // the browser process, but not persistent across service worker restarts. - // This token is set every time the worker starts, and is plumbed through to - // the corresponding ServiceWorkerGlobalScope in the renderer process. - std::optional<blink::ServiceWorkerToken> token_; - base::WeakPtrFactory<EmbeddedWorkerInstance> weak_factory_{this}; };
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index a12c88ec..9786b96 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -26,6 +26,7 @@ #include "content/browser/service_worker/service_worker_context_core_observer.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_hid_delegate_observer.h" +#include "content/browser/service_worker/service_worker_host.h" #include "content/browser/service_worker/service_worker_info.h" #include "content/browser/service_worker/service_worker_job_coordinator.h" #include "content/browser/service_worker/service_worker_offline_capability_checker.h" @@ -1190,7 +1191,7 @@ FROM_HERE, &ServiceWorkerContextCoreObserver::OnStarted, version->version_id(), version->scope(), version->embedded_worker()->process_id(), version->script_url(), - version->embedded_worker()->token().value(), version->key()); + version->worker_host()->token(), version->key()); break; case blink::EmbeddedWorkerStatus::kStopping: observer_list_->Notify(FROM_HERE,
diff --git a/content/browser/service_worker/service_worker_host.cc b/content/browser/service_worker/service_worker_host.cc index ad8f2fe2..b34ee96 100644 --- a/content/browser/service_worker/service_worker_host.cc +++ b/content/browser/service_worker/service_worker_host.cc
@@ -41,6 +41,7 @@ ServiceWorkerVersion* version, base::WeakPtr<ServiceWorkerContextCore> context) : version_(version), + token_(blink::ServiceWorkerToken()), broker_(this), container_host_(std::make_unique<content::ServiceWorkerContainerHost>( std::move(context))),
diff --git a/content/browser/service_worker/service_worker_host.h b/content/browser/service_worker/service_worker_host.h index 0fdf4e1..b90f8be5 100644 --- a/content/browser/service_worker/service_worker_host.h +++ b/content/browser/service_worker/service_worker_host.h
@@ -70,6 +70,7 @@ int worker_process_id() const { return worker_process_id_; } ServiceWorkerVersion* version() const { return version_; } + const blink::ServiceWorkerToken& token() const { return token_; } service_manager::InterfaceProvider& remote_interfaces() { return remote_interfaces_; @@ -144,6 +145,13 @@ // owns |this|. const raw_ptr<ServiceWorkerVersion> version_; + // A unique identifier for this service worker instance. This is unique across + // the browser process, but not persistent across service worker restarts. + // This token is generated every time the worker starts (i.e., + // ServiceWorkerHost is created), and is plumbed through to the corresponding + // ServiceWorkerGlobalScope in the renderer process. + const blink::ServiceWorkerToken token_; + // BrowserInterfaceBroker implementation through which this // ServiceWorkerHost exposes worker-scoped Mojo services to the corresponding // service worker in the renderer.
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index a93cd638..773d181 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -2378,9 +2378,8 @@ params->controller_receiver = std::move(controller_receiver_); params->provider_info = std::move(provider_info); - + params->service_worker_token = worker_host_->token(); params->ukm_source_id = ukm_source_id_; - params->storage_key = key_; // policy_container_host could be null for registration restored from old DB
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index f9f2743..040cc3c 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h
@@ -484,7 +484,7 @@ // The worker host hosting this version. Only valid while the version is // running. content::ServiceWorkerHost* worker_host() { - DCHECK(worker_host_); + CHECK(worker_host_); return worker_host_.get(); }
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index de4fadb..4d7c6228 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -1055,9 +1055,11 @@ // At this point either all IDPs are signed out or mediation:silent was used // and there are no returning accounts. For now reject with a generic error. // TODO(crbug.com/1307709): Handle FedCmMetrics properly for multiple IDPs. + bool should_delay_callback = + mediation_requirement_ == MediationRequirement::kSilent ? false : true; CompleteRequestWithError( FederatedAuthRequestResult::kError, TokenStatus::kNotSignedInWithIdp, - /*token_error=*/std::nullopt, /*should_delay_callback=*/false); + /*token_error=*/std::nullopt, should_delay_callback); return; } CHECK(!unique_idps.empty());
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index 829307e..f1fd996 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -4584,6 +4584,32 @@ EXPECT_TRUE(DidFetch(FetchedEndpoint::ACCOUNTS)); } +TEST_F(FederatedAuthRequestImplTest, MultiIdpLoggedOut) { + base::test::ScopedFeatureList list; + list.InitAndEnableFeature(features::kFedCmMultipleIdentityProviders); + + // Mark both IDPs as logged out so the request fails early. + test_permission_delegate_ + ->idp_signin_statuses_[OriginFromString(kProviderUrlFull)] = false; + test_permission_delegate_ + ->idp_signin_statuses_[OriginFromString(kProviderTwoUrlFull)] = false; + + RequestExpectations expectations = { + RequestTokenStatus::kError, FederatedAuthRequestResult::kError, + /*standalone_console_message=*/std::nullopt, + /*selected_idp_config_url=*/std::nullopt}; + + request_remote_.set_disconnect_handler(auth_helper_.quit_closure()); + + RunAuthDontWaitForCallback(kDefaultMultiIdpRequestParameters, + kConfigurationMultiIdpValid); + base::RunLoop().RunUntilIdle(); + // The callback must be delayed. + EXPECT_FALSE(auth_helper_.was_callback_called()); + WaitForCurrentAuthRequest(); + CheckAuthExpectations(kConfigurationMultiIdpValid, expectations); +} + TEST_F(FederatedAuthRequestImplTest, TooManyRequests) { base::RunLoop ukm_loop; ukm_recorder()->SetOnAddEntryCallback(FedCmEntry::kEntryName,
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java index e63c792..fccb8b7 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
@@ -17,8 +17,8 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner; @@ -27,7 +27,7 @@ /** Tests for WebContentsAccessibilityImpl integration with accessibility services. */ @RunWith(ContentJUnit4ClassRunner.class) @SuppressLint("VisibleForTests") -@DoNotBatch(reason = "Flaky tests") +@Batch(Batch.PER_CLASS) @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) public class WebContentsAccessibilityEventsTest { // File path that holds all the relevant tests.
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java index f4b23419..dadd1b6 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -102,10 +102,10 @@ import org.junit.runner.RunWith; import org.chromium.base.FeatureList; +import org.chromium.base.test.util.Batch; 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.DoNotBatch; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UrlUtils; @@ -125,7 +125,7 @@ * the interface. */ @RunWith(ContentJUnit4ClassRunner.class) -@DoNotBatch(reason = "Flaky tests") +@Batch(Batch.PER_CLASS) @SuppressLint("VisibleForTests") @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) public class WebContentsAccessibilityTest {
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java index 18908e0..d593a3c45 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java
@@ -19,10 +19,10 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Restriction; import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -31,7 +31,7 @@ /** Tests for WebContentsAccessibilityImpl integration with accessibility services. */ @RunWith(ContentJUnit4ClassRunner.class) @SuppressLint("VisibleForTests") -@DoNotBatch(reason = "Flaky tests") +@Batch(Batch.PER_CLASS) @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) public class WebContentsAccessibilityTreeTest { // File path that holds all the relevant tests.
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index 888d3dc..80d974c4 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -775,6 +775,9 @@ // Return the spare RenderProcessHost, if it exists. There is at most one // globally-used spare RenderProcessHost at any time. + // TODO(crbug.com/1519190): remove the non-test method once the performance + // investigation is finished. + static RenderProcessHost* GetSpareRenderProcessHost(); static RenderProcessHost* GetSpareRenderProcessHostForTesting(); // Registers a callback to be notified when the spare RenderProcessHost is
diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h index 69c6f20..b737083 100644 --- a/content/public/browser/service_process_host.h +++ b/content/public/browser/service_process_host.h
@@ -16,7 +16,6 @@ #include "base/observer_list_types.h" #include "base/process/process_handle.h" #include "base/strings/string_piece.h" -#include "build/chromecast_buildflags.h" #include "content/common/content_export.h" #include "content/public/browser/service_process_info.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h" @@ -25,11 +24,6 @@ #include "sandbox/policy/mojom/sandbox.mojom.h" #include "url/gurl.h" -// TODO(crbug.com/1328879): Remove this when fixing the bug. -#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID) -#include "mojo/public/cpp/system/message_pipe.h" -#endif // BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID) - #if BUILDFLAG(IS_WIN) #include "base/files/file_path.h" #include "base/types/pass_key.h" @@ -211,19 +205,6 @@ sandbox::mojom::Sandbox sandbox); }; -// TODO(crbug.com/1328879): Remove this method when fixing the bug. -#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID) -// DEPRECATED. DO NOT USE THIS. This is a helper for any remaining service -// launching code which uses an older code path to launch services in a utility -// process. All new code must use ServiceProcessHost instead of this API. -void CONTENT_EXPORT LaunchUtilityProcessServiceDeprecated( - const std::string& service_name, - const std::u16string& display_name, - sandbox::mojom::Sandbox sandbox_type, - mojo::ScopedMessagePipeHandle service_pipe, - base::OnceCallback<void(base::ProcessId)> callback); -#endif // BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID) - } // namespace content #endif // CONTENT_PUBLIC_BROWSER_SERVICE_PROCESS_HOST_H_
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index 5694c8b..df94a97 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -244,10 +244,6 @@ ":main_function_params", ":renderer_type", ":switches", - - # TODO(crbug.com/977637): Remove when - # content::LaunchUtilityProcessServiceDeprecated() gets removed. - "//build:chromecast_buildflags", "//content/common", "//content/public/common/zygote:buildflags", "//ipc",
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 818b3f1..8bb2dc3 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -1181,28 +1181,11 @@ "WebAssemblyExperimentalJSPI", base::FEATURE_DISABLED_BY_DEFAULT); -// Enable support for the WebAssembly Garbage Collection proposal: -// https://github.com/WebAssembly/gc. -BASE_FEATURE(kWebAssemblyGarbageCollection, - "WebAssemblyGarbageCollection", - base::FEATURE_ENABLED_BY_DEFAULT); - // Enable WebAssembly lazy compilation (JIT on first call). BASE_FEATURE(kWebAssemblyLazyCompilation, "WebAssemblyLazyCompilation", base::FEATURE_ENABLED_BY_DEFAULT); -// Enable the use of WebAssembly Relaxed SIMD operations -BASE_FEATURE(kWebAssemblyRelaxedSimd, - "WebAssemblyRelaxedSimd", - base::FEATURE_ENABLED_BY_DEFAULT); - -// Enable support for the WebAssembly Stringref proposal: -// https://github.com/WebAssembly/stringref. -BASE_FEATURE(kWebAssemblyStringref, - "WebAssemblyStringref", - base::FEATURE_DISABLED_BY_DEFAULT); - // Enable WebAssembly tiering (Liftoff -> TurboFan). BASE_FEATURE(kWebAssemblyTiering, "WebAssemblyTiering",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 2d3f9f7..a8fb8f6 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -289,10 +289,7 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAppSystemMediaControlsWin); CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAssemblyBaseline); CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnableExperimentalWebAssemblyJSPI); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAssemblyGarbageCollection); CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAssemblyLazyCompilation); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAssemblyRelaxedSimd); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAssemblyStringref); CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAssemblyTiering); CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebAssemblyTrapHandler); CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebBluetooth);
diff --git a/content/public/test/mock_captured_surface_controller.cc b/content/public/test/mock_captured_surface_controller.cc index d1885d5..7b3df4d 100644 --- a/content/public/test/mock_captured_surface_controller.cc +++ b/content/public/test/mock_captured_surface_controller.cc
@@ -41,19 +41,6 @@ std::make_pair(get_zoom_level_value, get_zoom_level_result); } -void MockCapturedSurfaceController::GetZoomLevel( - base::OnceCallback<void(std::optional<int> zoom_level, - blink::mojom::CapturedSurfaceControlResult result)> - reply_callback) { - CHECK(get_zoom_level_result_); - const std::pair<std::optional<int>, - blink::mojom::CapturedSurfaceControlResult> - get_zoom_level_result = *get_zoom_level_result_; - get_zoom_level_result_ = std::nullopt; - std::move(reply_callback) - .Run(get_zoom_level_result.first, get_zoom_level_result.second); -} - void MockCapturedSurfaceController::SetSetZoomLevelResponse( blink::mojom::CapturedSurfaceControlResult set_zoom_level_result) { set_zoom_level_result_ = set_zoom_level_result;
diff --git a/content/public/test/mock_captured_surface_controller.h b/content/public/test/mock_captured_surface_controller.h index f63b4bb..1d65d71 100644 --- a/content/public/test/mock_captured_surface_controller.h +++ b/content/public/test/mock_captured_surface_controller.h
@@ -36,11 +36,6 @@ std::optional<int> get_zoom_level_value, blink::mojom::CapturedSurfaceControlResult get_zoom_level_result); - void GetZoomLevel(base::OnceCallback< - void(std::optional<int> zoom_level, - blink::mojom::CapturedSurfaceControlResult result)> - reply_callback) override; - void SetSetZoomLevelResponse( blink::mojom::CapturedSurfaceControlResult set_zoom_level_result);
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc index 67a0305..6b3b4787 100644 --- a/content/renderer/render_process_impl.cc +++ b/content/renderer/render_process_impl.cc
@@ -173,21 +173,10 @@ "--experimental-wasm-jspi", "--no-experimental-wasm-jspi"); - SetV8FlagIfOverridden(features::kWebAssemblyGarbageCollection, - "--experimental-wasm-gc", "--no-experimental-wasm-gc"); - SetV8FlagIfOverridden(features::kWebAssemblyLazyCompilation, "--wasm-lazy-compilation", "--no-wasm-lazy-compilation"); - SetV8FlagIfOverridden(features::kWebAssemblyRelaxedSimd, - "--experimental-wasm-relaxed-simd", - "--no-experimental-wasm-relaxed-simd"); - - SetV8FlagIfOverridden(features::kWebAssemblyStringref, - "--experimental-wasm-stringref", - "--no-experimental-wasm-stringref"); - SetV8FlagIfOverridden(features::kWebAssemblyTiering, "--wasm-tier-up", "--no-wasm-tier-up");
diff --git a/content/shell/fuchsia/content_shell.cml b/content/shell/fuchsia/content_shell.cml index 5e8bbed..140f3cf 100644 --- a/content/shell/fuchsia/content_shell.cml +++ b/content/shell/fuchsia/content_shell.cml
@@ -57,5 +57,10 @@ rights: [ "r*" ], path: "/config/ssl", }, + { + directory: "tzdata-icu", + rights: [ "r*" ], + path: "/config/tzdata/icu", + }, ], }
diff --git a/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc b/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc index 588b7a5..8998ac0 100644 --- a/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc +++ b/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc
@@ -86,6 +86,21 @@ CreateSharedContext(preferences, workarounds, surface_, context_, context_state_, feature_info); + // On MacOS, the default texture target for native GpuMemoryBuffers is + // GL_TEXTURE_RECTANGLE_ARB. This is due to CGL's requirements for creating + // a GL surface. However, when ANGLE is used on top of SwiftShader or Metal, + // it's necessary to use GL_TEXTURE_2D instead. + // TODO(crbug.com/1056312): The proper behavior is to check the config + // parameter set by the EGL_ANGLE_iosurface_client_buffer extension +#if BUILDFLAG(IS_MAC) + if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE && + (gl::GetANGLEImplementation() == + gl::ANGLEImplementation::kSwiftShader || + gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal)) { + gpu::SetMacOSSpecificTextureTarget(GL_TEXTURE_2D); + } +#endif // BUILDFLAG(IS_MAC) + backing_factory_ = std::make_unique<SharedImageFactory>( preferences, workarounds, GpuFeatureInfo(), context_state_.get(), shared_image_manager_.get(), context_state_->memory_tracker(),
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc index 9131246..57ddd7b 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
@@ -7,6 +7,7 @@ #include <list> #include <utility> +#include "base/feature_list.h" #include "build/build_config.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/shared_image_usage.h" @@ -19,6 +20,10 @@ namespace gpu { namespace { +BASE_FEATURE(kCorrectFramebufferAttachmentComputationInGLTexture, + "CorrectFramebufferAttachmentComputationInGLTexture", + base::FEATURE_ENABLED_BY_DEFAULT); + constexpr uint32_t kWebGPUUsages = SHARED_IMAGE_USAGE_WEBGPU | SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE | SHARED_IMAGE_USAGE_WEBGPU_STORAGE_TEXTURE; @@ -208,10 +213,26 @@ base::span<const uint8_t> pixel_data) { DCHECK(CanCreateTexture(format, size, pixel_data, GL_TEXTURE_2D)); - const bool for_framebuffer_attachment = - (usage & - (SHARED_IMAGE_USAGE_RASTER_READ | SHARED_IMAGE_USAGE_RASTER_WRITE | - SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT)) != 0; + bool for_framebuffer_attachment = false; + // NOTE: We are in the process of computing writes to GL without using + // GLES2_FRAMEBUFFER_HINT as part of eliminating the latter. Here we make the + // change guarded by a killswitch. + // TODO(b/41491709): Remove this killswitch post safe rollout. + if (base::FeatureList::IsEnabled( + kCorrectFramebufferAttachmentComputationInGLTexture)) { + // GLTextureImageBackingFactory supports raster and display usage only for + // Ganesh-GL, meaning that raster/display write usage implies GL writes + // within Skia. + for_framebuffer_attachment = usage & (SHARED_IMAGE_USAGE_GLES2_WRITE | + SHARED_IMAGE_USAGE_RASTER_WRITE | + SHARED_IMAGE_USAGE_DISPLAY_WRITE); + } else { + for_framebuffer_attachment = + (usage & + (SHARED_IMAGE_USAGE_RASTER_READ | SHARED_IMAGE_USAGE_RASTER_WRITE | + SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT)) != 0; + } + const bool framebuffer_attachment_angle = for_framebuffer_attachment && texture_usage_angle_;
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm index 8cc10c7..bd012277 100644 --- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm +++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
@@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h" #include <optional> +#include "base/feature_list.h" #include "base/memory/scoped_refptr.h" #include "build/build_config.h" #include "components/viz/common/resources/resource_sizes.h" @@ -35,6 +36,31 @@ namespace gpu { namespace { +BASE_FEATURE(kCorrectFramebufferAttachmentComputationInAppleBacking, + "CorrectFramebufferAttachmentComputationInAppleBacking", + base::FEATURE_ENABLED_BY_DEFAULT); + +bool UsageWillResultInGLWrite(uint32_t usage, GrContextType gr_context_type) { + bool will_write_to_gl = false; + // NOTE: We are in the process of computing writes to GL without using + // GLES2_FRAMEBUFFER_HINT as part of eliminating the latter. Here we make the + // change guarded by a killswitch. + // TODO(b/41491709): Remove this killswitch post safe rollout. + if (base::FeatureList::IsEnabled( + kCorrectFramebufferAttachmentComputationInAppleBacking)) { + will_write_to_gl = (usage & SHARED_IMAGE_USAGE_GLES2_WRITE) || + ((gr_context_type == GrContextType::kGL) && + (usage & (SHARED_IMAGE_USAGE_RASTER_WRITE | + SHARED_IMAGE_USAGE_DISPLAY_WRITE))); + } else { + will_write_to_gl = + (usage & + (SHARED_IMAGE_USAGE_RASTER_READ | SHARED_IMAGE_USAGE_RASTER_WRITE | + SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT)) != 0; + } + return will_write_to_gl; +} + bool IsFormatSupported(viz::SharedImageFormat format) { return (format == viz::SinglePlaneFormat::kRGBA_8888) || (format == viz::SinglePlaneFormat::kRGBX_8888) || @@ -360,9 +386,7 @@ } const bool for_framebuffer_attachment = - (usage & - (SHARED_IMAGE_USAGE_RASTER_READ | SHARED_IMAGE_USAGE_RASTER_WRITE | - SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT)) != 0; + UsageWillResultInGLWrite(usage, gr_context_type_); // |scoped_progress_reporter| will notify |progress_reporter_| upon // construction and destruction. We limit the scope so that progress is @@ -473,9 +497,7 @@ } const bool for_framebuffer_attachment = - (usage & - (SHARED_IMAGE_USAGE_RASTER_READ | SHARED_IMAGE_USAGE_RASTER_WRITE | - SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT)) != 0; + UsageWillResultInGLWrite(usage, gr_context_type_); const bool framebuffer_attachment_angle = for_framebuffer_attachment && angle_texture_usage_; const bool retain_gl_texture = gr_context_type_ == GrContextType::kGL;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc index 36ab11f..37dfee7e 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc
@@ -494,24 +494,38 @@ #if BUILDFLAG(IS_ANDROID) CHECK(format.is_single_plane() && !format.IsLegacyMultiplanar()); #endif - if (format == viz::LegacyMultiPlaneFormat::kNV12 || - format == viz::MultiPlaneFormat::kNV12 || - format == viz::LegacyMultiPlaneFormat::kNV12A || - format == viz::MultiPlaneFormat::kNV12A) { - // Y and A planes are R8, UV is RG8. - return plane_index == 1 ? wgpu::TextureFormat::RG8Unorm - : wgpu::TextureFormat::R8Unorm; - } else if (format == viz::LegacyMultiPlaneFormat::kP010 || - format == viz::MultiPlaneFormat::kP010) { - // Y plane is R16, UV is RG16. - return plane_index == 0 ? wgpu::TextureFormat::R16Unorm - : wgpu::TextureFormat::RG16Unorm; - } else if (format == viz::LegacyMultiPlaneFormat::kYV12 || - format == viz::MultiPlaneFormat::kYV12 || - format == viz::MultiPlaneFormat::kI420 || - format == viz::MultiPlaneFormat::kI420A) { - // All planes are R8. - return wgpu::TextureFormat::R8Unorm; + if (format.is_multi_plane()) { + int num_channels = format.NumChannelsInPlane(plane_index); + switch (format.channel_format()) { + case viz::SharedImageFormat::ChannelFormat::k8: + return num_channels == 1 ? wgpu::TextureFormat::R8Unorm + : wgpu::TextureFormat::RG8Unorm; + case viz::SharedImageFormat::ChannelFormat::k10: + case viz::SharedImageFormat::ChannelFormat::k16: + return num_channels == 1 ? wgpu::TextureFormat::R16Unorm + : wgpu::TextureFormat::RG16Unorm; + case viz::SharedImageFormat::ChannelFormat::k16F: + // `k16F` channel formats do not support UV planes. + CHECK_EQ(num_channels, 1); + return wgpu::TextureFormat::R16Float; + } + } else if (format.IsLegacyMultiplanar()) { + // TODO(crbug.com/1366495): Remove legacy multiplanar checks once + // multiplanar SI support lands. + if (format == viz::LegacyMultiPlaneFormat::kNV12 || + format == viz::LegacyMultiPlaneFormat::kNV12A) { + // Y and A planes are R8, UV is RG8. + return plane_index == 1 ? wgpu::TextureFormat::RG8Unorm + : wgpu::TextureFormat::R8Unorm; + } else if (format == viz::LegacyMultiPlaneFormat::kP010) { + // Y plane is R16, UV is RG16. + return plane_index == 0 ? wgpu::TextureFormat::R16Unorm + : wgpu::TextureFormat::RG16Unorm; + } else { + // All planes are R8. + CHECK_EQ(format, viz::LegacyMultiPlaneFormat::kYV12); + return wgpu::TextureFormat::R8Unorm; + } } else { // Fallback to return single-plane format. return ToDawnFormat(format);
diff --git a/gpu/config/gpu_mode.h b/gpu/config/gpu_mode.h index 38249ff..6442b937 100644 --- a/gpu/config/gpu_mode.h +++ b/gpu/config/gpu_mode.h
@@ -14,6 +14,8 @@ HARDWARE_GL, // The GPU process is running with hardware acceleration, using Vulkan and GL. HARDWARE_VULKAN, + // The GPU process is running with hardware acceleration, using Graphite-Dawn. + HARDWARE_GRAPHITE, // The GPU process is running for SwiftShader WebGL. SWIFTSHADER, // The GPU process is running for the display compositor.
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index 00e161f5..323be4d 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -121,7 +121,6 @@ 'cros_board': 'jacuzzi', 'use_lkgm': True, 'bucket': 'chromiumos-image-archive', - 'dut_pool': 'chromium', 'public_builder': 'cros_test_platform_public', 'public_builder_bucket': 'testplatform-public', }, @@ -131,7 +130,6 @@ 'skylab': { 'cros_board': 'jacuzzi', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_JACUZZI_RELEASE_LKGM': { @@ -139,7 +137,6 @@ 'skylab': { 'cros_board': 'jacuzzi', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_OCTOPUS_PUBLIC_LKGM': { @@ -148,7 +145,6 @@ 'cros_board': 'octopus', 'use_lkgm': True, 'bucket': 'chromiumos-image-archive', - 'dut_pool': 'chromium', }, }, 'CROS_OCTOPUS_RELEASE_CHROME_FROM_TLS_ASH_LKGM': { @@ -157,7 +153,6 @@ 'cros_board': 'octopus', 'cros_model': 'casta', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_PUFF_RELEASE_BETA': { @@ -197,7 +192,6 @@ 'skylab': { 'cros_board': 'strongbad', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_TROGDOR_PUBLIC_LKGM': { @@ -206,7 +200,6 @@ 'cros_board': 'trogdor', 'cros_img': 'trogdor-public/R123-15763.0.0', 'bucket': 'chromiumos-image-archive', - 'dut_pool': 'chromium', }, }, 'CROS_TROGDOR_RELEASE_ASH_LKGM': { @@ -214,7 +207,6 @@ 'skylab': { 'cros_board': 'trogdor', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_VOLTEER_PUBLIC_LKGM': { @@ -246,7 +238,6 @@ 'skylab': { 'cros_board': 'volteer', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'DISABLE_FIELD_TRIAL_CONFIG': {
diff --git a/infra/config/targets/cros-skylab-variants.json b/infra/config/targets/cros-skylab-variants.json index 0b311e567..a1f28e3 100644 --- a/infra/config/targets/cros-skylab-variants.json +++ b/infra/config/targets/cros-skylab-variants.json
@@ -10,8 +10,8 @@ "CROS_BRYA_RELEASE_LKGM": { "skylab": { "cros_board": "brya", - "dut_pool": "chrome", - "use_lkgm": true + "use_lkgm": true, + "dut_pool": "chrome" }, "enabled": true, "identifier": "BRYA_RELEASE_LKGM" @@ -49,8 +49,8 @@ "CROS_FIZZ_RELEASE_LKGM": { "skylab": { "cros_board": "fizz", - "dut_pool": "chrome", - "use_lkgm": true + "use_lkgm": true, + "dut_pool": "chrome" }, "enabled": true, "identifier": "FIZZ_RELEASE_LKGM" @@ -88,8 +88,8 @@ "CROS_GUYBRUSH_RELEASE_LKGM": { "skylab": { "cros_board": "guybrush", - "dut_pool": "chrome", - "use_lkgm": true + "use_lkgm": true, + "dut_pool": "chrome" }, "enabled": true, "identifier": "GUYBRUSH_RELEASE_LKGM" @@ -127,8 +127,8 @@ "CROS_PUFF_RELEASE_LKGM": { "skylab": { "cros_board": "puff", - "dut_pool": "chrome", - "use_lkgm": true + "use_lkgm": true, + "dut_pool": "chrome" }, "enabled": true, "identifier": "PUFF_RELEASE_LKGM" @@ -166,7 +166,6 @@ "CROS_JACUZZI_RELEASE_LKGM": { "skylab": { "cros_board": "jacuzzi", - "dut_pool": "chrome", "use_lkgm": true }, "enabled": true, @@ -175,7 +174,6 @@ "CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM": { "skylab": { "cros_board": "jacuzzi", - "dut_pool": "chrome", "use_lkgm": true }, "identifier": "JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM" @@ -183,7 +181,6 @@ "CROS_JACUZZI_CQ_PUBLIC_LKGM": { "skylab": { "cros_board": "jacuzzi", - "dut_pool": "chromium", "use_lkgm": true, "bucket": "chromiumos-image-archive", "public_builder": "cros_test_platform_public", @@ -197,7 +194,6 @@ "cros_board": "trogdor", "cros_chrome_version": "123.0.6268.0", "cros_img": "trogdor-public/R123-15763.0.0", - "dut_pool": "chromium", "bucket": "chromiumos-image-archive" }, "enabled": true, @@ -206,7 +202,6 @@ "CROS_OCTOPUS_PUBLIC_LKGM": { "skylab": { "cros_board": "octopus", - "dut_pool": "chromium", "use_lkgm": true, "bucket": "chromiumos-image-archive" }, @@ -217,7 +212,6 @@ "skylab": { "cros_board": "octopus", "cros_model": "casta", - "dut_pool": "chrome", "use_lkgm": true }, "identifier": "OCTOPUS_RELEASE_CHROME_FROM_TLS_LKGM" @@ -225,7 +219,6 @@ "CROS_STRONGBAD_RELEASE_LKGM": { "skylab": { "cros_board": "strongbad", - "dut_pool": "chrome", "use_lkgm": true }, "enabled": true, @@ -234,7 +227,6 @@ "CROS_TROGDOR_RELEASE_ASH_LKGM": { "skylab": { "cros_board": "trogdor", - "dut_pool": "chrome", "use_lkgm": true }, "identifier": "TROGDOR_RELEASE_LKGM" @@ -268,9 +260,8 @@ "CROS_VOLTEER_RELEASE_ASH_LKGM": { "skylab": { "cros_board": "volteer", - "dut_pool": "chrome", "use_lkgm": true }, "identifier": "VOLTEER_RELEASE_LKGM" } -} +} \ No newline at end of file
diff --git a/ios/chrome/app/spotlight/searchable_item_factory.mm b/ios/chrome/app/spotlight/searchable_item_factory.mm index 5dd231a..31ff9a2a 100644 --- a/ios/chrome/app/spotlight/searchable_item_factory.mm +++ b/ios/chrome/app/spotlight/searchable_item_factory.mm
@@ -8,6 +8,7 @@ #import <string> +#import "base/containers/span.h" #import "base/functional/bind.h" #import "base/hash/md5.h" #import "base/memory/raw_ptr.h" @@ -290,10 +291,9 @@ NSString* key = [NSString stringWithFormat:@"%@ %@", base::SysUTF8ToNSString(URL.spec()), title]; const std::string clipboard = base::SysNSStringToUTF8(key); - const char* c_string = clipboard.c_str(); base::MD5Digest hash; - base::MD5Sum(c_string, strlen(c_string), &hash); + base::MD5Sum(base::as_byte_span(clipboard), &hash); uint64_t md5 = *(reinterpret_cast<uint64_t*>(hash.a)); return md5; }
diff --git a/ios/chrome/app/startup/BUILD.gn b/ios/chrome/app/startup/BUILD.gn index b07dc39..6fca4643 100644 --- a/ios/chrome/app/startup/BUILD.gn +++ b/ios/chrome/app/startup/BUILD.gn
@@ -77,6 +77,7 @@ "//components/password_manager/core/browser", "//components/search_engines:search_engines", "//ios/chrome/app", + "//ios/chrome/browser/default_browser/model:default_browser_interest_signals", "//ios/chrome/browser/default_browser/model:utils", "//ios/chrome/browser/first_run/model", "//ios/chrome/browser/net/model:model",
diff --git a/ios/chrome/app/startup/chrome_app_startup_parameters.mm b/ios/chrome/app/startup/chrome_app_startup_parameters.mm index a0f1917..ab7175f 100644 --- a/ios/chrome/app/startup/chrome_app_startup_parameters.mm +++ b/ios/chrome/app/startup/chrome_app_startup_parameters.mm
@@ -14,6 +14,7 @@ #import "base/strings/sys_string_conversions.h" #import "components/password_manager/core/browser/manage_passwords_referrer.h" #import "ios/chrome/app/startup/app_launch_metrics.h" +#import "ios/chrome/browser/default_browser/model/default_browser_interest_signals.h" #import "ios/chrome/browser/default_browser/model/utils.h" #import "ios/chrome/browser/shared/model/url/chrome_url_constants.h" #import "ios/chrome/browser/shared/public/features/features.h" @@ -187,7 +188,9 @@ // Histogram helper to log the UMA IOS.WidgetKit.Action histogram. void LogWidgetKitAction(WidgetKitExtensionAction action) { UmaHistogramEnumeration("IOS.WidgetKit.Action", action); - LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeMadeForIOS); + + // Notify Default Browser promo that user opened Chrome with widget. + default_browser::NotifyStartWithWidget(); } bool CallerAppIsFirstParty(MobileSessionCallerApp callerApp) { @@ -297,8 +300,6 @@ WidgetKitExtensionAction::ACTION_LOCKSCREEN_LAUNCHER_GAME); } - LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral); - GURL URL( base::StringPrintf("%s://%s", kChromeUIScheme, kChromeUIDinoHost)); ChromeAppStartupParameters* appStartupParameters = @@ -438,11 +439,12 @@ } UMA_HISTOGRAM_ENUMERATION(kUMAMobileSessionStartActionHistogram, action, MOBILE_SESSION_START_ACTION_COUNT); - // An HTTP(S) URL open that opened Chrome (e.g. default browser open) should - // be logged as significant activity for a potential user that would want - // Chrome as their default browser in case the user changes away from - // Chrome. This will leave a trace of this activity for re-prompting. - LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral); + // An HTTP(S) URL open that opened Chrome (e.g. default browser open or + // explictly opened from first party apps) should be logged as significant + // activity for a potential user that would want Chrome as their default + // browser in case the user changes away from Chrome. This will leave a + // trace of this activity for re-prompting. + default_browser::NotifyStartWithURL(); if (action == START_ACTION_OPEN_HTTP_FROM_OS || action == START_ACTION_OPEN_HTTPS_FROM_OS) { @@ -760,17 +762,6 @@ action = ACTION_NO_ACTION; } - if (action != ACTION_NO_ACTION) { - // An external action that opened Chrome (i.e. GrowthKit link open, open - // Search, search clipboard content) is activity that should indicate a user - // that would be interested in setting Chrome as the default browser. - LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral); - - // Log browser started indirectly for default browser promo experiment - // stats. - LogBrowserIndirectlylaunched(); - } - if ([secureAppID isEqualToString:app_group::kOpenCommandSourceSearchExtension]) { UMA_HISTOGRAM_ENUMERATION("IOS.SearchExtension.Action", action,
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 900b769e..a5dcf22 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -447,6 +447,11 @@ =1 {Bookmark saved} other {{count} Bookmarks saved}} </message> + <message name="IDS_IOS_BOOKMARKS_SAVED" desc="This confirmation message is intended to help users understand that multiple bookmarks have been saved. The confirmation message appears at the bottom of the page after users bulk add bookmarks, telling them how many bookmarks they've added. The tone should be informative."> + {count, plural, + =1 {Bookmark saved} + other {Bookmarks saved}} + </message> <message name="IDS_IOS_BOOKMARKS_BULK_SAVED_ACCOUNT" desc="This confirmation message is intended to help users understand that multiple bookmarks have been saved in their account. The confirmation message appears at the bottom of the page after users bulk add bookmarks, telling them how many bookmarks they've added into their account. The tone should be informative."> {count, plural, =1 {Bookmark saved in your Google Account, {email}} @@ -623,21 +628,41 @@ =1 {Bookmark saved to "{title}"} other {Bookmarks saved to "{title}"}} </message> + <message name="IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER" desc="This confirmation message is intended to help users understand that a bookmark has been saved in Chrome. These users are not signed in to a Google Account and are not syncing their data, so we do not specify where the bookmark is saved. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative."> + {count, plural, + =1 {Bookmark saved to "{title}"} + other {{count} Bookmarks saved to "{title}"}} + </message> <message name="IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE" desc="This confirmation message is intended to help users understand that a bookmark has been saved in Chrome. These users are not signed in to a Google Account and are not syncing their data, so we do not specify where the bookmark is saved. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative."> {count, plural, - =1 {Bookmark saved to "{title}". It is only saved to this device.} - other {Bookmarks saved to "{title}". It is only saved to this device.}} + =1 {Bookmark saved to "{title}". It is saved only to this device.} + other {Bookmarks saved to "{title}". They are only saved to this device.}} + </message> + <message name="IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER_TO_DEVICE" desc="This confirmation message is intended to help users understand that a bookmark has been saved in Chrome. These users are not signed in to a Google Account and are not syncing their data, so we do not specify where the bookmark is saved. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative."> + {count, plural, + =1 {Bookmark saved to "{title}". It is saved only to this device.} + other {{count} Bookmarks saved to "{title}". They are saved only to this device.}} </message> <message name="IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT" desc="This confirmation message is intended to help users understand that a bookmark has been saved in their Google Account. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative."> {count, plural, =1 {Bookmark saved in your Google Account, {email}} other {Bookmarks saved in your Google Account, {email}}} </message> + <message name="IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT" desc="This confirmation message is intended to help users understand that a bookmark has been saved in their Google Account. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative."> + {count, plural, + =1 {Bookmark saved in your Google Account, {email}} + other {{count} Bookmarks saved in your Google Account, {email}}} + </message> <message name="IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT_FOLDER" desc="This confirmation message is intended to help users understand that a bookmark has been saved to a particular folder in their Google Account. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative."> {count, plural, =1 {Bookmark saved to "{title}" in your account, {email}} other {Bookmarks saved to "{title}" in your account, {email}}} </message> + <message name="IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT_FOLDER" desc="This confirmation message is intended to help users understand that a bookmark has been saved to a particular folder in their Google Account. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative."> + {count, plural, + =1 {Bookmark saved to "{title}" in your account, {email}} + other {{count} Bookmarks saved to "{title}" in your account, {email}}} + </message> <message name="IDS_IOS_BOOKMARK_SNACKBAR_EDIT_BOOKMARK" desc="This string is found on a button that takes the user to the Edit Bookmark screen when the user taps it. The button is on a confirmation message that users see when they save a bookmark to their device or in their Google Account. This text is a verb and is short for the longer phrase 'edit the bookmark.' The tone should be informative. Use Apple-style title case. [CHAR_LIMIT=15]"> Edit </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARKS_SAVED.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARKS_SAVED.png.sha1 new file mode 100644 index 0000000..466a6e5 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARKS_SAVED.png.sha1
@@ -0,0 +1 @@ +9186f0d2bf3eda2b8f800f2273eda1f598e83196 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER.png.sha1 new file mode 100644 index 0000000..fc1af53e --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER.png.sha1
@@ -0,0 +1 @@ +5e2d22a6e8e804750ca7bb529601035cdfc8dd9a \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER_TO_DEVICE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER_TO_DEVICE.png.sha1 new file mode 100644 index 0000000..3794007e --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER_TO_DEVICE.png.sha1
@@ -0,0 +1 @@ +0a314bd25d4ff744b115b49bb2d27f2e993bcfa0 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT.png.sha1 new file mode 100644 index 0000000..fca82fe1 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT.png.sha1
@@ -0,0 +1 @@ +18a47b7905ce42786b9ce19b8d76b84e2f737b3c \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT_FOLDER.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT_FOLDER.png.sha1 new file mode 100644 index 0000000..2668377 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT_FOLDER.png.sha1
@@ -0,0 +1 @@ +ea71658b79b24f9e3b13fbeff373ca91bad973ec \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE.png.sha1 index 3794007e..7aa1d480 100644 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE.png.sha1 +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE.png.sha1
@@ -1 +1 @@ -0a314bd25d4ff744b115b49bb2d27f2e993bcfa0 \ No newline at end of file +e4d3919e910909497c65328950274d855e92859d \ No newline at end of file
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_am.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_am.xtb index 5561377..fae35b5 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_am.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_am.xtb
@@ -99,6 +99,7 @@ <translation id="3833326979834193417">Chromium እርስዎን ከውሂብ ጥሰቶች፣ ደህንነታቸው ካልተጠበቁ ድር ጣቢያዎች እና ሌሎችም ደህንነትዎ እንደተጠበቀ ለማቆየት በየቀኑ የደህንነት ፍተሻን በራስ-ሰር ያሄዳል። ስለ የደህንነት ፍተሻ በቅንብሮች ውስጥ የበለጠ ማግኘት ይችላሉ።</translation> <translation id="3855938650519180865">በChromium ውስጥ ምን አዲስ ነገር አለ</translation> <translation id="3886689467633467988">በሁሉም መሣሪያዎችዎ ላይ የእርስዎን ዕልባቶች እና ሌሎችም ለማግኘት ወደዚህ ጣቢያ እና Chromium ይግቡ።</translation> +<translation id="3904484643286601695">ምርጫዎችዎን በማንኛውም ጊዜ በChromium ቅንብሮች ውስጥ ማዘመን ይችላሉ።</translation> <translation id="394413318816989199">የይለፍ ሐረግ ምስጠራ የመክፈያ ዘዴዎችን እና አድራሻዎችን አያካትትም። ይህን ቅንብር ለመለወጥ <ph name="BEGIN_LINK" />በመለያዎ ውስጥ ያለውን የChromium ውሂብ ያጽዱ<ph name="END_LINK" />።</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ar.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ar.xtb index 067572d..2a67179e 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ar.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ar.xtb
@@ -204,6 +204,7 @@ ولا يمكن لأحد الوصول إلى بياناتك المشفّرة بدون استخدام عبارة المرور الخاصة بك. ولا تحصل Google على عبارة المرور هذه أو تخزّنها. في حال نسيت عبارة المرور أو أردت تغيير هذه الإعدادات، يمكنك <ph name="BEGIN_LINK" />محو بيانات Chromium في حسابك<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">لقد أصبح Chromium أفضل من ذي قبل! يتوفر إصدار جديد.</translation> +<translation id="6433172051771630690">نصائح حول الاستفادة إلى أقصى حدّ من Chromium</translation> <translation id="6502321914804101924">تم تسجيل الخروج من Chromium</translation> <translation id="6563921047760808519">مزيد من المعلومات حول <ph name="BEGIN_LINK" />الطريقة التي يتّبعها Chromium للحفاظ على خصوصية بياناتك<ph name="END_LINK" /></translation> <translation id="6625409903340039086">يمكن الآن في Chromium ضبط سياسات المستخدم للحساب المُدارَ</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">لن يتم تشفير طُرق الدفع والعناوين من Google Pay. ولن تتم مزامنة سجلّ التصفُّح من Chromium. ولا يمكن لأحد الوصول إلى بياناتك المشفّرة بدون استخدام عبارة المرور الخاصة بك. ولا تحصل Google على عبارة المرور هذه أو تخزّنها. في حال نسيت عبارة المرور أو أردت تغيير هذه الإعدادات، يمكنك <ph name="BEGIN_LINK" />محو بيانات Chromium في حسابك<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">للحصول على نصائح مفيدة حول استخدام Chromium، يمكنك تفعيل الإشعارات في إعدادات أجهزة iOS.</translation> <translation id="7995166854192397899">تستند الاقتراحات إلى نشاط التصفُّح على أجهزتك الأخرى. للحصول على اقتراحات، سجِّل الدخول إلى Chromium على جميع أجهزتك.</translation> <translation id="800195749539500647">يمكنك الاستفادة إلى أقصى حدّ من Chromium.</translation> <translation id="8013573822802650211">للاطّلاع على علامات التبويب من أي جهاز تستخدم فيه Chromium، سجِّل الدخول على جميع أجهزتك.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb index de8a772..460181e 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromiumএ আপোনাক ডেটা উলংঘন, অসুৰক্ষিত ৱেবছাইট আৰু অধিকৰ পৰা সুৰক্ষিত কৰি ৰাখিবলৈ প্ৰতিদিনে স্বয়ংক্ৰিয়ভাৱে সুৰক্ষা পৰীক্ষাটো চলায়। আপুনি ছেটিঙত সুৰক্ষা পৰীক্ষাৰ বিষয়ে অধিক তথ্য পাব পাৰে।</translation> <translation id="3855938650519180865">Chromiumত নতুন কি আছে</translation> <translation id="3886689467633467988">আপোনাৰ আটাইবোৰ ডিভাইচত আপোনাৰ বুকমাৰ্ক আৰু অধিক পাবলৈ এই ছাইট আৰু Chromiumত ছাইন ইন কৰক।</translation> +<translation id="3904484643286601695">আপুনি Chromium ছেটিঙত যিকোনো সময়তে আপোনাৰ বাছনিবোৰ আপডে’ট কৰিব পাৰে।</translation> <translation id="394413318816989199">পাছফ্ৰে’জ এনক্ৰিপশ্বনত পৰিশোধ পদ্ধতি আৰু ঠিকনা অন্তৰ্ভুক্ত নহয়। এই ছেটিংটো সলনি কৰিবলৈ, <ph name="BEGIN_LINK" />আপোনাৰ একাউণ্টৰ Chromiumৰ ডেটা মচক<ph name="END_LINK" />।</translation> @@ -204,6 +205,7 @@ আপোনাৰ পাছফ্ৰে’জ থকা লোকেহে আপোনাৰ এনক্ৰিপ্ট কৰা ডেটা পঢ়িব পাৰে। পাছফ্ৰে’জটো Googleলৈ পঠিওৱা নহয় অথবা Googleএ সেয়া ষ্ট’ৰ নকৰে। আপুনি যদি নিজৰ পাছফ্ৰে’জটো পাহৰে অথবা এই ছেটিংটো সলাব বিচাৰে, <ph name="BEGIN_LINK" />আপোনাৰ একাউণ্টৰ Chromiumৰ ডেটা মচক<ph name="END_LINK" />।</translation> <translation id="6424492062988593837">Chromium আৰু উন্নত হৈছে! এটা নতুন সংস্কৰণ আছে।</translation> +<translation id="6433172051771630690">Chromiumৰ পৰা পাৰ্যমানে উপকৃত হোৱাৰ কিটিপ।</translation> <translation id="6502321914804101924">Chromium ছাইন আউট হৈ আছে</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromiumএ কেনেকৈ আপোনাৰ ডেটা ব্যক্তিগত কৰি ৰাখে<ph name="END_LINK" /> সেই বিষয়ে অধিক জানক</translation> <translation id="6625409903340039086">Chromiumএ এতিয়া আপোনাৰ পৰিচালিত একাউণ্টৰ বাবে ব্যৱহাৰকাৰীৰ নীতি সমৰ্থন কৰে</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">Google Payৰ পৰা পৰিশোধ পদ্ধতি আৰু ঠিকনাসমূহ এনক্ৰিপ্ট কৰা নহ’ব। Chromiumৰ পৰা ব্ৰাউজিঙৰ ইতিহাস ছিংক কৰা নহ’ব। আপোনাৰ পাছফ্ৰে’জ থকা লোকেহে আপোনাৰ এনক্ৰিপ্ট কৰা ডেটা পঢ়িব পাৰে। পাছফ্ৰে’জটো Googleলৈ পঠিওৱা নহয় বা Googleএ সেয়া ষ্ট’ৰ নকৰে। আপুনি যদি নিজৰ পাছফ্ৰে’জটো পাহৰে বা এই ছেটিংটো সলনি কৰিব বিচাৰে, তেন্তে <ph name="BEGIN_LINK" />আপোনাৰ একাউণ্টৰ Chromiumৰ ডেটা মচক<ph name="END_LINK" />।</translation> +<translation id="7994322153108931467">Chromiumৰ সহায়ক কিটিপ পাবলৈ আপোনাৰ iOSৰ ছেটিঙত জাননী অন কৰক।</translation> <translation id="7995166854192397899">পৰামৰ্শসমূহ আপোনাৰ অন্য ডিভাইচত আপুনি কৰা কাৰ্যকলাপৰ ভিত্তিক। পৰামৰ্শসমূহ পাবলৈ, আপোনাৰ আটাইবোৰ ডিভাইচত Chromiumত ছাইন ইন কৰক।</translation> <translation id="800195749539500647">Chromiumৰ পৰা পাৰ্যমানে উপকৃত হওক</translation> <translation id="8013573822802650211">আপুনি Chromium ব্যৱহাৰ কৰা সকলো ডিভাইচৰ পৰা নিজৰ টেবসমূহ চাবলৈ আপোনাৰ সকলো ডিভাইচত ছাইন ইন কৰক</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_az.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_az.xtb index a26fb81..ec21a0f 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_az.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_az.xtb
@@ -204,6 +204,7 @@ Yalnız parol ifadəsini bilən şəxs şifrələnmiş datanı oxuya bilər. Google parol ifadəsini əldə etmir və ya saxlamır. Parol ifadəsini unutsanız, yaxud bu ayarı dəyişmək istəsəniz, <ph name="BEGIN_LINK" />hesabda Chromium datasını silin<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium yeniləndi! Yeni versiya əlçatandır.</translation> +<translation id="6433172051771630690">Chromium-dan maksimum yararlanmaq üçün məsləhətlər.</translation> <translation id="6502321914804101924">Chromium-dan çıxılıb</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium-un datanı məxfi saxlaması<ph name="END_LINK" /> haqqında ətraflı</translation> <translation id="6625409903340039086">Chromium indi idarə olunan hesabınız üçün istifadəçi siyasətlərini dəstəkləyir</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay-dən ödəniş metodu və ünvanlar şifrələnməyəcək. Chromium-dan baxış tarixçəsi sinxronlaşdırılmayacaq. Yalnız parol ifadəsini bilən şəxs şifrələnmiş datanı oxuya bilər. Google parol ifadəsini əldə etmir və ya saxlamır. Parol ifadəsini unutsanız, yaxud bu ayarı dəyişmək istəsəniz, <ph name="BEGIN_LINK" />hesabda Chromium datasını silin<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Faydalı Chromium məsləhətləri üçün iOS ayarlarında bildirişləri aktiv edin.</translation> <translation id="7995166854192397899">Təkliflər digər cihazlarda axtarış fəaliyyətinizə əsaslanır. Təkliflər əldə etmək üçün bütün cihazlarda Chromium-a daxil olun.</translation> <translation id="800195749539500647">Chromium-dan maksimum yararlanın</translation> <translation id="8013573822802650211">Chromium istifadə etdiyiniz hər yerdən tabları görmək üçün bütün cihazlarda daxil olun</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_bs.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_bs.xtb index 2b34ae6..fad8dee 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_bs.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_bs.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium automatski pokreće sigurnosnu provjeru svakog dana da vas zaštiti od narušavanja podataka, nesigurnih web lokacija i drugog. U Postavkama možete pronaći više informacija o sigurnosnoj provjeri.</translation> <translation id="3855938650519180865">Šta je novo u Chromiumu</translation> <translation id="3886689467633467988">Prijavite se na ovu web lokaciju i u Chromium da dobijete svoje oznake i još mnogo toga na svim svojim uređajima.</translation> +<translation id="3904484643286601695">Svoje odabire uvijek možete ažurirati u postavkama Chromiuma.</translation> <translation id="394413318816989199">Šifriranje pristupnim izrazom ne obuhvata načine plaćanja i adrese. Da promijenite ovu postavku, <ph name="BEGIN_LINK" />obrišite podatke Chromiuma na računu<ph name="END_LINK" />.</translation> @@ -204,6 +205,7 @@ Vaše šifrirane podatke može čitati samo osoba koja ima vaš pristupni izraz. Pristupni izraz se ne šalje Googleu niti ga Google pohranjuje. Ako zaboravite pristupni izraz ili želite promijeniti ovu postavku, <ph name="BEGIN_LINK" />obrišite podatke Chromiuma na računu<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium je sada još bolji! Dostupna je nova verzija.</translation> +<translation id="6433172051771630690">Savjeti za iskorištavanje svih prednosti Chromiuma.</translation> <translation id="6502321914804101924">Odjavljeni ste iz Chromiuma</translation> <translation id="6563921047760808519">Saznajte više o tome <ph name="BEGIN_LINK" />kako Chromium štiti privatnost vaših podataka<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium sada podržava korisnička pravila za vaš upravljani račun</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">Načini plaćanja i adrese s Google Paya se neće šifrirati. Historija pregledanja iz Chromiuma se neće sinhronizirati. Vaše šifrirane podatke može čitati samo osoba koja ima vaš pristupni izraz. Pristupni izraz se ne šalje Googleu niti ga on pohranjuje. Ako zaboravite pristupni izraz ili želite promijeniti ovu postavku, <ph name="BEGIN_LINK" />obrišite podatke Chromiuma na računu<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Da dobijate korisne savjete za Chromium, uključite obavještenja u postavkama iOS-a.</translation> <translation id="7995166854192397899">Prijedlozi se zasnivaju na vašoj aktivnosti pregledanja na drugim uređajima. Da dobijate prijedloge, prijavite se u Chromium na svim svojim uređajima.</translation> <translation id="800195749539500647">Iskoristite sve prednosti Chromiuma</translation> <translation id="8013573822802650211">Da vidite kartice s bilo kojeg uređaja na kojem koristite Chromium, prijavite se na svim uređajima</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ca.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ca.xtb index 2dc8e97f..fe8cb8a4 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ca.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ca.xtb
@@ -204,6 +204,7 @@ Només les persones que sàpiguen la teva frase de contrasenya podran llegir les dades encriptades. La frase de contrasenya no s'envia a Google, i Google tampoc no l'emmagatzema. Si oblides la frase de contrasenya o vols canviar aquesta opció de configuració, <ph name="BEGIN_LINK" />esborra les dades de Chromium del compte<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chrome ara és millor. Hi ha una versió nova disponible.</translation> +<translation id="6433172051771630690">Consells per treure el màxim partit de Chromium.</translation> <translation id="6502321914804101924">S'ha tancat la sessió de Chromium</translation> <translation id="6563921047760808519">Més informació sobre <ph name="BEGIN_LINK" />com Chromium manté la privadesa de les teves dades<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium ara admet polítiques dels usuaris per al compte gestionat</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Les formes de pagament i les adreces de Google Pay no s'encriptaran. L'historial de navegació de Chromium no se sincronitzarà. Només les persones que sàpiguen la teva frase de contrasenya podran llegir les dades encriptades. La frase de contrasenya no s'envia a Google, i Google tampoc no l'emmagatzema. Si oblides la frase de contrasenya o vols canviar aquesta opció de configuració, <ph name="BEGIN_LINK" />esborra les dades de Chromium del compte<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Per rebre consells útils sobre Chromium, activa les notificacions a la configuració d'iOS.</translation> <translation id="7995166854192397899">Els suggeriments es basen en la teva activitat de navegació als altres dispositius que fas servir. Per rebre suggeriments, inicia la sessió a Chromium en tots els teus dispositius.</translation> <translation id="800195749539500647">Treu el màxim profit de Chromium</translation> <translation id="8013573822802650211">Per veure les pestanyes des de tots els llocs on facis servir Chromium, inicia la sessió en tots els dispositius</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_cy.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_cy.xtb index 7ca7a7c..67709a1 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_cy.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_cy.xtb
@@ -204,6 +204,7 @@ Dim ond rhywun sydd â'ch cyfrinymadrodd all ddarllen eich data sydd wedi'u hamgryptio. Nid yw'r cyfrinymadrodd yn cael ei anfon at Google na'i storio. Os byddwch yn anghofio'ch cyfrinymadrodd neu eisiau newid y gosodiad hwn, <ph name="BEGIN_LINK" />cliriwch y data Chromium yn eich cyfrif<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Mae Chromium newydd fynd hyd yn oed yn well! Mae fersiwn newydd ar gael.</translation> +<translation id="6433172051771630690">Awgrymiadau i fanteisio i'r eithaf ar Chromium.</translation> <translation id="6502321914804101924">Mae Chromium wedi'i Allgofnodi</translation> <translation id="6563921047760808519">Dysgu rhagor am <ph name="BEGIN_LINK" />sut mae Chromium yn cadw eich data yn breifat<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Mae Chromium bellach yn cefnogi polisïau defnyddwyr ar gyfer eich cyfrif a reolir</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Ni fydd dulliau talu a chyfeiriadau o Google Pay yn cael eu hamgryptio. Ni fydd hanes pori o Chromium yn cysoni. Dim ond rhywun sydd â'ch cyfrinymadrodd all ddarllen eich data sydd wedi'u hamgryptio. Nid yw'r cyfrinymadrodd yn cael ei anfon at Google na'i storio. Os byddwch yn anghofio'ch cyfrinymadrodd neu eisiau newid y gosodiad hwn, <ph name="BEGIN_LINK" />cliriwch y data Chromium yn eich cyfrif<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">I gael awgrymiadau defnyddiol Chromium, trowch hysbysiadau ymlaen yn eich gosodiadau iOS.</translation> <translation id="7995166854192397899">Mae awgrymiadau yn seiliedig ar eich gweithgarwch pori ar eich dyfeisiau eraill. I gael awgrymiadau, mewngofnodwch i Chromium ar bob un o'ch dyfeisiau.</translation> <translation id="800195749539500647">Manteisio i'r eithaf ar Chromium</translation> <translation id="8013573822802650211">I weld eich tabiau o ble bynnag rydych yn defnyddio Chromium, mewngofnodwch ar eich holl ddyfeisiau</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_en-GB.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_en-GB.xtb index 7537dc3..0744777 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_en-GB.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_en-GB.xtb
@@ -204,6 +204,7 @@ Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, <ph name="BEGIN_LINK" />clear the Chromium data in your account<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium just got better! A new version is available.</translation> +<translation id="6433172051771630690">Tips on getting the most out of Chromium.</translation> <translation id="6502321914804101924">Chromium is signed out</translation> <translation id="6563921047760808519">Learn more about <ph name="BEGIN_LINK" />how Chromium keeps your data private<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium now supports user policies for your managed account</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Payment methods and addresses from Google Pay won't be encrypted. Browsing history from Chromium won't sync. Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, <ph name="BEGIN_LINK" />clear the Chromium data in your account<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">To get helpful Chromium tips, turn on notifications in your iOS settings.</translation> <translation id="7995166854192397899">Suggestions are based on your browsing activity on your other devices. To get suggestions, sign in to Chromium on all your devices.</translation> <translation id="800195749539500647">Get the most out of Chromium.</translation> <translation id="8013573822802650211">To see your tabs from wherever you use Chromium, sign in on all your devices</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_et.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_et.xtb index 366f694..57bf728 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_et.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_et.xtb
@@ -204,6 +204,7 @@ Teie krüpteeritud andmeid saab lugeda ainult isik, kes teab teie parooli. Parooli ei saadeta Google’ile ja Google ei salvesta seda. Kui parooli unustate või soovite seda seadet muuta, <ph name="BEGIN_LINK" />kustutage oma kontol Chromiumi andmed<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium muutus just veelgi paremaks! Saadaval on uus versioon.</translation> +<translation id="6433172051771630690">Nõuanded Chromiumi kasutamiseks.</translation> <translation id="6502321914804101924">Chromium on väljalogitud</translation> <translation id="6563921047760808519">Vaadake lisateavet, <ph name="BEGIN_LINK" />kuidas Chromium teie andmeid privaatsena hoiab<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium toetab nüüd hallatud konto puhul kasutajareegleid</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Payst pärinevaid makseviise ja aadresse ei krüpteerita. Chromiumi sirvimisajalugu ei sünkroonita. Teie krüpteeritud andmeid saab lugeda ainult isik, kes teab teie parooli. Parooli ei saadeta Google’ile ja Google ei salvesta seda. Kui parooli unustate või soovite seda seadet muuta, <ph name="BEGIN_LINK" />kustutage oma kontol Chromiumi andmed<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Lülitage iOS-i seadetes märguanded sisse, et saada Chromiumi kohta kasulikke nõuandeid.</translation> <translation id="7995166854192397899">Soovitused põhinevad teie sirvimistegevusel teie teistes seadmetes. Soovituste saamiseks logige kõigis oma seadmetes Chromiumi sisse.</translation> <translation id="800195749539500647">Chromiumi parimal moel kasutamine</translation> <translation id="8013573822802650211">Selleks et näha vahelehti kõikjalt, kus Chromiumi kasutate, logige kõigisse oma seadmetesse sisse</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_eu.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_eu.xtb index fe7b67cd2..3c689e4 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_eu.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_eu.xtb
@@ -204,6 +204,7 @@ Zure pasaesaldia dakitenek soilik irakur ditzakete zure datu enkriptatuak. Google-k ez du jasoko pasaesaldia, ezta gordeko ere. Pasaesaldia ahazten bazaizu edo ezarpena aldatu nahi baduzu, <ph name="BEGIN_LINK" />garbitu kontuko Chromium-eko datuak<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium hobetu egin dugu! Bertsio berria duzu erabilgarri.</translation> +<translation id="6433172051771630690">Chromium-i etekinik handiena ateratzeko aholkuak.</translation> <translation id="6502321914804101924">Chromium-en saioa amaituta dago</translation> <translation id="6563921047760808519">Lortu <ph name="BEGIN_LINK" />Chromium-ek zure datuen pribatutasuna babesteko duen moduari<ph name="END_LINK" /> buruzko informazio gehiago</translation> <translation id="6625409903340039086">Orain, Chromium-ek kontu kudeaturako erabiltzaile-gidalerroak onartzen ditu</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay-ko ordainketa-metodoak eta helbideak ez dira enkriptatuko. Chromium-eko arakatze-historia ez da sinkronizatuko. Zure pasaesaldia dakitenek soilik irakur ditzakete zure datu enkriptatuak. Google-k ez du jasoko pasaesaldia, ezta gordeko ere. Pasaesaldia ahazten bazaizu edo ezarpena aldatu nahi baduzu, <ph name="BEGIN_LINK" />garbitu kontuko Chromium-eko datuak<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Chromium-i buruzko aholku lagungarriak jasotzeko, aktibatu jakinarazpenak iOS-en ezarpenetan.</translation> <translation id="7995166854192397899">Beste gailuetan egin dituzun arakatze-jardueretan oinarrituta daude iradokizunak. Haiek jasotzeko, hasi saioa Chromium-en gailu guztietan.</translation> <translation id="800195749539500647">Atera ahalik eta etekin handiena Chromium-i</translation> <translation id="8013573822802650211">Chromium erabiltzen duzun gailu guztietan zure fitxak eskura izateko, hasi saioa gailu guztietan</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_fa.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_fa.xtb index 4ffd4444e..c6b8bab 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_fa.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_fa.xtb
@@ -204,6 +204,7 @@ فقط شخصی که گذرعبارت شما را دراختیار داشته باشد میتواند دادههای رمزگذاریشدهتان را بخواند. گذرعبارت به Google ارسال نمیشود یا توسط آن ذخیره نمیشود. اگر گذرعبارت را فراموش کردید یا میخواهید این تنظیم را تغییر دهید، <ph name="BEGIN_LINK" /> دادههای Chromium ذخیرهشده در حسابتان را پاک کنید<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium بهتر شده است! نسخه جدید آن در دسترس است.</translation> +<translation id="6433172051771630690">نکاتی برای اینکه بیشترین بهره را از Chromium ببرید.</translation> <translation id="6502321914804101924">Chromium از سیستم خارج شده است</translation> <translation id="6563921047760808519">درباره اینکه <ph name="BEGIN_LINK" />Chromium چگونه دادههای شما را خصوصی نگه میدارد<ph name="END_LINK" /> بیشتر بدانید</translation> <translation id="6625409903340039086">Chromium اکنون از خطمشیهای کاربر برای حساب مدیریتشده شما پشتیبانی میکند</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">روشهای پرداخت و نشانیهای ذخیرهشده در Google Pay رمزگذاری نخواهند شد. سابقه مرور Chromium همگامسازی نخواهد شد. فقط شخصی که گذرعبارت شما را دراختیار داشته باشد میتواند دادههای رمزگذاریشدهتان را بخواند. گذرعبارت به Google ارسال نمیشود یا توسط آن ذخیره نمیشود. اگر گذرعبارت را فراموش کردید یا میخواهید این تنظیم را تغییر دهید، <ph name="BEGIN_LINK" /> دادههای Chromium ذخیرهشده در حسابتان را پاک کنید<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">برای دریافت نکتههای مفید درباره Chromium، اعلانها را در تنظیمات iOS روشن کنید.</translation> <translation id="7995166854192397899">پیشنهادها براساس فعالیت مرور شما در دستگاههای دیگرتان ارائه میشود. برای دریافت پیشنهادها، در همه دستگاههایتان به سیستم Chromium وارد شوید.</translation> <translation id="800195749539500647">بیشترین بهره را از Chromium ببرید</translation> <translation id="8013573822802650211">در همه دستگاههایی که در آنها از Chromium استفاده میکنید، به سیستم وارد شوید تا بتوانید برگههایتان را ببینید</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_fil.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_fil.xtb index c70c25e3..d1607ac 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_fil.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_fil.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Awtomatikong pinapatakbo ng Chromium ang Pag-check sa Kaligtasan araw-araw para panatilihin kang ligtas laban sa mga paglabag sa data, hindi ligtas na website, at higit pa. Makakakita ka ng higit pa tungkol sa Pag-check sa Kaligtasan sa Mga Setting.</translation> <translation id="3855938650519180865">Ano'ng Bago sa Chromium</translation> <translation id="3886689467633467988">Mag-sign in sa site na ito at sa Chromium para makuha mo ang iyong mga bookmark at higit pa sa lahat ng device mo.</translation> +<translation id="3904484643286601695">Puwede mong i-update ang iyong mga pinili anumang oras sa Mga Setting ng Chromium.</translation> <translation id="394413318816989199">Hindi kasama sa pag-encrypt ng passphrase ang mga paraan ng pagbabayad at address. Para baguhin ang setting na ito, <ph name="BEGIN_LINK" />i-clear ang data sa Chromium sa iyong account<ph name="END_LINK" />.</translation> @@ -204,6 +205,7 @@ Ang taong may passphrase mo lang ang makakapagbasa sa iyong naka-encrypt na data. Hindi ipinapadala sa o sino-store ng Google ang passphrase. Kung makalimutan mo ang iyong passphrase o gusto mong baguhin ang setting na ito, <ph name="BEGIN_LINK" />i-clear ang data sa Chromium sa iyong account<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Naging mas mahusay na ang Chromium! Available na ang bagong bersyon.</translation> +<translation id="6433172051771630690">Mga tip para masulit ang Chromium.</translation> <translation id="6502321914804101924">Naka-sign out ang Chromium</translation> <translation id="6563921047760808519">Matuto pa tungkol sa kung <ph name="BEGIN_LINK" />paano pinapanatiling pribado ng Chromium ang iyong data<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Suportado na ngayon ng Chromium ang mga patakaran ng user para sa iyong pinamamahalaang account</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">Hindi mae-encrypt ang mga paraan ng pagbabayad at address mula sa Google Pay. Hindi masi-sync ang history ng pag-browse mula sa Chromium. Ang taong may passphrase mo lang ang makakapagbasa sa iyong naka-encrypt na data. Hindi ipinapadala sa o sino-store ng Google ang passphrase. Kung makakalimutan mo ang iyong passphrase o gusto mong baguhin ang setting na ito, <ph name="BEGIN_LINK" />i-clear ang data sa Chromium sa iyong account<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Para makakuha ng mga kapaki-pakinabang na tip sa Chromium, i-on ang mga notification sa iyong mga setting ng iOS.</translation> <translation id="7995166854192397899">Batay ang mga suhestyon sa iyong aktibidad sa pag-browse sa iba mo pang device. Para makatanggap ng mga suhestyon, mag-sign in sa Chromium sa lahat ng iyong device.</translation> <translation id="800195749539500647">Sulitin ang Chromium</translation> <translation id="8013573822802650211">Para makita ang iyong mga tab sa kahit saan ka man gumagamit ng Chromium, mag-sign in sa lahat ng device mo</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb index 66e6e6a..28e71b7 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb
@@ -204,6 +204,7 @@ Só poderá ler os teus datos encriptados quen teña a túa frase de acceso (Google non a recibirá nin a almacenará). Se esqueces a frase de acceso ou queres cambiar esta opción de configuración, <ph name="BEGIN_LINK" />borra os datos de Chromium da túa conta<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium introduciu melloras. Está dispoñible unha nova versión.</translation> +<translation id="6433172051771630690">Consellos para tirar o máximo proveito de Chromium.</translation> <translation id="6502321914804101924">Pechaches a sesión en Chromium</translation> <translation id="6563921047760808519">Máis información sobre <ph name="BEGIN_LINK" />como protexe Chromium a privacidade dos teus datos<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium xa admite políticas de usuario para a túa conta xestionada</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Non se encriptarán os métodos de pago nin os enderezos de Google Pay. Tampouco se sincronizará o historial de navegación de Chromium. Só poderán ler os teus datos encriptados as persoas que coñezan a túa frase de acceso. Google non recibirá nin almacenará a frase de acceso. Se esqueces a frase de acceso ou queres cambiar esta opción de configuración, <ph name="BEGIN_LINK" />borra os datos de Chromium da túa conta<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Se queres recibir consellos útiles sobre Chromium, activa as notificacións na configuración de iOS.</translation> <translation id="7995166854192397899">As suxestións baséanse na túa actividade de navegación noutros dispositivos. Para recibir suxestións, inicia sesión en Chromium en todos os teus dispositivos.</translation> <translation id="800195749539500647">Tira o máximo proveito de Chromium</translation> <translation id="8013573822802650211">Para ver as túas pestanas desde calquera dispositivo no que utilices Chromium, inicia sesión en todos eles</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_hr.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_hr.xtb index 28dc2ba9..90b54da 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_hr.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_hr.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium automatski pokreće sigurnosnu provjeru svaki dan kako bi vas zaštitio od neovlaštenog pristupa podacima, nesigurnih web-lokacija i drugih opasnosti. Više o sigurnosnoj provjeri možete pronaći u postavkama.</translation> <translation id="3855938650519180865">Novosti u Chromiumu</translation> <translation id="3886689467633467988">Prijavite se na ovu web-lokaciju i Chromium kako biste imali pristup svojim oznakama i još toga na svim svojim uređajima.</translation> +<translation id="3904484643286601695">Svoje odabire uvijek možete ažurirati u postavkama Chromiuma.</translation> <translation id="394413318816989199">Šifriranje šifre ne uključuje načine plaćanja i adrese. Kako biste promijenili tu postavku, <ph name="BEGIN_LINK" />izbrišite podatke Chromiuma na svom računu<ph name="END_LINK" />.</translation> @@ -204,6 +205,7 @@ Vaše šifrirane podatke može pročitati samo osoba koja ima vašu šifru. Šifra se ne šalje Googleu niti se pohranjuje na Googleu. Ako zaboravite šifru ili želite promijeniti tu postavku, <ph name="BEGIN_LINK" />izbrišite Chromiumove podatke na računu<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium je postao još bolji! Dostupna je nova verzija.</translation> +<translation id="6433172051771630690">Savjeti o tome kako iskoristiti sve prednosti Chromiuma.</translation> <translation id="6502321914804101924">Chromium je odjavljen</translation> <translation id="6563921047760808519">Saznajte više o tome <ph name="BEGIN_LINK" />kako Chromium štiti privatnost vaših podataka<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium sada za vaš upravljani račun podržava korisnička pravila</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">Načini plaćanja i adrese s Google Paya neće se šifrirati. Povijest pregledavanja iz Chromiuma neće se sinkronizirati. Vaše šifrirane podatke može pročitati samo osoba koja ima vašu šifru. Šifra se ne šalje Googleu niti se pohranjuje na Googleu. Ako zaboravite šifru ili želite promijeniti tu postavku, <ph name="BEGIN_LINK" />izbrišite Chromiumove podatke na računu<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Da biste primali korisne savjete o Chromiumu, uključite obavijesti u postavkama iOS-a.</translation> <translation id="7995166854192397899">Prijedlozi se temelje na vašoj aktivnosti pregledavanja na vašim drugim uređajima. Da biste primali prijedloge, prijavite se u Chromium na svim svojim uređajima.</translation> <translation id="800195749539500647">Iskoristite sve prednosti Chromiuma</translation> <translation id="8013573822802650211">Da biste vidjeli svoje kartice bez obzira na to gdje koristite Chromium, prijavite se na svim svojim uređajima</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb index 8a72b630..69d30f5a 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb
@@ -204,6 +204,7 @@ Hanya orang yang memiliki frasa sandi Anda yang dapat membaca data terenkripsi Anda. Frasa sandi tidak dikirim ke atau disimpan oleh Google. Jika lupa frasa sandi atau ingin mengubah setelan ini, <ph name="BEGIN_LINK" />hapus data Chromium di akun Anda<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium jadi semakin baik! Versi baru telah tersedia.</translation> +<translation id="6433172051771630690">Tips untuk mengoptimalkan penggunaan Chromium.</translation> <translation id="6502321914804101924">Logout dari Chromium</translation> <translation id="6563921047760808519">Pelajari lebih lanjut <ph name="BEGIN_LINK" />cara Chromium menjaga privasi data Anda<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium kini mendukung kebijakan pengguna untuk akun terkelola Anda</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Metode pembayaran dan alamat dari Google Pay tidak akan dienkripsi. Histori penjelajahan dari Chromium tidak akan disinkronkan. Hanya orang yang memiliki frasa sandi Anda yang dapat membaca data terenkripsi Anda. Frasa sandi tidak dikirim ke atau disimpan oleh Google. Jika lupa frasa sandi atau ingin mengubah setelan ini, <ph name="BEGIN_LINK" />hapus data Chromium di akun Anda<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Untuk mendapatkan tips Chromium yang berguna, aktifkan notifikasi di setelan iOS.</translation> <translation id="7995166854192397899">Saran didasarkan pada aktivitas penjelajahan Anda di perangkat lain. Untuk mendapatkan saran, login ke Chromium di semua perangkat Anda.</translation> <translation id="800195749539500647">Dapatkan manfaat optimal dari Chromium</translation> <translation id="8013573822802650211">Untuk melihat tab Chromium Anda dari perangkat lain, login ke semua perangkat Anda</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_is.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_is.xtb index acb481c..0a5c6944 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_is.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_is.xtb
@@ -204,6 +204,7 @@ Aðeins einstaklingar sem eru með aðgangsorðið þitt geta lesið dulkóðuðu gögnin þín. Aðgangsorðið er hvorki sent til né vistað hjá Google. Ef þú gleymir aðgangsorðinu eða vilt breyta þessari stillingu skaltu <ph name="BEGIN_LINK" />hreinsa Chromium-gögnin á reikningnum þínum<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium er nú enn betra! Ný útgáfa er í boði.</translation> +<translation id="6433172051771630690">Ráð um að fá sem mest út úr Chromium.</translation> <translation id="6502321914804101924">Þú ert skráð(ur) út af Chromium</translation> <translation id="6563921047760808519">Nánar um <ph name="BEGIN_LINK" />hvernig Chromium heldur gögnunum þínum leyndum<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium styður nú notendareglur fyrir stýrða reikninginn þinn</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Upplýsingar um greiðslumáta og heimilisföng frá Google Pay verða ekki dulkóðaðar. Vafraferill Chromium samstillist ekki. Aðeins einstaklingar sem eru með aðgangsorðið þitt geta lesið dulkóðuðu gögnin þín. Aðgangsorðið er hvorki sent til né vistað hjá Google. Ef þú gleymir aðgangsorðinu eða vilt breyta þessari stillingu skaltu <ph name="BEGIN_LINK" />hreinsa Chromium-gögnin á reikningnum þínum<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Til að fá gagnleg ráð um Chromium skaltu kveikja á tilkynningum í iOS-stillingum.</translation> <translation id="7995166854192397899">Tillögur miðast við vafranotkun þína í öðrum tækjum. Skráðu þig inn á Chromium í öllum tækjum til að fá tillögur.</translation> <translation id="800195749539500647">Fáðu sem mest út úr Chromium.</translation> <translation id="8013573822802650211">Skráðu þig inn í öllum tækjunum þínum til að sjá flipana þína hvar sem þú notar Chromium</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_iw.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_iw.xtb index 8538077..33d2176 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_iw.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_iw.xtb
@@ -204,6 +204,7 @@ רק מי שיודע את ביטוי הסיסמה יכול לקרוא את הנתונים המוצפנים. ביטוי הסיסמה לא נשלח אל Google ולא מאוחסן ב-Google. אם שכחת את ביטוי הסיסמה או שברצונך לשנות את ההגדרה הזו, <ph name="BEGIN_LINK" />עליך לנקות את נתוני Chromium בחשבון<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium ממשיך להשתפר! קיימת גרסה חדשה.</translation> +<translation id="6433172051771630690">טיפים שיעזרו לך ליהנות מהמיטב של Chromium.</translation> <translation id="6502321914804101924">יצאת מהחשבון ב-Chromium</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />מידע נוסף לגבי השמירה על פרטיות הנתונים ב-Chromium<ph name="END_LINK" /></translation> <translation id="6625409903340039086">עכשיו יש ב-Chromium תמיכה במדיניות משתמש בחשבון המנוהל שלך</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">אמצעי תשלום וכתובות שנשמרו ב-Google Pay לא יוצפנו. היסטוריית הגלישה ב-Chromium לא תסונכרן. רק מי שיודע את ביטוי הסיסמה יכול לקרוא את הנתונים המוצפנים. ביטוי הסיסמה לא נשלח אל Google ולא מאוחסן ב-Google. אם שכחת את ביטוי הסיסמה או שברצונך לשנות את ההגדרה הזו, <ph name="BEGIN_LINK" />עליך לנקות את נתוני Chromium בחשבון<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">כדי לקבל טיפים מועילים ל-Chromium, צריך להפעיל את ההתראות בהגדרות iOS.</translation> <translation id="7995166854192397899">ההצעות מבוססות על פעילות הגלישה במכשירים האחרים שלך. כדי לקבל הצעות, צריך להיכנס ל-Chromium בכל המכשירים.</translation> <translation id="800195749539500647">איך ליהנות מהמיטב של Chromium</translation> <translation id="8013573822802650211">כדי לראות את הכרטיסיות שלך מכל מקום שבו פתחת את Chromium יש להיכנס לחשבון בכל המכשירים</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ja.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ja.xtb index e1fd89a..c744475 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ja.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ja.xtb
@@ -204,6 +204,7 @@ パスフレーズを知っているユーザーだけが暗号化されたデータを見ることができます。パスフレーズは Google には送信されず、保存されることもありません。パスフレーズを忘れた場合や、この設定を変更する場合は、<ph name="BEGIN_LINK" />アカウントの Chromium データを消去<ph name="END_LINK" />してください。</translation> <translation id="6424492062988593837">Chromium のアップデートが見つかりました。新しいバージョンが利用可能です。</translation> +<translation id="6433172051771630690">Chromium を最大限に活用するためのヒント。</translation> <translation id="6502321914804101924">Chromium からログアウトしています</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium でユーザーデータのプライバシーを保護する方法<ph name="END_LINK" />についての詳細</translation> <translation id="6625409903340039086">Chromium で管理対象アカウントのユーザー ポリシーがサポートされるようになりました</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay のお支払い方法と住所は暗号化されません。また、Chromium の閲覧履歴は同期されません。 パスフレーズを知っているユーザーだけが暗号化されたデータを見ることができます。パスフレーズは Google には送信されず、保存されることもありません。パスフレーズを忘れた場合や、この設定を変更する場合は、<ph name="BEGIN_LINK" />アカウントの Chromium データを消去<ph name="END_LINK" />してください。</translation> +<translation id="7994322153108931467">Chromium を使いこなすヒントを受け取るには、iOS の設定で通知をオンにしてください。</translation> <translation id="7995166854192397899">候補は、他のデバイスでの閲覧アクティビティに基づいて表示されます。候補を表示するには、すべてのデバイスで Chromium にログインしてください。</translation> <translation id="800195749539500647">Chromium を最大限に活用</translation> <translation id="8013573822802650211">どのデバイスからでも Chromium で自分のタブにアクセスするには、すべてのデバイスでログインしてください</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb index 030c465..1c4b8e71 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb
@@ -204,6 +204,7 @@ Құпия фразасы бар адам ғана шифрланған деректеріңізді оқи алады. Құпия фраза Google компаниясына жіберілмейді немесе ол арқылы сақталмайды. Құпия фразаны ұмытып қалсаңыз немесе осы параметрді өзгерту керек болса, <ph name="BEGIN_LINK" />аккаунтыңыздағы Chromium деректерін өшіріңіз<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium жақсара түсті! Жаңа нұсқасы қолжетімді.</translation> +<translation id="6433172051771630690">Chromium-ді барынша тиімді пайдалануға көмектесетін кеңестер.</translation> <translation id="6502321914804101924">Chromium-нен шықтыңыз</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium-нің деректеріңізді құпия сақтау жолы<ph name="END_LINK" /> туралы толық ақпарат</translation> <translation id="6625409903340039086">Chromium енді басқарылатын аккаунттар үшін пайдаланушы саясаттарына қолдау көрсетеді</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay қызметіндегі төлеу әдістері мен мекенжайлары шифрланбайды. Chromium-нің браузерді қолдану тарихы синхрондалмайды. Құпия фразасы бар адам ғана шифрланған деректеріңізді оқи алады. Құпия фраза Google компаниясына жіберілмейді немесе ол құпия фразаңызды сақтамайды. Құпия фразаны ұмытып қалсаңыз немесе осы параметрді өзгерту керек болса, <ph name="BEGIN_LINK" />аккаунтыңыздағы Chromium деректерін өшіріңіз<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Пайдалы Chromium кеңестерін алу үшін iOS параметрлерінде хабарландыруларды қосыңыз.</translation> <translation id="7995166854192397899">Ұсыныстар басқа құрылғыларыңыздағы браузерді пайдалану тарихына негізделеді. Ұсыныстар алу үшін барлық құрылғыңызда Chromium-ге кіріңіз.</translation> <translation id="800195749539500647">Chromium мүмкіндіктерін барынша тиімді пайдаланыңыз</translation> <translation id="8013573822802650211">Chromium браузерін кез келген жерде пайдаланғанда, қойындыларды көру үшін барлық құрылғыларда аккаунтқа кіріңіз.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_km.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_km.xtb index 3db52c7..6841d4b 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_km.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_km.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium ដំណើរការការពិនិត្យសុវត្ថិភាពដោយស្វ័យប្រវត្តិជារៀងរាល់ថ្ងៃ ដើម្បីរក្សាសុវត្ថិភាពរបស់អ្នកឱ្យជៀសផុតពីការបែកធ្លាយទិន្នន័យ គេហទំព័រដែលគ្មានសុវត្ថិភាព និងអ្វីៗជាច្រើនទៀត។ អ្នកអាចស្វែងយល់បន្ថែមអំពីការពិនិត្យសុវត្ថិភាពនៅក្នុងការកំណត់។</translation> <translation id="3855938650519180865">អ្វីដែលថ្មីក្នុង Chromium</translation> <translation id="3886689467633467988">ចូលគណនីលើគេហទំព័រនេះ និង Chromium ដើម្បីទទួលបានចំណាំរបស់អ្នក និងអ្វីៗជាច្រើនទៀតនៅលើឧបករណ៍ទាំងអស់របស់អ្នក។</translation> +<translation id="3904484643286601695">អ្នកអាចធ្វើបច្ចុប្បន្នភាពការជ្រើសរើសរបស់អ្នកនៅពេលណាក៏បាននៅក្នុងការកំណត់ Chromium។</translation> <translation id="394413318816989199">ការអ៊ីនគ្រីបដោយប្រើឃ្លាសម្ងាត់មិនរួមបញ្ចូលវិធីបង់ប្រាក់ និងអាសយដ្ឋានទេ។ ដើម្បីប្ដូរការកំណត់នេះ សូម<ph name="BEGIN_LINK" />សម្អាតទិន្នន័យ Chromium នៅក្នុងគណនីរបស់អ្នក<ph name="END_LINK" />។</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_kn.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_kn.xtb index cd967f4d..910dc1e6 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_kn.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_kn.xtb
@@ -204,6 +204,7 @@ ನಿಮ್ಮ ಪಾಸ್ಫ್ರೇಸ್ ಹೊಂದಿರುವವರು ಮಾತ್ರ ನಿಮ್ಮ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಡೇಟಾವನ್ನು ಓದಬಹುದು. ಪಾಸ್ಫ್ರೇಸ್ ಅನ್ನು Google ಗೆ ಕಳುಹಿಸಲಾಗುವುದಿಲ್ಲ ಅಥವಾ ಅದನ್ನು Google ಸಂಗ್ರಹಿಸುವುದಿಲ್ಲ. ನಿಮ್ಮ ಪಾಸ್ಫ್ರೇಸ್ ಅನ್ನು ನೀವು ಮರೆತರೆ ಅಥವಾ ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸಲು ಬಯಸಿದರೆ, <ph name="BEGIN_LINK" />ನಿಮ್ಮ ಖಾತೆಯಲ್ಲಿರುವ Chromium ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chrome ಈಗ ತಾನೇ ಉತ್ತಮಗೊಂಡಿದೆ! ಹೊಸ ಆವೃತ್ತಿ ಲಭ್ಯವಿದೆ.</translation> +<translation id="6433172051771630690">Chromium ನಿಂದ ಅತ್ಯಧಿಕ ಪ್ರಯೋಜನ ಪಡೆಯುವ ಕುರಿತು ಸಲಹೆಗಳು.</translation> <translation id="6502321914804101924">Chromium ಅನ್ನು ಸೈನ್ ಔಟ್ ಮಾಡಲಾಗಿದೆ</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಹೇಗೆ ಖಾಸಗಿಯಾಗಿ ಇರಿಸುತ್ತದೆ<ph name="END_LINK" /> ಎಂಬುದರ ಕುರಿತು ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ</translation> <translation id="6625409903340039086">Chromium ಈಗ ನಿಮ್ಮ ನಿರ್ವಹಿಸಿದ ಖಾತೆಗಾಗಿ ಬಳಕೆದಾರರ ನೀತಿಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay ನಲ್ಲಿನ ಪಾವತಿ ವಿಧಾನಗಳು ಮತ್ತು ವಿಳಾಸಗಳನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ. Chromium ನ ಬ್ರೌಸಿಂಗ್ ಇತಿಹಾಸವು ಸಿಂಕ್ ಆಗುವುದಿಲ್ಲ. ನಿಮ್ಮ ಪಾಸ್ಫ್ರೇಸ್ ಹೊಂದಿರುವವರು ಮಾತ್ರ ನಿಮ್ಮ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಡೇಟಾವನ್ನು ಓದಬಹುದು. ಪಾಸ್ಫ್ರೇಸ್ ಅನ್ನು Google ಗೆ ಕಳುಹಿಸಲಾಗುವುದಿಲ್ಲ ಅಥವಾ ಅದನ್ನು Google ಸಂಗ್ರಹಿಸುವುದಿಲ್ಲ. ನಿಮ್ಮ ಪಾಸ್ಫ್ರೇಸ್ ಅನ್ನು ನೀವು ಮರೆತರೆ ಅಥವಾ ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸಲು ಬಯಸಿದರೆ, <ph name="BEGIN_LINK" />ನಿಮ್ಮ ಖಾತೆಯಲ್ಲಿರುವ Chromium ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">ಸಹಾಯಕವಾದ Chromium ಸಲಹೆಗಳನ್ನು ಪಡೆಯಲು, ನಿಮ್ಮ iOS ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ.</translation> <translation id="7995166854192397899">ಸಲಹೆಗಳು, ನಿಮ್ಮ ಇತರ ಸಾಧನಗಳಲ್ಲಿನ ನಿಮ್ಮ ಬ್ರೌಸಿಂಗ್ ಚಟುವಟಿಕೆಯನ್ನು ಆಧರಿಸಿವೆ. ಸಲಹೆಗಳನ್ನು ಪಡೆಯಲು, ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಲ್ಲಿ Chromium ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ.</translation> <translation id="800195749539500647">Chromium ನಿಂದ ಇನ್ನಷ್ಟು ಪ್ರಯೋಜನ ಪಡೆಯಿರಿ</translation> <translation id="8013573822802650211">ನೀವು Chromium ಅನ್ನು ಎಲ್ಲಿ ಬಳಸುತ್ತೀರೋ ಅಲ್ಲಿ ನಿಮ್ಮ ಟ್ಯಾಬ್ಗಳನ್ನು ನೋಡಲು, ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಲ್ಲಿ ಸೈನ್ ಇನ್ ಮಾಡಿ</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ko.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ko.xtb index 40bc74a..fc6ebcd1 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ko.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ko.xtb
@@ -204,6 +204,7 @@ 암호를 아는 사람만 암호화된 내 데이터를 읽을 수 있습니다. 암호는 Google로 전송되거나 Google에 저장되지 않습니다. 암호가 기억나지 않거나 이 설정을 변경하려면 <ph name="BEGIN_LINK" />계정의 Chromium 데이터를 삭제<ph name="END_LINK" />하세요.</translation> <translation id="6424492062988593837">한층 개선된 Chromium의 최신 버전이 출시되었습니다.</translation> +<translation id="6433172051771630690">Chromium을 최대한 활용하기 위한 도움말입니다.</translation> <translation id="6502321914804101924">Chromium에서 로그아웃됨</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium에서 데이터를 비공개로 유지하는 방법<ph name="END_LINK" /> 자세히 알아보기</translation> <translation id="6625409903340039086">이제 Chromium에서 관리 계정에 대한 사용자 정책을 지원합니다</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay의 결제 수단 및 주소는 암호화되지 않습니다. Chromium 방문 기록은 동기화되지 않습니다. 암호를 아는 사람만 암호화된 내 데이터를 읽을 수 있습니다. 암호는 Google로 전송되거나 Google에 저장되지 않습니다. 암호가 기억나지 않거나 이 설정을 변경하려면 <ph name="BEGIN_LINK" />계정의 Chromium 데이터를 삭제<ph name="END_LINK" />하세요.</translation> +<translation id="7994322153108931467">유용한 Chromium 도움말을 확인하려면 iOS 설정에서 알림을 사용 설정하세요</translation> <translation id="7995166854192397899">추천은 다른 기기에서 탐색한 활동을 기반으로 합니다. 추천을 받으려면 모든 기기에서 Chromium에 로그인하세요.</translation> <translation id="800195749539500647">Chromium 최대한 활용하기</translation> <translation id="8013573822802650211">Chromium을 사용하는 어느 곳에서나 탭을 확인하려면 모든 기기에서 로그인하세요.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb index 186099d..f62fbbb3 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium ເອີ້ນໃຊ້ການກວດສອບຄວາມປອດໄພໂດຍອັດຕະໂນມັດທຸກມື້ເພື່ອຊ່ວຍໃຫ້ທ່ານປອດໄພຈາກການລະເມີດຂໍ້ມູນ, ເວັບໄຊທີ່ບໍ່ປອດໄພ ແລະ ອື່ນໆ. ທ່ານສາມາດຊອກຫາຂໍ້ມູນເພີ່ມເຕີມກ່ຽວກັບການກວດສອບຄວາມປອດໄພໄດ້ໃນການຕັ້ງຄ່າ.</translation> <translation id="3855938650519180865">ມີຫຍັງໃໝ່ໃນ Chromium</translation> <translation id="3886689467633467988">ເຂົ້າສູ່ລະບົບເວັບໄຊນີ້ ແລະ Chromium ເພື່ອຮັບບຸກມາກຂອງທ່ານ ແລະ ອື່ນໆຢູ່ອຸປະກອນທັງໝົດຂອງທ່ານ.</translation> +<translation id="3904484643286601695">ທ່ານສາມາດອັບເດດສິ່ງທີ່ທ່ານເລືອກໄດ້ທຸກເວລາໃນການຕັ້ງຄ່າ Chromium.</translation> <translation id="394413318816989199">ການເຂົ້າລະຫັດດ້ວຍລະຫັດຜ່ານບໍ່ຮວມເຖິງວິທີການຈ່າຍເງິນ ແລະ ທີ່ຢູ່. ເພື່ອປ່ຽນການຕັ້ງຄ່ານີ້, ໃຫ້ <ph name="BEGIN_LINK" />ລຶບລ້າງຂໍ້ມູນ Chromium ໃນບັນຊີຂອງທ່ານ<ph name="END_LINK" /> ກ່ອນ.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_lt.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_lt.xtb index 8c96566..c82fa9b 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_lt.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_lt.xtb
@@ -204,6 +204,7 @@ Tik jūsų slaptafrazę turintis asmuo galės perskaityti šifruotus duomenis. Slaptafrazė nesiunčiama ir nesaugoma „Google“. Jei pamiršite slaptafrazę ar norėsite pakeisti šį nustatymą, <ph name="BEGIN_LINK" />išvalykite „Chromium“ duomenis paskyroje<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">„Chromium“ patobulėjo! Galima nauja versija.</translation> +<translation id="6433172051771630690">Patarimai, kaip išnaudoti visas „Chromium“ galimybes.</translation> <translation id="6502321914804101924">Atsijungta nuo „Chromium“</translation> <translation id="6563921047760808519">Sužinokite daugiau, <ph name="BEGIN_LINK" />kaip „Chromium“ užtikrina jūsų duomenų privatumą<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Dabar „Chromium“ palaiko valdomos paskyros naudotojo politiką</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">„Google Pay“ mokėjimo metodai ir adresai nebus šifruojami. Naršymo istorija iš „Chromium“ nebus sinchronizuojama. Tik jūsų slaptafrazę turintis asmuo galės perskaityti šifruotus duomenis. Slaptafrazė nesiunčiama ir nesaugoma „Google“. Jei pamiršite slaptafrazę ar norėsite pakeisti šį nustatymą, <ph name="BEGIN_LINK" />išvalykite „Chromium“ duomenis paskyroje<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Jei norite gauti naudingų „Chromium“ patarimų, įjunkite pranešimus „iOS“ nustatymuose.</translation> <translation id="7995166854192397899">Pasiūlymai pagrįsti jūsų naršymo veikla kituose įrenginiuose. Jei norite gauti pasiūlymų, prisijunkite prie „Chromium“ visuose savo įrenginiuose.</translation> <translation id="800195749539500647">Išnaudokite visas „Chromium“ galimybes</translation> <translation id="8013573822802650211">Kad matytumėte skirtukus iš visų įrenginių, kuriuose naudojate „Chromium“, prisijunkite visuose įrenginiuose</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_lv.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_lv.xtb index 5edde452..901f93a1 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_lv.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_lv.xtb
@@ -204,6 +204,7 @@ Jūsu šifrētos datus var lasīt tikai personas, kurām ir jūsu ieejas frāze. Ieejas frāze netiek sūtīta uzņēmumam Google, un uzņēmums Google to neuzglabā. Ja esat aizmirsis ieejas frāzi vai vēlaties mainīt šo iestatījumu, <ph name="BEGIN_LINK" />notīriet Chromium datus savā kontā<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Lietojumprogramma Chromium ir uzlabota! Ir pieejama jauna versija.</translation> +<translation id="6433172051771630690">Padomi par pilnvērtīgu Chromium izmantošanu.</translation> <translation id="6502321914804101924">Esat izrakstījies no pārlūka Chromium</translation> <translation id="6563921047760808519">Uzziniet vairāk par to, <ph name="BEGIN_LINK" />kā pārlūkā Chromium tiek saglabāta jūsu datu konfidencialitāte<ph name="END_LINK" />.</translation> <translation id="6625409903340039086">Pārlūkā Chromium tagad tiek atbalstīta lietotāju politiku izmantošana jūsu pārvaldītajos kontos</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Maksājumu veidi un adreses no pakalpojuma Google Pay netiks šifrētas. Pārlūkā Chromium saglabātā pārlūkošanas vēsture netiks sinhronizēta. Jūsu šifrētos datus var lasīt tikai personas, kurām ir jūsu ieejas frāze. Ieejas frāze netiek sūtīta uzņēmumam Google, un uzņēmums Google to neuzglabā. Ja esat aizmirsis ieejas frāzi vai vēlaties mainīt šo iestatījumu, <ph name="BEGIN_LINK" />notīriet Chromium datus savā kontā<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Lai saņemtu noderīgus Chromium padomus, ieslēdziet paziņojumus iOS iestatījumos.</translation> <translation id="7995166854192397899">Ieteikumu pamatā ir pārlūkošanas darbības citās ierīcēs. Lai saņemtu ieteikumus, visās savās ierīcēs pierakstieties pārlūkā Chromium.</translation> <translation id="800195749539500647">Izmantojiet pārlūku Chromium pilnvērtīgi</translation> <translation id="8013573822802650211">Lai skatītu cilnes no ierīcēm, kurās lietojat pārlūku Chromium, pierakstieties visās savās ierīcēs.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_mn.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_mn.xtb index 2478b30..a658c95 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_mn.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_mn.xtb
@@ -204,6 +204,7 @@ Зөвхөн таны нэвтрэх үгтэй хэн нэгэн шифрлэгдсэн өгөгдлийг тань унших боломжтой. Нэвтрэх үгийг Google-д илгээдэггүй эсвэл хадгалдаггүй. Хэрэв та нэвтрэх үгээ мартсан эсвэл энэ тохиргоог өөрчлөхийг хүсвэл <ph name="BEGIN_LINK" />бүртгэлийнхээ Chromium-н өгөгдлийг арилгана уу<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium-ыг сайжрууллаа! Одоо шинэ хувилбарыг ашиглах боломжтой.</translation> +<translation id="6433172051771630690">Chromium-г бүрэн ашиглах зөвлөгөөнүүд.</translation> <translation id="6502321914804101924">Chromium-с гарсан байна</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium таны өгөгдлийг хэрхэн хувийн байлгадаг<ph name="END_LINK" /> талаар нэмэлт мэдээлэл авах</translation> <translation id="6625409903340039086">Chromium одоо таны тохиргоо хийгдсэн бүртгэлд хэрэглэгчийн бодлогыг дэмжинэ</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay-н төлбөрийн хэрэгсэл болон хаягуудыг шифрлэхгүй. Chromium-н хөтчийн түүхийг синк хийхгүй. Зөвхөн таны нэвтрэх үгтэй хэн нэгэн шифрлэгдсэн өгөгдлийг тань унших боломжтой. Нэвтрэх үгийг Google-д илгээдэггүй эсвэл хадгалдаггүй. Хэрэв та нэвтрэх үгээ мартсан эсвэл энэ тохиргоог өөрчлөхийг хүсвэл <ph name="BEGIN_LINK" />бүртгэлийнхээ Chromium-н өгөгдлийг арилгана уу<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Chromium-н хэрэгтэй зөвлөгөөнүүдийг авахын тулд iOS тохиргоондоо мэдэгдлүүдийг асаана уу.</translation> <translation id="7995166854192397899">Зөвлөмжүүдийг таны бусад төхөөрөмжийн хөтчийн үйл ажиллагаанд тань тулгуурлан харуулдаг. Зөвлөмжүүд авахын тулд бүх төхөөрөмждөө Chromium-д нэвтэрнэ үү.</translation> <translation id="800195749539500647">Chromium-г бүрэн ашиглаарай</translation> <translation id="8013573822802650211">Та Chromium-г хаанаас ч ашигласан бай табуудаа харахын тулд бүх төхөөрөмж дээрээ нэвтэрнэ үү</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_mr.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_mr.xtb index 6a10e38..c9a4611 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_mr.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_mr.xtb
@@ -204,6 +204,7 @@ फक्त तुमचा पासफ्रेझ असलेली कोणतीही व्यक्ती तुमचा एन्क्रिप्ट केलेला डेटा वाचू शकते. पासफ्रेझ Google कडे पाठवला किंवा त्याद्वारे स्टोअर केलेला नाही. तुम्ही तुमचा पासफ्रेझ विसरल्यास किंवा हे सेटिंग बदलायचे असल्यास, <ph name="BEGIN_LINK" />तुमच्या खात्यामधील Chromium डेटा साफ करणे<ph name="END_LINK" /> हे करा.</translation> <translation id="6424492062988593837">Chrome आता सर्वोत्तम झाले आहे! नवीन आवृत्ती उपलब्ध आहे.</translation> +<translation id="6433172051771630690">Chromium चा पुरेपूर वापर करण्यासाठी टिपा.</translation> <translation id="6502321914804101924">Chromium साइन आउट केले आहे</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium तुमचा डेटा खाजगी कसा ठेवते<ph name="END_LINK" /> याविषयी अधिक जाणून घ्या</translation> <translation id="6625409903340039086">Chromium आता तुमच्या व्यवस्थापित केलेल्या खात्यासाठी वापरकर्ता धोरणांना सपोर्ट करते</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay वरील पेमेंट पद्धती आणि पत्ते एन्क्रिप्ट केले जाणार नाहीत. Chromium वरील ब्राउझिंग इतिहास सिंक होणार नाही. फक्त तुमचा पासफ्रेझ असलेली कोणतीही व्यक्ती तुमचा एन्क्रिप्ट केलेला डेटा वाचू शकते. पासफ्रेझ Google कडे पाठवला किंवा त्याद्वारे स्टोअर केलेला नाही. तुम्ही तुमचा पासफ्रेझ विसरल्यास किंवा हे सेटिंग बदलायचे असल्यास, <ph name="BEGIN_LINK" />तुमच्या खात्यामधील Chromium डेटा साफ करणे<ph name="END_LINK" /> हे करा.</translation> +<translation id="7994322153108931467">Chromium बद्दल उपयुक्त टिपा मिळवण्यासाठी, तुमच्या iOS सेटिंग्जमध्ये सूचना सुरू करा.</translation> <translation id="7995166854192397899">सूचना या तुमच्या इतर डिव्हाइसवरील तुमच्या ब्राउझिंग ॲक्टिव्हिटीवर आधारित असतात. सूचना मिळवण्यासाठी, तुमच्या सर्व डिव्हाइसवर Chromium मध्ये साइन इन करा.</translation> <translation id="800195749539500647">Chromium चा पुरेपूर वापर करा</translation> <translation id="8013573822802650211">तुम्ही जेथून Chromium वापरत असाल तेथून तुमचे टॅब पाहण्यासाठी, तुमच्या सर्व डिव्हाइसवर साइन इन करा</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb index 17bd430..9638e86 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium menjalankan Pemeriksaan Keselamatan secara automatik setiap hari untuk memastikan anda selamat daripada pelanggaran data, laman web yang tidak selamat dan pelbagai lagi. Anda boleh mendapatkan maklumat lanjut tentang Pemeriksaan Keselamatan dalam Tetapan.</translation> <translation id="3855938650519180865">Item Baharu dalam Chromium</translation> <translation id="3886689467633467988">Log masuk laman ini dan Chromium untuk mendapatkan penanda halaman anda dan banyak lagi pada semua peranti anda.</translation> +<translation id="3904484643286601695">Anda boleh mengemaskinikan pilihan anda pada bila-bila masa dalam Tetapan Chromium.</translation> <translation id="394413318816989199">Penyulitan ungkapan laluan tidak termasuk kaedah pembayaran dan alamat. Untuk menukar tetapan ini, <ph name="BEGIN_LINK" />kosongkan data Chromium dalam akaun anda<ph name="END_LINK" />.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ne.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ne.xtb index c868afbe..a8b19db 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ne.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ne.xtb
@@ -203,6 +203,7 @@ तपाईंको पासफ्रेज भएका व्यक्ति मात्र इन्क्रिप्ट गरिएको जानकारी पढ्न सक्छ। उक्त पासफ्रेज Google मा पठाइँदैन वा Google ले उक्त पासफ्रेज भण्डारण गरेर राख्दैन। तपाईंले आफ्नो पासफ्रेज बिर्सनुभयो वा तपाईं यो सेटिङ परिवर्तन गर्न चाहनुहुन्छ भने <ph name="BEGIN_LINK" />आफ्नो खातामा गएर Chromium को डेटा मेटाउनुहोस्<ph name="END_LINK" />।</translation> <translation id="6424492062988593837">Chromium भर्खरै झन राम्रो भयो! एक नयाँ संस्करण उपलब्ध छ।</translation> +<translation id="6433172051771630690">Chromium बाट अधिकतम फाइदा लिन सघाउने सुझावहरू।</translation> <translation id="6502321914804101924">Chromium बाट साइन आउट गरिएको छ</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium ले तपाईंको डेटा कसरी गोप्य राख्छ<ph name="END_LINK" /> भन्ने बारेमा थप जान्नुहोस्</translation> <translation id="6625409903340039086">अब व्यवस्थापन गरिएको तपाईंको खाताका हकमा Chromium मा प्रयोगकर्तासम्बन्धी नीतिहरू लागू गर्न सकिन्छ</translation> @@ -255,6 +256,7 @@ <translation id="7990085102929105708">Google Pay मा भएका भुक्तानी विधि र ठेगानाहरू इन्क्रिप्ट गरिने छैनन्। Chromium को ब्राउजिङ हिस्ट्री सिंक गरिने छैन। तपाईंको पासफ्रेज भएका व्यक्ति मात्र इन्क्रिप्ट गरिएको जानकारी पढ्न सक्छन्। उक्त पासफ्रेज Google मा पठाइँदैन वा Google ले उक्त पासफ्रेज भण्डारण गरेर राख्दैन। तपाईंले आफ्नो पासफ्रेज बिर्सनुभयो वा तपाईं यो सेटिङ परिवर्तन गर्न चाहनुहुन्छ भने <ph name="BEGIN_LINK" />आफ्नो खातामा गएर Chromium को डेटा मेटाउनुहोस्<ph name="END_LINK" />।</translation> +<translation id="7994322153108931467">Chromium सम्बन्धी उपयोगी सुझावहरू प्राप्त गर्न iOS का सेटिङमा गई सूचना प्राप्त गर्ने सुविधा अन गर्नुहोस्।</translation> <translation id="7995166854192397899">सुझावहरू तपाईंले अन्य डिभाइसमा ब्राउजर प्रयोग गरी गरेका क्रियाकलापमा आधारित हुन्छन्। सुझावहरू प्राप्त गर्न तपाईंका सबै डिभाइसहरूको Chromium मा साइन इन गर्नुहोस्।</translation> <translation id="800195749539500647">Chromium बाट बढीभन्दा बढी फाइदा लिनुहोस्</translation> <translation id="8013573822802650211">आफूले Chromium प्रयोग गर्ने सबै डिभाइसमा खोलिएका ट्याबहरू हेर्न ती सबै डिभाइसमा साइन इन गर्नुहोस्</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_nl.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_nl.xtb index 998109a..1edf826 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_nl.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_nl.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium voert elke dag automatisch de Veiligheidscheck uit om je te beschermen tegen onder andere gegevenslekken en onveilige websites. Je vindt meer informatie over de Veiligheidscheck in Instellingen.</translation> <translation id="3855938650519180865">Nieuw in Chromium</translation> <translation id="3886689467633467988">Log in op deze site en bij Chromium om onder andere je bookmarks op al je apparaten te gebruiken.</translation> +<translation id="3904484643286601695">Je kunt je selecties op elk moment updaten in de Chromium-instellingen.</translation> <translation id="394413318816989199">Versleuteling van wachtwoordzinnen omvat geen betaalmethoden en adressen. Als je deze instelling wilt wijzigen, <ph name="BEGIN_LINK" />wis je de Chromium-gegevens in je account<ph name="END_LINK" />.</translation> @@ -204,6 +205,7 @@ Alleen iemand met je wachtwoordzin kan je versleutelde gegevens lezen. De wachtwoordzin wordt niet gestuurd naar of opgeslagen door Google. Als je je wachtwoordzin vergeet of deze instelling wilt wijzigen, <ph name="BEGIN_LINK" />wis je de Chromium-gegevens in je account<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium is nu nog beter! Er is een nieuwe versie beschikbaar.</translation> +<translation id="6433172051771630690">Tips om het maximale uit Chromium te halen.</translation> <translation id="6502321914804101924">Je bent uitgelogd bij Chromium</translation> <translation id="6563921047760808519">Meer informatie over <ph name="BEGIN_LINK" />hoe Chromium je gegevens privé houdt<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium ondersteunt nu gebruikersbeleid voor je beheerde account</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">Betaalmethoden en adressen van Google Pay worden niet versleuteld. De browsegeschiedenis in Chromium wordt niet gesynchroniseerd. Alleen iemand met je wachtwoordzin kan je versleutelde gegevens lezen. De wachtwoordzin wordt niet gestuurd naar of opgeslagen door Google. Als je je wachtwoordzin vergeet of deze instelling wilt wijzigen, <ph name="BEGIN_LINK" />wis je de Chromium-gegevens in je account<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Zet meldingen aan via de iOS-instellingen om nuttige Chromium-tips te krijgen.</translation> <translation id="7995166854192397899">Suggesties zijn gebaseerd op je browse-activiteit op je andere apparaten. Log op al je apparaten in bij Chromium om suggesties te krijgen.</translation> <translation id="800195749539500647">Het maximale uit Chromium halen</translation> <translation id="8013573822802650211">Log in op al je apparaten om je tabbladen te bekijken vanaf elk apparaat waarop je Chromium gebruikt</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_no.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_no.xtb index 10ab9ac..e410ee4b 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_no.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_no.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium kjører sikkerhetssjekken automatisk hver dag for å beskytte deg mot databrudd, utrygge nettsteder med mer. Du kan finne ut mer om sikkerhetssjekken i innstillingene.</translation> <translation id="3855938650519180865">Dette er nytt i Chromium</translation> <translation id="3886689467633467988">Logg på dette nettstedet og Chromium for å få bokmerkene dine med mer på alle enhetene dine.</translation> +<translation id="3904484643286601695">Du kan når som helst oppdatere valgene dine i Chromium-innstillingene.</translation> <translation id="394413318816989199">Kryptering med passordfrase inkluderer ikke betalingsmåter eller adresser. For å endre denne innstillingen, <ph name="BEGIN_LINK" />slett Chromium-dataene i kontoen din<ph name="END_LINK" />.</translation> @@ -204,6 +205,7 @@ Bare personer som har passordfrasen din, kan lese de krypterte dataene. Passordfrasen blir verken sendt til eller lagret av Google. Hvis du glemmer passordfrasen eller vil endre denne innstillingen, kan du <ph name="BEGIN_LINK" />slette Chromium-dataene i kontoen din<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium har blitt enda bedre. En ny versjon er nå tilgjengelig.</translation> +<translation id="6433172051771630690">Tips for å få mest mulig ut av Chromium.</translation> <translation id="6502321914804101924">Chromium er logget av</translation> <translation id="6563921047760808519">Finn ut mer om <ph name="BEGIN_LINK" />hvordan Chromium holder dataene dine private<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium støtter nå brukerinnstillinger for den administrerte kontoen din</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">Betalingsmåter og adresser fra Google Pay krypteres ikke. Nettleserloggen fra Chromium synkroniseres ikke. Bare personer som har passordfrasen din, kan lese de krypterte dataene. Passordfrasen blir verken sendt til eller lagret av Google. Hvis du glemmer passordfrasen eller vil endre denne innstillingen, kan du <ph name="BEGIN_LINK" />slette Chromium-dataene i kontoen din<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">For å få nyttige Chromium-tips, slå på varsler i iOS-innstillingene.</translation> <translation id="7995166854192397899">Forslagene er basert på nettleseraktiviteten din på de andre enhetene dine. For å få forslag, logg på Chromium på alle enhetene dine.</translation> <translation id="800195749539500647">Få mest mulig ut av Chromium</translation> <translation id="8013573822802650211">For å se fanene dine overalt hvor du bruker Chromium, logg på alle enhetene dine</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_pa.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_pa.xtb index 942ba9f..7b79ef3 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_pa.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_pa.xtb
@@ -204,6 +204,7 @@ ਸਿਰਫ਼ ਤੁਹਾਡੇ ਪਾਸਫਰੇਜ਼ ਨਾਲ ਹੀ ਕੋਈ ਤੁਹਾਡੇ ਇਨਕ੍ਰਿਪਟਡ ਡਾਟੇ ਨੂੰ ਪੜ੍ਹ ਸਕਦਾ ਹੈ। ਪਾਸਫਰੇਜ਼ Google ਨੂੰ ਨਹੀਂ ਭੇਜਿਆ ਜਾਂਦਾ ਜਾਂ ਇਸ ਵੱਲੋਂ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ। ਜੇ ਤੁਸੀਂ ਆਪਣਾ ਪਾਸਫਰੇਜ਼ ਭੁੱਲ ਜਾਂਦੇ ਹੋ ਜਾਂ ਇਸ ਸੈਟਿੰਗ ਨੂੰ ਬਦਲਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ <ph name="BEGIN_LINK" />ਆਪਣੇ ਖਾਤੇ ਵਿੱਚ Chromium ਡਾਟੇ ਨੂੰ ਕਲੀਅਰ ਕਰੋ<ph name="END_LINK" />।</translation> <translation id="6424492062988593837">Chromium ਬਿਹਤਰ ਬਣ ਗਿਆ ਹੈ! ਇੱਕ ਨਵਾਂ ਵਰਜਨ ਉਪਲਬਧ ਹੈ।</translation> +<translation id="6433172051771630690">Chromium ਦਾ ਵੱਧ ਤੋਂ ਵੱਧ ਲਾਹਾ ਲੈਣ ਸੰਬੰਧੀ ਨੁਕਤੇ।</translation> <translation id="6502321914804101924">Chromium ਸਾਈਨ-ਆਊਟ ਕੀਤਾ ਗਿਆ ਹੈ</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium ਤੁਹਾਡੇ ਡਾਟੇ ਨੂੰ ਨਿੱਜੀ ਕਿਵੇਂ ਰੱਖਦਾ ਹੈ<ph name="END_LINK" /> ਇਸ ਬਾਰੇ ਹੋਰ ਜਾਣੋ</translation> <translation id="6625409903340039086">Chromium ਹੁਣ ਤੁਹਾਡੇ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਖਾਤੇ ਲਈ ਵਰਤੋਂਕਾਰ ਨੀਤੀਆਂ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay ਦੀਆਂ ਭੁਗਤਾਨ ਵਿਧੀਆਂ ਅਤੇ ਪਤਿਆਂ ਨੂੰ ਇਨਕ੍ਰਿਪਟ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ। Chromium ਦੇ ਬ੍ਰਾਊਜ਼ਿੰਗ ਇਤਿਹਾਸ ਨੂੰ ਸਿੰਕ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ। ਸਿਰਫ਼ ਤੁਹਾਡੇ ਪਾਸਫਰੇਜ਼ ਨਾਲ ਹੀ ਕੋਈ ਤੁਹਾਡੇ ਇਨਕ੍ਰਿਪਟਡ ਡਾਟੇ ਨੂੰ ਪੜ੍ਹ ਸਕਦਾ ਹੈ। ਪਾਸਫਰੇਜ਼ Google ਨੂੰ ਨਹੀਂ ਭੇਜਿਆ ਜਾਂਦਾ ਜਾਂ ਇਸ ਵੱਲੋਂ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ। ਜੇ ਤੁਸੀਂ ਆਪਣਾ ਪਾਸਫਰੇਜ਼ ਭੁੱਲ ਜਾਂਦੇ ਹੋ ਜਾਂ ਇਸ ਸੈਟਿੰਗ ਨੂੰ ਬਦਲਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ <ph name="BEGIN_LINK" />ਆਪਣੇ ਖਾਤੇ ਵਿੱਚ Chromium ਡਾਟੇ ਨੂੰ ਕਲੀਅਰ ਕਰੋ<ph name="END_LINK" />।</translation> +<translation id="7994322153108931467">ਲਾਹੇਵੰਦ Chromium ਨੁਕਤੇ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਆਪਣੀਆਂ iOS ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ।</translation> <translation id="7995166854192397899">ਸੁਝਾਅ ਤੁਹਾਡੇ ਹੋਰ ਡੀਵਾਈਸਾਂ 'ਤੇ ਤੁਹਾਡੀ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਰਗਰਮੀ 'ਤੇ ਆਧਾਰਿਤ ਹਨ। ਸੁਝਾਅ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਆਪਣੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ 'ਤੇ Chromium ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰੋ।</translation> <translation id="800195749539500647">Chromium ਦਾ ਵੱਧ ਤੋਂ ਵੱਧ ਲਾਹਾ ਲਓ</translation> <translation id="8013573822802650211">ਜਿਸ ਡੀਵਾਈਸ 'ਤੇ ਵੀ ਤੁਸੀਂ Chromium ਵਰਤਦੇ ਹੋ, ਉੱਥੇ ਆਪਣੀਆਂ ਟੈਬਾਂ ਦੇਖਣ ਲਈ ਸਾਈਨ-ਇਨ ਕਰੋ</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_pt-BR.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_pt-BR.xtb index 07e4f4f..78e03a6d 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_pt-BR.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_pt-BR.xtb
@@ -204,6 +204,7 @@ Só uma pessoa com sua senha longa pode ler seus dados criptografados. Essa senha longa não é enviada ao Google nem armazenada por ele. Se você esquecer a senha longa ou quiser mudar essa configuração, <ph name="BEGIN_LINK" />limpe os dados do Chromium na sua conta<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">O Chromium ficou ainda melhor! Uma nova versão está disponível.</translation> +<translation id="6433172051771630690">Dicas para aproveitar o Chromium ao máximo.</translation> <translation id="6502321914804101924">A conta foi desconectada do Chromium</translation> <translation id="6563921047760808519">Saiba mais sobre <ph name="BEGIN_LINK" />como o Chromium mantém a privacidade dos seus dados<ph name="END_LINK" /></translation> <translation id="6625409903340039086">O Chromium agora tem suporte a políticas do usuário na sua conta gerenciada</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">As formas de pagamento e os endereços do Google Pay não serão criptografados. O histórico de navegação do Chromium não será sincronizado. Só uma pessoa com sua senha longa pode ler seus dados criptografados. Essa senha longa não é enviada ao Google nem armazenada por ele. Se você esquecer a senha longa ou quiser mudar essa configuração, <ph name="BEGIN_LINK" />limpe os dados do Chromium na sua conta<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Para receber dicas úteis sobre o Chromium, ative as notificações nos ajustes do iOS.</translation> <translation id="7995166854192397899">As sugestões são baseadas na sua atividade de navegação em outros dispositivos. Para receber sugestões, faça login no Chromium em todos os seus dispositivos.</translation> <translation id="800195749539500647">Aproveite o Chromium ao máximo</translation> <translation id="8013573822802650211">Para acessar suas guias em qualquer lugar onde você usar o Chromium, faça login em todos os seus dispositivos</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ro.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ro.xtb index f93aace..c8deff81 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ro.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ro.xtb
@@ -204,6 +204,7 @@ Numai un utilizator care deține expresia ta de acces îți poate citi datele criptate. Expresia de acces nu este trimisă la sau stocată de Google. Dacă uiți expresia de acces sau dorești să modifici această setare, <ph name="BEGIN_LINK" />șterge datele Chromium din cont<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium a devenit și mai bun! Este disponibilă o nouă versiune.</translation> +<translation id="6433172051771630690">Sfaturi pentru a profita din plin de Chromium.</translation> <translation id="6502321914804101924">Te-ai deconectat de la Chromium</translation> <translation id="6563921047760808519">Află mai multe despre <ph name="BEGIN_LINK" />cum îți păstrează Chromium datele private<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium acceptă acum politicile privind utilizatorii pentru contul tău gestionat</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Metodele de plată și adresele din Google Pay nu vor fi criptate. Istoricul de navigare din Chromium nu se va sincroniza. Numai un utilizator care deține expresia ta de acces îți poate citi datele criptate. Expresia de acces nu este trimisă la sau stocată de Google. Dacă uiți expresia de acces sau dorești să modifici această setare, <ph name="BEGIN_LINK" />șterge datele Chromium din cont<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Pentru a primi sfaturi utile privind Chromium, activează notificările din setările iOS.</translation> <translation id="7995166854192397899">Sugestiile se bazează pe activitatea de navigare de pe celelalte dispozitive. Pentru a primi sugestii, conectează-te la Chromium pe toate dispozitivele.</translation> <translation id="800195749539500647">Profită din plin de Chromium</translation> <translation id="8013573822802650211">Conectează-te pe toate dispozitivele ca să vezi toate filele tale deschise în Chromium</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_si.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_si.xtb index f12f765..5b19b8b 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_si.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_si.xtb
@@ -204,6 +204,7 @@ ඔබේ සංකේතිත දත්ත කියවිය හැක්කේ ඔබේ මුර වැකිකඩ සහිත කෙනෙකුට පමණි. මුර වැකිකඩ Google වෙත යවන්නේ හෝ ගබඩා කරන්නේ නැත. ඔබට ඔබේ මුර වැකිකඩ අමතක වුවහොත් හෝ මෙම සැකසීම වෙනස් කිරීමට අවශ්ය නම් <ph name="BEGIN_LINK" />ඔබේ ගිණුම තුළ ඇති Chromium දත්ත හිස් කරන්න<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium වඩා යහපත් විය. නව අනුවාදයක් තිබේ.</translation> +<translation id="6433172051771630690">Chromium වෙතින් උපරිම ප්රයෝජන ගැනීම සඳහා ඉඟි.</translation> <translation id="6502321914804101924">Chromium වරනය වී ඇත</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium ඔබේ දත්ත පෞද්ගලිකව තබා ගන්නා ආකාරය<ph name="END_LINK" /> පිළිබඳව තව දැන ගන්න</translation> <translation id="6625409903340039086">Chromium දැන් ඔබගේ කළමනාකරණය කළ ගිණුම සඳහා පරිශීලක ප්රතිපත්තිවලට සහාය දක්වයි</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay වෙතින් ගෙවීම් ක්රම සහ ලිපින සංකේතනය නොකෙරේ. Chromium වෙතින් බ්රවුස් කිරීමේ ඉතිහාසය සමමුහූර්ත නොවේ. ඔබේ සංකේතිත දත්ත කියවිය හැක්කේ ඔබේ මුර වැකිකඩ සහිත කෙනෙකුට පමණි. මුර වැකිකඩ Google වෙත යවන්නේ හෝ ගබඩා කරන්නේ නැත. ඔබට ඔබේ මුර වැකිකඩ අමතක වුවහොත් හෝ මෙම සැකසීම වෙනස් කිරීමට අවශ්ය නම් <ph name="BEGIN_LINK" />ඔබේ ගිණුම තුළ ඇති Chromium දත්ත හිස් කරන්න<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">ප්රයෝජනවත් Chromium ඉඟි ලබා ගැනීමට, ඔබේ iOS සැකසීම් තුළ දැනුම්දීම් සක්රීය කරන්න.</translation> <translation id="7995166854192397899">යෝජනා ඔබේ අනෙකුත් උපාංගවල ඔබේ බ්රවුස් කිරීමේ ක්රියාකාරකම් මත පදනම් වේ. යෝජනා ලබා ගැනීම සඳහා, ඔබේ සියලු උපාංග මත Chromium වෙත පුරන්න.</translation> <translation id="800195749539500647">Chromium වෙතින් උපරිම ඵලය ලබන්න</translation> <translation id="8013573822802650211">ඔබ Chromium භාවිත කරන ඕනෑම ස්ථානයක සිට ඔබේ ටැබ බැලීමට, ඔබේ සියලු උපාංගවල පුරන්න</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_sl.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_sl.xtb index 0a9a697..1318994c 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_sl.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_sl.xtb
@@ -204,6 +204,7 @@ Vaše šifrirane podatke lahko bere samo oseba, ki ima vaše geslo. Geslo ni poslano Googlu in ga Google ne hrani. Če pozabite geslo ali želite to nastavitev spremeniti, <ph name="BEGIN_LINK" />izbrišite podatke iz Chromiuma v računu<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium je izboljšan! Na voljo je nova različica.</translation> +<translation id="6433172051771630690">Nasveti, kako najbolje izkoristiti Chromium.</translation> <translation id="6502321914804101924">Chromium je odjavljen</translation> <translation id="6563921047760808519">Preberite več o tem, <ph name="BEGIN_LINK" />kako Chromium zagotavlja zasebnost vaših podatkov<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium zdaj podpira uporabniške pravilnike za vaš upravljani račun</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Plačilna sredstva in naslovi iz Googla Pay ne bodo šifrirani. Zgodovina brskanja v Chromiumu se ne bo sinhronizirala. Vaše šifrirane podatke lahko bere samo oseba, ki ima vaše geslo. Geslo ni poslano Googlu in ga Google ne hrani. Če pozabite geslo ali želite to nastavitev spremeniti, <ph name="BEGIN_LINK" />izbrišite podatke iz Chromiuma v računu<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Če želite prejemati uporabne nasvete za Chromium, v nastavitvah sistema iOS vklopite obvestila.</translation> <translation id="7995166854192397899">Predlogi temeljijo na vaši dejavnosti brskanja v drugih napravah. Če želite prejemati predloge, se v vseh napravah prijavite v Chromium.</translation> <translation id="800195749539500647">Kar najbolje izkoristite Chromium</translation> <translation id="8013573822802650211">Če si želite ogledati zavihke iz naprav, v katerih uporabljate Chromium, se prijavite v vseh napravah</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_sr-Latn.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_sr-Latn.xtb index 10435d0..46253cbf 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_sr-Latn.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_sr-Latn.xtb
@@ -204,6 +204,7 @@ Samo neko ko ima pristupnu frazu može da čita šifrovane podatke. Pristupna fraza se ne šalje Google-u niti se čuva na Google-u. Ako zaboravite pristupnu frazu ili želite da promenite ovo podešavanje, <ph name="BEGIN_LINK" />obrišite Chromium podatke na nalogu<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium je upravo postao bolji! Dostupna je nova verzija.</translation> +<translation id="6433172051771630690">Saveti kako da na najbolji način koristite Chromium.</translation> <translation id="6502321914804101924">Chromium je odjavljen</translation> <translation id="6563921047760808519">Saznajte više o tome <ph name="BEGIN_LINK" />kako Chromium štiti privatnost podataka<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium sada podržava smernice za korisnika za upravljani nalog</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Načini plaćanja i adrese iz Google Pay-a se neće šifrovati. Istorija pregledanja iz Chromium-a se neće sinhronizovati. Samo neko ko ima pristupnu frazu može da čita šifrovane podatke. Pristupna fraza se ne šalje Google-u niti se čuva na Google-u. Ako zaboravite pristupnu frazu ili želite da promenite ovo podešavanje, <ph name="BEGIN_LINK" />obrišite Chromium podatke na nalogu<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Da biste dobijali korisne savete za Chromium, uključite obaveštenja u podešavanjima iOS-a.</translation> <translation id="7995166854192397899">Predlozi su zasnovani na aktivnostima pregledanja na drugim uređajima. Da biste dobijali predloge, prijavite se u Chromium na svim uređajima.</translation> <translation id="800195749539500647">Koristite Chromium na najbolji način</translation> <translation id="8013573822802650211">Da biste videli kartice na bilo kojem uređaju na kom koristite Chromium, prijavite se na svim uređajima</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_sr.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_sr.xtb index 7698c6e7..5ee38375 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_sr.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_sr.xtb
@@ -204,6 +204,7 @@ Само неко ко има приступну фразу може да чита шифроване податке. Приступна фраза се не шаље Google-у нити се чува на Google-у. Ако заборавите приступну фразу или желите да промените ово подешавање, <ph name="BEGIN_LINK" />обришите Chromium податке на налогу<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium је управо постао бољи! Доступна је нова верзија.</translation> +<translation id="6433172051771630690">Савети како да на најбољи начин користите Chromium.</translation> <translation id="6502321914804101924">Chromium је одјављен</translation> <translation id="6563921047760808519">Сазнајте више о томе <ph name="BEGIN_LINK" />како Chromium штити приватност података<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium сада подржава смернице за корисника за управљани налог</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Начини плаћања и адресе из Google Pay-а се неће шифровати. Историја прегледања из Chromium-а се неће синхронизовати. Само неко ко има приступну фразу може да чита шифроване податке. Приступна фраза се не шаље Google-у нити се чува на Google-у. Ако заборавите приступну фразу или желите да промените ово подешавање, <ph name="BEGIN_LINK" />обришите Chromium податке на налогу<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Да бисте добијали корисне савете за Chromium, укључите обавештења у подешавањима iOS-а.</translation> <translation id="7995166854192397899">Предлози су засновани на активностима прегледања на другим уређајима. Да бисте добијали предлоге, пријавите се у Chromium на свим уређајима.</translation> <translation id="800195749539500647">Користите Chromium на најбољи начин</translation> <translation id="8013573822802650211">Да бисте видели картице на било којем уређају на ком користите Chromium, пријавите се на свим уређајима</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_te.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_te.xtb index 0f217a5..5b38b9e 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_te.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_te.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">డేటా ఉల్లంఘనలు, సురక్షితం కాని వెబ్సైట్లు, మరిన్నింటి నుండి మిమ్మల్ని సురక్షితంగా ఉంచడానికి Chromium ప్రతిరోజూ సేఫ్టీ చెక్ను ఆటోమేటిక్గా అమలు చేస్తుంది. మీరు సెట్టింగ్లలో సేఫ్టీ చెక్ గురించి మరింత తెలుసుకోవచ్చు.</translation> <translation id="3855938650519180865">Chromiumలో కొత్త అప్డేట్లు ఏంటి</translation> <translation id="3886689467633467988">మీ పరికరాలన్నింటిలో మీ బుక్మార్క్లతో పాటు మరిన్నింటిని పొందడానికి ఈ సైట్కు, Chromiumకు సైన్ ఇన్ చేయండి.</translation> +<translation id="3904484643286601695">మీరు Chromium సెట్టింగ్లలో ఎప్పుడైనా మీ ఎంపికలను అప్డేట్ చేయవచ్చు.</translation> <translation id="394413318816989199">రహస్య పదబంధ ఎన్క్రిప్షన్లో పేమెంట్ ఆప్షన్లు, అడ్రస్లు ఉండవు. ఈ సెట్టింగ్ను మార్చడానికి, <ph name="BEGIN_LINK" />మీ ఖాతాలోని Chromium డేటాను తీసివేయండి<ph name="END_LINK" />.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_th.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_th.xtb index 57dea78..d25ee2e6 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_th.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_th.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium เรียกใช้การตรวจสอบความปลอดภัยโดยอัตโนมัติทุกวันเพื่อช่วยให้คุณปลอดภัยจากการละเมิดข้อมูล เว็บไซต์ที่เป็นอันตราย และอื่นๆ ดูข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบความปลอดภัยได้ในการตั้งค่า</translation> <translation id="3855938650519180865">มีอะไรใหม่ใน Chromium</translation> <translation id="3886689467633467988">ลงชื่อเข้าใช้เว็บไซต์นี้และ Chromium เพื่อรับบุ๊กมาร์กและอื่นๆ ในอุปกรณ์ทุกเครื่อง</translation> +<translation id="3904484643286601695">คุณอัปเดตสิ่งที่เลือกไว้ได้ทุกเมื่อในการตั้งค่า Chromium</translation> <translation id="394413318816989199">การเข้ารหัสด้วยรหัสผ่านจะไม่รวมวิธีการชำระเงินและที่อยู่ หากต้องการเปลี่ยนการตั้งค่านี้ ให้<ph name="BEGIN_LINK" />ล้างข้อมูล Chromium ในบัญชี<ph name="END_LINK" /></translation> @@ -204,6 +205,7 @@ เฉพาะผู้ที่มีรหัสผ่านของคุณเท่านั้นที่จะอ่านข้อมูลที่เข้ารหัสได้ Google จะไม่ได้รับหรือจัดเก็บรหัสผ่านดังกล่าว หากลืมรหัสผ่านหรือต้องการเปลี่ยนการตั้งค่านี้ ให้<ph name="BEGIN_LINK" />ล้างข้อมูล Chromium ในบัญชี<ph name="END_LINK" /></translation> <translation id="6424492062988593837">Chromium พัฒนาใหม่! มีรุ่นใหม่ให้ใช้งานแล้ว</translation> +<translation id="6433172051771630690">เคล็ดลับในการรับประโยชน์สูงสุดจาก Chromium</translation> <translation id="6502321914804101924">ออกจากระบบ Chromium แล้ว</translation> <translation id="6563921047760808519">ดูข้อมูลเพิ่มเติมเกี่ยวกับ<ph name="BEGIN_LINK" />วิธีที่ Chromium ช่วยรักษาข้อมูลของคุณให้เป็นส่วนตัว<ph name="END_LINK" /></translation> <translation id="6625409903340039086">ตอนนี้ Chromium รองรับนโยบายผู้ใช้สำหรับบัญชีที่จัดการแล้ว</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">ที่อยู่และวิธีการชำระเงินจาก Google Pay จะไม่มีการเข้ารหัส ประวัติการท่องเว็บจาก Chromium จะไม่ซิงค์ เฉพาะผู้ที่มีรหัสผ่านของคุณเท่านั้นที่จะอ่านข้อมูลที่เข้ารหัสได้ Google จะไม่ได้รับหรือจัดเก็บรหัสผ่านดังกล่าว หากลืมรหัสผ่านหรือต้องการเปลี่ยนการตั้งค่านี้ ให้<ph name="BEGIN_LINK" />ล้างข้อมูล Chromium ในบัญชี<ph name="END_LINK" /></translation> +<translation id="7994322153108931467">หากต้องการรับเคล็ดลับที่มีประโยชน์เกี่ยวกับ Chromium ให้เปิดการแจ้งเตือนในการตั้งค่า iOS</translation> <translation id="7995166854192397899">คำแนะนำต่างๆ จะอิงตามกิจกรรมการท่องเว็บในอุปกรณ์อื่นๆ ของคุณ หากต้องการรับคำแนะนำ ให้ลงชื่อเข้าใช้ Chromium ในอุปกรณ์ทั้งหมดของคุณ</translation> <translation id="800195749539500647">รับประโยชน์สูงสุดจาก Chromium</translation> <translation id="8013573822802650211">ลงชื่อเข้าใช้ในอุปกรณ์ทุกเครื่องเพื่อดูแท็บที่เปิดไว้จากอุปกรณ์ที่คุณใช้ Chromium</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_uk.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_uk.xtb index 049f625..27fb7a3 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_uk.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_uk.xtb
@@ -204,6 +204,7 @@ Зашифровані дані може читати лише користувач, який знає вашу парольну фразу. Парольна фраза не надсилається й не зберігається в Google. Якщо ви забули парольну фразу або хочете змінити це налаштування, <ph name="BEGIN_LINK" />очистьте дані Chromium у своєму обліковому записі<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium став ще кращим! Доступна нова версія.</translation> +<translation id="6433172051771630690">Поради з ефективного використання Chromium.</translation> <translation id="6502321914804101924">Ви вийшли з Chromium</translation> <translation id="6563921047760808519">Докладніше про те, <ph name="BEGIN_LINK" />як Chromium захищає ваші дані<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Тепер Chromium підтримує правила для користувачів, які можуть застосовуватися до вашого керованого облікового запису</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Способи оплати й адреси з Google Pay не шифруватимуться. Історія веб-перегляду з Chromium не синхронізуватиметься. Зашифровані дані може читати лише користувач, який знає вашу парольну фразу. Парольна фраза не надсилається й не зберігається в Google. Якщо ви забули парольну фразу або хочете змінити це налаштування, <ph name="BEGIN_LINK" />очистьте дані Chromium у своєму обліковому записі<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Щоб отримувати корисні поради щодо Chromium, увімкніть сповіщення в налаштуваннях iOS.</translation> <translation id="7995166854192397899">Підказки створюються на основі ваших дій у веб-переглядачі на інших пристроях. Щоб отримувати підказки, увійдіть у Chromium на всіх своїх пристроях.</translation> <translation id="800195749539500647">Користуйтеся всіма можливостями Chromium</translation> <translation id="8013573822802650211">Щоб переглядати свої вкладки Chromium на будь-якому пристрої, увійдіть на ньому в обліковий запис</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ur.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ur.xtb index 9f91b63..3d00584 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_ur.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ur.xtb
@@ -204,6 +204,7 @@ صرف پاس فریز کا حامل شخص ہی آپ کے مرموز کردہ ڈیٹا کو پڑھ سکتا ہے۔ پاس فریز Google کو نہیں بھیجا جاتا، نہ ہی وہ اسے اسٹور کرتا ہے۔ اگر آپ اپنا پاس فریز بھول جاتے ہیں یا اس ترتیب کو تبدیل کرنا چاہتے ہیں تو <ph name="BEGIN_LINK" />اپنے اکاؤنٹ میں موجود Chromium ڈیٹا کو صاف کریں<ph name="END_LINK" />۔</translation> <translation id="6424492062988593837">Chromium اور بھی بہتر ہوگیا ہے! ایک نیا ورژن دستیاب ہے۔</translation> +<translation id="6433172051771630690">Chromium سے زیادہ سے زیادہ فائدہ اٹھانے کے لیے تجاویز۔</translation> <translation id="6502321914804101924">Chromium سائن آؤٹ ہو گیا ہے</translation> <translation id="6563921047760808519">اس بارے میں مزید جانیں کہ <ph name="BEGIN_LINK" />Chromium آپ کے ڈیٹا کو کس طرح نجی رکھتا ہے<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium اب آپ کے نظم کردہ اکاؤنٹ کے لیے صارف کی پالیسیوں کو سپورٹ کرتا ہے</translation> @@ -256,6 +257,7 @@ <translation id="7990085102929105708">Google Pay سے ادائیگی کے طریقے اور پتے اینکرپٹ نہیں ہوں گے۔ Chromium سے براؤزنگ کی سرگزشت مطابقت پذیر نہیں ہوگی۔ صرف پاس فریز کا حامل شخص ہی آپ کے مرموز کردہ ڈیٹا کو پڑھ سکتا ہے۔ پاس فریز Google کو نہیں بھیجا جاتا، نہ ہی وہ اسے اسٹور کرتا ہے۔ اگر آپ اپنا پاس فریز بھول جاتے ہیں یا اس ترتیب کو تبدیل کرنا چاہتے ہیں تو <ph name="BEGIN_LINK" />اپنے اکاؤنٹ میں موجود Chromium ڈیٹا کو صاف کریں<ph name="END_LINK" />۔</translation> +<translation id="7994322153108931467">Chromium کی کارآمد تجاویز حاصل کرنے کے لیے، اپنی iOS کی ترتیبات میں اطلاعات کو آن کریں۔</translation> <translation id="7995166854192397899">تجاویز آپ کے دیگر آلات پر آپ کی براؤزنگ سرگرمی پر مبنی ہیں۔ تجاویز حاصل کرنے کے لیے، اپنے تمام آلات پر Chromium میں سائن ان کریں۔</translation> <translation id="800195749539500647">Chromium سے زیادہ سے زیادہ فائدہ اٹھائیں</translation> <translation id="8013573822802650211">اپنے ٹیبز کو دیکھنے کے لئے جہاں بھی آپ Chromium استعمال کرتے ہیں، اپنے تمام آلات پر سائن ان کریں</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_uz.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_uz.xtb index a2f3085..76848ae 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_uz.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_uz.xtb
@@ -40,7 +40,7 @@ <translation id="2054703085270098503">Chromium bilan himoyalaning</translation> <translation id="2098023844024447022">Oxirgi varagʻimni Chromiumda och</translation> <translation id="2109439615198500433">Chromium maslahati</translation> -<translation id="2147210759439165826">Chromium masalahatlarini olish uchun kontentni varaqlang.</translation> +<translation id="2147210759439165826">Chromium maslahatlarini olish uchun kontentni varaqlang.</translation> <translation id="2168108852149185974">Ba’zi kengaytmalar Chromium brauzerini ishdan chiqaradi. O‘chirilishi kerak bo‘lgan kengaytmalar:</translation> <translation id="2178608107313874732">Chromium hozir kamerangizdan foydalana olmaydi.</translation> <translation id="2195025571279539885">Chromium har doim bu saytning <ph name="LANGUAGE_NAME" /> tilidagi sahifalarini tarjima qilishni taklif qilsinmi?</translation> @@ -99,6 +99,7 @@ <translation id="3833326979834193417">Chromium maʼlumotlarni oshkor qilish, xavfli saytlar va boshqalardan himoyalash uchun har kuni Xavfsizlik tekshiruvini bajaradi. Xavfsizlik tekshiruvi haqida batafsil axborotni Sozlamalardan olish mumkin.</translation> <translation id="3855938650519180865">Yangilangan Chromium</translation> <translation id="3886689467633467988">Bukmarklar va boshqalarni barcha qurilmalarda olish uchun bu sayt va Chromiumga Google hisobingizdan kiring.</translation> +<translation id="3904484643286601695">Tanlovlarni istalgan vaqt Chromium sozlamalari orqali yangilash mumkin.</translation> <translation id="394413318816989199">Kodli ibora bilan shifrlash ichiga toʻlov usullari va manzillar kirmaydi. Bu sozlamani oʻzgartirish uchun <ph name="BEGIN_LINK" />hisobingizda Chromium maʼlumotlarini tozalang<ph name="END_LINK" />.</translation> @@ -203,6 +204,7 @@ Shifrlangan maʼlumotlarni faqatgina kodli ibora yordamida oʻqish mumkin. Kodli ibora ulashilmaydi va Google serverlarida saqlanmaydi. Agar kodli iborani unutsangiz yoki bu sozlamani oʻzgartirmoqchi boʻlsangiz, <ph name="BEGIN_LINK" />hisobingizda Chromium maʼlumotlarini tozalang<ph name="END_LINK" />.</translation> <translation id="6424492062988593837">Chromium ancha yaxshilandi! Yangi versiya mavjud.</translation> +<translation id="6433172051771630690">Chromiumdan unumli foydalanish maslahatlari.</translation> <translation id="6502321914804101924">Chromium hisobidan chiqarildi</translation> <translation id="6563921047760808519"><ph name="BEGIN_LINK" />Chromium maʼlumotlaringizni qanday xavfsiz saqlashi<ph name="END_LINK" /> haqida batafsil</translation> <translation id="6625409903340039086">Chromium endi boshqariladigan hisobingiz uchun foydalanuvchi siyosatlarini qoʻllab-quvvatlaydi</translation> @@ -255,6 +257,7 @@ <translation id="7990085102929105708">Google Pay xizmatidagi toʻlov usullari va manzillar shifrlanmaydi. Chromium brauzer tarixi sinxronlanmaydi. Shifrlangan maʼlumotlarni faqatgina kodli ibora yordamida oʻqish mumkin. Kodli ibora ulashilmaydi va Google serverlarida saqlanmaydi. Agar kodli iborani unutsangiz yoki bu sozlamani oʻzgartirmoqchi boʻlsangiz, <ph name="BEGIN_LINK" />hisobingizda Chromium maʼlumotlarini tozalang<ph name="END_LINK" />.</translation> +<translation id="7994322153108931467">Chromium haqida tavsiyalar olish uchun iOS sozlamalari orqali bildirishnomalarni yoqing.</translation> <translation id="7995166854192397899">Tavsiyalar boshqa qurilmalardagi brauzer tarixi asosida tuziladi. Tavsiyalar olish uchun barcha qurilmalarda Chromium hisobiga kiring.</translation> <translation id="800195749539500647">Chromiumdan unumli foydalaning</translation> <translation id="8013573822802650211">Boshqa qurilmalardagi Chromium varaqlarini koʻrish uchun barcha qurilmalarda hisobingizga kiring</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_zh-HK.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_zh-HK.xtb index 3e2af17c..082badb2 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_zh-HK.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_zh-HK.xtb
@@ -25,7 +25,7 @@ <translation id="1617663976202781617">來自 Chromium Sync 的資料</translation> <translation id="1647558790457890304">Chromium 設定</translation> <translation id="164952285225495380">你已使用 Chromium 追蹤此包裹。</translation> -<translation id="1707458603865303524">隨時可以使用 Chromium 開啟訊息或其他應用程式中的連結。</translation> +<translation id="1707458603865303524">隨時使用 Chromium 開啟訊息或其他應用程式中的連結。</translation> <translation id="1722370509450468186">密碼將會儲存在您的帳戶 (<ph name="EMAIL" />) 中。</translation> <translation id="1736662517232558588">已清除 Chromium 的資料</translation> <translation id="1791845338122684020">開啟 Chromium 記錄頁面。</translation> @@ -98,8 +98,9 @@ <translation id="3805899903892079518">Chromium 沒有存取相片或影片的權限。請前往「iOS 設定」>「私隱」>「相片」開放權限。</translation> <translation id="3827545470516145620">此裝置即將啟用標準安全保護功能保護</translation> <translation id="3833326979834193417">Chromium 每日會自動執行「安全檢查」功能,避免資料外洩或不安全網站等。你可在「設定」中進一步瞭解「安全檢查」功能。</translation> -<translation id="3855938650519180865">Chromium 新功能</translation> +<translation id="3855938650519180865">Chromium 的新功能</translation> <translation id="3886689467633467988">登入此網站和 Chromium,即可在所有裝置上存取書籤及其他設定。</translation> +<translation id="3904484643286601695">你可隨時在 Chromium 設定中更新所選項目。</translation> <translation id="394413318816989199">密碼短語加密的資料不包括付款方法和地址。 如要變更此設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chromium 資料<ph name="END_LINK" />。</translation> @@ -163,7 +164,7 @@ <translation id="5688047395118852662">此資訊卡會建議您如何充分運用 Chromium 的功能。</translation> <translation id="5700709190537129682">Chromium 無法檢查密碼</translation> <translation id="5777187867430702742">Chromium 頁面</translation> -<translation id="584239279770005676">Chromium 提示:將 Chromium 設為預設瀏覽器</translation> +<translation id="584239279770005676">Chromium 提示:將 Chromium 設定為預設瀏覽器</translation> <translation id="584550191241316896">登入 Chromium</translation> <translation id="5889847953983052353">開啟時: <ph name="BEGIN_INDENT" /> • 可協助 Chromium 為使用者提供更優質的使用體驗。<ph name="END_INDENT" /> @@ -187,7 +188,7 @@ 1. 開啟「設定」 2. 輕按 [預設瀏覽器應用程式] 3. 選取 [Chromium]。</translation> -<translation id="6132149203299792222">登入 Google 帳戶就能同步處理密碼、書籤和其他資訊。</translation> +<translation id="6132149203299792222">登入 Google 帳戶就能同步處理密碼、書籤和其他資料。</translation> <translation id="6154098560469640583">隨時使用 Chromium 開啟訊息、文件和其他應用程式中的連結。</translation> <translation id="6170619162539716595">允許 Chromium 使用「Google 地圖」,為偵測到的地址提供路線和本地資訊。</translation> <translation id="6175967839221456271">分享 Chromium</translation> @@ -204,6 +205,7 @@ 只有知道密碼短語的使用者,才能讀取已加密的資料。系統不會將密碼短語傳送給 Google,Google 亦不會儲存密碼短語。如果忘記密碼短語或想變更此設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chromium 資料<ph name="END_LINK" />。</translation> <translation id="6424492062988593837">Chromium 現在更進一步!歡迎您升級使用新版本。</translation> +<translation id="6433172051771630690">可協助你充分運用 Chromium 的各項提示。</translation> <translation id="6502321914804101924">你已登出 Chromium</translation> <translation id="6563921047760808519">進一步瞭解 <ph name="BEGIN_LINK" />Chromium 如何確保你的資料保密<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium 現在支援受管帳戶的使用者政策</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">系統將不會加密你在 Google Pay 中的付款方法和地址,Chromium 上的瀏覽記錄將不會同步。 只有知道密碼短語的使用者,才能讀取已加密的資料。系統不會將密碼短語傳送給 Google,Google 亦不會儲存密碼短語。如果忘記密碼短語或想變更此設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chromium 資料<ph name="END_LINK" />。</translation> +<translation id="7994322153108931467">如要取得 Chromium 的實用提示,請在 iOS 設定中開啟通知功能。</translation> <translation id="7995166854192397899">系統會根據你在其他裝置的瀏覽活動提供建議。如要取得建議,請在所有裝置上登入 Chromium。</translation> <translation id="800195749539500647">充分運用 Chromium 的所有功能</translation> <translation id="8013573822802650211">如要在任何使用 Chromium 的裝置上查看分頁,請在所有裝置上登入</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_zh-TW.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_zh-TW.xtb index 9d58b264..d298604 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_zh-TW.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_zh-TW.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">Chromium 每天都會自動執行安全檢查,防範資料侵害或不安全網站等等。你可以前往「設定」進一步瞭解安全檢查功能。</translation> <translation id="3855938650519180865">Chromium 新功能</translation> <translation id="3886689467633467988">登入這個網站和 Chromium,即可在所有裝置上存取書籤及其他設定。</translation> +<translation id="3904484643286601695">你隨時可以在 Chromium 設定中更新所選項目。</translation> <translation id="394413318816989199">通關密語加密的資料不包括付款方式和地址。 如要變更這項設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chromium 資料<ph name="END_LINK" />。</translation> @@ -204,6 +205,7 @@ 只有知道通關密語的人才能讀取你的加密資料。系統不會將通關密語傳送給 Google,Google 也不會儲存通關密語。如果忘記通關密語或想要變更這項設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chromium 資料<ph name="END_LINK" />。</translation> <translation id="6424492062988593837">Chromium 現在變得更進步了!歡迎你升級使用新版本。</translation> +<translation id="6433172051771630690">可協助你充分運用 Chromium 的各項提示。</translation> <translation id="6502321914804101924">你已登出 Chromium</translation> <translation id="6563921047760808519">進一步瞭解 <ph name="BEGIN_LINK" />Chromium 如何保護你的資料隱私<ph name="END_LINK" /></translation> <translation id="6625409903340039086">Chromium 現在支援受管理帳戶的使用者政策</translation> @@ -256,6 +258,7 @@ <translation id="7990085102929105708">系統將不會加密你在 Google Pay 中的付款方式和地址,也不會同步 Chromium 中的瀏覽記錄。 只有知道通關密語的人才能讀取你的加密資料。系統不會將通關密語傳送給 Google,Google 也不會儲存通關密語。如果忘記通關密語或想要變更這項設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chromium 資料<ph name="END_LINK" />。</translation> +<translation id="7994322153108931467">如要取得 Chromium 的實用提示,請在 iOS 設定中開啟通知功能。</translation> <translation id="7995166854192397899">系統會根據你在其他裝置的瀏覽活動提供建議。如要取得建議,請在所有裝置上登入 Chromium。</translation> <translation id="800195749539500647">充分運用 Chromium 的各項功能</translation> <translation id="8013573822802650211">在你所有的裝置上登入帳戶後,不論從何處使用 Chromium 都能查看你的分頁</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 2c233f1..a41a46e 100644 --- a/ios/chrome/app/strings/resources/ios_chromium_strings_zu.xtb +++ b/ios/chrome/app/strings/resources/ios_chromium_strings_zu.xtb
@@ -100,6 +100,7 @@ <translation id="3833326979834193417">I-Chromium isebenzisa ngokuzenzakalelayo Ukuhlola Ukuphepha nsuku zonke ukuze ikugcine uphephile ekwephulweni kwesivumelwano sedatha, amawebhusayithi angaphephile nokuningi. Ungathola okwengeziwe mayelana Nokuhlolwa Kokuphepha ku-Amasethingi.</translation> <translation id="3855938650519180865">Yini entsha ku-Chromium</translation> <translation id="3886689467633467988">Ngena ngemvume kule sayithi naku-Chromium ukuze uthole amabhukhimakhi akho kanye nokuningi kuwo wonke amadivayisi akho.</translation> +<translation id="3904484643286601695">Ungabuyekeza okukhethile noma nini Kumasethingi e-Chromium.</translation> <translation id="394413318816989199">Ukubethelwa komushwana wokungena akubandakanyi izindlela zokukhokha namakheli. Ukuze ushintshe la masethingi, <ph name="BEGIN_LINK" />sula idatha ye-Chromium ku-akhawunti yakho<ph name="END_LINK" />.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_am.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_am.xtb index 733fe21..91559b14 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_am.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_am.xtb
@@ -77,6 +77,7 @@ <translation id="2702250627063295552">የንባብ ዝርዝር ንጥልን ወደ Chrome ያክሉ</translation> <translation id="2703746758996815929">አጋዥ የሆኑ የChromium ምክሮችን ለማግኘት፣ በiOS ቅንብሮችዎ ውስጥ ማሳወቂያዎችን ያብሩ።</translation> <translation id="2736805085127235148">አሁን ላይ በእርስዎ የመሣሪያ ቅንብሮች ውስጥ የChrome ማሳወቂያዎች ጠፍተዋል።</translation> +<translation id="2750626042242931740">ምርጫዎችዎን በማንኛውም ጊዜ በChromium ቅንብሮች ውስጥ ማዘመን ይችላሉ።</translation> <translation id="2767464022270041271">ምንም የተቀመጡ የይለፍ ቃላት የሉም። Google የይለፍ ቃል አስተዳዳሪ የይለፍ ቃላትዎን ሲያስቀምጡ ሊፈትሻቸው ይችላል።</translation> <translation id="2789947168960170215">የይለፍ ሐረግዎን ከረሱ ወይም ይህን ቅንብር መለወጥ ከፈለጉ፣ <ph name="BEGIN_LINK" />በመለያዎ ውስጥ ያለውን የChrome ውሂብ ያጽዱ<ph name="END_LINK" />።</translation> <translation id="2868822340714096138">Chrome ውስጥ የአሰሳ ውሂብን ያጽዱ</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb index 7f4f427..f954368 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">للخروج من حسابك على Google في جميع المواقع الإلكترونية، عليك <ph name="BEGIN_LINK" />تسجيل الخروج من Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">تعذّر على Chrome البحث عن تحديثات. يُرجى إعادة المحاولة لاحقًا.</translation> <translation id="2702250627063295552">إضافة عنصر "قائمة القراءة" إلى متصفِّح Chrome</translation> +<translation id="2703746758996815929">للحصول على نصائح مفيدة حول Chrome، يمكنك تفعيل الإشعارات في إعدادات أجهزة iOS.</translation> <translation id="2736805085127235148">إنّ إشعارات Chrome غير مفعَّلة حاليًا في إعدادات جهازك.</translation> <translation id="2767464022270041271">ما مِن كلمات مرور محفوظة. لا يستطيع "مدير كلمات المرور في Google" التأكد من كلمات المرور إلّا عند حفظها.</translation> <translation id="2789947168960170215">في حال نسيت عبارة المرور أو أردت تغيير هذه الإعدادات، يمكنك <ph name="BEGIN_LINK" />محو بيانات Chrome في حسابك<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ لتغيير هذه الإعدادات، يُرجى <ph name="BEGIN_LINK" />محو بيانات Chrome في حسابك<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">تعذَّر على "مدير كلمات المرور في Google" التأكد من جميع كلمات المرور. يُرجى إعادة المحاولة غدًا.</translation> <translation id="8865415417596392024">بيانات Chrome في حسابك</translation> +<translation id="8874688701962049679">نصائح حول الاستفادة إلى أقصى حدّ من Chrome</translation> <translation id="8891935667620843985">يمكنك فتح الروابط في Chrome تلقائيًا من خلال جعله تطبيق المتصفّح التلقائي.</translation> <translation id="8897749957032330183">يتم حفظ كلمات المرور في "مدير كلمات المرور في Google" على هذا الجهاز.</translation> <translation id="8949681853939555434">اختيار Chrome ليكون متصفِّحك التلقائي</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb index a54b389..5296213 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">আটাইবোৰ ৱেবছাইটত আপোনাৰ Google একাউণ্টৰ পৰা ছাইন আউট কৰিবলৈ <ph name="BEGIN_LINK" />Chromeৰ পৰা ছাইন আউট কৰক<ph name="END_LINK" />।</translation> <translation id="2695886661449553974">Chromeএ আপডে’টৰ বাবে পৰীক্ষা কৰিব নোৱাৰিলে। পাছত পুনৰ চেষ্টা কৰক।</translation> <translation id="2702250627063295552">Chromeত পঢ়াৰ সূচীৰ বস্তু যোগ দিয়ক</translation> +<translation id="2703746758996815929">Chromeৰ সহায়ক কিটিপ পাবলৈ আপোনাৰ iOSৰ ছেটিঙত জাননী অন কৰক।</translation> <translation id="2736805085127235148">আপোনাৰ ডিভাইচৰ ছেটিঙত বৰ্তমান Chromeৰ জাননী অফ কৰা আছে।</translation> +<translation id="2750626042242931740">আপুনি Chrome ছেটিঙত যিকোনো সময়তে আপোনাৰ বাছনিবোৰ আপডে’ট কৰিব পাৰে।</translation> <translation id="2767464022270041271">কোনো ছেভ কৰা পাছৱৰ্ড নাই। আপুনি নিজৰ পাছৱৰ্ডসমূহ ছেভ কৰিলে Google Password Managerএ সেইসমূহ পৰীক্ষা কৰিব পাৰে।</translation> <translation id="2789947168960170215">আপুনি যদি নিজৰ পাছফ্ৰে’জটো পাহৰিছে অথবা এই ছেটিংটো সলাব বিচাৰে, <ph name="BEGIN_LINK" />আপোনাৰ একাউণ্টৰ Chromeৰ ডেটা মচক<ph name="END_LINK" />।</translation> <translation id="2868822340714096138">Chromeত ব্ৰাউজিঙৰ ডেটা মচক</translation> @@ -297,6 +299,7 @@ এই ছেটিংটো সলনি কৰিবলৈ, <ph name="BEGIN_LINK" />আপোনাৰ একাউণ্টৰ Chromeৰ ডেটা মচক<ph name="END_LINK" />।</translation> <translation id="8857676124663337448">Google Password Managerএ আটাইবোৰ পাছৱৰ্ড পৰীক্ষা কৰিব নোৱাৰিলে। কাইলৈ পুনৰ চেষ্টা কৰক।</translation> <translation id="8865415417596392024">আপোনাৰ একাউণ্টত থকা Chromeৰ ডেটা</translation> +<translation id="8874688701962049679">Chromeৰ পৰা পাৰ্যমানে উপকৃত হোৱাৰ কিটিপ।</translation> <translation id="8891935667620843985">আপুনি Chromeক আপোনাৰ ডিফ’ল্ট ব্ৰাউজাৰ এপ্ বনাই তাত স্বয়ংক্ৰিয়ভাৱে লিংকসমূহ খুলিব পাৰে।</translation> <translation id="8897749957032330183">পাছৱৰ্ডসমূহ এই ডিভাইচটোত থকা Google Password Managerত ছেভ কৰা হয়</translation> <translation id="8949681853939555434">Chromeক আপোনাৰ ডিফ’ল্ট ব্ৰাউজাৰ হিচাপে ছেট কৰক</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_az.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_az.xtb index 669c0a9a..c423d06a 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_az.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_az.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Bütün vebsaytlarda Google Hesabınızdan çıxmaq üçün <ph name="BEGIN_LINK" />Chrome'dan çıxın<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome güncəlləmələri yoxlaya bilmədi. Sonra cəhd edin.</translation> <translation id="2702250627063295552">Oxu siyahısı elementini Chrome-a əlavə edin</translation> +<translation id="2703746758996815929">Faydalı Chrome məsləhətləri üçün iOS ayarlarında bildirişləri aktiv edin.</translation> <translation id="2736805085127235148">Hazırda Chrome bildirişləri cihaz ayarlarında deaktivdir.</translation> <translation id="2767464022270041271">Yadda saxlanmış parol yoxdur. Parollarınızı yadda saxladıqda Google Parol Meneceri onları yoxlaya bilər.</translation> <translation id="2789947168960170215">Parol ifadəsini unutsanız, yaxud bu ayarı dəyişmək istəsəniz, <ph name="BEGIN_LINK" />hesabda Chrome datasını silin<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Bu ayarı dəyişmək üçün <ph name="BEGIN_LINK" />hesabda Chrome datasını silin<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Parol Meneceri bütün parolları yoxlaya bilmədi. Sabah yenidən cəhd edin.</translation> <translation id="8865415417596392024">Hesabdakı Chrome datası</translation> +<translation id="8874688701962049679">Chrome-dan maksimum yararlanmaq üçün məsləhətlər.</translation> <translation id="8891935667620843985">Defolt Brauzer Tətbiqiniz etməklə, keçidləri Chrome'da avtomatik aça bilərsiniz.</translation> <translation id="8897749957032330183">Parollar bu cihazda Google Parol Menecerində saxlanılır.</translation> <translation id="8949681853939555434">Chrome-u defolt brauzer təyin edin</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_bs.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_bs.xtb index b274de5..2e66a6b 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_bs.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_bs.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">Da se odjavite s Google računa na svim web lokacijama, <ph name="BEGIN_LINK" />odjavite se iz Chromea<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome nije mogao provjeriti ima li ažuriranja. Pokušajte ponovo kasnije.</translation> <translation id="2702250627063295552">Dodavanje stavke na listu za čitanje u Chromeu</translation> +<translation id="2703746758996815929">Da dobijate korisne savjete za Chrome, uključite obavještenja u postavkama iOS-a.</translation> <translation id="2736805085127235148">Obavještenja Chromea su trenutno isključena u postavkama uređaja.</translation> +<translation id="2750626042242931740">Svoje odabire uvijek možete ažurirati u postavkama Chromea.</translation> <translation id="2767464022270041271">Nije sačuvana nijedna lozinka. Google upravitelj lozinki može provjeriti vaše lozinke kada ih sačuvate.</translation> <translation id="2789947168960170215">Ako ste zaboravili pristupni izraz ili želite promijeniti ovu postavku, <ph name="BEGIN_LINK" />obrišite podatke Chromea na računu<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Obriši podatke o pregledanju u Chromeu</translation> @@ -297,6 +299,7 @@ Da promijenite ovu postavku, <ph name="BEGIN_LINK" />obrišite podatke Chromea na računu<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google upravitelj lozinki nije uspio provjeriti sve lozinke. Pokušajte ponovo sutra.</translation> <translation id="8865415417596392024">Podaci Chromea na vašem računu</translation> +<translation id="8874688701962049679">Savjeti za iskorištavanje svih prednosti Chromea.</translation> <translation id="8891935667620843985">Možete automatski otvarati linkove u Chromeu ako ga postavite kao zadanu aplikaciju preglednika.</translation> <translation id="8897749957032330183">Lozinke se pohranjuju u Google upravitelju lozinki na ovom uređaju.</translation> <translation id="8949681853939555434">Postavite Chrome kao zadani preglednik</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ca.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ca.xtb index feb37ae..fe39f94 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ca.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ca.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Per tancar la sessió del teu Compte de Google en tots els llocs web, <ph name="BEGIN_LINK" />tanca la sessió de Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome no ha pogut cercar actualitzacions. Torna-ho a provar més tard.</translation> <translation id="2702250627063295552">Afegeix un element de llista de lectura a Chrome</translation> +<translation id="2703746758996815929">Per rebre consells útils sobre Chrome, activa les notificacions a la configuració d'iOS.</translation> <translation id="2736805085127235148">En aquests moments, les notificacions de Chrome estan desactivades a la configuració del dispositiu.</translation> <translation id="2767464022270041271">No hi ha cap contrasenya desada. El gestor de contrasenyes de Google pot comprovar les teves contrasenyes quan les deses.</translation> <translation id="2789947168960170215">Si has oblidat la frase de contrasenya o vols canviar aquesta opció de configuració, <ph name="BEGIN_LINK" />esborra les dades de Chrome del compte<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Per canviar aquesta opció de configuració, <ph name="BEGIN_LINK" />esborra les dades de Chrome del compte<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">El gestor de contrasenyes de Google no ha pogut comprovar totes les contrasenyes. Torna-ho a provar demà.</translation> <translation id="8865415417596392024">Dades de Chrome al teu compte</translation> +<translation id="8874688701962049679">Consells per treure el màxim partit de Chrome.</translation> <translation id="8891935667620843985">Pots obrir enllaços automàticament a l'aplicació Chrome convertint-la en la predeterminada com a navegador.</translation> <translation id="8897749957032330183">Les contrasenyes es desen al gestor de contrasenyes de Google en aquest dispositiu.</translation> <translation id="8949681853939555434">Defineix Chrome com a navegador predeterminat</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_cy.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_cy.xtb index fa4b8ac..a716f5f 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_cy.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_cy.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">I allgofnodi o'ch Cyfrif Google ar bob gwefan, <ph name="BEGIN_LINK" />allgofnodwch o Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Ni allai Chrome wirio am ddiweddariadau. Rhowch gynnig arall arni'n nes ymlaen.</translation> <translation id="2702250627063295552">Ychwanegu Eitem Rhestr Ddarllen at Chrome</translation> +<translation id="2703746758996815929">I gael awgrymiadau defnyddiol Chrome, trowch hysbysiadau ymlaen yn eich gosodiadau iOS.</translation> <translation id="2736805085127235148">Mae hysbysiadau Chrome wedi'u diffodd yng ngosodiadau eich dyfais ar hyn o bryd.</translation> <translation id="2767464022270041271">Nid oes unrhyw gyfrineiriau sydd wedi'u cadw. Gall Rheolwr Cyfrineiriau Google wirio'ch cyfrineiriau pan fyddwch yn eu cadw.</translation> <translation id="2789947168960170215">Os byddwch yn anghofio'ch cyfrinymadrodd neu eisiau newid y gosodiad hwn, <ph name="BEGIN_LINK" />cliriwch y data Chrome yn eich cyfrif<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ I newid y gosodiad hwn, <ph name="BEGIN_LINK" />cliriwch y data Chrome yn eich cyfrif<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Ni allai Rheolwr Cyfrineiriau Google wirio pob cyfrinair. Rhowch gynnig arall arni yfory.</translation> <translation id="8865415417596392024">Data Chrome yn eich cyfrif</translation> +<translation id="8874688701962049679">Awgrymiadau i fanteisio i'r eithaf ar Chrome.</translation> <translation id="8891935667620843985">Gallwch agor dolenni yn Chrome yn awtomatig drwy ei osod fel eich Ap Porwr Diofyn.</translation> <translation id="8897749957032330183">Mae cyfrineiriau'n cael eu cadw i Reolwr Cyfrineiriau Google ar y ddyfais hon.</translation> <translation id="8949681853939555434">Gosodwch Chrome fel eich Porwr Diofyn</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_en-GB.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_en-GB.xtb index d28af38..2ae9da1 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_en-GB.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_en-GB.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">To sign out of your Google Account on all websites, <ph name="BEGIN_LINK" />sign out of Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome couldn't check for updates. Try again later.</translation> <translation id="2702250627063295552">Add Reading List item to Chrome</translation> +<translation id="2703746758996815929">To get helpful Chrome tips, turn on notifications in your iOS settings.</translation> <translation id="2736805085127235148">Chrome notifications are currently turned off in your device settings.</translation> <translation id="2767464022270041271">No saved passwords. Google Password Manager can check your passwords when you save them.</translation> <translation id="2789947168960170215">If you forgot your passphrase or want to change this setting, <ph name="BEGIN_LINK" />clear the Chrome data in your account<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ To change this setting, <ph name="BEGIN_LINK" />clear the Chrome data in your account<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Password Manager couldn't check all passwords. Try again tomorrow.</translation> <translation id="8865415417596392024">Chrome data in your account</translation> +<translation id="8874688701962049679">Tips on getting the most out of Chrome.</translation> <translation id="8891935667620843985">You can open links in Chrome automatically by making it your default browser app.</translation> <translation id="8897749957032330183">Passwords are saved to Google Password Manager on this device.</translation> <translation id="8949681853939555434">Set Chrome as your default browser</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_et.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_et.xtb index 6fe4cf3..51726f3e 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_et.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_et.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Selleks et oma Google'i kontolt kõikidel veebisaitidel välja logida, <ph name="BEGIN_LINK" />logige välja Chrome'ist<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome ei saanud värskendusi otsida. Proovige hiljem uuesti.</translation> <translation id="2702250627063295552">Lisa Chrome'i lugemisloendi üksus</translation> +<translation id="2703746758996815929">Lülitage iOS-i seadetes märguanded sisse, et saada Chrome'i kohta kasulikke nõuandeid.</translation> <translation id="2736805085127235148">Chrome’i märguanded on praegu teie seadme seadetes välja lülitatud.</translation> <translation id="2767464022270041271">Salvestatud paroole ei ole. Google'i paroolihaldur saab teie paroole kontrollida, kui olete need salvestanud.</translation> <translation id="2789947168960170215">Kui unustasite parooli või soovite seda seadet muuta, <ph name="BEGIN_LINK" />kustutage oma kontol Chrome’i andmed<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Selle seade muutmiseks <ph name="BEGIN_LINK" />kustutage oma kontol Chrome’i andmed<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google'i paroolihalduril ei õnnestunud kõiki paroole kontrollida. Proovige homme uuesti.</translation> <translation id="8865415417596392024">Chrome'i andmed teie kontol</translation> +<translation id="8874688701962049679">Nõuanded Chrome’i kasutamiseks.</translation> <translation id="8891935667620843985">Saate Chrome'is linke avada automaatselt, muutes selle oma vaikebrauserirakenduseks.</translation> <translation id="8897749957032330183">Paroolid salvestatakse selles seadmes Google'i paroolihaldurisse.</translation> <translation id="8949681853939555434">Chrome'i vaikebrauseriks määramine</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_eu.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_eu.xtb index c1b1bf2..36ec38e4 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_eu.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_eu.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Google-ko kontuko saioa webgune guztietan amaitzeko, <ph name="BEGIN_LINK" />amaitu Chrome-ko saioa<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome-k ezin izan ditu bilatu eguneratzeak. Saiatu berriro geroago.</translation> <translation id="2702250627063295552">Gehitu irakurketa-zerrendako elementu bat Chrome-n</translation> +<translation id="2703746758996815929">Chrome-ri buruzko aholku lagungarriak jasotzeko, aktibatu jakinarazpenak iOS-en ezarpenetan.</translation> <translation id="2736805085127235148">Chrome-ren jakinarazpenak desaktibatuta daude une honetan gailuaren ezarpenetan.</translation> <translation id="2767464022270041271">Ez dago pasahitzik gordeta. Gordetako pasahitzak egiaztatzeko gai da Google-ren Pasahitz-kudeatzailea.</translation> <translation id="2789947168960170215">Pasaesaldia ahazten bazaizu edo ezarpena aldatu nahi baduzu, <ph name="BEGIN_LINK" />garbitu kontuko Chrome-ko datuak<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Ezarpen hori aldatzeko, <ph name="BEGIN_LINK" />garbitu kontuko Chrome-ko datuak<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google-ren Pasahitz-kudeatzailea zerbitzuak ezin izan ditu egiaztatu pasahitz guztiak. Saiatu berriro bihar.</translation> <translation id="8865415417596392024">Kontuan gordeta dauzkazun Chrome-ko datuak</translation> +<translation id="8874688701962049679">Chrome-ri etekinik handiena ateratzeko aholkuak.</translation> <translation id="8891935667620843985">Ezarri Chrome arakatzaile lehenetsi gisa eta ireki estekak bertan automatikoki.</translation> <translation id="8897749957032330183">Pasahitzak gailu honetan gordetzen dira, Google-ren Pasahitz-kudeatzailea zerbitzuan.</translation> <translation id="8949681853939555434">Ezarri Chrome arakatzaile lehenetsi gisa</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fa.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fa.xtb index 5d10995..def04a24 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fa.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fa.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">برای خارج شدن از سیستم «حساب Google» خود در همه وبسایتها، <ph name="BEGIN_LINK" />از سیستم Chrome خارج شوید<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome موفق نشد بهروزرسانیها را بررسی کند. بعداً دوباره امتحان کنید.</translation> <translation id="2702250627063295552">افزودن مورد «فهرست خواندن» به Chrome</translation> +<translation id="2703746758996815929">برای دریافت نکتههای مفید درباره Chrome، اعلانها را در تنظیمات iOS روشن کنید.</translation> <translation id="2736805085127235148">اعلانهای Chrome درحالحاضر در تنظیمات دستگاهتان خاموش است.</translation> <translation id="2767464022270041271">گذرواژهای ذخیره نشده است. اگر گذرواژههایتان را ذخیره کنید، «مدیر گذرواژه Google» میتواند آنها را بررسی کند.</translation> <translation id="2789947168960170215">اگر گذرعبارت را فراموش کردید یا میخواهید این تنظیم را تغییر دهید، <ph name="BEGIN_LINK" />دادههای Chrome ذخیرهشده در حسابتان را پاک کنید<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ برای تغییر این تنظیم، <ph name="BEGIN_LINK" />دادههای Chrome ذخیرهشده در حسابتان را پاک کنید<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">«مدیر گذرواژه Google» نتوانست همه گذرواژهها را بررسی کند. فردا دوباره امتحان کنید.</translation> <translation id="8865415417596392024">دادههای Chrome در حساب شما</translation> +<translation id="8874688701962049679">نکاتی برای اینکه بیشترین بهره را از Chrome ببرید.</translation> <translation id="8891935667620843985">با تنظیم Chrome بهعنوان «برنامه مرورگر پیشفرض» میتوانید پیوندها را بهطور خودکار در آن باز کنید.</translation> <translation id="8897749957032330183">گذرواژهها در «مدیر گذرواژه Google» در این دستگاه ذخیره میشوند.</translation> <translation id="8949681853939555434">تنظیم Chrome بهعنوان مرورگر پیشفرض</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fil.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fil.xtb index 3bcd7e3a..59b879660 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fil.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fil.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">Para mag-sign out sa iyong Google Account sa lahat ng website, <ph name="BEGIN_LINK" />mag-sign out sa Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Hindi matingnan ng Chrome kung may mga update. Subukan ulit sa ibang pagkakataon.</translation> <translation id="2702250627063295552">Magdagdag ng Item sa Listahan ng Babasahin sa Chrome</translation> +<translation id="2703746758996815929">Para makakuha ng mga kapaki-pakinabang na tip sa Chrome, i-on ang mga notification sa iyong mga setting ng iOS.</translation> <translation id="2736805085127235148">Kasalukuyang naka-off ang mga notification sa Chrome sa mga setting ng iyong device.</translation> +<translation id="2750626042242931740">Puwede mong i-update ang iyong mga pinili anumang oras sa Mga Setting ng Chrome.</translation> <translation id="2767464022270041271">Walang naka-save na password. Masusuri ng Google Password Manager ang iyong mga password kapag na-save mo ang mga ito.</translation> <translation id="2789947168960170215">Kung nakalimutan mo ang iyong passphrase o gusto mong baguhin ang setting na ito, <ph name="BEGIN_LINK" />i-clear ang data sa Chrome sa iyong account<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">I-clear ang Data Mula sa Pagba-browse sa Chrome</translation> @@ -297,6 +299,7 @@ Para baguhin ang setting na ito, <ph name="BEGIN_LINK" />i-clear ang data sa Chrome sa iyong account<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Hindi masuri ng Google Password Manager ang lahat ng password. Subukan ulit bukas.</translation> <translation id="8865415417596392024">Data ng Chrome sa iyong account</translation> +<translation id="8874688701962049679">Mga tip para masulit ang Chrome.</translation> <translation id="8891935667620843985">Awtomatiko mong mabubuksan ang mga link sa Chrome sa pamamagitan ng pagtatakda nito bilang iyong Default na Browser App.</translation> <translation id="8897749957032330183">Sine-save ang mga password sa Google Password Manager sa device na ito.</translation> <translation id="8949681853939555434">Itakda ang Chrome bilang iyong Default na Browser</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb index 88050f7..ade0cf5 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Para pechar sesión na túa Conta de Google en todos os sitios web, <ph name="BEGIN_LINK" />pecha sesión en Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome non puido buscar actualizacións. Téntao máis tarde.</translation> <translation id="2702250627063295552">Engadir o elemento da lista de lectura a Chrome</translation> +<translation id="2703746758996815929">Se queres recibir consellos útiles sobre Chrome, activa as notificacións na configuración de iOS.</translation> <translation id="2736805085127235148">As notificacións de Chrome están desactivadas actualmente na configuración do dispositivo.</translation> <translation id="2767464022270041271">Non hai contrasinais gardados. O xestor de contrasinais de Google poderá comprobar os teus contrasinais cando os gardes.</translation> <translation id="2789947168960170215">Se esqueciches a frase de acceso ou queres cambiar esta opción de configuración, <ph name="BEGIN_LINK" />borra os datos de Chrome da túa conta<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Para cambiar esta opción de configuración, <ph name="BEGIN_LINK" />borra os datos de Chrome da túa conta<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">O xestor de contrasinais de Google non puido comprobar todos os contrasinais. Téntao de novo mañá.</translation> <translation id="8865415417596392024">Datos de Chrome na túa conta</translation> +<translation id="8874688701962049679">Consellos para tirar o máximo proveito de Chrome.</translation> <translation id="8891935667620843985">Se configuras Chrome como aplicación de navegador predeterminada, poderás abrir ligazóns nel automaticamente.</translation> <translation id="8897749957032330183">Os contrasinais gárdanse no xestor de contrasinais de Google neste dispositivo.</translation> <translation id="8949681853939555434">Define Chrome como o teu navegador predeterminado</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_hr.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_hr.xtb index aa56383a..32043b07 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_hr.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_hr.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">Da biste se odjavili sa svojeg Google računa na svim web-lokacijama, <ph name="BEGIN_LINK" />odjavite se iz Chromea<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome nije uspio provjeriti ima li ažuriranja. Pokušajte ponovo kasnije.</translation> <translation id="2702250627063295552">Dodaj stavku popisa za čitanje u Chrome</translation> +<translation id="2703746758996815929">Da biste primali korisne savjete za Chrome, uključite obavijesti u postavkama iOS-a.</translation> <translation id="2736805085127235148">Obavijesti Chromea trenutačno su isključene u postavkama uređaja.</translation> +<translation id="2750626042242931740">Svoje odabire uvijek možete ažurirati u postavkama Chromea.</translation> <translation id="2767464022270041271">Nema nijedne spremljene zaporke. Google upravitelj zaporki može provjeriti vaše zaporke kad ih spremite.</translation> <translation id="2789947168960170215">Ako ste zaboravili šifru ili želite promijeniti tu postavku, <ph name="BEGIN_LINK" />izbrišite Chromeove podatke na računu<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Brisanje podataka o pregledavanju u Chromeu</translation> @@ -297,6 +299,7 @@ Kako biste promijenili tu postavku, <ph name="BEGIN_LINK" />izbrišite podatke Chromea na svom računu<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google upravitelj zaporki nije uspio provjeriti sve zaporke. Pokušajte ponovo sutra.</translation> <translation id="8865415417596392024">Podaci iz Chromea na vašem računu</translation> +<translation id="8874688701962049679">Savjeti o tome kako iskoristiti sve prednosti Chromea.</translation> <translation id="8891935667620843985">Veze u Chromeu možete otvoriti automatski tako da ga postavite kao zadanu aplikaciju preglednika.</translation> <translation id="8897749957032330183">Zaporke se spremaju u Google upravitelj zaporki na ovom uređaju.</translation> <translation id="8949681853939555434">Postavite Chrome kao zadani preglednik</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb index 69f2a33c..a7d0f4f 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Untuk logout dari Akun Google Anda di semua situs, <ph name="BEGIN_LINK" />logout dari Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome tidak dapat memeriksa update. Coba lagi nanti.</translation> <translation id="2702250627063295552">Tambahkan Item Daftar Bacaan ke Chrome</translation> +<translation id="2703746758996815929">Untuk mendapatkan tips Chrome yang berguna, aktifkan notifikasi di setelan iOS.</translation> <translation id="2736805085127235148">Notifikasi Chrome saat ini dinonaktifkan di setelan perangkat.</translation> <translation id="2767464022270041271">Tidak ada sandi tersimpan. Pengelola Sandi Google dapat memeriksa sandi Anda jika Anda menyimpannya.</translation> <translation id="2789947168960170215">Jika lupa frasa sandi atau ingin mengubah setelan ini, <ph name="BEGIN_LINK" />hapus data Chrome di akun Anda<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Untuk mengubah setelan ini, <ph name="BEGIN_LINK" />hapus data Chrome di akun Anda<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Pengelola Sandi Google tidak dapat memeriksa semua sandi. Coba lagi besok.</translation> <translation id="8865415417596392024">Data Chrome di akun Anda</translation> +<translation id="8874688701962049679">Tips untuk mengoptimalkan penggunaan Chrome.</translation> <translation id="8891935667620843985">Anda dapat membuka link di Chrome secara otomatis dengan menjadikan Chrome sebagai Aplikasi Browser Default Anda.</translation> <translation id="8897749957032330183">Sandi disimpan ke Pengelola Sandi Google di perangkat ini.</translation> <translation id="8949681853939555434">Setel Chrome sebagai Browser Default Anda</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_is.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_is.xtb index 7724507..3521c09 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_is.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_is.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Til að skrá þig út af Google reikningnum þínum á öllum vefsvæðum skaltu <ph name="BEGIN_LINK" />skrá þig út af Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome gat ekki leitað að uppfærslum. Reyndu aftur síðar.</translation> <translation id="2702250627063295552">Bæta leslistaatriði við Chrome</translation> +<translation id="2703746758996815929">Til að fá gagnleg ráð um Chrome skaltu kveikja á tilkynningum í iOS-stillingum.</translation> <translation id="2736805085127235148">Slökkt er á Chrome-tilkynningum í stillingum tækisins.</translation> <translation id="2767464022270041271">Engin vistuð aðgangsorð. Google-aðgangsorðastjórnun getur athugað aðgangsorðin þín þegar þú vistar þau.</translation> <translation id="2789947168960170215">Ef þú gleymdir aðgangsorðinu eða vilt breyta þessari stillingu skaltu <ph name="BEGIN_LINK" />hreinsa Chrome-gögnin á reikningnum þínum<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Til að breyta þessari stillingu skaltu <ph name="BEGIN_LINK" />hreinsa Chrome-gögnin á reikningnum þínum<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google-aðgangsorðastjórnun gat ekki athugað öll aðgangsorð. Reyndu aftur á morgun.</translation> <translation id="8865415417596392024">Chrome-gögn á reikningnum þínum</translation> +<translation id="8874688701962049679">Ráð um að fá sem mest út úr Chrome.</translation> <translation id="8891935667620843985">Þú getur opnað tengla sjálfkrafa í Chrome með því að stilla það sem sjálfgefið vafraforrit.</translation> <translation id="8897749957032330183">Aðgangsorð eru vistuð í Google aðgangsorðastjórnun í þessu tæki.</translation> <translation id="8949681853939555434">Stilltu Chrome sem sjálfgefinn vafra</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb index eeb26d1e..c6e68be9 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">כדי לצאת מחשבון Google שלך בכל האתרים, עליך <ph name="BEGIN_LINK" />לצאת מ-Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome לא הצליח לחפש עדכונים. אפשר לנסות שוב מאוחר יותר.</translation> <translation id="2702250627063295552">הוספת פריט מרשימת הקריאה ל-Chrome</translation> +<translation id="2703746758996815929">כדי לקבל טיפים מועילים ל-Chrome, צריך להפעיל את ההתראות בהגדרות iOS.</translation> <translation id="2736805085127235148">ההתראות מ-Chrome מושבתות עכשיו בהגדרות המכשיר.</translation> <translation id="2767464022270041271">אין סיסמאות שמורות. למנהל הסיסמאות של Google יש אפשרות לבדוק את הסיסמאות שלך רק אם שמרת אותן.</translation> <translation id="2789947168960170215">אם שכחת את ביטוי הסיסמה או שברצונך לשנות את ההגדרה הזו, <ph name="BEGIN_LINK" />עליך לנקות את נתוני Chrome בחשבון<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ כדי לשנות את ההגדרה הזו, עליך <ph name="BEGIN_LINK" />לנקות את נתוני Chrome בחשבון<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">למנהל הסיסמאות של Google לא הייתה אפשרות לבדוק את כל הסיסמאות. אפשר לנסות שוב מחר.</translation> <translation id="8865415417596392024">נתוני Chrome בחשבון שלך</translation> +<translation id="8874688701962049679">טיפים שיעזרו לך ליהנות מהמיטב של Chrome.</translation> <translation id="8891935667620843985">אפשר לפתוח קישורים ב-Chrome באופן אוטומטי. כדי לעשות זאת, צריך להגדיר אותו כאפליקציית ברירת המחדל לדפדפן.</translation> <translation id="8897749957032330183">סיסמאות נשמרות במנהל הסיסמאות של Google במכשיר הזה.</translation> <translation id="8949681853939555434">הגדרת Chrome כדפדפן ברירת המחדל</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb index ad70571..23549b1 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">すべてのウェブサイトで Google アカウントからログアウトするには、<ph name="BEGIN_LINK" />Chrome からログアウト<ph name="END_LINK" />します。</translation> <translation id="2695886661449553974">Chrome でアップデートを確認できませんでした。しばらくしてからもう一度お試しください。</translation> <translation id="2702250627063295552">Chrome にリーディング リストの項目を追加する</translation> +<translation id="2703746758996815929">Chrome を使いこなすヒントを受け取るには、iOS の設定で通知をオンにしてください。</translation> <translation id="2736805085127235148">現在、デバイスの設定で Chrome の通知がオフになっています。</translation> <translation id="2767464022270041271">保存されているパスワードがありません。パスワードを保存すると、Google パスワード マネージャーで確認できるようになります。</translation> <translation id="2789947168960170215">パスフレーズを忘れた場合や、この設定を変更する場合は、<ph name="BEGIN_LINK" />アカウントの Chrome データを消去<ph name="END_LINK" />してください。</translation> @@ -297,6 +298,7 @@ この設定を変更するには、<ph name="BEGIN_LINK" />アカウントの Chrome データを消去<ph name="END_LINK" />します。</translation> <translation id="8857676124663337448">Google パスワード マネージャーですべてのパスワードを確認できませんでした。明日もう一度お試しください。</translation> <translation id="8865415417596392024">アカウント内の Chrome のデータ</translation> +<translation id="8874688701962049679">Chrome を最大限に活用するためのヒント。</translation> <translation id="8891935667620843985">Chrome をデフォルトのブラウザアプリに設定すると、Chrome で自動的にリンクを開くことができます。</translation> <translation id="8897749957032330183">パスワードは、このデバイスの Google パスワード マネージャーに保存されます。</translation> <translation id="8949681853939555434">Chrome をデフォルトのブラウザに設定する</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb index 891c53d..a2b0477d 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Барлық веб-сайтта Google аккаунтынан шығу үшін <ph name="BEGIN_LINK" />Chrome-нан шығыңыз<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome жаңа нұсқалардың бар-жоғын тексере алмады. Кейінірек қайталап көріңіз.</translation> <translation id="2702250627063295552">Оқу тізімі элементін Chrome-ға қосу</translation> +<translation id="2703746758996815929">Пайдалы Chrome кеңестерін алу үшін iOS параметрлерінде хабарландыруларды қосыңыз.</translation> <translation id="2736805085127235148">Қазіргі уақытта құрылғы параметрлерінде Chrome хабарландырулары өшірілген.</translation> <translation id="2767464022270041271">Ешқандай құпия сөз сақталмаған. Google Password Manager құпия сөздерді сақтаған кезде оларды тексере алады.</translation> <translation id="2789947168960170215">Құпия фразаны ұмытып қалған болсаңыз немесе осы параметрді өзгерту керек болса, <ph name="BEGIN_LINK" />аккаунтыңыздағы Chrome деректерін өшіріңіз<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Бұл параметрді өзгерту үшін <ph name="BEGIN_LINK" />аккаунтыңыздағы Chrome деректерін өшіріңіз<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Password Manager барлық құпия сөзді тексере алмады. Ертең қайталап көріңіз.</translation> <translation id="8865415417596392024">Аккаунтыңыздағы Chrome деректері</translation> +<translation id="8874688701962049679">Chrome-ды барынша тиімді пайдалануға көмектесетін кеңестер.</translation> <translation id="8891935667620843985">Chrome қолданбасын әдепкі браузер етіп қойсаңыз, сілтемелер автоматты түрде сол браузерде ашылады.</translation> <translation id="8897749957032330183">Құпия сөздер осы құрылғыдағы Google Құпия сөз менеджеріне сақталады.</translation> <translation id="8949681853939555434">Chrome-ды әдепкі браузер ретінде орнату</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_km.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_km.xtb index 7c07aea..7d48179 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_km.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_km.xtb
@@ -77,6 +77,7 @@ <translation id="2702250627063295552">បញ្ចូលធាតុបញ្ជីអានទៅ Chrome</translation> <translation id="2703746758996815929">ដើម្បីទទួលបានគន្លឹះ Chrome ដែលមានប្រយោជន៍ សូមបើកការជូនដំណឹងនៅក្នុងការកំណត់ iOS របស់អ្នក។</translation> <translation id="2736805085127235148">បច្ចុប្បន្ន ការជូនដំណឹងនៅលើ Chrome ត្រូវបានបិទនៅក្នុងការកំណត់ឧបករណ៍របស់អ្នក។</translation> +<translation id="2750626042242931740">អ្នកអាចធ្វើបច្ចុប្បន្នភាពការជ្រើសរើសរបស់អ្នកនៅពេលណាក៏បាននៅក្នុងការកំណត់ Chrome។</translation> <translation id="2767464022270041271">មិនមានពាក្យសម្ងាត់ដែលបានរក្សាទុកទេ។ កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់អាចពិនិត្យមើលពាក្យសម្ងាត់របស់អ្នក នៅពេលអ្នករក្សាទុកពាក្យសម្ងាត់ទាំងនោះ។</translation> <translation id="2789947168960170215">ប្រសិនបើអ្នកភ្លេចឃ្លាសម្ងាត់របស់អ្នក ឬចង់ប្ដូរការកំណត់នេះ សូម<ph name="BEGIN_LINK" />សម្អាតទិន្នន័យ Chrome នៅក្នុងគណនីរបស់អ្នក<ph name="END_LINK" />។</translation> <translation id="2868822340714096138">សម្អាតទិន្នន័យរុករកនៅក្នុង Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_kn.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_kn.xtb index e09026b..c0ed4e02 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_kn.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_kn.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">ಎಲ್ಲಾ ವೆಬ್ಸೈಟ್ಗಳಲ್ಲಿ ನಿಮ್ಮ Google ಖಾತೆಯಿಂದ ಸೈನ್ ಔಟ್ ಮಾಡಲು, <ph name="BEGIN_LINK" />Chrome ನಿಂದ ಸೈನ್ ಔಟ್ ಮಾಡಿ<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">ಅಪ್ಡೇಟ್ಗಳಿವೆಯೇ ಎಂಬುದನ್ನು ಪರಿಶೀಲಿಸಲು Chrome ಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.</translation> <translation id="2702250627063295552">Chrome ಗೆ ಓದುವಿಕೆ ಪಟ್ಟಿ ಐಟಂ ಅನ್ನು ಸೇರಿಸಿ</translation> +<translation id="2703746758996815929">ಸಹಾಯಕವಾದ Chrome ಸಲಹೆಗಳನ್ನು ಪಡೆಯಲು, ನಿಮ್ಮ iOS ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ.</translation> <translation id="2736805085127235148">ನಿಮ್ಮ ಸಾಧನದ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಪ್ರಸ್ತುತ Chrome ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ.</translation> <translation id="2767464022270041271">ಉಳಿಸಿರುವ ಯಾವುದೇ ಪಾಸ್ವರ್ಡ್ಗಳಿಲ್ಲ. ನೀವು ಅವುಗಳನ್ನು ಉಳಿಸಿದಾಗ Google Password Manager ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಬಹುದು.</translation> <translation id="2789947168960170215">ಪಾಸ್ಫ್ರೇಸ್ ಅನ್ನು ಮರೆತಿದ್ದರೆ ಅಥವಾ ಈ ಸೆಟ್ಟಿಂಗ್ ಬದಲಾಯಿಸಬೇಕಾದರೆ <ph name="BEGIN_LINK" />ನಿಮ್ಮ ಖಾತೆಯಲ್ಲಿರುವ Chrome ಡೇಟಾ ತೆರವುಗೊಳಿಸಿ<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸಲು, <ph name="BEGIN_LINK" />ನಿಮ್ಮ ಖಾತೆಯಲ್ಲಿರುವ Chrome ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Password Manager ಎಲ್ಲಾ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ನಾಳೆ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.</translation> <translation id="8865415417596392024">ನಿಮ್ಮ ಖಾತೆಯಲ್ಲಿರುವ Chrome ಡೇಟಾ</translation> +<translation id="8874688701962049679">Chrome ನಿಂದ ಅತ್ಯಧಿಕ ಪ್ರಯೋಜನ ಪಡೆಯುವ ಕುರಿತು ಸಲಹೆಗಳು.</translation> <translation id="8891935667620843985">Chrome ಅನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಬ್ರೌಸರ್ ಆ್ಯಪ್ ಮಾಡಿಕೊಳ್ಳುವ ಮೂಲಕ ಅದರಲ್ಲಿ ಲಿಂಕ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆರೆಯಿರಿ.</translation> <translation id="8897749957032330183">ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಈ ಸಾಧನದಲ್ಲಿನ Google ಪಾಸ್ವರ್ಡ್ ನಿರ್ವಾಹಕದಲ್ಲಿ ಸೇವ್ ಮಾಡಲಾಗಿದೆ.</translation> <translation id="8949681853939555434">Chrome ಅನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಬ್ರೌಸರ್ ಆಗಿ ಸೆಟ್ ಮಾಡಿ</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ko.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ko.xtb index c0f1d970..1694043 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ko.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ko.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">웹사이트에 로그인되어 있는 Google 계정에서 모두 로그아웃하려면 <ph name="BEGIN_LINK" />Chrome에서 로그아웃<ph name="END_LINK" />하세요.</translation> <translation id="2695886661449553974">Chrome에서 업데이트를 확인할 수 없습니다. 나중에 다시 시도해 주세요.</translation> <translation id="2702250627063295552">Chrome에 읽기 목록 항목 추가</translation> +<translation id="2703746758996815929">유용한 Chrome 도움말을 확인하려면 iOS 설정에서 알림을 사용 설정하세요</translation> <translation id="2736805085127235148">현재 기기 설정에서 Chrome 알림이 사용 중지되어 있습니다.</translation> <translation id="2767464022270041271">저장된 비밀번호가 없습니다. 비밀번호를 저장하면 Google 비밀번호 관리자에서 확인할 수 있습니다.</translation> <translation id="2789947168960170215">암호가 기억나지 않거나 이 설정을 변경하려면 <ph name="BEGIN_LINK" />계정에서 Chrome 데이터를 삭제<ph name="END_LINK" />하세요.</translation> @@ -297,6 +298,7 @@ 이 설정을 변경하려면 <ph name="BEGIN_LINK" />계정의 Chrome 데이터를 삭제<ph name="END_LINK" />하세요.</translation> <translation id="8857676124663337448">Google 비밀번호 관리자에서 일부 비밀번호를 확인할 수 없습니다. 내일 다시 시도해 보세요.</translation> <translation id="8865415417596392024">계정의 Chrome 데이터</translation> +<translation id="8874688701962049679">Chrome을 최대한 활용하기 위한 도움말입니다.</translation> <translation id="8891935667620843985">Chrome을 기본 브라우저 앱으로 설정하면 링크가 자동으로 Chrome에서 열립니다.</translation> <translation id="8897749957032330183">비밀번호가 이 기기의 Google 비밀번호 관리자에 저장됩니다.</translation> <translation id="8949681853939555434">Chrome을 기본 브라우저로 설정</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb index 08513c94..aa8df8b8 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb
@@ -77,6 +77,7 @@ <translation id="2702250627063295552">ເພີ່ມລາຍການລາຍຊື່ການອ່ານໃສ່ Chrome</translation> <translation id="2703746758996815929">ເພື່ອຮັບເຄັດລັບ Chrome ທີ່ເປັນປະໂຫຍດ, ໃຫ້ເປີດການແຈ້ງເຕືອນໃນການຕັ້ງຄ່າ iOS ຂອງທ່ານ.</translation> <translation id="2736805085127235148">ຕອນນີ້ການແຈ້ງເຕືອນ Chrome ປິດຢູ່ໃນການຕັ້ງຄ່າອຸປະກອນຂອງທ່ານ.</translation> +<translation id="2750626042242931740">ທ່ານສາມາດອັບເດດສິ່ງທີ່ທ່ານເລືອກໄດ້ທຸກເວລາໃນການຕັ້ງຄ່າ Chrome.</translation> <translation id="2767464022270041271">ບໍ່ມີລະຫັດຜ່ານທີ່ບັນທຶກໄວ້. ຕົວຈັດການລະຫັດຜ່ານ Google ສາມາດກວດສອບລະຫັດຜ່ານຂອງທ່ານໃນເວລາທີ່ທ່ານບັນທຶກພວກມັນໄດ້.</translation> <translation id="2789947168960170215">ຫາກທ່ານລືມລະຫັດຜ່ານຂອງທ່ານ ຫຼື ຕ້ອງການປ່ຽນການຕັ້ງຄ່ານີ້, ໃຫ້ <ph name="BEGIN_LINK" />ລຶບລ້າງຂໍ້ມູນ Chrome ໃນບັນຊີຂອງທ່ານ<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">ລຶບລ້າງຂໍ້ມູນການທ່ອງເວັບໃນ Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lt.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lt.xtb index 307ed4dc..47755f86 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lt.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lt.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Jei norite atsijungti nuo „Google“ paskyros visose svetainėse, <ph name="BEGIN_LINK" />atsijunkite nuo „Chrome“<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">„Chrome“ nepavyko patikrinti, ar yra naujinių. Bandykite dar kartą vėliau.</translation> <translation id="2702250627063295552">Pridėti skaitymo sąrašo elementą prie „Chrome“</translation> +<translation id="2703746758996815929">Jei norite gauti naudingų „Chrome“ patarimų, įjunkite pranešimus „iOS“ nustatymuose.</translation> <translation id="2736805085127235148">„Chrome“ pranešimai šiuo metu išjungti įrenginio nustatymuose.</translation> <translation id="2767464022270041271">Nėra išsaugotų slaptažodžių. „Google“ slaptažodžių tvarkyklė gali tikrinti slaptažodžius, kai juos išsaugote.</translation> <translation id="2789947168960170215">Jei pamiršote slaptafrazę ar norite pakeisti šį nustatymą, <ph name="BEGIN_LINK" />išvalykite „Chrome“ duomenis paskyroje<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Jei norite pakeisti šį nustatymą, <ph name="BEGIN_LINK" />išvalykite „Chrome“ duomenis paskyroje<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">„Google“ slaptažodžių tvarkyklei nepavyko patikrinti visų slaptažodžių. Rytoj bandykite dar kartą.</translation> <translation id="8865415417596392024">„Chrome“ duomenys jūsų paskyroje</translation> +<translation id="8874688701962049679">Patarimai, kaip išnaudoti visas „Chrome“ galimybes.</translation> <translation id="8891935667620843985">Galite automatiškai atidaryti nuorodas naršyklėje „Chrome“, nustatę ją kaip numatytąją naršyklės programą.</translation> <translation id="8897749957032330183">Slaptažodžiai saugomi „Google“ slaptažodžių tvarkyklėje šiame įrenginyje.</translation> <translation id="8949681853939555434">„Chrome“ nustatymas kaip numatytosios naršyklės</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lv.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lv.xtb index a426514..f8630b1 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lv.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lv.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Lai izrakstītos no sava Google konta visās vietnēs, <ph name="BEGIN_LINK" />izrakstieties no pārlūka Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Pārlūkā Chrome nevarēja pārbaudīt atjauninājumu pieejamību. Vēlāk mēģiniet vēlreiz.</translation> <translation id="2702250627063295552">Pievienot lasīšanas saraksta vienumu pārlūkam Chrome</translation> +<translation id="2703746758996815929">Lai saņemtu noderīgus Chrome padomus, ieslēdziet paziņojumus iOS iestatījumos.</translation> <translation id="2736805085127235148">Chrome paziņojumi pašlaik ir izslēgti jūsu ierīces iestatījumos.</translation> <translation id="2767464022270041271">Nav saglabātu paroļu. Google paroļu pārvaldnieks var pārbaudīt jūsu paroles, ja jūs tās saglabājat.</translation> <translation id="2789947168960170215">Ja esat aizmirsis ieejas frāzi vai vēlaties mainīt šo iestatījumu, <ph name="BEGIN_LINK" />notīriet Chrome datus savā kontā<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Lai mainītu šo iestatījumu, <ph name="BEGIN_LINK" />notīriet Chrome datus savā kontā<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google paroļu pārvaldnieks nevarēja pārbaudīt visas paroles. Rit mēģiniet vēlreiz.</translation> <translation id="8865415417596392024">Chrome dati jūsu kontā</translation> +<translation id="8874688701962049679">Padomi par pilnvērtīgu Chrome izmantošanu.</translation> <translation id="8891935667620843985">Varat automātiski atvērt saites pārlūkā Chrome, iestatot to kā savu noklusējuma pārlūka lietotni.</translation> <translation id="8897749957032330183">Paroles tiek saglabātas Google paroļu pārvaldniekā šajā ierīcē.</translation> <translation id="8949681853939555434">Chrome iestatīšana par noklusējuma pārlūku</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_mn.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_mn.xtb index 4163b99..99f8136 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_mn.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_mn.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Бүх вебсайт дээр Google Бүртгэлээсээ гарахын тулд <ph name="BEGIN_LINK" />Chrome-с гарна уу<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome-н шинэчлэлтийг шалгаж чадсангүй. Дараа дахин оролдоно уу.</translation> <translation id="2702250627063295552">Унших жагсаалтын зүйлийг Chrome-д нэмэх</translation> +<translation id="2703746758996815929">Chrome-н хэрэгтэй зөвлөгөөнүүдийг авахын тулд iOS тохиргоондоо мэдэгдлүүдийг асаана уу.</translation> <translation id="2736805085127235148">Chrome-н мэдэгдлийг одоогоор таны төхөөрөмжийн тохиргоонд унтраасан байна.</translation> <translation id="2767464022270041271">Хадгалсан ямар ч нууц үг алга. Google Password Manager таныг нууц үгнүүдээ хадгалсан үед тэдгээрийг шалгах боломжтой.</translation> <translation id="2789947168960170215">Хэрэв та нэвтрэх үгээ мартсан эсвэл энэ тохиргоог өөрчлөхийг хүсвэл <ph name="BEGIN_LINK" />бүртгэлийнхээ Chrome-н өгөгдлийг арилгана уу<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Энэ тохиргоог өөрчлөхийн тулд <ph name="BEGIN_LINK" />бүртгэлийнхээ Chrome-н өгөгдлийг арилгана уу<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Password Manager бүх нууц үгийг шалгаж чадсангүй. Маргааш дахин оролдоно уу.</translation> <translation id="8865415417596392024">Таны бүртгэлийн Chrome-н өгөгдөл</translation> +<translation id="8874688701962049679">Chrome-г бүрэн ашиглах зөвлөгөөнүүд.</translation> <translation id="8891935667620843985">Та Chrome-г өгөгдмөл хөтчийн програм болгосноор холбоосуудыг автоматаар нээх боломжтой.</translation> <translation id="8897749957032330183">Нууц үгнүүдийг энэ төхөөрөмж дээр Google Password Manager-т хадгалдаг.</translation> <translation id="8949681853939555434">Chrome-г өгөгдмөл хөтчөөрөө тохируулах</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_mr.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_mr.xtb index 7c4e905..7835182 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_mr.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_mr.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">सर्व वेबसाइटवरील तुमच्या Google खाते मधून साइन आउट करण्यासाठी, <ph name="BEGIN_LINK" />Chrome मधून साइन आउट करणे<ph name="END_LINK" /> हे करा.</translation> <translation id="2695886661449553974">Chrome ला अपडेट तपासता आली नाहीत. नंतर पुन्हा प्रयत्न करा.</translation> <translation id="2702250627063295552">Chrome मध्ये वाचन सूची आयटम जोडा</translation> +<translation id="2703746758996815929">Chrome बद्दल उपयुक्त टिपा मिळवण्यासाठी, तुमच्या iOS सेटिंग्जमध्ये सूचना सुरू करा.</translation> <translation id="2736805085127235148">तुमच्या डिव्हाइस सेटिंग्जमध्ये Chrome सूचना सध्या बंद केल्या आहेत.</translation> <translation id="2767464022270041271">सेव्ह केलेले कोणतेही पासवर्ड नाहीत. तुम्ही तुमचे पासवर्ड सेव्ह करता, तेव्हा Google Password Manager तुमचे पासवर्ड तपासू शकते.</translation> <translation id="2789947168960170215">तुम्ही तुमचा पासफ्रेझ विसरल्यास किंवा हे सेटिंग बदलायचे असल्यास, <ph name="BEGIN_LINK" />तुमच्या खात्यामधील Chrome डेटा साफ करणे<ph name="END_LINK" /> हे करा.</translation> @@ -297,6 +298,7 @@ हे सेटिंग बदलण्यासाठी, <ph name="BEGIN_LINK" />तुमच्या खात्यामधील Chrome डेटा साफ करणे<ph name="END_LINK" /> हे करा.</translation> <translation id="8857676124663337448">Google Password Manager ला सर्व पासवर्ड तपासता आले नाहीत. उद्या पुन्हा प्रयत्न करा.</translation> <translation id="8865415417596392024">तुमच्या खात्यामधील Chrome डेटा</translation> +<translation id="8874688701962049679">Chrome चा पुरेपूर वापर करण्यासाठी टिपा.</translation> <translation id="8891935667620843985">तुम्ही Chrome ला तुमचे डीफॉल्ट ब्राउझर अॅप सेट करून त्यामध्ये आपोआप लिंक उघडू शकता.</translation> <translation id="8897749957032330183">पासवर्ड हे Google Password Manager यामध्ये या डिव्हाइसवर सेव्ह केले जातात.</translation> <translation id="8949681853939555434">तुमचा डीफॉल्ट ब्राउझर म्हणून Chrome सेट करा</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb index 7543dbc..7ee6a6da 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb
@@ -77,6 +77,7 @@ <translation id="2702250627063295552">Tambahkan Item Senarai Bacaan pada Chrome</translation> <translation id="2703746758996815929">Untuk mendapatkan petua berguna Chrome, hidupkan pemberitahuan pada tetapan iOS anda.</translation> <translation id="2736805085127235148">Pemberitahuan Chrome dimatikan dalam tetapan peranti anda pada masa ini.</translation> +<translation id="2750626042242931740">Anda boleh mengemaskinikan pilihan anda pada bila-bila masa dalam Tetapan Chrome.</translation> <translation id="2767464022270041271">Tiada kata laluan yang disimpan. Google Password Manager boleh menyemak kata laluan anda yang disimpan.</translation> <translation id="2789947168960170215">Jika anda terlupa ungkapan laluan anda atau mahu menukar tetapan ini, <ph name="BEGIN_LINK" />kosongkan data Chrome dalam akaun anda<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Kosongkan Data Semakan Imbas dalam Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ne.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ne.xtb index 739c59b..6ad9467 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ne.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ne.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">सबै वेबसाइटहरूमा आफ्नो Google खाताबाट साइन आउट गर्न <ph name="BEGIN_LINK" />Chrome बाट साइन आउट गर्नुहोस्<ph name="END_LINK" />।</translation> <translation id="2695886661449553974">Chrome ले अपडेटहरू उपलब्ध छन् कि छैनन् भन्ने कुरा जाँच गर्न सकेन। पछि फेरि प्रयास गर्नुहोस्।</translation> <translation id="2702250627063295552">रिडिङ लिस्टमा भएको सामग्री Chrome मा हालियोस्</translation> +<translation id="2703746758996815929">Chrome सम्बन्धी उपयोगी सुझावहरू प्राप्त गर्न iOS का सेटिङमा गई सूचना प्राप्त गर्ने सुविधा अन गर्नुहोस्।</translation> <translation id="2736805085127235148">हाल तपाईंको डिभाइसका सेटिङमा Chrome सम्बन्धी सूचना प्राप्त गर्ने सुविधा अफ गरिएको छ।</translation> <translation id="2767464022270041271">कुनै पनि पासवर्ड सेभ गरिएको छैन। तपाईंले आफ्ना पासवर्डहरू सेभ गर्नुभएको छ भने मात्र Google पासवर्ड म्यानेजरले ती पासवर्डहरू जाँच्न सक्छ।</translation> <translation id="2789947168960170215">तपाईंले आफ्नो पासफ्रेज बिर्सनुभयो वा तपाईं यो सेटिङ परिवर्तन गर्न चाहनुहुन्छ भने <ph name="BEGIN_LINK" />आफ्नो खातामा गएर Chrome को डेटा मेटाउनुहोस्<ph name="END_LINK" />।</translation> @@ -297,6 +298,7 @@ यो सेटिङ परिवर्तन गर्न <ph name="BEGIN_LINK" />आफ्नो खातामा गएर Chrome को डेटा मेटाउनुहोस्<ph name="END_LINK" />।</translation> <translation id="8857676124663337448">Google पासवर्ड म्यानेजरले सबै पासवर्डहरू जाँच्न सकेन। भोलि फेरि प्रयास गर्नुहोस्।</translation> <translation id="8865415417596392024">तपाईंको खातामा रहेको Chrome को डेटा</translation> +<translation id="8874688701962049679">Chrome बाट अधिकतम फाइदा लिन सघाउने सुझावहरू।</translation> <translation id="8891935667620843985">तपाईं Chrome लाई आफ्नो डिफल्ट ब्राउजर एप बनाएर लिंकहरू स्वतः Chrome मा खोल्न सक्नुहुन्छ।</translation> <translation id="8897749957032330183">पासवर्डहरू यो डिभाइसको Google पासवर्ड म्यानेजरमा सेभ गरिन्छन्।</translation> <translation id="8949681853939555434">Chrome लाई आफ्नो डिफल्ट ब्राउजरका रूपमा सेट गर्नुहोस्</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_nl.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_nl.xtb index b3a49f4..b038826 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_nl.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_nl.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">Als je op alle websites wilt uitloggen van je Google-account, <ph name="BEGIN_LINK" />log je uit bij Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome kan niet checken op updates. Probeer het later opnieuw.</translation> <translation id="2702250627063295552">Item toevoegen aan leeslijst in Chrome</translation> +<translation id="2703746758996815929">Zet meldingen aan via de iOS-instellingen om nuttige Chrome-tips te krijgen.</translation> <translation id="2736805085127235148">Chrome-meldingen staan momenteel uit in je apparaatinstellingen.</translation> +<translation id="2750626042242931740">Je kunt je selecties op elk moment updaten in de Chrome-instellingen.</translation> <translation id="2767464022270041271">Geen opgeslagen wachtwoorden. Google Wachtwoordmanager kan je wachtwoorden checken als je deze opslaat.</translation> <translation id="2789947168960170215">Als je je wachtwoordzin bent vergeten of deze instelling wilt wijzigen, <ph name="BEGIN_LINK" />wis je de Chrome-gegevens in je account<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Browsegegevens in Chrome wissen</translation> @@ -297,6 +299,7 @@ Als je deze instelling wilt wijzigen, <ph name="BEGIN_LINK" />wis je de Chrome-gegevens in je account<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Wachtwoordmanager kan niet alle wachtwoorden checken. Probeer het morgen opnieuw.</translation> <translation id="8865415417596392024">Chrome-gegevens in je account</translation> +<translation id="8874688701962049679">Tips om het maximale uit Chrome te halen.</translation> <translation id="8891935667620843985">Je kunt links automatisch openen in Chrome door Chrome in te stellen als je standaard browser-app.</translation> <translation id="8897749957032330183">Wachtwoorden worden opgeslagen in Google Wachtwoordmanager op dit apparaat.</translation> <translation id="8949681853939555434">Chrome instellen als je standaardbrowser</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_no.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_no.xtb index c27ff4de..f8042776 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_no.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_no.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">For å logge av Google-kontoen din på alle nettsteder, <ph name="BEGIN_LINK" />logg av Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome kunne ikke se etter oppdateringer. Prøv på nytt senere.</translation> <translation id="2702250627063295552">Legg til elementet på leselisten i Chrome</translation> +<translation id="2703746758996815929">For å få nyttige Chrome-tips, slå på varsler i iOS-innstillingene.</translation> <translation id="2736805085127235148">Chrome-varsler er nå slått av i enhetsinnstillingene.</translation> +<translation id="2750626042242931740">Du kan når som helst oppdatere valgene dine i Chrome-innstillingene.</translation> <translation id="2767464022270041271">Ingen lagrede passord. Google Passordlagring kan sjekke passordene dine når du lagrer dem.</translation> <translation id="2789947168960170215">Hvis du har glemt passordfrasen eller vil endre denne innstillingen, kan du <ph name="BEGIN_LINK" />slette Chrome-dataene i kontoen din<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Slett nettlesingsdata i Chrome</translation> @@ -297,6 +299,7 @@ For å endre denne innstillingen, <ph name="BEGIN_LINK" />slett Chrome-dataene i kontoen din<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Passordlagring kunne ikke sjekke alle passordene. Prøv på nytt i morgen.</translation> <translation id="8865415417596392024">Chrome-data i kontoen din</translation> +<translation id="8874688701962049679">Tips for å få mest mulig ut av Chrome.</translation> <translation id="8891935667620843985">Du kan åpne linker i Chrome automatisk ved å angi Chrome som standard nettleserapp.</translation> <translation id="8897749957032330183">Passord lagres i Google Passordlagring på denne enheten.</translation> <translation id="8949681853939555434">Bruk Chrome som standardnettleser</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_pa.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_pa.xtb index f9337a4b..41598810 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_pa.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_pa.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">ਸਾਰੀਆਂ ਵੈੱਬਸਾਈਟਾਂ 'ਤੇ ਆਪਣੇ Google ਖਾਤੇ ਤੋਂ ਸਾਈਨ-ਆਊਟ ਕਰਨ ਲਈ, <ph name="BEGIN_LINK" />Chrome ਤੋਂ ਸਾਈਨ-ਆਊਟ ਕਰੋ<ph name="END_LINK" />।</translation> <translation id="2695886661449553974">Chrome ਅੱਪਡੇਟਾਂ ਲਈ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਿਆ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation> <translation id="2702250627063295552">Chrome ਦੀ ਪੜ੍ਹਨ-ਸੂਚੀ ਵਿੱਚ ਆਈਟਮ ਸ਼ਾਮਲ ਕਰੋ</translation> +<translation id="2703746758996815929">ਲਾਹੇਵੰਦ Chrome ਨੁਕਤੇ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਆਪਣੀਆਂ iOS ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ।</translation> <translation id="2736805085127235148">ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀਆਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ Chrome ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਫ਼ਿਲਹਾਲ ਬੰਦ ਹਨ।</translation> <translation id="2767464022270041271">ਕੋਈ ਰੱਖਿਅਤ ਕੀਤਾ ਪਾਸਵਰਡ ਨਹੀਂ। ਤੁਹਾਡੇ ਵੱਲੋਂ ਆਪਣੇ ਪਾਸਵਰਡ ਰੱਖਿਅਤ ਕਰਨ 'ਤੇ Google Password Manager ਉਨ੍ਹਾਂ ਦੀ ਜਾਂਚ ਕਰ ਸਕਦਾ ਹੈ।</translation> <translation id="2789947168960170215">ਜੇ ਤੁਸੀਂ ਆਪਣਾ ਪਾਸਫਰੇਜ਼ ਭੁੱਲ ਗਏ ਹੋ ਜਾਂ ਇਸ ਸੈਟਿੰਗ ਨੂੰ ਬਦਲਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ <ph name="BEGIN_LINK" />ਆਪਣੇ ਖਾਤੇ ਵਿੱਚ Chrome ਡਾਟੇ ਨੂੰ ਕਲੀਅਰ ਕਰੋ<ph name="END_LINK" />।</translation> @@ -297,6 +298,7 @@ ਇਸ ਸੈਟਿੰਗ ਨੂੰ ਬਦਲਣ ਲਈ, <ph name="BEGIN_LINK" />ਆਪਣੇ ਖਾਤੇ ਵਿੱਚ Chrome ਡਾਟੇ ਨੂੰ ਕਲੀਅਰ ਕਰੋ<ph name="END_LINK" />।</translation> <translation id="8857676124663337448">Google Password Manager ਸਾਰੇ ਪਾਸਵਰਡਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਿਆ। ਕੱਲ੍ਹ ਨੂੰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation> <translation id="8865415417596392024">ਤੁਹਾਡੇ ਖਾਤੇ ਵਿਚਲਾ Chrome ਡਾਟਾ</translation> +<translation id="8874688701962049679">Chrome ਦਾ ਵੱਧ ਤੋਂ ਵੱਧ ਲਾਹਾ ਸੰਬੰਧੀ ਨੁਕਤੇ।</translation> <translation id="8891935667620843985">ਤੁਸੀਂ Chrome ਨੂੰ ਆਪਣੀ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਬ੍ਰਾਊਜ਼ਰ ਐਪ ਬਣਾ ਕੇ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਇਸ ਵਿੱਚ ਲਿੰਕ ਖੋਲ੍ਹ ਸਕਦੇ ਹੋ।</translation> <translation id="8897749957032330183">ਪਾਸਵਰਡ ਇਸ ਡੀਵਾਈਸ ਦੇ Google Password Manager ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤੇ ਗਏ ਹਨ।</translation> <translation id="8949681853939555434">Chrome ਨੂੰ ਆਪਣੇ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਬ੍ਰਾਊਜ਼ਰ ਵਜੋਂ ਸੈੱਟ ਕਰੋ</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb index 719ef7d..491de99d 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Para sair da sua Conta do Google em todos os sites, <ph name="BEGIN_LINK" />saia do Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Não foi possível verificar se há atualizações. Tente novamente mais tarde.</translation> <translation id="2702250627063295552">Adicionar item da Lista de leitura ao Chrome</translation> +<translation id="2703746758996815929">Para receber dicas úteis sobre o Chrome, ative as notificações nos ajustes do iOS.</translation> <translation id="2736805085127235148">As notificações do Chrome estão desativadas nas configurações do dispositivo no momento.</translation> <translation id="2767464022270041271">Nenhuma senha salva. O Gerenciador de senhas do Google pode verificar suas senhas quando você as salva.</translation> <translation id="2789947168960170215">Se você esquecer a senha longa ou quiser mudar essa configuração, <ph name="BEGIN_LINK" />limpe os dados do Chrome na sua conta<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Para mudar essa configuração, <ph name="BEGIN_LINK" />limpe os dados do Chrome na sua conta<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">O Gerenciador de senhas do Google não conseguiu verificar todas as senhas. Tente de novo amanhã.</translation> <translation id="8865415417596392024">Dados do Chrome na sua conta</translation> +<translation id="8874688701962049679">Dicas para aproveitar o Chrome ao máximo.</translation> <translation id="8891935667620843985">Defina o Chrome como seu navegador padrão para abrir links nele automaticamente.</translation> <translation id="8897749957032330183">As senhas são salvas no Gerenciador de senhas do Google neste dispositivo.</translation> <translation id="8949681853939555434">Definir o Chrome como seu navegador padrão</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ro.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ro.xtb index b98279d..a75ee937 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ro.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ro.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Pentru a te deconecta de la Contul Google pe toate site-urile, <ph name="BEGIN_LINK" />deconectează-te de la Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome nu a putut căuta actualizări. Încearcă din nou mai târziu.</translation> <translation id="2702250627063295552">Adaugă un element din Lista de lecturi în Chrome</translation> +<translation id="2703746758996815929">Pentru a primi sfaturi utile privind Chrome, activează notificările din setările iOS.</translation> <translation id="2736805085127235148">Notificările din Chrome sunt momentan dezactivate în setările dispozitivului.</translation> <translation id="2767464022270041271">Nu există parole salvate. Managerul de parole Google îți poate verifica parolele atunci când le salvezi.</translation> <translation id="2789947168960170215">Dacă uiți expresia de acces sau dorești să modifici această setare, <ph name="BEGIN_LINK" />șterge datele Chrome din cont<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Pentru a modifica această setare, <ph name="BEGIN_LINK" />șterge datele Chrome din cont<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Managerul de parole Google nu a putut verifica toate parolele. Încearcă din nou mâine.</translation> <translation id="8865415417596392024">Datele Chrome din cont</translation> +<translation id="8874688701962049679">Sfaturi pentru a profita din plin de Chrome.</translation> <translation id="8891935667620843985">Poți deschide automat linkuri în Chrome, setând-o ca aplicație browser prestabilită.</translation> <translation id="8897749957032330183">Parolele sunt salvate în Managerul de parole Google pe acest dispozitiv.</translation> <translation id="8949681853939555434">Setează Chrome ca browser prestabilit</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_si.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_si.xtb index cbdfb13f..7fbeb4a6 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_si.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_si.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">සියලු වෙබ් අඩවිවල ඔබේ Google ගිණුමෙන් වැරීම සඳහා, <ph name="BEGIN_LINK" />Chrome වෙතින් වරන්න<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome හට යාවත්කාලීන සඳහා පරීක්ෂා කළ නොහැකි විය. පසුව නැවත උත්සාහ කරන්න.</translation> <translation id="2702250627063295552">Chrome වෙත කියවීම් ලැයිස්තු අයිතමය එක් කරන්න</translation> +<translation id="2703746758996815929">ප්රයෝජනවත් Chrome ඉඟි ලබා ගැනීමට, ඔබේ iOS සැකසීම් තුළ දැනුම්දීම් සක්රීය කරන්න.</translation> <translation id="2736805085127235148">Chrome දැනුම්දීම් දැනට ඔබේ උපාංග සැකසීම් තුළ ක්රියා විරහිත කර ඇත.</translation> <translation id="2767464022270041271">සුරැකි මුරපද නැත. ඔබ ඔබේ මුරපද සුරකින විට Google මුරපද කළමනාකරු හට ඒවා පරීක්ෂා කළ හැක.</translation> <translation id="2789947168960170215">ඔබට ඔබේ මුර-වැකිකඩ අමතක වුවහොත් හෝ මෙම සැකසීම වෙනස් කිරීමට අවශ්ය නම්, <ph name="BEGIN_LINK" />ඔබේ ගිණුමේ ඇති Chrome දත්ත හිස් කරන්න<ph name="END_LINK" />.</translation> @@ -296,6 +297,7 @@ මෙම සැකසීම වෙනස් කිරීමට <ph name="BEGIN_LINK" />ඔබේ ගිණුම තුළ ඇති Chrome දත්ත හිස් කරන්න<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google මුරපද කළමනාකරු හට සියලු මුරපද පරීක්ෂා කළ නොහැකි විය. හෙට නැවත උත්සාහ කරන්න.</translation> <translation id="8865415417596392024">ඔබේ ගිණුමේ Chrome දත්ත</translation> +<translation id="8874688701962049679">Chrome වෙතින් උපරිම දේ ලබා ගැනීම සඳහා ඉඟි.</translation> <translation id="8891935667620843985">එය ඔබේ පෙරනිමි බ්රව්සර යෙදුම බවට පත් කිරීමෙන් ඔබට Chrome තුළ සබැඳි ස්වයංක්රීයව විවෘත කළ හැක.</translation> <translation id="8897749957032330183">මුරපද මෙම උපාංගයෙහි Google මුරපද කළමනාකරු තුළ සුරැකේ.</translation> <translation id="8949681853939555434">Chrome ඔබේ පෙරනිමි බ්රවුසරය ලෙස සකසන්න</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sl.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sl.xtb index 896ca83..17942e3a 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sl.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sl.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Če se želite odjaviti iz računa Google na vseh spletnih mestih, <ph name="BEGIN_LINK" />se odjavite iz Chroma<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome ni mogel preveriti, ali so na voljo posodobitve. Poskusite pozneje.</translation> <translation id="2702250627063295552">Dodajanje elementa bralnega seznama v Chromu</translation> +<translation id="2703746758996815929">Če želite prejemati uporabne nasvete za Chrome, v nastavitvah sistema iOS vklopite obvestila.</translation> <translation id="2736805085127235148">Obvestila za Chrome so trenutno izklopljena v nastavitvah naprave.</translation> <translation id="2767464022270041271">Ni shranjenih gesel. Googlov upravitelj gesel lahko preveri gesla, če jih shranite.</translation> <translation id="2789947168960170215">Če ste pozabili geslo ali želite to nastavitev spremeniti, <ph name="BEGIN_LINK" />izbrišite podatke iz Chroma v računu<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Če želite spremeniti to nastavitev, <ph name="BEGIN_LINK" />izbrišite podatke iz Chroma v računu<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Googlovemu upravitelju gesel ni uspelo preveriti vseh gesel. Poskusite znova jutri.</translation> <translation id="8865415417596392024">Podatki v Chromu v računu</translation> +<translation id="8874688701962049679">Nasveti, kako najbolje izkoristiti Chrome.</translation> <translation id="8891935667620843985">Če nastavite Chrome kot privzeto aplikacijo za brskanje, lahko samodejno odpirate povezave v njem.</translation> <translation id="8897749957032330183">Gesla so shranjena v Googlovem upravitelju gesel v tej napravi.</translation> <translation id="8949681853939555434">Nastavite Chrome kot privzeti brskalnik</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr-Latn.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr-Latn.xtb index 3951c1d0..d0a0062 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr-Latn.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr-Latn.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Da biste se odjavili sa Google naloga na svim veb-sajtovima, <ph name="BEGIN_LINK" />odjavite se iz Chrome-a<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome ne može da traži ažuriranja. Probajte ponovo kasnije.</translation> <translation id="2702250627063295552">Dodaj stavku liste za čitanje u Chrome</translation> +<translation id="2703746758996815929">Da biste dobijali korisne savete za Chrome, uključite obaveštenja u podešavanjima iOS-a.</translation> <translation id="2736805085127235148">Chrome obaveštenja su trenutno isključena u podešavanjima uređaja.</translation> <translation id="2767464022270041271">Nema sačuvanih lozinki. Google menadžer lozinki može da vam proverava lozinke kada ih sačuvate.</translation> <translation id="2789947168960170215">Ako ste zaboravili pristupnu frazu ili želite da promenite ovo podešavanje, <ph name="BEGIN_LINK" />obrišite Chrome podatke na nalogu<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Da biste promenili ovo podešavanje, <ph name="BEGIN_LINK" />obrišite Chrome podatke na nalogu<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google menadžer lozinki nije uspeo da proveri sve lozinke. Probajte ponovo sutra.</translation> <translation id="8865415417596392024">Chrome podaci na nalogu</translation> +<translation id="8874688701962049679">Saveti kako da na najbolji način koristite Chrome.</translation> <translation id="8891935667620843985">Možete da automatski otvarate linkove u Chrome-u tako što ćete ga podesiti kao podrazumevanu aplikaciju za pregledanje.</translation> <translation id="8897749957032330183">Lozinke se čuvaju u Google menadžeru lozinki na ovom uređaju.</translation> <translation id="8949681853939555434">Podesite Chrome kao podrazumevani pregledač</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr.xtb index c8194201..a3792146 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sr.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Да бисте се одјавили са Google налога на свим веб-сајтовима, <ph name="BEGIN_LINK" />одјавите се из Chrome-а<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome не може да тражи ажурирања. Пробајте поново касније.</translation> <translation id="2702250627063295552">Додај ставку листе за читање у Chrome</translation> +<translation id="2703746758996815929">Да бисте добијали корисне савете за Chrome, укључите обавештења у подешавањима iOS-а.</translation> <translation id="2736805085127235148">Chrome обавештења су тренутно искључена у подешавањима уређаја.</translation> <translation id="2767464022270041271">Нема сачуваних лозинки. Google менаџер лозинки може да вам проверава лозинке када их сачувате.</translation> <translation id="2789947168960170215">Ако сте заборавили приступну фразу или желите да промените ово подешавање, <ph name="BEGIN_LINK" />обришите Chrome податке на налогу<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Да бисте променили ово подешавање, <ph name="BEGIN_LINK" />обришите Chrome податке на налогу<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google менаџер лозинки није успео да провери све лозинке. Пробајте поново сутра.</translation> <translation id="8865415417596392024">Chrome подаци на налогу</translation> +<translation id="8874688701962049679">Савети како да на најбољи начин користите Chrome.</translation> <translation id="8891935667620843985">Можете да аутоматски отварате линкове у Chrome-у тако што ћете га подесити као подразумевану апликацију за прегледање.</translation> <translation id="8897749957032330183">Лозинке се чувају у Google менаџеру лозинки на овом уређају.</translation> <translation id="8949681853939555434">Подесите Chrome као подразумевани прегледач</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_te.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_te.xtb index e390114..580af2ca 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_te.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_te.xtb
@@ -77,6 +77,7 @@ <translation id="2702250627063295552">Chromeకు చదవాల్సిన లిస్ట్ ఐటెమ్ను జోడించండి</translation> <translation id="2703746758996815929">సహాయకరంగా ఉండే Chrome చిట్కాలను పొందడానికి, మీ iOS సెట్టింగ్లలో నోటిఫికేషన్లను ఆన్ చేయండి.</translation> <translation id="2736805085127235148">మీ పరికర సెట్టింగ్లలో ప్రస్తుతం Chrome నోటిఫికేషన్లు ఆఫ్ చేయబడ్డాయి.</translation> +<translation id="2750626042242931740">మీరు Chrome సెట్టింగ్లలో ఎప్పుడైనా మీ ఎంపికలను అప్డేట్ చేయవచ్చు.</translation> <translation id="2767464022270041271">సేవ్ చేసిన పాస్వర్డ్లు ఏవీ లేవు. మీరు వాటిని సేవ్ చేసినప్పుడు Google Password Manager మీ పాస్వర్డ్లను చెక్ చేయవచ్చు.</translation> <translation id="2789947168960170215">మీ రహస్య పదబంధాన్ని మీరు మర్చిపోయినా లేదా ఈ సెట్టింగ్ను మార్చాలనుకున్నా, <ph name="BEGIN_LINK" />మీ ఖాతాలోని Chrome డేటాను తీసివేయండి<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Chromeలో బ్రౌజింగ్ డేటాను క్లియర్ చేయండి</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_th.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_th.xtb index 40ea34e..ec9fce5 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_th.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_th.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">หากต้องการออกจากระบบบัญชี Google ในเว็บไซต์ทั้งหมด ให้<ph name="BEGIN_LINK" />ออกจากระบบ Chrome<ph name="END_LINK" /></translation> <translation id="2695886661449553974">Chrome ตรวจหาอัปเดตไม่ได้ โปรดลองอีกครั้งภายหลัง</translation> <translation id="2702250627063295552">เพิ่มรายการเรื่องรออ่านใน Chrome</translation> +<translation id="2703746758996815929">หากต้องการรับเคล็ดลับที่มีประโยชน์เกี่ยวกับ Chrome ให้เปิดการแจ้งเตือนในการตั้งค่า iOS</translation> <translation id="2736805085127235148">ตอนนี้การแจ้งเตือนของ Chrome ปิดอยู่ในการตั้งค่าอุปกรณ์</translation> +<translation id="2750626042242931740">คุณอัปเดตสิ่งที่เลือกไว้ได้ทุกเมื่อในการตั้งค่า Chrome</translation> <translation id="2767464022270041271">ไม่มีรหัสผ่านที่บันทึกไว้ เครื่องมือจัดการรหัสผ่านบน Google จะตรวจสอบรหัสผ่านได้เมื่อคุณบันทึกไว้</translation> <translation id="2789947168960170215">หากลืมรหัสผ่านหรือต้องการเปลี่ยนการตั้งค่านี้ ให้<ph name="BEGIN_LINK" />ล้างข้อมูล Chrome ในบัญชี<ph name="END_LINK" /></translation> <translation id="2868822340714096138">ล้างข้อมูลการท่องเว็บใน Chrome</translation> @@ -297,6 +299,7 @@ หากต้องการเปลี่ยนแปลงการตั้งค่านี้ ให้<ph name="BEGIN_LINK" />ล้างข้อมูล Chrome ในบัญชี<ph name="END_LINK" /></translation> <translation id="8857676124663337448">เครื่องมือจัดการรหัสผ่านบน Google ตรวจสอบรหัสผ่านได้ไม่ครบทั้งหมด โปรดลองอีกครั้งในวันพรุ่งนี้</translation> <translation id="8865415417596392024">ข้อมูล Chrome ในบัญชี</translation> +<translation id="8874688701962049679">เคล็ดลับในการรับประโยชน์สูงสุดจาก Chrome</translation> <translation id="8891935667620843985">คุณเปิดลิงก์ใน Chrome โดยอัตโนมัติได้ด้วยการตั้งเป็นแอปเบราว์เซอร์เริ่มต้น</translation> <translation id="8897749957032330183">รหัสผ่านจะบันทึกอยู่ในเครื่องมือจัดการรหัสผ่านบน Google ในอุปกรณ์นี้</translation> <translation id="8949681853939555434">ตั้ง Chrome เป็นเบราว์เซอร์เริ่มต้น</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_uk.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_uk.xtb index c6026bf8..e4c6337 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_uk.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_uk.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">Щоб вийти з облікового запису Google на всіх веб-сайтах, <ph name="BEGIN_LINK" />вийдіть із Chrome<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Веб-переглядачу Chrome не вдалося перевірити наявність оновлень. Повторіть спробу пізніше.</translation> <translation id="2702250627063295552">Додати пункт до списку читання в Chrome</translation> +<translation id="2703746758996815929">Щоб отримувати корисні поради щодо Chrome, увімкніть сповіщення в налаштуваннях iOS.</translation> <translation id="2736805085127235148">Сповіщення Chrome зараз вимкнено в налаштуваннях пристрою.</translation> <translation id="2767464022270041271">Немає збережених паролів. Google Менеджер паролів зможе перевірити ваші паролі, коли ви їх збережете.</translation> <translation id="2789947168960170215">Якщо ви забули парольну фразу або хочете змінити це налаштування, <ph name="BEGIN_LINK" />очистьте дані Chrome у своєму обліковому записі<ph name="END_LINK" />.</translation> @@ -297,6 +298,7 @@ Щоб змінити це налаштування, <ph name="BEGIN_LINK" />очистьте дані Chrome у своєму обліковому записі<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Менеджеру паролів не вдалося перевірити всі паролі. Спробуйте завтра.</translation> <translation id="8865415417596392024">Дані Chrome у вашому обліковому записі</translation> +<translation id="8874688701962049679">Поради з ефективного використання Chrome.</translation> <translation id="8891935667620843985">Щоб автоматично відкривати посилання в додатку Chrome, зробіть його своїм веб-переглядачем за умовчанням</translation> <translation id="8897749957032330183">Паролі збережено в Google Менеджері паролів на цьому пристрої.</translation> <translation id="8949681853939555434">Зробіть Chrome веб-переглядачем за умовчанням</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ur.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ur.xtb index 72506aff..cdeb8c6 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ur.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ur.xtb
@@ -75,6 +75,7 @@ <translation id="2689064829982324496">سبھی ویب سائٹس پر اپنے Google اکاؤنٹ سے سائن آؤٹ کرنے کے لیے <ph name="BEGIN_LINK" />Chrome سے سائن آؤٹ کریں<ph name="END_LINK" />۔</translation> <translation id="2695886661449553974">Chrome اپ ڈیٹس چیک نہیں کر سکا۔ بعد میں دوبارہ کوشش کریں۔</translation> <translation id="2702250627063295552">Chrome میں پڑھنے کی فہرست آئٹم شامل کریں</translation> +<translation id="2703746758996815929">Chrome کی کارآمد تجاویز حاصل کرنے کے لیے، اپنی iOS کی ترتیبات میں اطلاعات کو آن کریں۔</translation> <translation id="2736805085127235148">Chrome کی اطلاعات فی الحال آپ کے آلے کی ترتیبات میں آف ہیں۔</translation> <translation id="2767464022270041271">کوئی محفوظ کردہ پاس ورڈز نہیں۔ جب آپ اپنے پاس ورڈز کو محفوظ کرتے ہیں تو Google پاس ورڈ مینیجر انہیں چیک کر سکتا ہے۔</translation> <translation id="2789947168960170215">اگر آپ اپنا پاس فریز بھول گئے ہیں یا اس ترتیب کو تبدیل کرنا چاہتے ہیں تو <ph name="BEGIN_LINK" />اپنے اکاؤنٹ میں موجود Chrome ڈیٹا کو صاف کریں<ph name="END_LINK" />۔</translation> @@ -297,6 +298,7 @@ اس ترتیب کو تبدیل کرنے کے لیے، <ph name="BEGIN_LINK" />اپنے اکاؤنٹ میں موجود Chrome ڈیٹا کو صاف کریں<ph name="END_LINK" />۔</translation> <translation id="8857676124663337448">Google پاس ورڈ مینیجر تمام پاس ورڈز کو چیک نہیں کر سکتا۔ کل دوبارہ کوشش کریں۔</translation> <translation id="8865415417596392024">آپ کے اکاؤنٹ میں Chrome کا ڈیٹا</translation> +<translation id="8874688701962049679">Chrome سے زیادہ سے زیادہ فائدہ اٹھانے کے لیے تجاویز۔</translation> <translation id="8891935667620843985">آپ Chrome میں لنکس کو اپنی ڈیفالٹ براؤزر ایپ بنا کر خودکار طور پر اسے کھول سکتے ہیں۔</translation> <translation id="8897749957032330183">پاس ورڈز اس آلہ پر Google پاس ورڈ مینیجر میں محفوظ کیے جاتے ہیں۔</translation> <translation id="8949681853939555434">Chrome کو اپنے ڈیفالٹ براؤزر کے طور پر سیٹ کریں</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_uz.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_uz.xtb index e36b8ce..87bf0d2 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_uz.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_uz.xtb
@@ -76,7 +76,9 @@ <translation id="2689064829982324496">Barcha saytlarda Google hisobingizdan chiqish uchun <ph name="BEGIN_LINK" />Chrome brauzerida hisobdan chiqing<ph name="END_LINK" />.</translation> <translation id="2695886661449553974">Chrome yangilanishlar chiqqanini tekshira olmadi. Keyinroq qayta urining.</translation> <translation id="2702250627063295552">Saqlangan sahifalar bandini Chromeʼa qoʻshish</translation> +<translation id="2703746758996815929">Chrome haqida tavsiyalar olish uchun iOS sozlamalari orqali bildirishnomalarni yoqing.</translation> <translation id="2736805085127235148">Chrome bildirishnomalari ayni vaqtda qurilma sozlamalarida yoniq emas</translation> +<translation id="2750626042242931740">Tanlovlarni istalgan vaqt Chrome sozlamalari orqali yangilash mumkin.</translation> <translation id="2767464022270041271">Hech qanday parol saqlanmagan. Google Parollar menejeri parollarni saqlanishidan oldin tekshirishi mumkin.</translation> <translation id="2789947168960170215">Agar kodli iborani unutsangiz yoki bu sozlamani oʻzgartirmoqchi boʻlsangiz, <ph name="BEGIN_LINK" />hisobingizda Chrome maʼlumotlarini tozalang<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Chrome brauzer maʼlumotlarini tozalash</translation> @@ -298,6 +300,7 @@ Bu sozlamani oʻzgartirish uchun <ph name="BEGIN_LINK" />hisobingizda Chrome maʼlumotlarini tozalang<ph name="END_LINK" />.</translation> <translation id="8857676124663337448">Google Parollar menejeri barcha parollarni tekshira olmadi. Ertaga qayta urining.</translation> <translation id="8865415417596392024">Hisobingizdagi Chrome maʼlumotlari</translation> +<translation id="8874688701962049679">Chromedan unumli foydalanish maslahatlari.</translation> <translation id="8891935667620843985">Saytlar Chrome brauzerida avtomatik ochilishi uchun uni birlamchi brauzer etib tayinlash kifoya.</translation> <translation id="8897749957032330183">Parollar shu qurilmadagi Google Parollar menejeriga saqlanadi.</translation> <translation id="8949681853939555434">Chromeni asosiy brauzer deb belgilang</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-HK.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-HK.xtb index 220292b..e1a9af8 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-HK.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-HK.xtb
@@ -75,7 +75,9 @@ <translation id="2689064829982324496">如要在所有網站上登出 Google 帳戶,請<ph name="BEGIN_LINK" />登出 Chrome<ph name="END_LINK" />。</translation> <translation id="2695886661449553974">Chrome 無法檢查更新,請稍後再試。</translation> <translation id="2702250627063295552">將閱讀清單項目新增至 Chrome</translation> +<translation id="2703746758996815929">如要取得 Chrome 的實用提示,請在 iOS 設定中開啟通知功能。</translation> <translation id="2736805085127235148">目前未在裝置設定中開啟 Chrome 通知。</translation> +<translation id="2750626042242931740">你可隨時在 Chrome 設定中更新所選項目。</translation> <translation id="2767464022270041271">沒有已儲存的密碼。當您儲存密碼時,「Google 密碼管理工具」可檢查您的密碼。</translation> <translation id="2789947168960170215">如果忘記密碼短語或想變更此設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chrome 資料<ph name="END_LINK" />。</translation> <translation id="2868822340714096138">清除 Chrome 中的瀏覽資料</translation> @@ -179,7 +181,7 @@ <translation id="6054613632208573261">預設為使用 Chrome</translation> <translation id="6063091872902370735">允許登入 Chrome</translation> <translation id="6110625574506755980">部分 Chrome 功能將無法再使用。</translation> -<translation id="6132149203299792222">登入 Google 帳戶就能同步處理密碼、書籤和其他資訊。</translation> +<translation id="6132149203299792222">登入 Google 帳戶就能同步處理密碼、書籤和其他資料。</translation> <translation id="6177442314419606057">在 Chrome 中搜尋</translation> <translation id="6181930887571472871">切換至 Chrome</translation> <translation id="6238746320622508509">讓 Chrome 鎖定您的無痕式分頁。</translation> @@ -251,8 +253,8 @@ <translation id="7897703007638178753">查看 Chrome 最近開啟的分頁</translation> <translation id="7925119591961387184">選取 [Chrome]。</translation> <translation id="7933491483529363150">在 Chrome 中開啟「我的最新分頁」。</translation> -<translation id="7948283758957877064">Chrome 新功能</translation> -<translation id="8006014511203279255">隨時可以使用 Chrome 開啟訊息或其他應用程式中的連結。</translation> +<translation id="7948283758957877064">Chrome 的新功能</translation> +<translation id="8006014511203279255">隨時使用 Chrome 開啟訊息或其他應用程式中的連結。</translation> <translation id="8022947259858476807">預設使用 Chrome 來開啟連結、從小工具搜尋,以及在其他應用程式中自動填入密碼</translation> <translation id="804638182476029347">允許 Chrome 顯示通知才能接收降價快訊</translation> <translation id="8065292699993359127">在 Chrome 中以無痕模式開啟網址</translation> @@ -289,7 +291,7 @@ <translation id="8765470054473112089">在網址列或搜尋框中輸入內容時,Chrome 會將輸入的內容傳送至預設搜尋引擎,以便取得更切合需求的建議。此功能不會在無痕模式下啟用。</translation> <translation id="8772179140489533211">顯示登入 Chrome 的指示。</translation> <translation id="8788269841521769222">您不需記住此密碼。密碼將會儲存至 <ph name="EMAIL" /> 的「Google 密碼管理工具」</translation> -<translation id="878917453316810648">Chrome 提示:將 Chrome 設為預設瀏覽器</translation> +<translation id="878917453316810648">Chrome 提示:將 Chrome 設定為預設瀏覽器</translation> <translation id="8808828119384186784">Chrome 設定</translation> <translation id="8855781063981781621">在 iPad 上關閉「封鎖模式」,就能在 Chrome 中停用此模式。</translation> <translation id="8856877214925961642">密碼短語加密的資料不包括付款方法和地址。 @@ -297,6 +299,7 @@ 如要變更此設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chrome 資料<ph name="END_LINK" />。</translation> <translation id="8857676124663337448">「Google 密碼管理工具」無法檢查所有密碼。請明天再試。</translation> <translation id="8865415417596392024">帳戶中的 Chrome 資料</translation> +<translation id="8874688701962049679">可協助你充分運用 Chrome 的各項提示。</translation> <translation id="8891935667620843985">將 Chrome 設定為「預設瀏覽器應用程式」,即可自動以 Chrome 開啟連結。</translation> <translation id="8897749957032330183">密碼會儲存至此裝置上的「Google 密碼管理工具」。</translation> <translation id="8949681853939555434">將 Chrome 設定為預設瀏覽器</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-TW.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-TW.xtb index 9b469db..7499faad 100644 --- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-TW.xtb +++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-TW.xtb
@@ -73,7 +73,9 @@ <translation id="2689064829982324496">如要從所有網站中登出 Google 帳戶,請<ph name="BEGIN_LINK" />登出 Chrome<ph name="END_LINK" />。</translation> <translation id="2695886661449553974">Chrome 無法檢查更新,請稍後再試。</translation> <translation id="2702250627063295552">將閱讀清單項目加入 Chrome</translation> +<translation id="2703746758996815929">如要取得 Chrome 的實用提示,請在 iOS 設定中開啟通知功能。</translation> <translation id="2736805085127235148">目前未在裝置設定中開啟 Chrome 通知。</translation> +<translation id="2750626042242931740">你隨時可以在 Chrome 設定中更新所選項目。</translation> <translation id="2767464022270041271">尚未儲存任何密碼。你必須先儲存密碼,才能使用 Google 密碼管理工具的檢查功能。</translation> <translation id="2789947168960170215">如果忘記通關密語或想要變更這項設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chrome 資料<ph name="END_LINK" />。</translation> <translation id="2868822340714096138">清除 Chrome 中的瀏覽資料</translation> @@ -295,6 +297,7 @@ 如要變更這項設定,請<ph name="BEGIN_LINK" />清除帳戶中的 Chrome 資料<ph name="END_LINK" />。</translation> <translation id="8857676124663337448">Google 密碼管理工具無法檢查所有密碼,請明天再試。</translation> <translation id="8865415417596392024">你帳戶中的 Chrome 資料</translation> +<translation id="8874688701962049679">可協助你充分運用 Chrome 的各項提示。</translation> <translation id="8891935667620843985">只要將 Chrome 設為預設瀏覽器應用程式,即可自動在 Chrome 中開啟連結。</translation> <translation id="8897749957032330183">密碼會儲存至這部裝置的 Google 密碼管理工具。</translation> <translation id="8949681853939555434">將 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 5a2c977..cf9f7f59 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
@@ -76,6 +76,7 @@ <translation id="2695886661449553974">I-Chrome ayikwazanga ukuhlola izibuyekezo. Zama futhi emuva kwesikhathi.</translation> <translation id="2702250627063295552">Ifaka Into Yohlu Lokufunda ku-Chrome</translation> <translation id="2736805085127235148">Izaziso ze-Chrome okwamanje zivaliwe kumasethingi edivayisi yakho.</translation> +<translation id="2750626042242931740">Ungabuyekeza okukhethile noma nini Kumasethingi e-Chrome.</translation> <translation id="2767464022270041271">Awekho amaphasiwedi alondoloziwe. Isiphathi Sephasiwedi ye-Google singahlola amaphasiwedi akho uma uwalondoloza.</translation> <translation id="2789947168960170215">Uma ukhohlwa umushwana wakho wokungena noma ufuna ukushintsha le sethingi, <ph name="BEGIN_LINK" />sula idatha ye-Chrome ku-akhawunti yakho<ph name="END_LINK" />.</translation> <translation id="2868822340714096138">Sula Idatha Yokubhrawuza ku-Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_am.xtb b/ios/chrome/app/strings/resources/ios_strings_am.xtb index 3af75ca..765005c 100644 --- a/ios/chrome/app/strings/resources/ios_strings_am.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_am.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">ማውረድ ተጠናቅቋል</translation> <translation id="3968505803272650567">ፍላጎቶችን አቀናብር</translation> <translation id="3989635538409502728">ዘግተህ ውጣ</translation> +<translation id="3994422733891749358">የትኛዎቹን ማስታወቂያዎች መቀበል እንደሚፈልጉ ይምረጡ</translation> <translation id="3995521777587992544">የገጽ መጫን ሂደት አሞሌ፣ <ph name="EMAIL" /> ተጭኗል።</translation> <translation id="3997522473364371632">የይለፍ ቃል ማጋራት በአስተዳዳሪዎ ተሰናክሏል።</translation> <translation id="4002019827078931033">የአድራሻ አሞሌን ወደ ላይ ይውሰዱ</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">የቁልፍ ሰሌዳ</translation> <translation id="4601095002996233687">ለሚያጠራጥሩ ውርዶች በጥልቀት የሚደረጉ ቅኝቶች።</translation> <translation id="4606247758155004938">የእርስዎ አሳሽ በእርስዎ ድርጅት የሚተዳደር ነው።</translation> +<translation id="4607887340472970274">የዋጋ ክትትል</translation> <translation id="4611811151908969241"><ph name="DOMAIN_NAME" /> አለመከተልን ደብቅ</translation> <translation id="461440297010471931">በGoogle መፈለግ</translation> <translation id="4616391354457235490">ቀልብስ</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">በማንነትን የማያሳውቅ ይከፈት?</translation> <translation id="4803185665210547709">በእርስዎ ድርጅት የሚተዳደር። <ph name="BEGIN_LINK" />የበለጠ ለመረዳት<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">በዝንባሌዎችዎ ላይ የተመሰረተ ዜና እና ይዘት።</translation> <translation id="4805759445554688327">ልክ ያልሆነ የካርድ ቁጥር</translation> <translation id="4808646838864186379">የእርስዎ ማድረስ ተሰርዟል</translation> <translation id="4808744395915275922">ዝማኔዎች</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> ያልተነበቡ ጽሑፎች።</translation> <translation id="7412027924265291969">ቀጥል</translation> <translation id="741204030948306876">አዎ፣ ገብቼያለሁ</translation> +<translation id="7417689656810783109">ቡድንን እንደገና ይሰይሙ</translation> <translation id="7418640008860669073">አስቀምጥ በ...</translation> <translation id="7425346204213733349">በእርስዎ ዕልባቶች፣ ታሪክ፣ የይለፍ ቃላት እና ሌሎች ቅንብሮች ላይ የተደረጉ ለውጦች ከአሁን በኋላ ከእርስዎ የGoogle መለያ ጋር አይሠምሩም። ሆኖም ግን ነባር ውሂብዎ በእርስዎ የGoogle መለያ ላይ እንደተከማቸ ይቆያል።</translation> <translation id="7431991332293347422">ፍለጋን እና ተጨማሪ ነገሮችን ግላዊነት ለማላበስ የእርስዎ የአሰሳ ታሪክ እንዴት ጥቅም ላይ እንደሚውል ይቆጣጠሩ</translation> @@ -1415,6 +1419,7 @@ <translation id="828291969289324795">{count,plural, =1{ትር ወደ አዲስ ቡድን ያክሉ}one{ትር ወደ አዲስ ቡድን ያክሉ}other{ትሮችን ወደ አዲስ ቡድን ያክሉ}}</translation> <translation id="8283172974887967105">ያቀናብሩ…</translation> <translation id="8286036467436129157">ግባ</translation> +<translation id="8292843446079898078">ለሚከታተሏቸው ምርቶች የዋጋ ቅናሽ ማንቂያዎችን ይቀበሉ።</translation> <translation id="8299417921174340354">የይለፍ ቃላትን ለመጠቀም መጀመሪያ በመሣሪያዎ ላይ የይለፍ ኮድ ማቀናበር አለብዎት።</translation> <translation id="8299613349954694191">ድሩን በግል ለማሰስ ማንነት የማያሳውቅ ትር ይክፈቱ።</translation> <translation id="8311853334103696030">ዋጋ ተከታተል የሚለውን ደብቅ</translation> @@ -1422,6 +1427,7 @@ <translation id="8328777765163860529">ሁሉንም ዝጋ</translation> <translation id="8343993175958086504">የእርስዎን ነገሮች ምትኬ ያስቀምጡ እና በማንኛውም መሣሪያ ላይ ይጠቀሙበት።</translation> <translation id="834783239627985533">በብዛት የተጎበኙ ጣቢያዎች</translation> +<translation id="8358401059263985056">ማሳወቂያዎችን አብራ</translation> <translation id="8364841868226993049">በGoogle ፎቶዎች ውስጥ ለ<ph name="USER_EMAIL" /> ምስልን በማስቀመጥ ላይ...</translation> <translation id="8370406443343902172">ወደ ቅንብሮች ሂድ…</translation> <translation id="8374977641764177587">ማሳወቂያዎችን አብራ?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ar.xtb b/ios/chrome/app/strings/resources/ios_strings_ar.xtb index a80cbac..1bd69cf 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ar.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ar.xtb
@@ -1414,6 +1414,7 @@ <translation id="8273982424131314219">سيتم ملء المعلومات في <ph name="URL" />.</translation> <translation id="8281781826761538115">التلقائي - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">التخطّي</translation> +<translation id="828291969289324795">{count,plural, =1{إضافة علامة التبويب إلى مجموعة جديدة}zero{إضافة علامات التبويب إلى مجموعة جديدة}two{إضافة علامتَي التبويب إلى مجموعة جديدة}few{إضافة علامات التبويب إلى مجموعة جديدة}many{إضافة علامات التبويب إلى مجموعة جديدة}other{إضافة علامات التبويب إلى مجموعة جديدة}}</translation> <translation id="8283172974887967105">ضبط…</translation> <translation id="8286036467436129157">تسجيل الدخول</translation> <translation id="8299417921174340354">لاستخدام كلمات المرور، عليك أولاً إعداد رمز مرور على جهازك.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_as.xtb b/ios/chrome/app/strings/resources/ios_strings_as.xtb index ba0f488..eba8c4a 100644 --- a/ios/chrome/app/strings/resources/ios_strings_as.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_as.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">ডাউনল’ড সম্পূৰ্ণ হ’ল</translation> <translation id="3968505803272650567">আগ্ৰহসমূহ পৰিচালনা কৰক</translation> <translation id="3989635538409502728">ছাইন আউট কৰক</translation> +<translation id="3994422733891749358">আপুনি লাভ কৰিব বিচৰা জাননীসমূহ বাছনি কৰক</translation> <translation id="3995521777587992544">পৃষ্ঠা ল’ড হোৱাৰ প্ৰগতিৰ বাৰ, <ph name="EMAIL" /> ল’ড হৈছে।</translation> <translation id="3997522473364371632">আপোনাৰ প্ৰশাসকে পাছৱৰ্ড শ্বেয়াৰ কৰাটো অক্ষম কৰিছে।</translation> <translation id="4002019827078931033">ঠিকনাৰ বাৰ ওপৰলৈ লৈ যাওক</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">কীব’ৰ্ড</translation> <translation id="4601095002996233687">সন্দেহজনক ডাউনল’ডৰ বাবে বিস্তাৰিত স্কেনৰ সুবিধা</translation> <translation id="4606247758155004938">আপোনাৰ প্ৰতিষ্ঠানে আপোনাৰ ব্ৰাউজাৰটো পৰিচালনা কৰে।</translation> +<translation id="4607887340472970274">মূল্য ট্ৰেকিং</translation> <translation id="4611811151908969241"><ph name="DOMAIN_NAME" />ক আনফ’ল’ কৰাৰ সুবিধাটো লুকুৱাওক</translation> <translation id="461440297010471931">Googleৰ জৰিয়তে সন্ধান কৰি থকা হৈছে</translation> <translation id="4616391354457235490">আনডু কৰক</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">ইনক’গনিট’ ম’ডত খুলিবনে?</translation> <translation id="4803185665210547709">আপোনাৰ প্ৰতিষ্ঠানে পৰিচালনা কৰে। <ph name="BEGIN_LINK" />অধিক জানক<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">আপোনাৰ আগ্ৰহৰ ওপৰত ভিত্তি কৰি লাভ কৰা বাতৰি আৰু সমল।</translation> <translation id="4805759445554688327">কার্ডৰ নম্বৰ অমান্য</translation> <translation id="4808646838864186379">আপোনাৰ ডেলিভাৰীটো বাতিল কৰা হৈছে</translation> <translation id="4808744395915275922">আপডে’টসমূহ</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" />টা নপঢ়া প্ৰবন্ধ।</translation> <translation id="7412027924265291969">অব্যাহত ৰাখক</translation> <translation id="741204030948306876">হয়, মই সন্মত</translation> +<translation id="7417689656810783109">গোটটোৰ নতুন নাম দিয়ক</translation> <translation id="7418640008860669073">ইয়াত ছেভ কৰক...</translation> <translation id="7425346204213733349">আপোনাৰ বুকমাৰ্ক, ইতিহাস, পাছৱৰ্ড আৰু অন্য ছেটিংসমূহত কৰা সলনি কার্যসমূহ আপোনাৰ Google একাউণ্টত আৰু ছিংক কৰা নহয়। তথাপিও, আপোনাৰ পূর্বে থকা ডেটাসমূহ নিজৰ Google একাউণ্টত সঞ্চিত হৈ থাকিব।</translation> <translation id="7431991332293347422">আপোনাক Search আৰু অন্য সেৱাসমূহত ব্যক্তিগতকৰণ কৰা অভিজ্ঞতা প্ৰদান কৰিবলৈ কেনেকৈ আপোনাৰ ব্ৰাউজিংৰ ইতিহাস ব্যৱহাৰ কৰা হয় সেয়া নিয়ন্ত্ৰণ কৰক</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">আপুনি <ph name="URL" />ত তথ্য পূৰ কৰিব</translation> <translation id="8281781826761538115">ডিফ’ল্ট - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">এৰি যাওক</translation> +<translation id="828291969289324795">{count,plural, =1{নতুন গোটত টেব যোগ দিয়ক}one{নতুন গোটত টেবসমূহ যোগ দিয়ক}other{নতুন গোটত টেবসমূহ যোগ দিয়ক}}</translation> <translation id="8283172974887967105">ছেট কৰক…</translation> <translation id="8286036467436129157">ছাইন ইন কৰক</translation> +<translation id="8292843446079898078">আপুনি ট্ৰেক কৰা প্ৰ’ডাক্টসমূহৰ বাবে মূল্য কমাৰ সতৰ্কবাৰ্তা লাভ কৰক।</translation> <translation id="8299417921174340354">পাছৱৰ্ডসমূহ ব্যৱহাৰ কৰিবলৈ আপুনি প্ৰথমে নিজৰ ডিভাইচত এটা পাছক’ড ছেট কৰিবই লাগিব।</translation> <translation id="8299613349954694191">ৱেব ব্যক্তিগতভাৱে ব্ৰাউজ কৰিবলৈ কোনো ইনক’গনিট‘ টেব খোলক।</translation> <translation id="8311853334103696030">দাম ট্ৰেক কৰক লুকুৱাওক</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">সকলো বন্ধ কৰক</translation> <translation id="8343993175958086504">আপোনাৰ বস্তুবোৰৰ বেক আপ লওক আৰু সেইবোৰ যিকোনো ডিভাইচত ব্যৱহাৰ কৰক।</translation> <translation id="834783239627985533">আটাইতকৈ বেছিকৈ চোৱা ছাইটসমূহ</translation> +<translation id="8358401059263985056">জাননী অন কৰক</translation> <translation id="8364841868226993049"><ph name="USER_EMAIL" />ৰ বাবে Google Photosত প্ৰতিচ্ছবি ছেভ কৰি থকা হৈছে...</translation> <translation id="8370406443343902172">ছেটিঙলৈ যাওক...</translation> <translation id="8374977641764177587">জাননী অন কৰিবনে?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_az.xtb b/ios/chrome/app/strings/resources/ios_strings_az.xtb index a58ee94..ad30345 100644 --- a/ios/chrome/app/strings/resources/ios_strings_az.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_az.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Məlumatlar <ph name="URL" /> saytına daxil ediləcək</translation> <translation id="8281781826761538115">Defolt - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Keçin</translation> +<translation id="828291969289324795">{count,plural, =1{Yeni qrupa tab əlavə edin}other{Yeni qrupa tablar əlavə edin}}</translation> <translation id="8283172974887967105">Ayarlayın:</translation> <translation id="8286036467436129157">Giriş</translation> <translation id="8299417921174340354">Parollardan istifadə etmək üçün əvvəlcə cihazınızda parol ayarlamalısınız.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_bs.xtb b/ios/chrome/app/strings/resources/ios_strings_bs.xtb index 7682f04b..16c84061 100644 --- a/ios/chrome/app/strings/resources/ios_strings_bs.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_bs.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Preuzimanje je završeno</translation> <translation id="3968505803272650567">Upravljajte interesovanjima</translation> <translation id="3989635538409502728">Odjava</translation> +<translation id="3994422733891749358">Odaberite obavijesti koje želite primati</translation> <translation id="3995521777587992544">Traka napretka učitavanja stranice, učitano <ph name="EMAIL" />.</translation> <translation id="3997522473364371632">Dijeljenje lozinke je onemogućio administrator.</translation> <translation id="4002019827078931033">Premjesti traku za adresu na vrh</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Tastatura</translation> <translation id="4601095002996233687">Detaljna skeniranja radi provjere sumnjivih preuzimanja.</translation> <translation id="4606247758155004938">Preglednikom upravlja vaša organizacija.</translation> +<translation id="4607887340472970274">Praćenje cijene</translation> <translation id="4611811151908969241">Sakrij prestanak praćenja domene <ph name="DOMAIN_NAME" /></translation> <translation id="461440297010471931">Pretraživanje s Googleom</translation> <translation id="4616391354457235490">Poništi</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Otvoriti u anonimnom načinu rada?</translation> <translation id="4803185665210547709">Upravlja vaša organizacija. <ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Vijesti i sadržaj na temelju vaših interesa.</translation> <translation id="4805759445554688327">Nevažeći broj kartice</translation> <translation id="4808646838864186379">Isporuka je otkazana</translation> <translation id="4808744395915275922">Ažuriranja</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906">Broj nepročitanih članaka: <ph name="UNREAD_COUNT" />.</translation> <translation id="7412027924265291969">Nastavi</translation> <translation id="741204030948306876">Da, želim</translation> +<translation id="7417689656810783109">Preimenovanje grupe</translation> <translation id="7418640008860669073">Pohranjivanje na lokaciju…</translation> <translation id="7425346204213733349">Promjene vaših oznaka, historije, lozinki i drugih postavki neće se više sinhronizirati s vašim Google računom. Međutim, vaši postojeći podaci će ostati pohranjeni na vašem Google računu.</translation> <translation id="7431991332293347422">Kontrolirajte kako se koristi vaša historija pregledanja za personalizaciju Pretraživanja i još mnogo toga</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">Popunit ćete informacije na web lokaciji <ph name="URL" /></translation> <translation id="8281781826761538115">Zadano – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Preskoči</translation> +<translation id="828291969289324795">{count,plural, =1{Dodaj karticu u novu grupu}one{Dodaj kartice u novu grupu}few{Dodaj kartice u novu grupu}other{Dodaj kartice u novu grupu}}</translation> <translation id="8283172974887967105">Postavi…</translation> <translation id="8286036467436129157">Prijava</translation> +<translation id="8292843446079898078">Primajte upozorenja o padu cijena za proizvode koje pratite.</translation> <translation id="8299417921174340354">Prvo postavite šifru na uređaju da koristite lozinke.</translation> <translation id="8299613349954694191">Otvorite anonimnu karticu za privatno pregledanje weba.</translation> <translation id="8311853334103696030">Sakrij praćenje cijena</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">Zatvori sve</translation> <translation id="8343993175958086504">Napravite sigurnosnu kopiju svojih stvari i koristite ih na bilo kojem uređaju.</translation> <translation id="834783239627985533">Najposjećenije web lokacije</translation> +<translation id="8358401059263985056">Uključi obavijesti</translation> <translation id="8364841868226993049">Pohranjivanje slike u Google Fotografijama za <ph name="USER_EMAIL" />…</translation> <translation id="8370406443343902172">Odlazak u Postavke…</translation> <translation id="8374977641764177587">Uključiti obavještenja?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ca.xtb b/ios/chrome/app/strings/resources/ios_strings_ca.xtb index a57d0b27..ad69c9d 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ca.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ca.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Emplenaràs informació a <ph name="URL" /></translation> <translation id="8281781826761538115">Idioma predeterminat: <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Omet</translation> +<translation id="828291969289324795">{count,plural, =1{Afegeix una pestanya al grup nou}other{Afegeix pestanyes al grup nou}}</translation> <translation id="8283172974887967105">Estableix…</translation> <translation id="8286036467436129157">Inicia la sessió</translation> <translation id="8299417921174340354">Per utilitzar les contrasenyes, primer has d'establir una contrasenya al dispositiu.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_cy.xtb b/ios/chrome/app/strings/resources/ios_strings_cy.xtb index 5757f88..6177e04 100644 --- a/ios/chrome/app/strings/resources/ios_strings_cy.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_cy.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Byddwch yn llenwi gwybodaeth i mewn i <ph name="URL" /></translation> <translation id="8281781826761538115">Diofyn - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Neidio</translation> +<translation id="828291969289324795">{count,plural, =1{Ychwanegu'r Tab at Grŵp Newydd}zero{Ychwanegu'r Tabiau at Grŵp Newydd}two{Ychwanegu'r Tabiau at Grŵp Newydd}few{Ychwanegu'r Tabiau at Grŵp Newydd}many{Ychwanegu'r Tabiau at Grŵp Newydd}other{Ychwanegu'r Tabiau at Grŵp Newydd}}</translation> <translation id="8283172974887967105">Gosod…</translation> <translation id="8286036467436129157">Mewngofnodi</translation> <translation id="8299417921174340354">I ddefnyddio cyfrineiriau, rhaid i chi osod cod pas ar eich dyfais yn gyntaf.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_de.xtb b/ios/chrome/app/strings/resources/ios_strings_de.xtb index 3ed6a04..77b34525 100644 --- a/ios/chrome/app/strings/resources/ios_strings_de.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_de.xtb
@@ -978,7 +978,7 @@ <translation id="6059830886158432458">Hier kannst du festlegen, welche Meldungen und Aktivitäten dir angezeigt werden</translation> <translation id="6064824697233747382">Deine Organisation verlangt, dass du die Synchronisierung deaktivierst.</translation> <translation id="6066301408025741299">Zum Abbrechen tippen</translation> -<translation id="6067849159007176401">Surfschutz hinzufügen</translation> +<translation id="6067849159007176401">Browsing-Schutz hinzufügen</translation> <translation id="607620096698446287"><ph name="FILENAME" /> (<ph name="FILESIZE" />) konnte nicht hochgeladen werden</translation> <translation id="6084848228346514841">Tabs auswählen</translation> <translation id="6100617279104942061">Angemeldet als <ph name="USER_EMAIL" />. Die Einstellungen werden geöffnet.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb b/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb index 1ee960fc..877f5ce 100644 --- a/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">You'll fill info into <ph name="URL" /></translation> <translation id="8281781826761538115">Default - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Skip</translation> +<translation id="828291969289324795">{count,plural, =1{Add tab to new group}other{Add tabs to new group}}</translation> <translation id="8283172974887967105">Set…</translation> <translation id="8286036467436129157">Sign In</translation> <translation id="8299417921174340354">To use passwords, you must first set a passcode on your device.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_et.xtb b/ios/chrome/app/strings/resources/ios_strings_et.xtb index 8d75795..d0546ff 100644 --- a/ios/chrome/app/strings/resources/ios_strings_et.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_et.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Te sisestate teabe aadressile <ph name="URL" /></translation> <translation id="8281781826761538115">Vaikimisi – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Jäta vahele</translation> +<translation id="828291969289324795">{count,plural, =1{Vahelehe lisamine uude gruppi}other{Vahelehtede lisamine uude gruppi}}</translation> <translation id="8283172974887967105">Määra …</translation> <translation id="8286036467436129157">Logi sisse</translation> <translation id="8299417921174340354">Paroolide kasutamiseks peate oma seadmes esmalt pääsukoodi seadistama.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_eu.xtb b/ios/chrome/app/strings/resources/ios_strings_eu.xtb index aeb5def..cbcd3031 100644 --- a/ios/chrome/app/strings/resources/ios_strings_eu.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_eu.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219"><ph name="URL" /> helbideari emango diozu informazioa</translation> <translation id="8281781826761538115">Lehenetsia - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Saltatu</translation> +<translation id="828291969289324795">{count,plural, =1{Gehitu fitxa talde berrian}other{Gehitu fitxak talde berrian}}</translation> <translation id="8283172974887967105">Ezarri…</translation> <translation id="8286036467436129157">Hasi saioa</translation> <translation id="8299417921174340354">Pasahitzak erabiltzeko, lehenik, pasakode bat ezarri behar duzu gailuan.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_fa.xtb b/ios/chrome/app/strings/resources/ios_strings_fa.xtb index 6aea9a7..cbfd299 100644 --- a/ios/chrome/app/strings/resources/ios_strings_fa.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_fa.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">اطلاعات را در <ph name="URL" /> تکمیل خواهید کرد</translation> <translation id="8281781826761538115">پیشفرض - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">رد شدن</translation> +<translation id="828291969289324795">{count,plural, =1{افزودن برگه به گروه جدید}one{افزودن برگهها به گروه جدید}other{افزودن برگهها به گروه جدید}}</translation> <translation id="8283172974887967105">تنظیم…</translation> <translation id="8286036467436129157">ورود به سیستم</translation> <translation id="8299417921174340354">برای استفاده از گذرواژهها، ابتدا باید گذرنویسهای در دستگاه تنظیم کنید.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_fil.xtb b/ios/chrome/app/strings/resources/ios_strings_fil.xtb index 03972f5..8297b00 100644 --- a/ios/chrome/app/strings/resources/ios_strings_fil.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_fil.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Tapos na ang pag-download</translation> <translation id="3968505803272650567">Pamahalaan ang Mga Interes</translation> <translation id="3989635538409502728">Mag-sign Out</translation> +<translation id="3994422733891749358">Piliin ang mga notification na gusto mong matanggap</translation> <translation id="3995521777587992544">Progress bar ng pag-load ng page, na-load ang <ph name="EMAIL" />.</translation> <translation id="3997522473364371632">Na-disable ng iyong administrator ang pag-share ng password.</translation> <translation id="4002019827078931033">Ilipat Ang Address Bar Sa Itaas</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Keyboard</translation> <translation id="4601095002996233687">Mga detalyadong pag-scan para sa mga kahina-hinalang pag-download.</translation> <translation id="4606247758155004938">Pinapamahalaan ng iyong organisasyon ang browser mo.</translation> +<translation id="4607887340472970274">Pagsubaybay sa Presyo</translation> <translation id="4611811151908969241">I-hide ang Huwag Nang Subaybayan ang <ph name="DOMAIN_NAME" /></translation> <translation id="461440297010471931">Paghahanap gamit ang Google</translation> <translation id="4616391354457235490">I-undo</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Buksan sa Incognito?</translation> <translation id="4803185665210547709">Pinapamahalaan ng iyong organisasyon. <ph name="BEGIN_LINK" />Matuto Pa<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Balita at content batay sa iyong mga interes.</translation> <translation id="4805759445554688327">Invalid ang Numero ng Card</translation> <translation id="4808646838864186379">Nakansela ang iyong delivery</translation> <translation id="4808744395915275922">Mga Update</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> (na) hindi pa nababasang artikulo.</translation> <translation id="7412027924265291969">Magpatuloy</translation> <translation id="741204030948306876">Oo, sali ako</translation> +<translation id="7417689656810783109">I-rename ang Grupo</translation> <translation id="7418640008860669073">I-save sa...</translation> <translation id="7425346204213733349">Hindi na masi-sync sa Google Account mo ang mga pagbabago sa iyong mga bookmark, history, password, at iba pang setting. Gayunpaman, mananatiling naka-store sa Google account mo ang iyong kasalukuyang data.</translation> <translation id="7431991332293347422">Kontrolin kung paano ginagamit ang iyong history ng pag-browse para i-personalize ang Paghahanap at higit pa</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">Maglalagay ka ng impormasyon sa <ph name="URL" /></translation> <translation id="8281781826761538115">Default - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Laktawan</translation> +<translation id="828291969289324795">{count,plural, =1{Magdagdag ng Tab sa Bagong Grupo}one{Magdagdag ng Mga Tab sa Bagong Grupo}other{Magdagdag ng Mga Tab sa Bagong Grupo}}</translation> <translation id="8283172974887967105">Itakda…</translation> <translation id="8286036467436129157">Mag-sign In</translation> +<translation id="8292843446079898078">Makatanggap ng mga alerto sa pagbaba ng presyo para sa mga produktong sinusubaybayan mo.</translation> <translation id="8299417921174340354">Para gumamit ng mga password, dapat ka munang magtakda ng passcode sa iyong device.</translation> <translation id="8299613349954694191">Magbukas ng tab na Incognito para pribadong i-browse ang web.</translation> <translation id="8311853334103696030">I-hide ang Subaybayan ang Presyo</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">Isara Lahat</translation> <translation id="8343993175958086504">I-back up ang iyong mga file at gamitin ito sa anumang device.</translation> <translation id="834783239627985533">Mga Pinakamadalas Bisitahing Site</translation> +<translation id="8358401059263985056">I-on ang Mga Notification</translation> <translation id="8364841868226993049">Sine-save ang larawan sa Google Photos para sa <ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">Pumunta sa Mga Setting...</translation> <translation id="8374977641764177587">I-on ang Mga Notification?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_gl.xtb b/ios/chrome/app/strings/resources/ios_strings_gl.xtb index f1e7403..d399cfca 100644 --- a/ios/chrome/app/strings/resources/ios_strings_gl.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_gl.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Completarás a información en <ph name="URL" /></translation> <translation id="8281781826761538115">Idioma predeterminado: <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Omitir</translation> +<translation id="828291969289324795">{count,plural, =1{Engadir pestana ao grupo novo}other{Engadir pestanas ao grupo novo}}</translation> <translation id="8283172974887967105">Definir…</translation> <translation id="8286036467436129157">Iniciar sesión</translation> <translation id="8299417921174340354">Para usar os contrasinais, en primeiro lugar debes definir un contrasinal no teu dispositivo.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_hr.xtb b/ios/chrome/app/strings/resources/ios_strings_hr.xtb index c198705..0b17fd5 100644 --- a/ios/chrome/app/strings/resources/ios_strings_hr.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_hr.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Preuzimanje dovršeno</translation> <translation id="3968505803272650567">Upravljaj interesima</translation> <translation id="3989635538409502728">Odjava</translation> +<translation id="3994422733891749358">Odaberite obavijesti koje želite primati</translation> <translation id="3995521777587992544">Traka napretka učitavanja stranice, učitano <ph name="EMAIL" />.</translation> <translation id="3997522473364371632">Dijeljenje zaporki onemogućio je vaš administrator.</translation> <translation id="4002019827078931033">Pomaknite adresnu traku na vrh</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Tipkovnica</translation> <translation id="4601095002996233687">Dubinska pretraživanja mogućih sumnjivih preuzimanja.</translation> <translation id="4606247758155004938">Vašim preglednikom upravlja vaša organizacija.</translation> +<translation id="4607887340472970274">Praćenje cijene</translation> <translation id="4611811151908969241">Sakrij prestanak praćenja <ph name="DOMAIN_NAME" /></translation> <translation id="461440297010471931">Pretraživanje putem Googlea</translation> <translation id="4616391354457235490">Poništi</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Otvoriti u anonimnom načinu?</translation> <translation id="4803185665210547709">Pod upravljanjem vaše organizacije. <ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Vijesti i sadržaj na temelju vaših interesa.</translation> <translation id="4805759445554688327">Nevažeći broj kartice</translation> <translation id="4808646838864186379">Isporuka otkazana</translation> <translation id="4808744395915275922">Ažuriranja</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906">Nepročitanih članaka: <ph name="UNREAD_COUNT" />.</translation> <translation id="7412027924265291969">Nastavi</translation> <translation id="741204030948306876">Da, u redu</translation> +<translation id="7417689656810783109">Preimenovanje grupe</translation> <translation id="7418640008860669073">Spremi u...</translation> <translation id="7425346204213733349">Promjene oznaka, povijesti, zaporki i drugih postavki više se neće sinkronizirati s vašim Google računom. No vaši postojeći podaci ostat će pohranjeni na vašem Google računu.</translation> <translation id="7431991332293347422">Odredite na koji će se način vaša povijest pregledavanja upotrebljavati za prilagodbu Pretraživanja i drugih značajki</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">Unijet ćete podatke u <ph name="URL" /></translation> <translation id="8281781826761538115">Zadano – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Preskoči</translation> +<translation id="828291969289324795">{count,plural, =1{Dodaj karticu novoj grupi}one{Dodaj kartice novoj grupi}few{Dodaj kartice novoj grupi}other{Dodaj kartice novoj grupi}}</translation> <translation id="8283172974887967105">Postavi…</translation> <translation id="8286036467436129157">Prijava</translation> +<translation id="8292843446079898078">Primajte upozorenja o padu cijena za proizvode koje pratite.</translation> <translation id="8299417921174340354">Da biste koristili zaporke, najprije morate postaviti šifru na uređaju.</translation> <translation id="8299613349954694191">Otvorite anonimnu karticu da biste pregledavali web privatno.</translation> <translation id="8311853334103696030">Sakrij opciju Praćenje cijene</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">Zatvori sve</translation> <translation id="8343993175958086504">Sigurnosno kopirajte svoje sadržaje i upotrebljavajte ih na bilo kojem uređaju.</translation> <translation id="834783239627985533">Najposjećenije web-lokacije</translation> +<translation id="8358401059263985056">Uključi obavijesti</translation> <translation id="8364841868226993049">Spremanje slike na Google fotografije za <ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">Otvori postavke...</translation> <translation id="8374977641764177587">Želite li uključiti obavijesti?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_id.xtb b/ios/chrome/app/strings/resources/ios_strings_id.xtb index c729bdc..ce02de8 100644 --- a/ios/chrome/app/strings/resources/ios_strings_id.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_id.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Anda akan mengisi info ke <ph name="URL" /></translation> <translation id="8281781826761538115">Default - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Lewati</translation> +<translation id="828291969289324795">{count,plural, =1{Tambahkan Tab ke Grup Baru}other{Tambahkan Tab ke Grup Baru}}</translation> <translation id="8283172974887967105">Setel …</translation> <translation id="8286036467436129157">Login</translation> <translation id="8299417921174340354">Untuk menggunakan sandi, Anda harus menyetel kode sandi di perangkat terlebih dahulu.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_is.xtb b/ios/chrome/app/strings/resources/ios_strings_is.xtb index 2545dbf..f2d5102 100644 --- a/ios/chrome/app/strings/resources/ios_strings_is.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_is.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Þú fyllir upplýsingarnar þínar út á <ph name="URL" /></translation> <translation id="8281781826761538115">Sjálfgefið – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Sleppa</translation> +<translation id="828291969289324795">{count,plural, =1{Bæta flipa við nýjan hóp}one{Bæta flipum við nýjan hóp}other{Bæta flipum við nýjan hóp}}</translation> <translation id="8283172974887967105">Stilla…</translation> <translation id="8286036467436129157">Skrá inn</translation> <translation id="8299417921174340354">Til að nota aðgangsorð þarftu fyrst að stilla aðgangskóða í tækinu þínu.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_iw.xtb b/ios/chrome/app/strings/resources/ios_strings_iw.xtb index c1a255c..d344a956 100644 --- a/ios/chrome/app/strings/resources/ios_strings_iw.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_iw.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">הפרטים ימולאו באתר <ph name="URL" /></translation> <translation id="8281781826761538115">ברירת מחדל - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">דילוג</translation> +<translation id="828291969289324795">{count,plural, =1{הוספת הכרטיסייה לקבוצה חדשה}one{הוספת הכרטיסיות לקבוצה חדשה}two{הוספת הכרטיסיות לקבוצה חדשה}other{הוספת הכרטיסיות לקבוצה חדשה}}</translation> <translation id="8283172974887967105">להגדרה…</translation> <translation id="8286036467436129157">כניסה</translation> <translation id="8299417921174340354">כדי שניתן יהיה להשתמש בסיסמאות, יש להגדיר תחילה קוד גישה במכשיר.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ja.xtb b/ios/chrome/app/strings/resources/ios_strings_ja.xtb index facf4db..d542c69 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ja.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ja.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219"><ph name="URL" /> に情報を入力します</translation> <translation id="8281781826761538115">デフォルト - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">スキップ</translation> +<translation id="828291969289324795">{count,plural, =1{タブを新しいグループに追加}other{タブを新しいグループに追加}}</translation> <translation id="8283172974887967105">設定…</translation> <translation id="8286036467436129157">ログイン</translation> <translation id="8299417921174340354">パスワードを使用するには、まずデバイスにパスコードを設定する必要があります。</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_kk.xtb b/ios/chrome/app/strings/resources/ios_strings_kk.xtb index a5127fa..00f4ec1 100644 --- a/ios/chrome/app/strings/resources/ios_strings_kk.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_kk.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219"><ph name="URL" /> бетінде ақпаратты толтырасыз</translation> <translation id="8281781826761538115">Әдепкі - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Өткізіп жіберу</translation> +<translation id="828291969289324795">{count,plural, =1{Қойындыны жаңа топқа қосу}other{Қойындыларды жаңа топқа қосу}}</translation> <translation id="8283172974887967105">Орнату…</translation> <translation id="8286036467436129157">Кіру</translation> <translation id="8299417921174340354">Құпия сөздерді пайдалану үшін алдымен құрылғыға рұқсат кодын орнату керек.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_km.xtb b/ios/chrome/app/strings/resources/ios_strings_km.xtb index 84efbc44..30dace8b 100644 --- a/ios/chrome/app/strings/resources/ios_strings_km.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_km.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">ការទាញយកបានបញ្ចប់</translation> <translation id="3968505803272650567">គ្រប់គ្រងចំណាប់អារម្មណ៍</translation> <translation id="3989635538409502728">ចេញ</translation> +<translation id="3994422733891749358">ជ្រើសរើសការជូនដំណឹងដែលអ្នកចង់ទទួលបាន</translation> <translation id="3995521777587992544">របារដំណើរការនៃការផ្ទុកទំព័រ បានផ្ទុក <ph name="EMAIL" /> ។</translation> <translation id="3997522473364371632">ការចែករំលែកពាក្យសម្ងាត់ត្រូវបានបិទដោយអ្នកគ្រប់គ្រងរបស់អ្នក។</translation> <translation id="4002019827078931033">ផ្លាស់ទីរបារអាសយដ្ឋានទៅផ្នែកខាងលើ</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">ក្ដារចុច</translation> <translation id="4601095002996233687">ការស្កេនស៊ីជម្រៅ ដើម្បីរកមើលការទាញយកគួរឱ្យសង្ស័យ។</translation> <translation id="4606247758155004938">កម្មវិធីរុករកតាមអ៊ីនធឺណិតរបស់អ្នកស្ថិតក្រោមការគ្រប់គ្រងរបស់ស្ថាប័នអ្នក។</translation> +<translation id="4607887340472970274">ការតាមដានតម្លៃ</translation> <translation id="4611811151908969241">លាក់ "ឈប់តាមដាន <ph name="DOMAIN_NAME" />"</translation> <translation id="461440297010471931">ស្វែងរកដោយប្រើ Google</translation> <translation id="4616391354457235490">ត្រឡប់វិញ</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">បើកនៅក្នុងមុខងារឯកជនឬ?</translation> <translation id="4803185665210547709">គ្រប់គ្រងដោយស្ថាប័នរបស់អ្នក។ <ph name="BEGIN_LINK" />ស្វែងយល់បន្ថែម<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">ព័ត៌មាន និងខ្លឹមសារដែលផ្អែកលើចំណាប់អារម្មណ៍របស់អ្នក។</translation> <translation id="4805759445554688327">លេខកាតមិនត្រឹមត្រូវ</translation> <translation id="4808646838864186379">ការដឹកជញ្ជូនរបស់អ្នកត្រូវបានបោះបង់</translation> <translation id="4808744395915275922">កំណែថ្មី</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906">អត្ថបទមិនទាន់អាន <ph name="UNREAD_COUNT" />។</translation> <translation id="7412027924265291969">បន្ត</translation> <translation id="741204030948306876">បាទ/ចាស ខ្ញុំយល់ព្រម</translation> +<translation id="7417689656810783109">ប្ដូរឈ្មោះក្រុម</translation> <translation id="7418640008860669073">រក្សាទុកនៅក្នុង...</translation> <translation id="7425346204213733349">ការផ្លាស់ប្តូរចំពោះចំណាំ ប្រវត្តិ ពាក្យសម្ងាត់ និងការកំណត់ផ្សេងទៀតរបស់អ្នកនឹងមិនត្រូវបានធ្វើសមកាលកម្មជាមួយគណនី Google របស់អ្នកទៀតទេ។ ទោះបីជាយ៉ាងណាក៏ដោយ ទិន្នន័យដែលមានសម្រាប់របស់អ្នកនឹងនៅតែផ្ទុកក្នុងគណនី Google របស់អ្នកដដែល។</translation> <translation id="7431991332293347422">គ្រប់គ្រងរបៀបដែលប្រវត្តិរុករករបស់អ្នកត្រូវបានប្រើប្រាស់ ដើម្បីកំណត់ឱ្យការស្វែងរក និងអ្វីៗជាច្រើនទៀតស្របនឹងអ្នក</translation> @@ -1415,6 +1419,7 @@ <translation id="828291969289324795">{count,plural, =1{បញ្ចូលផ្ទាំងទៅក្រុមថ្មី}other{បញ្ចូលផ្ទាំងទៅក្រុមថ្មី}}</translation> <translation id="8283172974887967105">កំណត់…</translation> <translation id="8286036467436129157">ចូល</translation> +<translation id="8292843446079898078">ទទួលបានការជូនដំណឹងអំពីការធ្លាក់ថ្លៃសម្រាប់ផលិតផលដែលអ្នកតាមដាន។</translation> <translation id="8299417921174340354">ដើម្បីប្រើពាក្យសម្ងាត់ អ្នកត្រូវតែកំណត់លេខកូដសម្ងាត់នៅលើឧបករណ៍របស់អ្នកជាមុនសិន។</translation> <translation id="8299613349954694191">បើកផ្ទាំងឯកជន ដើម្បីរុករកលើអ៊ីនធឺណិតជាលក្ខណៈឯកជន។</translation> <translation id="8311853334103696030">លាក់ "តាមដានតម្លៃ"</translation> @@ -1422,6 +1427,7 @@ <translation id="8328777765163860529">បិទទាំងអស់</translation> <translation id="8343993175958086504">បម្រុងទុកទិន្នន័យរបស់អ្នក និងប្រើវានៅលើឧបករណ៍ណាក៏បាន។</translation> <translation id="834783239627985533">គេហទំព័រដែលចូលមើលញឹកញាប់បំផុត</translation> +<translation id="8358401059263985056">បើកការជូនដំណឹង</translation> <translation id="8364841868226993049">កំពុងរក្សាទុករូបភាពនៅក្នុង Google រូបថតសម្រាប់ <ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">ចូលទៅកាន់ការកំណត់...</translation> <translation id="8374977641764177587">បើកការជូនដំណឹងឬ?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_kn.xtb b/ios/chrome/app/strings/resources/ios_strings_kn.xtb index 21eb70f..ede0c40 100644 --- a/ios/chrome/app/strings/resources/ios_strings_kn.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_kn.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">ನೀವು <ph name="URL" /> ರಲ್ಲಿ ಮಾಹಿತಿಯನ್ನು ಭರ್ತಿ ಮಾಡುತ್ತೀರಿ</translation> <translation id="8281781826761538115">ಡಿಫಾಲ್ಟ್ - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">ಸ್ಕಿಪ್ ಮಾಡಿ</translation> +<translation id="828291969289324795">{count,plural, =1{ಹೊಸ ಗುಂಪಿಗೆ ಟ್ಯಾಬ್ ಸೇರಿಸಿ}one{ಹೊಸ ಗುಂಪಿಗೆ ಟ್ಯಾಬ್ಗಳನ್ನು ಸೇರಿಸಿ}other{ಹೊಸ ಗುಂಪಿಗೆ ಟ್ಯಾಬ್ಗಳನ್ನು ಸೇರಿಸಿ}}</translation> <translation id="8283172974887967105">ಸೆಟ್ ಮಾಡಿ…</translation> <translation id="8286036467436129157">ಸೈನ್ ಇನ್</translation> <translation id="8299417921174340354">ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಬಳಸಲು, ನೀವು ಮೊದಲು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪಾಸ್ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಬೇಕು.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ko.xtb b/ios/chrome/app/strings/resources/ios_strings_ko.xtb index b855293..0b7aba86 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ko.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ko.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219"><ph name="URL" />에 정보를 입력합니다</translation> <translation id="8281781826761538115">기본값 - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">건너뛰기</translation> +<translation id="828291969289324795">{count,plural, =1{새 그룹에 탭 추가}other{새 그룹에 탭 추가}}</translation> <translation id="8283172974887967105">설정…</translation> <translation id="8286036467436129157">로그인</translation> <translation id="8299417921174340354">비밀번호를 사용하려면 기기에 비밀번호를 설정해야 합니다.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_lo.xtb b/ios/chrome/app/strings/resources/ios_strings_lo.xtb index 672c43c..f9e7164 100644 --- a/ios/chrome/app/strings/resources/ios_strings_lo.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_lo.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">ດາວໂຫຼດສຳເລັດ</translation> <translation id="3968505803272650567">ຈັດການຄວາມສົນໃຈ</translation> <translation id="3989635538409502728">ອອກຈາກລະບົບ</translation> +<translation id="3994422733891749358">ເລືອກການແຈ້ງເຕືອນທີ່ທ່ານຕ້ອງການຮັບ</translation> <translation id="3995521777587992544">ແຖບສະແດງຄວາມຄືບໜ້າການໂຫຼດໜ້າ, ໂຫຼດ <ph name="EMAIL" /> ແລ້ວ.</translation> <translation id="3997522473364371632">ການແບ່ງປັນລະຫັດຜ່ານຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ.</translation> <translation id="4002019827078931033">ຍ້າຍແຖບທີ່ຢູ່ໄປໄວ້ເທິງສຸດ</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">ແປ້ນພິມ</translation> <translation id="4601095002996233687">ການສະແກນແບບເຈາະເລິກສຳລັບການດາວໂຫຼດທີ່ໜ້າສົງໄສ.</translation> <translation id="4606247758155004938">ໂປຣແກຣມທ່ອງເວັບຂອງທ່ານແມ່ນຈັດການໂດຍອົງການຂອງທ່ານ.</translation> +<translation id="4607887340472970274">ການຕິດຕາມລາຄາ</translation> <translation id="4611811151908969241">ເຊື່ອງ ເຊົາຕິດຕາມ <ph name="DOMAIN_NAME" /></translation> <translation id="461440297010471931">ກຳລັງຊອກຫາດ້ວຍ Google</translation> <translation id="4616391354457235490">ຍົກເລີກ</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">ທ່ານຕ້ອງການເປີດໃນໂໝດບໍ່ເຜີຍຕົວຕົນບໍ່?</translation> <translation id="4803185665210547709">ຈັດການໂດຍອົງການຂອງທ່ານ. <ph name="BEGIN_LINK" />ສຶກສາເພີ່ມເຕີມ<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">ຂ່າວ ແລະ ເນື້ອຫາໂດຍອີງຕາມຄວາມສົນໃຈຂອງທ່ານ.</translation> <translation id="4805759445554688327">ເລກບັດບໍ່ຖືກຕ້ອງ</translation> <translation id="4808646838864186379">ການຈັດສົ່ງຂອງທ່ານຖືກຍົກເລີກແລ້ວ</translation> <translation id="4808744395915275922">ອັບເດດ</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> ບົດຄວາມທີ່ຍັງບໍ່ໄດ້ອ່ານ.</translation> <translation id="7412027924265291969">ສືບຕໍ່</translation> <translation id="741204030948306876">ແມ່ນ, ຂ້ອຍຂໍເຂົ້າຮ່ວມ</translation> +<translation id="7417689656810783109">ປ່ຽນຊື່ກຸ່ມ</translation> <translation id="7418640008860669073">ບັນທຶກໃນ...</translation> <translation id="7425346204213733349">ການປ່ຽນແປງຕໍ່ກັບບຸກມາກ, ປະຫວັດ, ລະຫັດຜ່ານ ແລະ ການຕັ້ງຄ່າອື່ນຂອງທ່ານຈະບໍ່ຖືກຊິ້ງກັບບັນຊີ Google ຂອງທ່ານອີກຕໍ່ໄປ. ແນວໃດກໍຕາມ, ຂໍ້ມູນທີ່ມີຢູ່ຂອງທ່ານຈະຍັງຄົງເກັບຮັກສາໄວ້ໃນບັນຊີ Google ຂອງທ່ານ.</translation> <translation id="7431991332293347422">ຄວບຄຸມວ່າຈະໃຫ້ໃຊ້ປະຫວັດການທ່ອງເວັບຂອງທ່ານແນວໃດເພື່ອປັບແຕ່ງການຊອກຫາ ແລະ ອື່ນໆອີກໃຫ້ເປັນແບບສ່ວນຕົວ</translation> @@ -1415,6 +1419,7 @@ <translation id="828291969289324795">{count,plural, =1{ເພີ່ມແຖບໃສ່ກຸ່ມໃໝ່}other{ເພີ່ມແຖບໃສ່ກຸ່ມໃໝ່}}</translation> <translation id="8283172974887967105">ຕັ້ງ…</translation> <translation id="8286036467436129157">ເຂົ້າສູ່ລະບົບ</translation> +<translation id="8292843446079898078">ຮັບການແຈ້ງເຕືອນເມື່ອລາຄາຜະລິດຕະພັນທີ່ທ່ານຕິດຕາມຕ່ຳລົງ.</translation> <translation id="8299417921174340354">ເພື່ອໃຊ້ລະຫັດຜ່ານ, ທ່ານຕ້ອງຕັ້ງລະຫັດຜ່ານໃນອຸປະກອນຂອງທ່ານກ່ອນ.</translation> <translation id="8299613349954694191">ເປີດແຖບບໍ່ເປີດເຜີຍຕົວຕົນເພື່ອທ່ອງເວັບແບບສ່ວນຕົວ.</translation> <translation id="8311853334103696030">ເຊື່ອງຕິດຕາມລາຄາ</translation> @@ -1422,6 +1427,7 @@ <translation id="8328777765163860529">ປິດທັງໝົດ</translation> <translation id="8343993175958086504">ສຳຮອງຂໍ້ມູນຂອງທ່ານ ແລະ ໃຊ້ມັນຢູ່ອຸປະກອນໃດກໍໄດ້.</translation> <translation id="834783239627985533">ເວັບໄຊທີ່ເຂົ້າເບິ່ງຫຼາຍທີ່ສຸດ</translation> +<translation id="8358401059263985056">ເປີດການແຈ້ງເຕືອນ</translation> <translation id="8364841868226993049">ກຳລັງບັນທຶກຮູບໃນ Google ຮູບພາບສຳລັບ <ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">ເຂົ້າໄປການຕັ້ງຄ່າ...</translation> <translation id="8374977641764177587">ເປີດການແຈ້ງເຕືອນບໍ?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_lt.xtb b/ios/chrome/app/strings/resources/ios_strings_lt.xtb index 371b2111..0b1eb5b 100644 --- a/ios/chrome/app/strings/resources/ios_strings_lt.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_lt.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Informaciją užpildysite adresu <ph name="URL" /></translation> <translation id="8281781826761538115">Numatytoji – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Praleisti</translation> +<translation id="828291969289324795">{count,plural, =1{Pridėti skirtuką prie naujos grupės}one{Pridėti skirtukų prie naujos grupės}few{Pridėti skirtukų prie naujos grupės}many{Pridėti skirtukų prie naujos grupės}other{Pridėti skirtukų prie naujos grupės}}</translation> <translation id="8283172974887967105">Nustatyti…</translation> <translation id="8286036467436129157">Prisijungti</translation> <translation id="8299417921174340354">Jei norite naudoti slaptažodžius, pirmiausia turite nustatyti įrenginio slaptažodį.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_lv.xtb b/ios/chrome/app/strings/resources/ios_strings_lv.xtb index 1410c93..e237deb 100644 --- a/ios/chrome/app/strings/resources/ios_strings_lv.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_lv.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Jūs aizpildīsiet informāciju vietnē <ph name="URL" />.</translation> <translation id="8281781826761538115">Noklusējuma — <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Izlaist</translation> +<translation id="828291969289324795">{count,plural, =1{Pievienot cilni jaunai grupai}zero{Pievienot cilnes jaunai grupai}one{Pievienot cilnes jaunai grupai}other{Pievienot cilnes jaunai grupai}}</translation> <translation id="8283172974887967105">Iestatīt…</translation> <translation id="8286036467436129157">Pierakstīties</translation> <translation id="8299417921174340354">Lai izmantotu paroles, vispirms ierīcei ir jāiestata piekļuves kods.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mn.xtb b/ios/chrome/app/strings/resources/ios_strings_mn.xtb index 28ed62fe..bfc40ecd 100644 --- a/ios/chrome/app/strings/resources/ios_strings_mn.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Та мэдээллийг <ph name="URL" />-д бөглөнө</translation> <translation id="8281781826761538115">Өгөгдмөл - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Алгасах</translation> +<translation id="828291969289324795">{count,plural, =1{Табыг шинэ бүлэгт нэмэх}other{Табуудыг шинэ бүлэгт нэмэх}}</translation> <translation id="8283172974887967105">Тохируулах…</translation> <translation id="8286036467436129157">Нэвтрэх</translation> <translation id="8299417921174340354">Нууц үгсийг ашиглахын тулд та эхлээд төхөөрөмж дээрээ нууц код тохируулах ёстой.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mr.xtb b/ios/chrome/app/strings/resources/ios_strings_mr.xtb index c27d41a..3b32089 100644 --- a/ios/chrome/app/strings/resources/ios_strings_mr.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_mr.xtb
@@ -597,7 +597,7 @@ <translation id="4113030288477039509">तुमच्या ॲडमिनिस्ट्रेटरद्वारे व्यवस्थापित</translation> <translation id="4113957097611235433">तुमचे पासवर्ड बदला</translation> <translation id="4120936477286528673">ही साइट वारंवार दुसरे अॅप्लिकेशन उघडण्याचा प्रयत्न करत आहे.</translation> -<translation id="4121993058175073134">निव्वळ-एक्सपोर्ट डेटा पाठविण्यासाठी, कृपया सेटिंग्ज ॲप मध्ये तुमचे ईमेल खाते कॉंफिगर करा.</translation> +<translation id="4121993058175073134">निव्वळ-एक्सपोर्ट डेटा पाठविण्यासाठी, कृपया सेटिंग्ज ॲप मध्ये तुमचे ईमेल खाते कॉन्फिगर करा.</translation> <translation id="4124987746317609294">वेळ वर्गवारी</translation> <translation id="4133265950310064865">वर्धित संरक्षण</translation> <translation id="4147897805161313378">Google Photos</translation> @@ -1413,6 +1413,7 @@ <translation id="8273982424131314219">तुम्ही <ph name="URL" /> मध्ये माहिती भराल</translation> <translation id="8281781826761538115">डीफॉल्ट - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">वगळा</translation> +<translation id="828291969289324795">{count,plural, =1{नवीन गट यामध्ये टॅब जोडा}other{नवीन गट यामध्ये टॅब जोडा}}</translation> <translation id="8283172974887967105">सेट करा…</translation> <translation id="8286036467436129157">साइन इन</translation> <translation id="8299417921174340354">पासवर्ड वापरण्यासाठी, तुम्ही आधी तुमच्या डिव्हाइसवर पासकोड सेट करणे आवश्यक आहे.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ms.xtb b/ios/chrome/app/strings/resources/ios_strings_ms.xtb index 7e9e5aa..b0a59cc 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ms.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ms.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Muat turun selesai</translation> <translation id="3968505803272650567">Urus Minat</translation> <translation id="3989635538409502728">Log Keluar</translation> +<translation id="3994422733891749358">Pilih pemberitahuan yang mahu anda terima</translation> <translation id="3995521777587992544">Bar kemajuan pemuatan halaman, <ph name="EMAIL" /> dimuatkan.</translation> <translation id="3997522473364371632">Perkongsian kata laluan dilumpuhkan oleh pentadbir anda.</translation> <translation id="4002019827078931033">Alihkan Bar Alamat Ke Bahagian Atas</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Papan kekunci</translation> <translation id="4601095002996233687">Imbasan secara mendalam untuk muat turun yang mencurigakan.</translation> <translation id="4606247758155004938">Penyemak imbas anda diurus oleh organisasi anda.</translation> +<translation id="4607887340472970274">Penjejakan Harga</translation> <translation id="4611811151908969241">Sembunyikan Berhenti Mengikuti <ph name="DOMAIN_NAME" /></translation> <translation id="461440297010471931">Mencari dengan Google</translation> <translation id="4616391354457235490">Buat asal</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Buka dalam Inkognito?</translation> <translation id="4803185665210547709">Diurus oleh organisasi anda. <ph name="BEGIN_LINK" />Ketahui Lebih Lanjut<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Berita dan kandungan berdasarkan minat anda.</translation> <translation id="4805759445554688327">Nombor Kad Tidak Sah</translation> <translation id="4808646838864186379">Penghantaran anda telah dibatalkan</translation> <translation id="4808744395915275922">Kemaskinian</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> artikel belum dibaca.</translation> <translation id="7412027924265291969">Teruskan</translation> <translation id="741204030948306876">Ya, saya setuju</translation> +<translation id="7417689656810783109">Namakan Semula Kumpulan</translation> <translation id="7418640008860669073">Simpan dalam...</translation> <translation id="7425346204213733349">Perubahan kepada penanda halaman, sejarah, kata laluan dan tetapan anda yang lain tidak akan disegerakkan ke Google Account anda lagi. Walau bagaimanapun, data sedia ada akan kekal disimpan dalam Google Account anda.</translation> <translation id="7431991332293347422">Kawal cara sejarah penyemakan imbas anda digunakan untuk memperibadikan Carian dan pelbagai lagi</translation> @@ -1415,6 +1419,7 @@ <translation id="828291969289324795">{count,plural, =1{Tambahkan Tab pada Kumpulan Baharu}other{Tambahkan Tab pada Kumpulan Baharu}}</translation> <translation id="8283172974887967105">Tetapkan…</translation> <translation id="8286036467436129157">Log Masuk</translation> +<translation id="8292843446079898078">Terima makluman penurunan harga untuk produk yang anda jejaki.</translation> <translation id="8299417921174340354">Untuk menggunakan kata laluan, anda mesti menetapkan kod laluan pada peranti anda dahulu.</translation> <translation id="8299613349954694191">Buka tab Inkognito untuk menyemak imbas web secara tertutup.</translation> <translation id="8311853334103696030">Sembunyikan Jejak Harga</translation> @@ -1422,6 +1427,7 @@ <translation id="8328777765163860529">Tutup Semua</translation> <translation id="8343993175958086504">Sandarkan bahan anda dan gunakan bahan itu pada mana-mana peranti.</translation> <translation id="834783239627985533">Laman yang Paling Kerap Dilawati</translation> +<translation id="8358401059263985056">Hidupkan Pemberitahuan</translation> <translation id="8364841868226993049">Menyimpan imej dalam Google Photos untuk <ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">Akses Tetapan...</translation> <translation id="8374977641764177587">Hidupkan Pemberitahuan?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ne.xtb b/ios/chrome/app/strings/resources/ios_strings_ne.xtb index 8010632..5711a61b 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ne.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ne.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">तपाईंले <ph name="URL" /> मा जानकारी भर्नु पर्ने हुन्छ</translation> <translation id="8281781826761538115">डिफल्ट - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">स्किप गर्नुहोस्</translation> +<translation id="828291969289324795">{count,plural, =1{यो ट्याब नयाँ समूहमा हाल्नुहोस्}other{यी ट्याबहरू नयाँ समूहमा हाल्नुहोस्}}</translation> <translation id="8283172974887967105">सेट गर्नुहोस्…</translation> <translation id="8286036467436129157">साइन इन गर्नुहोस्</translation> <translation id="8299417921174340354">पासवर्डहरू प्रयोग गर्न सर्वप्रथम तपाईंले आफ्नो यन्त्रमा अनिवार्य रूपमा कुनै पासकोड सेट गर्नु पर्छ।</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_nl.xtb b/ios/chrome/app/strings/resources/ios_strings_nl.xtb index 4d14285e..60c1295 100644 --- a/ios/chrome/app/strings/resources/ios_strings_nl.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_nl.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Downloaden voltooid</translation> <translation id="3968505803272650567">Interesses beheren</translation> <translation id="3989635538409502728">Afmelden</translation> +<translation id="3994422733891749358">Kies welke meldingen je wilt krijgen</translation> <translation id="3995521777587992544">Voortgangsbalk voor laden van pagina, <ph name="EMAIL" /> geladen.</translation> <translation id="3997522473364371632">Wachtwoord delen is uitgezet door je beheerder.</translation> <translation id="4002019827078931033">Adresbalk naar boven verplaatsen</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Toetsenbord</translation> <translation id="4601095002996233687">Uitgebreide scans voor verdachte downloads.</translation> <translation id="4606247758155004938">Je browser wordt beheerd door je organisatie.</translation> +<translation id="4607887340472970274">Prijzen volgen</translation> <translation id="4611811151908969241"><ph name="DOMAIN_NAME" /> niet meer volgen verbergen</translation> <translation id="461440297010471931">Zoeken met Google</translation> <translation id="4616391354457235490">Ongedaan maken</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Openen in incognitomodus?</translation> <translation id="4803185665210547709">Beheerd door je organisatie. <ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Nieuws en content op basis van je interesses.</translation> <translation id="4805759445554688327">Ongeldig creditcardnummer</translation> <translation id="4808646838864186379">Je bezorging is geannuleerd</translation> <translation id="4808744395915275922">Updates</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> ongelezen artikelen.</translation> <translation id="7412027924265291969">Doorgaan</translation> <translation id="741204030948306876">Ja, aanzetten</translation> +<translation id="7417689656810783109">Naam van groep wijzigen</translation> <translation id="7418640008860669073">Opslaan in…</translation> <translation id="7425346204213733349">Wijzigingen in je bookmarks, geschiedenis, wachtwoorden en andere instellingen worden niet meer gesynchroniseerd met je Google-account. Je bestaande gegevens blijven echter opgeslagen in je Google-account.</translation> <translation id="7431991332293347422">Beheren hoe je browsegeschiedenis wordt gebruikt om Google Zoeken en meer te personaliseren</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">Je vult informatie in op <ph name="URL" /></translation> <translation id="8281781826761538115">Standaard - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Overslaan</translation> +<translation id="828291969289324795">{count,plural, =1{Tabblad toevoegen aan nieuwe groep}other{Tabbladen toevoegen aan nieuwe groep}}</translation> <translation id="8283172974887967105">Instellen…</translation> <translation id="8286036467436129157">Inloggen</translation> +<translation id="8292843446079898078">Krijg meldingen over prijsdalingen voor producten die je volgt.</translation> <translation id="8299417921174340354">Als je wachtwoorden wilt gebruiken, moet je eerst een toegangscode instellen op je apparaat.</translation> <translation id="8299613349954694191">Open een incognitotabblad om privé op internet te browsen.</translation> <translation id="8311853334103696030">Prijs volgen verbergen</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">Alles sluiten</translation> <translation id="8343993175958086504">Maak een back-up van je gegevens en gebruik deze op elk apparaat.</translation> <translation id="834783239627985533">Meest bezochte sites</translation> +<translation id="8358401059263985056">Meldingen aanzetten</translation> <translation id="8364841868226993049">Afbeelding in Google Foto's opslaan voor <ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">Naar Instellingen…</translation> <translation id="8374977641764177587">Meldingen aanzetten?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_no.xtb b/ios/chrome/app/strings/resources/ios_strings_no.xtb index 68bbd6b1..08fe2bf 100644 --- a/ios/chrome/app/strings/resources/ios_strings_no.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_no.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Nedlasting fullført</translation> <translation id="3968505803272650567">Administrer interesser</translation> <translation id="3989635538409502728">Logg av</translation> +<translation id="3994422733891749358">Velg hvilke varsler du vil motta</translation> <translation id="3995521777587992544">Fremdriftslinje for sideinnlasting, <ph name="EMAIL" /> er lastet inn.</translation> <translation id="3997522473364371632">Administratoren din har slått av passorddeling.</translation> <translation id="4002019827078931033">Flytt adressefeltet til toppen</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Tastatur</translation> <translation id="4601095002996233687">Dybdeskanninger av mistenkelige nedlastinger.</translation> <translation id="4606247758155004938">Nettleseren administreres av organisasjonen din.</translation> +<translation id="4607887340472970274">Prissporing</translation> <translation id="4611811151908969241">Skjul Slutt å følge <ph name="DOMAIN_NAME" /></translation> <translation id="461440297010471931">Søker med Google</translation> <translation id="4616391354457235490">Angre</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Vil du åpne linken i Inkognito?</translation> <translation id="4803185665210547709">Administreres av organisasjonen din. <ph name="BEGIN_LINK" />Finn ut mer<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Nyheter og innhold basert på interessene dine.</translation> <translation id="4805759445554688327">Ugyldig kortnummer</translation> <translation id="4808646838864186379">Leveringen er kansellert</translation> <translation id="4808744395915275922">Oppdateringer</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> uleste artikler.</translation> <translation id="7412027924265291969">Fortsett</translation> <translation id="741204030948306876">Ja, jeg er med</translation> +<translation id="7417689656810783109">Gi gruppen nytt navn</translation> <translation id="7418640008860669073">Lagre i…</translation> <translation id="7425346204213733349">Endringer i bokmerkene, loggoppføringene, passordene og de andre innstillingene dine blir ikke synkronisert med Google-kontoen din lenger. Data som allerede er lagret i Google-kontoen din, blir imidlertid ikke fjernet.</translation> <translation id="7431991332293347422">Kontroller hvordan nettleserloggen din brukes til blant annet personlig tilpasning av søk</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">Du fyller ut informasjon på <ph name="URL" /></translation> <translation id="8281781826761538115">Standard – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Hopp over</translation> +<translation id="828291969289324795">{count,plural, =1{Legg fanen til i en ny gruppe}other{Legg fanene til i en ny gruppe}}</translation> <translation id="8283172974887967105">Angi…</translation> <translation id="8286036467436129157">Logg på</translation> +<translation id="8292843446079898078">Få varsler om avslag for produkter du sporer.</translation> <translation id="8299417921174340354">For å bruke passord må du først angi en adgangskode på enheten din.</translation> <translation id="8299613349954694191">Åpne en inkognitofane for å surfe privat på nettet.</translation> <translation id="8311853334103696030">Skjul «Spor prisen»</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">Lukk alle</translation> <translation id="8343993175958086504">Sikkerhetskopier tingene dine, og bruk dem på alle enheter.</translation> <translation id="834783239627985533">Mest besøkte nettsteder</translation> +<translation id="8358401059263985056">Slå på varsler</translation> <translation id="8364841868226993049">Lagrer bildet i Google Foto for <ph name="USER_EMAIL" /> …</translation> <translation id="8370406443343902172">Gå til Innstillinger…</translation> <translation id="8374977641764177587">Vil du slå på varsler?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_pa.xtb b/ios/chrome/app/strings/resources/ios_strings_pa.xtb index 3828882..582166f 100644 --- a/ios/chrome/app/strings/resources/ios_strings_pa.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_pa.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">ਤੁਸੀਂ <ph name="URL" /> ਵਿੱਚ ਜਾਣਕਾਰੀ ਭਰੋਗੇ</translation> <translation id="8281781826761538115">ਪੂਰਵ-ਨਿਰਧਾਰਤ - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">ਛੱਡੋ</translation> +<translation id="828291969289324795">{count,plural, =1{ਟੈਬ ਨੂੰ ਨਵੇਂ ਗਰੁੱਪ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ}one{ਟੈਬ ਨੂੰ ਨਵੇਂ ਗਰੁੱਪ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ}other{ਟੈਬਾਂ ਨੂੰ ਨਵੇਂ ਗਰੁੱਪ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ}}</translation> <translation id="8283172974887967105">ਸੈੱਟ ਕਰੋ…</translation> <translation id="8286036467436129157">ਸਾਈਨ-ਇਨ ਕਰੋ</translation> <translation id="8299417921174340354">ਪਾਸਵਰਡਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ ਆਪਣੇ ਡੀਵਾਈਸ 'ਤੇ ਪਾਸਕੋਡ ਸੈੱਟ ਕਰਨਾ ਲਾਜ਼ਮੀ ਹੈ।</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb b/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb index ec247ff..c408155 100644 --- a/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb
@@ -1240,7 +1240,7 @@ <translation id="741204030948306876">Sim</translation> <translation id="7418640008860669073">Salvar em…</translation> <translation id="7425346204213733349">Alterações feitas nos seus favoritos, histórico, senhas e outras configurações não serão mais sincronizadas com sua Conta do Google. No entanto, os dados já existentes permanecerão armazenados na Conta do Google.</translation> -<translation id="7431991332293347422">Controla como o histórico de navegação é usado para personalizar a Pesquisa e muito mais</translation> +<translation id="7431991332293347422">Controlar como o histórico de navegação é usado para personalizar a Pesquisa e muito mais</translation> <translation id="7435356471928173109">Desativado pelo administrador</translation> <translation id="7436239899443308800">{count,plural, =1{1 guia}one{{count} guia}other{{count} guias}}</translation> <translation id="7438481509621345350">Agora, você verá stories de <ph name="CHANNEL_NAME" /> quando abrir uma nova guia.</translation> @@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Você vai preencher informações em <ph name="URL" /></translation> <translation id="8281781826761538115">Padrão: <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Pular</translation> +<translation id="828291969289324795">{count,plural, =1{Adicionar guia ao novo grupo}one{Adicionar guia ao novo grupo}other{Adicionar guias ao novo grupo}}</translation> <translation id="8283172974887967105">Definir…</translation> <translation id="8286036467436129157">Fazer login</translation> <translation id="8299417921174340354">Para usar senhas, defina uma no dispositivo primeiro.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ro.xtb b/ios/chrome/app/strings/resources/ios_strings_ro.xtb index 640034a..87a82412 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ro.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ro.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Vei completa informațiile la <ph name="URL" /></translation> <translation id="8281781826761538115">Prestabilit – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Omite</translation> +<translation id="828291969289324795">{count,plural, =1{Adaugă fila într-un grup nou}few{Adaugă filele într-un grup nou}other{Adaugă filele într-un grup nou}}</translation> <translation id="8283172974887967105">Setează…</translation> <translation id="8286036467436129157">Conectați-vă</translation> <translation id="8299417921174340354">Pentru a folosi parolele, trebuie mai întâi să setezi o parolă pe dispozitiv.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_si.xtb b/ios/chrome/app/strings/resources/ios_strings_si.xtb index f970e89..43ffe23 100644 --- a/ios/chrome/app/strings/resources/ios_strings_si.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_si.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">ඔබ <ph name="URL" /> වෙත තතු පුරවනු ඇත</translation> <translation id="8281781826761538115">පෙරනිමි - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">මඟහරින්න</translation> +<translation id="828291969289324795">{count,plural, =1{නව සමූහයට පටිත්ත එක් කරන්න}one{නව සමූහයට පටිති එක් කරන්න}other{නව සමූහයට පටිති එක් කරන්න}}</translation> <translation id="8283172974887967105">සකසන්න…</translation> <translation id="8286036467436129157">පුරන්න</translation> <translation id="8299417921174340354">මුරපද භාවිත කිරීමට, ඔබ පළමුව ඔබේ උපාංගයේ මුරකේතයක් සැකසිය යුතුය.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_sl.xtb b/ios/chrome/app/strings/resources/ios_strings_sl.xtb index 37cbc73..e084fe2 100644 --- a/ios/chrome/app/strings/resources/ios_strings_sl.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_sl.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Podatke boste vnesli na spletnem mestu <ph name="URL" /></translation> <translation id="8281781826761538115">Privzeto - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Preskoči</translation> +<translation id="828291969289324795">{count,plural, =1{Dodaj zavihek novi skupini}one{Dodaj zavihke novi skupini}two{Dodaj zavihke novi skupini}few{Dodaj zavihke novi skupini}other{Dodaj zavihke novi skupini}}</translation> <translation id="8283172974887967105">Nastavi …</translation> <translation id="8286036467436129157">Prijava</translation> <translation id="8299417921174340354">Če želite uporabiti gesla, morate najprej nastaviti geslo v napravi.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_sr-Latn.xtb b/ios/chrome/app/strings/resources/ios_strings_sr-Latn.xtb index 42ef96a0..d9df27a 100644 --- a/ios/chrome/app/strings/resources/ios_strings_sr-Latn.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_sr-Latn.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Popunićete informacije na <ph name="URL" /></translation> <translation id="8281781826761538115">Podrazumevano – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Preskoči</translation> +<translation id="828291969289324795">{count,plural, =1{Dodaj karticu u novu grupu}one{Dodaj kartice u novu grupu}few{Dodaj kartice u novu grupu}other{Dodaj kartice u novu grupu}}</translation> <translation id="8283172974887967105">Podesi…</translation> <translation id="8286036467436129157">Prijavi me</translation> <translation id="8299417921174340354">Da biste koristili lozinke, prvo morate da podesite šifru na uređaju.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_sr.xtb b/ios/chrome/app/strings/resources/ios_strings_sr.xtb index bf9185c..de9fb3d 100644 --- a/ios/chrome/app/strings/resources/ios_strings_sr.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_sr.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Попунићете информације на <ph name="URL" /></translation> <translation id="8281781826761538115">Подразумевано – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Прескочи</translation> +<translation id="828291969289324795">{count,plural, =1{Додај картицу у нову групу}one{Додај картице у нову групу}few{Додај картице у нову групу}other{Додај картице у нову групу}}</translation> <translation id="8283172974887967105">Подеси…</translation> <translation id="8286036467436129157">Пријави ме</translation> <translation id="8299417921174340354">Да бисте користили лозинке, прво морате да подесите шифру на уређају.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_te.xtb b/ios/chrome/app/strings/resources/ios_strings_te.xtb index 725e88e..a1531a7 100644 --- a/ios/chrome/app/strings/resources/ios_strings_te.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_te.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">డౌన్లోడ్ పూర్తయింది</translation> <translation id="3968505803272650567">ఆసక్తులను మేనేజ్ చేయండి</translation> <translation id="3989635538409502728">సైన్ అవుట్</translation> +<translation id="3994422733891749358">మీరు స్వీకరించాలనుకుంటున్న నోటిఫికేషన్లను ఎంచుకోండి</translation> <translation id="3995521777587992544">పేజీ లోడ్ పురోగతి బార్, <ph name="EMAIL" /> లోడ్ చేయబడింది.</translation> <translation id="3997522473364371632">పాస్వర్డ్ షేరింగ్ను మీ అడ్మినిస్ట్రేటర్ డిజేబుల్ చేస్తారు.</translation> <translation id="4002019827078931033">అడ్రస్ బార్ను పై భాగానికి తరలించండి</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">కీబోర్డ్</translation> <translation id="4601095002996233687">అనుమానాస్పద డౌన్లోడ్ల కోసం లోతైన స్కాన్లు చేయండి.</translation> <translation id="4606247758155004938">మీ బ్రౌజర్ను మీ సంస్థ మేనేజ్ చేస్తోంది.</translation> +<translation id="4607887340472970274">ధర ట్రాకింగ్</translation> <translation id="4611811151908969241">'<ph name="DOMAIN_NAME" />ను అన్-ఫాలో చేయండి'ని చూపవద్దు</translation> <translation id="461440297010471931">Googleతో శోధిస్తోంది</translation> <translation id="4616391354457235490">చర్య రద్దు చేయి</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">అజ్ఞాత మోడ్లో తెరవాలా?</translation> <translation id="4803185665210547709">మీ సంస్థ ద్వారా మేనేజ్ చేయబడుతోంది. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">మీ ఆసక్తుల ఆధారంగా వార్తలు, కంటెంట్.</translation> <translation id="4805759445554688327">చెల్లని కార్డ్ నంబర్</translation> <translation id="4808646838864186379">మీ డెలివరీ రద్దు చేయబడింది</translation> <translation id="4808744395915275922">అప్డేట్లు</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> చదవని కథనాలు ఉన్నాయి.</translation> <translation id="7412027924265291969">కొనసాగించండి</translation> <translation id="741204030948306876">సరే, సమ్మతమే</translation> +<translation id="7417689656810783109">గ్రూప్ పేరుమార్చు</translation> <translation id="7418640008860669073">దీనిలో సేవ్ చేయండి...</translation> <translation id="7425346204213733349">మీ బుక్మార్క్లు, హిస్టరీ, పాస్వర్డ్లు, ఇతర సెట్టింగ్లకు చేసే మార్పులు ఇకపై మీ Google ఖాతాకు సింక్ చేయబడవు. అయితే, ఇప్పటికే ఉన్న మీ డేటా మీ Google ఖాతాలో అలాగే స్టోరేజ్ చేయబడి ఉంటుంది.</translation> <translation id="7431991332293347422">సెర్చ్లు మరియు మరిన్నింటిని వ్యక్తిగతీకరించడానికి మీ బ్రౌజింగ్ హిస్టరీ ఎలా ఉపయోగించబడుతుందో నియంత్రించండి</translation> @@ -1415,6 +1419,7 @@ <translation id="828291969289324795">{count,plural, =1{ట్యాబ్ను కొత్త గ్రూప్నకు జోడించండి}other{ట్యాబ్లను కొత్త గ్రూప్నకు జోడించండి}}</translation> <translation id="8283172974887967105">సెట్ చేయి…</translation> <translation id="8286036467436129157">సైన్ ఇన్ చేయండి</translation> +<translation id="8292843446079898078">మీరు ట్రాక్ చేసే ప్రోడక్ట్ల కోసం ధర తగ్గుదల అలర్ట్లను స్వీకరించండి.</translation> <translation id="8299417921174340354">పాస్వర్డ్లను ఉపయోగించడానికి, మీరు ముందుగా తప్పనిసరిగా మీ పరికరంలో పాస్కోడ్ను సెట్ చేయాలి.</translation> <translation id="8299613349954694191">వెబ్ను ప్రైవేట్గా బ్రౌజ్ చేయడానికి అజ్ఞాత ట్యాబ్ను తెరవండి.</translation> <translation id="8311853334103696030">'ధరను ట్రాక్ చేయండి'ని దాచండి</translation> @@ -1422,6 +1427,7 @@ <translation id="8328777765163860529">అన్నింటినీ మూసివేయి</translation> <translation id="8343993175958086504">మీ అంశాలను బ్యాకప్ చేసి, వాటిని ఏ పరికరంలో అయినా ఉపయోగించండి.</translation> <translation id="834783239627985533">అత్యంత ఎక్కువగా సందర్శించిన సైట్లు</translation> +<translation id="8358401059263985056">నోటిఫికేషన్లను ఆన్ చేయండి</translation> <translation id="8364841868226993049"><ph name="USER_EMAIL" /> కోసం Google Photosలో ఇమేజ్ను సేవ్ చేస్తోంది...</translation> <translation id="8370406443343902172">సెట్టింగ్లకు వెళ్లండి...</translation> <translation id="8374977641764177587">నోటిఫికేషన్లను ఆన్ చేయాలా?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_th.xtb b/ios/chrome/app/strings/resources/ios_strings_th.xtb index 13e8130..33dcc37 100644 --- a/ios/chrome/app/strings/resources/ios_strings_th.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_th.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">ดาวน์โหลดเสร็จสมบูรณ์</translation> <translation id="3968505803272650567">จัดการความสนใจ</translation> <translation id="3989635538409502728">ออกจากระบบ</translation> +<translation id="3994422733891749358">เลือกการแจ้งเตือนที่ต้องการรับ</translation> <translation id="3995521777587992544">แถบความคืบหน้าการโหลดหน้าเว็บ โหลดแล้ว <ph name="EMAIL" /></translation> <translation id="3997522473364371632">ผู้ดูแลระบบปิดใช้การแชร์รหัสผ่าน</translation> <translation id="4002019827078931033">ย้ายแถบที่อยู่ไปยังด้านบน</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">แป้นพิมพ์</translation> <translation id="4601095002996233687">การสแกนเชิงลึกสำหรับการดาวน์โหลดที่น่าสงสัย</translation> <translation id="4606247758155004938">องค์กรของคุณเป็นผู้จัดการเบราว์เซอร์</translation> +<translation id="4607887340472970274">การติดตามราคา</translation> <translation id="4611811151908969241">ซ่อน "เลิกติดตาม <ph name="DOMAIN_NAME" />"</translation> <translation id="461440297010471931">กำลังค้นหาด้วย Google</translation> <translation id="4616391354457235490">เลิกทำ</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">เปิดในโหมดไม่ระบุตัวตนไหม</translation> <translation id="4803185665210547709">จัดการโดยองค์กร <ph name="BEGIN_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">ข่าวและเนื้อหาตามความสนใจของคุณ</translation> <translation id="4805759445554688327">หมายเลขบัตรไม่ถูกต้อง</translation> <translation id="4808646838864186379">ยกเลิกการนำส่งแล้ว</translation> <translation id="4808744395915275922">อัปเดต</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906">บทความที่ยังไม่ได้อ่าน <ph name="UNREAD_COUNT" /> รายการ</translation> <translation id="7412027924265291969">ดำเนินการต่อ</translation> <translation id="741204030948306876">ได้สิ ตกลง</translation> +<translation id="7417689656810783109">เปลี่ยนชื่อกลุ่ม</translation> <translation id="7418640008860669073">บันทึกใน...</translation> <translation id="7425346204213733349">การเปลี่ยนแปลงบุ๊กมาร์ก ประวัติการเข้าชม รหัสผ่าน และการตั้งค่าอื่นๆ จะไม่ซิงค์กับบัญชี Google ของคุณอีกต่อไป อย่างไรก็ตาม ข้อมูลที่คุณมีจะยังคงจัดเก็บอยู่ในบัญชี Google</translation> <translation id="7431991332293347422">ควบคุมการใช้ประวัติการท่องเว็บเพื่อปรับเปลี่ยน Search และบริการอื่นๆ ในแบบของคุณ</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">คุณจะกรอกข้อมูลลงใน <ph name="URL" /></translation> <translation id="8281781826761538115">ค่าเริ่มต้น - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">ข้าม</translation> +<translation id="828291969289324795">{count,plural, =1{เพิ่มแท็บไปยังกลุ่มใหม่}other{เพิ่มแท็บไปยังกลุ่มใหม่}}</translation> <translation id="8283172974887967105">ตั้งค่า…</translation> <translation id="8286036467436129157">ลงชื่อเข้าใช้</translation> +<translation id="8292843446079898078">รับการแจ้งเตือนเมื่อราคาผลิตภัณฑ์ที่ติดตามต่ำลง</translation> <translation id="8299417921174340354">หากต้องการใช้รหัสผ่าน คุณต้องตั้งรหัสผ่านในอุปกรณ์ก่อน</translation> <translation id="8299613349954694191">เปิดแท็บที่ไม่ระบุตัวตนเพื่อท่องเว็บในแบบส่วนตัว</translation> <translation id="8311853334103696030">ซ่อน "ติดตามราคา"</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">ปิดทั้งหมด</translation> <translation id="8343993175958086504">สำรองข้อมูลและใช้ในอุปกรณ์เครื่องใดก็ได้</translation> <translation id="834783239627985533">เว็บไซต์ที่เข้าชมบ่อยที่สุด</translation> +<translation id="8358401059263985056">เปิดการแจ้งเตือน</translation> <translation id="8364841868226993049">กำลังบันทึกรูปภาพใน Google Photos สำหรับ <ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">ไปที่การตั้งค่า...</translation> <translation id="8374977641764177587">เปิดการแจ้งเตือนไหม</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_uk.xtb b/ios/chrome/app/strings/resources/ios_strings_uk.xtb index edc6c80..da35990 100644 --- a/ios/chrome/app/strings/resources/ios_strings_uk.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_uk.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">Ваші дані буде введено на веб-сайті <ph name="URL" /></translation> <translation id="8281781826761538115">За умовчанням – <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Пропустити</translation> +<translation id="828291969289324795">{count,plural, =1{Додати вкладку в нову групу}one{Додати вкладки в нову групу}few{Додати вкладки в нову групу}many{Додати вкладки в нову групу}other{Додати вкладки в нову групу}}</translation> <translation id="8283172974887967105">Так…</translation> <translation id="8286036467436129157">Вхід</translation> <translation id="8299417921174340354">Щоб використовувати паролі, спершу потрібно налаштувати код доступу на пристрої.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ur.xtb b/ios/chrome/app/strings/resources/ios_strings_ur.xtb index 68c365b..2fa4cb9 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ur.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ur.xtb
@@ -1412,6 +1412,7 @@ <translation id="8273982424131314219">آپ <ph name="URL" /> میں معلومات پر کریں گے</translation> <translation id="8281781826761538115">ڈیفالٹ - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">نظر انداز کریں</translation> +<translation id="828291969289324795">{count,plural, =1{نئے گروپ میں ٹیب شامل کریں}other{نئے گروپ میں ٹیبز شامل کریں}}</translation> <translation id="8283172974887967105">سیٹ کریں…</translation> <translation id="8286036467436129157">سائن ان کریں</translation> <translation id="8299417921174340354">پاس ورڈز استعمال کرنے کے ليے، آپ کو اپنے آلے پر پہلے پاس کوڈ سیٹ کرنا ہوگا۔</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_uz.xtb b/ios/chrome/app/strings/resources/ios_strings_uz.xtb index ccf16dd..5f462e8 100644 --- a/ios/chrome/app/strings/resources/ios_strings_uz.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_uz.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Yuklab olindi</translation> <translation id="3968505803272650567">Qiziqishlarni sozlash</translation> <translation id="3989635538409502728">Chiqish</translation> +<translation id="3994422733891749358">Qaysi bildirishnomalar kelishini tanlang</translation> <translation id="3995521777587992544">Sahifa yuklanishidagi kutish qatori: <ph name="EMAIL" /> yuklandi.</translation> <translation id="3997522473364371632">Parol ulashuvi administrator tomonidan faolsizlantirilgan.</translation> <translation id="4002019827078931033">Manzillar qatorini tepaga olish</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Klaviatura</translation> <translation id="4601095002996233687">Shubhali yuklanmalarni chuqur tekshirish</translation> <translation id="4606247758155004938">Brauzeringiz tashkilotingiz boshqaruvida.</translation> +<translation id="4607887340472970274">Narx kuzatuvi</translation> <translation id="4611811151908969241"><ph name="DOMAIN_NAME" /> kuzatuvini bekor qilish amalini berkitish</translation> <translation id="461440297010471931">Google orqali qidiruv</translation> <translation id="4616391354457235490">Bekor qilish</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Inkognito rejimida ochilsinmi?</translation> <translation id="4803185665210547709">Tashkilotingiz tomonidan boshqariladi. <ph name="BEGIN_LINK" />Batafsil<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Qiziqishlar asosidagi yangiliklar va kontent</translation> <translation id="4805759445554688327">Karta raqami xato kiritildi</translation> <translation id="4808646838864186379">Joʻnatmangiz bekor qilindi</translation> <translation id="4808744395915275922">Yangilanishlar</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> ta maqola ochilmagan.</translation> <translation id="7412027924265291969">Davom etish</translation> <translation id="741204030948306876">Ha, roziman</translation> +<translation id="7417689656810783109">Guruhni qayta nomlash</translation> <translation id="7418640008860669073">Saqlash joyi...</translation> <translation id="7425346204213733349">Endi xatcho‘plar, brauzer tarixi va boshqa sozlamalaringiz Google hisobingizga sinxronlanmaydi. Shunday bo‘lsa-da, mavjud ma’lumotlaringiz Google hisobingizda saqlanib qoladi.</translation> <translation id="7431991332293347422">Moslashtirilgan qidiruv, reklama va boshqa tashriflar tarixi parametrlarini tanlang</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">Axborot <ph name="URL" /> sahifasida kiritiladi</translation> <translation id="8281781826761538115">Standart - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">Tashlab ketish</translation> +<translation id="828291969289324795">{count,plural, =1{Varaqni yangi guruhga kiritish}other{Varaqlarni yangi guruhga kiritish}}</translation> <translation id="8283172974887967105">Belgilash…</translation> <translation id="8286036467436129157">Kirish</translation> +<translation id="8292843446079898078">Kuzatuvdagi mahsulotlar narxi tushganda xabar olish.</translation> <translation id="8299417921174340354">Parollarni ishlatish uchun qurilmangizni maxfiy kod bilan qulflang.</translation> <translation id="8299613349954694191">Brauzer tarixi saqlanmasligi uchun inkognito tab oching.</translation> <translation id="8311853334103696030">Narxni kuzatishni yashirish</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">Hammasini yopish</translation> <translation id="8343993175958086504">Maʼlumotlaringizni zaxiralang va istalgan qurilmada oching.</translation> <translation id="834783239627985533">Eng koʻp ochilgan saytlar</translation> +<translation id="8358401059263985056">Bildirishnomalarni yoqish</translation> <translation id="8364841868226993049">Rasm <ph name="USER_EMAIL" /> uchun Google Photos xizmatiga saqlanmoqda...</translation> <translation id="8370406443343902172">Sozlamalar ochilmoqda...</translation> <translation id="8374977641764177587">Bildirishnomalar yoqilsinmi?</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_vi.xtb b/ios/chrome/app/strings/resources/ios_strings_vi.xtb index 17cd38e..248d543 100644 --- a/ios/chrome/app/strings/resources/ios_strings_vi.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_vi.xtb
@@ -430,7 +430,7 @@ <translation id="3174662312949010067">Bạn cũng có thể dùng mật khẩu đã lưu trên các thiết bị khác.</translation> <translation id="3175081911749765310">Dịch vụ web</translation> <translation id="3178650076442119961">Hoạt động hôm nay</translation> -<translation id="3181825792072797598">Bật Đồng bộ hóa</translation> +<translation id="3181825792072797598">Bật tính năng đồng bộ hóa</translation> <translation id="3181954750937456830">Duyệt web an toàn (bảo vệ bạn cũng như thiết bị của bạn khỏi các trang web nguy hiểm)</translation> <translation id="3184767182050912705">Mở khóa bằng <ph name="BIOMETRIC_AUTHENITCATION_TYPE" /></translation> <translation id="3190736958609431397">Bỏ theo dõi</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb b/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb index df40cb69..60f4f7a 100644 --- a/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">下載完成</translation> <translation id="3968505803272650567">管理興趣</translation> <translation id="3989635538409502728">登出</translation> +<translation id="3994422733891749358">選擇要接收的通知</translation> <translation id="3995521777587992544">網頁載入進度列,已經載入咗 <ph name="EMAIL" />。</translation> <translation id="3997522473364371632">管理員已停用分享密碼功能。</translation> <translation id="4002019827078931033">將網址列移至頂部</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">鍵盤</translation> <translation id="4601095002996233687">提供深入掃瞄功能,檢查是否有可疑的下載內容。</translation> <translation id="4606247758155004938">您的瀏覽器由機構管理。</translation> +<translation id="4607887340472970274">價格追蹤</translation> <translation id="4611811151908969241">隱藏「取消追蹤 <ph name="DOMAIN_NAME" />」</translation> <translation id="461440297010471931">目前嘅搜尋引擎係 Google</translation> <translation id="4616391354457235490">復原</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">要以無痕模式開啟嗎?</translation> <translation id="4803185665210547709">由您的機構管理。 <ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">根據個人興趣接收新聞和內容相關通知。</translation> <translation id="4805759445554688327">信用卡號碼無效</translation> <translation id="4808646838864186379">已取消送貨</translation> <translation id="4808744395915275922">更新</translation> @@ -907,7 +910,7 @@ <translation id="5737974891429562743">帳戶登入資料已過時。請先更新,然後開始同步資料。</translation> <translation id="5738385766833540397">管理如何接收已追蹤產品的減價通知</translation> <translation id="5738887413654608789">這樣您便可根據周圍環境探索相關網頁。</translation> -<translation id="5744274077973758795">已開啟 <ph name="FEATURE_NAME" />通知功能</translation> +<translation id="5744274077973758795">已開啟「<ph name="FEATURE_NAME" />」通知功能</translation> <translation id="5745916533876677730">前往上一個分頁</translation> <translation id="574762237186762643">活動</translation> <translation id="5748177854685749242">將於 <ph name="DATE" />送達</translation> @@ -932,7 +935,7 @@ <translation id="5850913622988109693">追蹤包裹選項</translation> <translation id="5854790677617711513">超過 30 天</translation> <translation id="5857090052475505287">新資料夾</translation> -<translation id="5857361196621230935">將分頁加入群組</translation> +<translation id="5857361196621230935">在群組中加入分頁</translation> <translation id="5857770089550859117">必須輸入密碼短語,才能開始同步資料。</translation> <translation id="5859715514067755465">繼續</translation> <translation id="5860033963881614850">關閉</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> 篇未讀嘅文章。</translation> <translation id="7412027924265291969">繼續</translation> <translation id="741204030948306876">確認</translation> +<translation id="7417689656810783109">重新命名群組</translation> <translation id="7418640008860669073">儲存位置…</translation> <translation id="7425346204213733349">系統不會將您變更的書籤、記錄、密碼和其他設定繼續同步至您的 Google 帳戶,但 Google 帳戶內現有的資料仍會保留。</translation> <translation id="7431991332293347422">控制系統如何使用您的瀏覽記錄,為您提供個人化的搜尋內容和其他服務</translation> @@ -1285,7 +1289,7 @@ <translation id="7649070708921625228">說明</translation> <translation id="7658239707568436148">取消</translation> <translation id="7666861622396822790">你可在「<ph name="BEGIN_LINK" />內容設定<ph name="END_LINK" />」中管理此選項。</translation> -<translation id="7669493687462784703">要繼續從「<ph name="WEBSITE" />」下載組態設定檔嗎?</translation> +<translation id="7669493687462784703">要繼續從 <ph name="WEBSITE" /> 下載設定描述檔嗎?</translation> <translation id="7671141431838911305">安裝</translation> <translation id="7673346542062368520">向左滑動即可使用無痕模式瀏覽。</translation> <translation id="7679915578945954324">已複製網址</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">你將在 <ph name="URL" /> 中填入資料</translation> <translation id="8281781826761538115">預設 - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">略過</translation> +<translation id="828291969289324795">{count,plural, =1{在新群組中加入分頁}other{在新群組中加入分頁}}</translation> <translation id="8283172974887967105">設定…</translation> <translation id="8286036467436129157">登入</translation> +<translation id="8292843446079898078">接收已追蹤產品的減價通知。</translation> <translation id="8299417921174340354">如要使用密碼,您必須先在裝置上設定密碼。</translation> <translation id="8299613349954694191">開啟無痕式分頁就能以私密模式瀏覽網頁。</translation> <translation id="8311853334103696030">隱藏「追蹤價格」</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">全部關閉</translation> <translation id="8343993175958086504">備份資料即可在任何裝置上使用。</translation> <translation id="834783239627985533">最常瀏覽的網站</translation> +<translation id="8358401059263985056">開啟通知功能</translation> <translation id="8364841868226993049">正在將圖片儲存至 <ph name="USER_EMAIL" /> 的「Google 相片」…</translation> <translation id="8370406443343902172">前往「設定」…</translation> <translation id="8374977641764177587">要啟用通知嗎?</translation> @@ -1536,7 +1543,7 @@ <translation id="891282356902782456">此密碼只會儲存至此裝置。如要在其他裝置上使用此密碼,請將密碼儲存在您的 Google 帳戶 (<ph name="EMAIL" />) 中。</translation> <translation id="8917490105272468696">係,我同意</translation> <translation id="8928133177108699615">桌面模式</translation> -<translation id="8937676484307616731">開啟 <ph name="FEATURE_NAME" />通知功能</translation> +<translation id="8937676484307616731">開啟「<ph name="FEATURE_NAME" />」通知功能</translation> <translation id="894191600409472540">建立安全度高的密碼</translation> <translation id="8952559610785099500">新增密碼</translation> <translation id="8953046091948372197">這裡會顯示您的密碼</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb b/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb index c0b92c8..5e74382c 100644 --- a/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb
@@ -290,7 +290,7 @@ <translation id="2496626742194544812">前往第一個分頁</translation> <translation id="2499505845365628575">你可以在<ph name="HISTORY_BUTTON_ACCESSIBILITY_LABEL" />中查看所有瀏覽記錄。</translation> <translation id="2500374554657206846">儲存密碼的選項</translation> -<translation id="2511117522375201202">你有 <ph name="NUMBER_OF_PASSWORDS" /> 組遭外洩的密碼,可能導致安全性風險。</translation> +<translation id="2511117522375201202">你有 <ph name="NUMBER_OF_PASSWORDS" /> 組密碼外洩,可能導致安全性風險。</translation> <translation id="2529021024822217800">全部開啟</translation> <translation id="2536991091671391962">你可以在任何裝置上使用儲存的密碼,系統會將密碼儲存至 <ph name="EMAIL" /> 的 Google 密碼管理工具。</translation> <translation id="2542268842667970959">隱藏「安全檢查」</translation> @@ -575,6 +575,7 @@ <translation id="3967822245660637423">下載完成</translation> <translation id="3968505803272650567">管理興趣喜好</translation> <translation id="3989635538409502728">登出</translation> +<translation id="3994422733891749358">選擇要接收的通知</translation> <translation id="3995521777587992544">網頁載入進度列,已載入 <ph name="EMAIL" />。</translation> <translation id="3997522473364371632">系統管理員已停用分享密碼功能。</translation> <translation id="4002019827078931033">將網址列移至頂端</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">鍵盤</translation> <translation id="4601095002996233687">提供深入掃描功能,檢查是否有可疑的下載內容。</translation> <translation id="4606247758155004938">你的瀏覽器是由貴機構管理。</translation> +<translation id="4607887340472970274">價格追蹤</translation> <translation id="4611811151908969241">隱藏「取消追蹤 <ph name="DOMAIN_NAME" />」</translation> <translation id="461440297010471931">目前的搜尋引擎是 Google</translation> <translation id="4616391354457235490">復原</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">要以無痕模式開啟嗎?</translation> <translation id="4803185665210547709">由貴機構管理。 <ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">依興趣接收新聞、體育賽事和內容通知。</translation> <translation id="4805759445554688327">卡號無效</translation> <translation id="4808646838864186379">已取消配送</translation> <translation id="4808744395915275922">更新</translation> @@ -1226,7 +1229,7 @@ <translation id="734758817008927353">卡片儲存選項</translation> <translation id="7352651011704765696">發生錯誤</translation> <translation id="7353432112255316844">驗證身分</translation> -<translation id="7367530036083223701">在主畫面上使用「密碼管理工具」小工具安全存取密碼。</translation> +<translation id="7367530036083223701">使用「密碼管理工具」在主畫面提供的小工具,就能安全存取密碼。</translation> <translation id="7380220816562673297">目前只能與家庭成員分享密碼。你可以<ph name="BEGIN_LINK" />建立家庭群組<ph name="END_LINK" /> (最多 6 位成員),讓 Google 的產品和訂閱服務發揮更多價值。</translation> <translation id="7383797227493018512">閱讀清單</translation> <translation id="739101637685146669">要將哪個網址加入書籤?</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> 篇未讀文章。</translation> <translation id="7412027924265291969">繼續</translation> <translation id="741204030948306876">是,我要啟用</translation> +<translation id="7417689656810783109">變更群組名稱</translation> <translation id="7418640008860669073">儲存位置...</translation> <translation id="7425346204213733349">你更改過的書籤、歷史記錄、密碼和其他設定不會繼續與 Google 帳戶中的資料保持同步,但是 Google 帳戶現有的資料仍會保留。</translation> <translation id="7431991332293347422">控管 Google 如何使用瀏覽記錄,提供個人化的搜尋服務和其他內容</translation> @@ -1412,8 +1416,10 @@ <translation id="8273982424131314219">你將在「<ph name="URL" />」中填入資訊</translation> <translation id="8281781826761538115">預設 - <ph name="DEFAULT_LOCALE" /></translation> <translation id="8281886186245836920">略過</translation> +<translation id="828291969289324795">{count,plural, =1{將分頁加入新群組}other{將分頁加入新群組}}</translation> <translation id="8283172974887967105">設定…</translation> <translation id="8286036467436129157">登入</translation> +<translation id="8292843446079898078">接收追蹤產品降價快訊。</translation> <translation id="8299417921174340354">你必須先在裝置上設定螢幕解鎖密碼才能使用密碼。</translation> <translation id="8299613349954694191">開啟無痕分頁就能以私密模式瀏覽網頁。</translation> <translation id="8311853334103696030">隱藏「追蹤價格」</translation> @@ -1421,6 +1427,7 @@ <translation id="8328777765163860529">關閉全部</translation> <translation id="8343993175958086504">備份資料即可在任何裝置上使用。</translation> <translation id="834783239627985533">最常造訪的網站</translation> +<translation id="8358401059263985056">開啟通知功能</translation> <translation id="8364841868226993049">正在將圖片儲存至 <ph name="USER_EMAIL" /> 的 Google 相簿...</translation> <translation id="8370406443343902172">前往「設定」...</translation> <translation id="8374977641764177587">要開啟通知嗎?</translation> @@ -1460,7 +1467,7 @@ <translation id="8533670235862049797">已啟用安全瀏覽功能</translation> <translation id="8534481786647257214">已順利發布到 Google+。</translation> <translation id="8548878600947630424">在網頁中尋找...</translation> -<translation id="854938212724803178">你有 1 組遭外洩的密碼,請立即修正以確保安全。</translation> +<translation id="854938212724803178">你有 1 組密碼外洩,請立即修正確保安全。</translation> <translation id="8556590991644167667">{count,plural, =1{你已忽略 {count} 則警告}other{你已忽略 {count} 則警告}}</translation> <translation id="8560253818350321773">優先顯示常用項目。</translation> <translation id="8569721750632860947">你想將哪個網址加入閱讀清單?</translation> @@ -1482,7 +1489,7 @@ <translation id="8654802032646794042">取消</translation> <translation id="8663764600409216912">目前使用的密碼不容易讓人猜中</translation> <translation id="8668210798914567634">此網頁內容已儲存至你的閱讀清單。</translation> -<translation id="8674716540979958118">你使用的密碼已外洩。</translation> +<translation id="8674716540979958118">你有密碼外洩。</translation> <translation id="8680787084697685621">帳戶登入詳細資料已過期。</translation> <translation id="868773710103052534">大功告成!</translation> <translation id="8692689525339542358">守護網頁瀏覽安全,有效防堵危險網站、下載內容和擴充功能。</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zu.xtb b/ios/chrome/app/strings/resources/ios_strings_zu.xtb index 040c78f..58696ec5 100644 --- a/ios/chrome/app/strings/resources/ios_strings_zu.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_zu.xtb
@@ -575,6 +575,7 @@ <translation id="3967822245660637423">Ukulanda kuqedile</translation> <translation id="3968505803272650567">Phatha ongaba nentshisekelo kukho</translation> <translation id="3989635538409502728">Phuma ngemvume</translation> +<translation id="3994422733891749358">Khetha izaziso ofuna ukuzithola</translation> <translation id="3995521777587992544">Ibha yenqubo yokulayisha ikhasi, i-<ph name="EMAIL" /> ilayishiwe.</translation> <translation id="3997522473364371632">Ukwabelana ngephasiwedi kukhutshazwe umlawuli wakho.</translation> <translation id="4002019827078931033">Hambisa Ibha Lekheli Phezulu</translation> @@ -684,6 +685,7 @@ <translation id="4592368184551360546">Ikhibhodi</translation> <translation id="4601095002996233687">Ukuskena okujulile kokudawunilodwa okusolisayo.</translation> <translation id="4606247758155004938">Ibhrawuza yakho iphethwe inhlangano yakho.</translation> +<translation id="4607887340472970274">Ukulandelela Intengo</translation> <translation id="4611811151908969241">Fihla Ukuyekela Ukulandela <ph name="DOMAIN_NAME" /></translation> <translation id="461440297010471931">Ukusesha nge-Google</translation> <translation id="4616391354457235490">Hlehlisa</translation> @@ -724,6 +726,7 @@ <translation id="478808905805139173">Uyivula ku-incognito?</translation> <translation id="4803185665210547709">Kuphethwe inhlangano yakho. <ph name="BEGIN_LINK" />Funda kabanzi<ph name="END_LINK" /></translation> +<translation id="4805558373042023669">Izindaba nokuqukethwe okususelwe kuzintshisekelo zakho.</translation> <translation id="4805759445554688327">Inombolo yekhadi engavumelekile</translation> <translation id="4808646838864186379">Okudilivwayo kwakho kukhanseliwe</translation> <translation id="4808744395915275922">Izibuyekezo</translation> @@ -1238,6 +1241,7 @@ <translation id="7409985198648820906"><ph name="UNREAD_COUNT" /> ama-athikili angafundiwe.</translation> <translation id="7412027924265291969">Qhubeka</translation> <translation id="741204030948306876">Yebo, ngingenile</translation> +<translation id="7417689656810783109">Qamba Kabusha Iqembu</translation> <translation id="7418640008860669073">Londoloza kokuthi...</translation> <translation id="7425346204213733349">Izinguquko kumabhukhimakhi akho, umlando, amaphasiwedi, nezinye izilungiselelo ngeke kusavumelaniswa ku-akhawunti yakho ye-Google. Yize kunjalo, idatha yakho ekhona izohlala igcinwe ku-akhawunti yakho ye-Google.</translation> <translation id="7431991332293347422">Lawula ukuthi umlando wakho wokuphequlula usetshenziswa kanjani ukuze kwenziwe kube ngokwakho Usesho nokuningi</translation> @@ -1414,6 +1418,7 @@ <translation id="8281886186245836920">Yeqa</translation> <translation id="8283172974887967105">Setha…</translation> <translation id="8286036467436129157">Ngena Ngemvume</translation> +<translation id="8292843446079898078">Thola izexwayiso zokwehla kwentengo yemikhiqizo oyilandelelayo.</translation> <translation id="8299417921174340354">Ukuze usebenzise amaphasiwedi, kuzomele uqale usethe ikhodi yokudlula kudivayisi yakho.</translation> <translation id="8299613349954694191">Vula i ithebhu ye-incognito ukuze uphequlule iwebhu ngokuyimfihlo.</translation> <translation id="8311853334103696030">Fihla Inani Lethrekhi</translation> @@ -1421,6 +1426,7 @@ <translation id="8328777765163860529">Vala konke</translation> <translation id="8343993175958086504">Yenza isipele izinto zakho futhi uzisebenzise kunoma iyiphi idivayisi.</translation> <translation id="834783239627985533">Amasayithi Avakashelwe Kaningi</translation> +<translation id="8358401059263985056">Vula Izaziso</translation> <translation id="8364841868226993049">Ilondoloza umfanekiso ku-Google Photos ka-<ph name="USER_EMAIL" />...</translation> <translation id="8370406443343902172">Iya kokuthi Amasethingi...</translation> <translation id="8374977641764177587">Vula Izaziso?</translation>
diff --git a/ios/chrome/browser/application_context/model/application_context_impl.mm b/ios/chrome/browser/application_context/model/application_context_impl.mm index 2e718072..182bee9 100644 --- a/ios/chrome/browser/application_context/model/application_context_impl.mm +++ b/ios/chrome/browser/application_context/model/application_context_impl.mm
@@ -597,9 +597,6 @@ // Cleanup obsolete preferences. MigrateObsoleteLocalStatePrefs(local_state_.get()); - // Delete obsolete data from user storage. - CleanupUnusedStorage(); - // Delete obsolete data from NSUserDefaults. MigrateObsoleteUserDefault(); }
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_client_impl.cc b/ios/chrome/browser/bookmarks/model/bookmark_client_impl.cc index 014c29f..27630c7 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_client_impl.cc +++ b/ios/chrome/browser/bookmarks/model/bookmark_client_impl.cc
@@ -115,11 +115,19 @@ return false; } -std::string BookmarkClientImpl::EncodeBookmarkSyncMetadata() { +std::string BookmarkClientImpl::EncodeLocalOrSyncableBookmarkSyncMetadata() { return bookmark_sync_service_->EncodeBookmarkSyncMetadata(); } -void BookmarkClientImpl::DecodeBookmarkSyncMetadata( +std::string BookmarkClientImpl::EncodeAccountBookmarkSyncMetadata() { + // On iOS, for historic reasons, a dedicated BookmarkModel is used for account + // bookmarks and, counter-intuitively, the local-or-syncable nodes within are + // used to represent account data. The same is true for sync metadata, so + // account sync metadata remains unused. + return std::string(); +} + +void BookmarkClientImpl::DecodeLocalOrSyncableBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) { // On iOS, for historic reasons, a dedicated BookmarkModel is used for account @@ -133,6 +141,13 @@ sync_bookmarks::BookmarkModelViewUsingLocalOrSyncableNodes>(model_)); } +void BookmarkClientImpl::DecodeAccountBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) { + // See comment in `EncodeAccountBookmarkSyncMetadata()` for rationale about + // why account sync metadata remains unused on iOS. +} + void BookmarkClientImpl::OnBookmarkNodeRemovedUndoable( bookmarks::BookmarkModel* model, const bookmarks::BookmarkNode* parent,
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_client_impl.h b/ios/chrome/browser/bookmarks/model/bookmark_client_impl.h index 9b9f4e3..78d63f3 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_client_impl.h +++ b/ios/chrome/browser/bookmarks/model/bookmark_client_impl.h
@@ -54,8 +54,12 @@ bool CanSetPermanentNodeTitle( const bookmarks::BookmarkNode* permanent_node) override; bool IsNodeManaged(const bookmarks::BookmarkNode* node) override; - std::string EncodeBookmarkSyncMetadata() override; - void DecodeBookmarkSyncMetadata( + std::string EncodeLocalOrSyncableBookmarkSyncMetadata() override; + std::string EncodeAccountBookmarkSyncMetadata() override; + void DecodeLocalOrSyncableBookmarkSyncMetadata( + const std::string& metadata_str, + const base::RepeatingClosure& schedule_save_closure) override; + void DecodeAccountBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) override; void OnBookmarkNodeRemovedUndoable(
diff --git a/ios/chrome/browser/default_browser/model/BUILD.gn b/ios/chrome/browser/default_browser/model/BUILD.gn index 421b6b7..a28d007 100644 --- a/ios/chrome/browser/default_browser/model/BUILD.gn +++ b/ios/chrome/browser/default_browser/model/BUILD.gn
@@ -26,6 +26,14 @@ frameworks = [ "Foundation.framework" ] } +source_set("default_browser_interest_signals") { + sources = [ + "default_browser_interest_signals.h", + "default_browser_interest_signals.mm", + ] + deps = [ ":utils" ] +} + source_set("test_support") { testonly = true sources = [
diff --git a/ios/chrome/browser/default_browser/model/default_browser_interest_signals.h b/ios/chrome/browser/default_browser/model/default_browser_interest_signals.h new file mode 100644 index 0000000..9154223 --- /dev/null +++ b/ios/chrome/browser/default_browser/model/default_browser_interest_signals.h
@@ -0,0 +1,18 @@ +// 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 IOS_CHROME_BROWSER_DEFAULT_BROWSER_MODEL_DEFAULT_BROWSER_INTEREST_SIGNALS_H_ +#define IOS_CHROME_BROWSER_DEFAULT_BROWSER_MODEL_DEFAULT_BROWSER_INTEREST_SIGNALS_H_ + +namespace default_browser { + +// Records all necessary information for Chrome start with widget. +void NotifyStartWithWidget(); + +// Records all necessary information for Chrome start with URL event. +void NotifyStartWithURL(); + +} // namespace default_browser + +#endif // IOS_CHROME_BROWSER_DEFAULT_BROWSER_MODEL_DEFAULT_BROWSER_INTEREST_SIGNALS_H_
diff --git a/ios/chrome/browser/default_browser/model/default_browser_interest_signals.mm b/ios/chrome/browser/default_browser/model/default_browser_interest_signals.mm new file mode 100644 index 0000000..97fb8f8 --- /dev/null +++ b/ios/chrome/browser/default_browser/model/default_browser_interest_signals.mm
@@ -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. + +#import "ios/chrome/browser/default_browser/model/default_browser_interest_signals.h" + +#import "ios/chrome/browser/default_browser/model/utils.h" + +namespace default_browser { + +void NotifyStartWithWidget() { + // TODO(b/322358517): Migrate to FET. + LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeMadeForIOS); + LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral); +} + +void NotifyStartWithURL() { + // TODO(b/322358517): Migrate to FET. + LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral); +} + +} // namespace default_browser
diff --git a/ios/chrome/browser/default_browser/model/utils.h b/ios/chrome/browser/default_browser/model/utils.h index cfb500d..33e74f39 100644 --- a/ios/chrome/browser/default_browser/model/utils.h +++ b/ios/chrome/browser/default_browser/model/utils.h
@@ -305,10 +305,6 @@ // post restore default browser promo. bool IsPostRestoreDefaultBrowserEligibleUser(); -// Removes unused data from NSUserDefaults. This method should be periodically -// pruned of cleanups that have been present for multiple milestones. -void CleanupUnusedStorage(); - // Converts Default browser promo type NSEnum to an enum that can be used by // UMA. DefaultPromoTypeForUMA GetDefaultPromoTypeForUMA(DefaultPromoType type);
diff --git a/ios/chrome/browser/default_browser/model/utils.mm b/ios/chrome/browser/default_browser/model/utils.mm index cc4842d..f2a52cb4 100644 --- a/ios/chrome/browser/default_browser/model/utils.mm +++ b/ios/chrome/browser/default_browser/model/utils.mm
@@ -88,18 +88,6 @@ NSString* const kTailoredPromoInteractionCount = @"tailoredPromoInteractionCount"; -// TODO(crbug.com/1445218): Remove in M116+. -// Key in storage containing an NSDate indicating the last time a user -// interacted with the "remind me later" panel. -NSString* const kRemindMeLaterPromoActionInteraction = - @"remindMeLaterPromoActionInteraction"; - -// TODO(crbug.com/1445240): Remove in M116+. -// Key in storage containing a bool indicating if the user tapped on -// button to open settings. -NSString* const kOpenSettingsActionInteraction = - @"openSettingsActionInteraction"; - // Key in storage containing the timestamp of the last time the user opened the // app via first-party intent. NSString* const kTimestampAppLastOpenedViaFirstPartyIntent = @@ -895,7 +883,6 @@ kDisplayedFullscreenPromoCount, kTailoredPromoInteractionCount, kGenericPromoInteractionCount, - kRemindMeLaterPromoActionInteraction, // clang-format on ]; @@ -972,15 +959,6 @@ IsChromeLikelyDefaultBrowser(); } -void CleanupUnusedStorage() { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - - // TODO(crbug.com/1445240): Remove in M116+. - [defaults removeObjectForKey:kOpenSettingsActionInteraction]; - // TODO(crbug.com/1445218): Remove in M116+. - [defaults removeObjectForKey:kRemindMeLaterPromoActionInteraction]; -} - DefaultPromoTypeForUMA GetDefaultPromoTypeForUMA(DefaultPromoType type) { switch (type) { case DefaultPromoTypeGeneral:
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn index 589a5f0..7805496f 100644 --- a/ios/chrome/browser/flags/BUILD.gn +++ b/ios/chrome/browser/flags/BUILD.gn
@@ -65,7 +65,7 @@ "//ios/chrome/browser/drag_and_drop/model", "//ios/chrome/browser/find_in_page/model:util", "//ios/chrome/browser/follow/model:feature_flags", - "//ios/chrome/browser/iph_for_new_chrome_user/model", + "//ios/chrome/browser/iph_for_new_chrome_user/model:features", "//ios/chrome/browser/parcel_tracking:features", "//ios/chrome/browser/policy/model", "//ios/chrome/browser/policy/model:constants",
diff --git a/ios/chrome/browser/iph_for_new_chrome_user/model/BUILD.gn b/ios/chrome/browser/iph_for_new_chrome_user/model/BUILD.gn index 403f021f..22a2d7a 100644 --- a/ios/chrome/browser/iph_for_new_chrome_user/model/BUILD.gn +++ b/ios/chrome/browser/iph_for_new_chrome_user/model/BUILD.gn
@@ -4,14 +4,13 @@ source_set("model") { sources = [ - "features.h", - "features.mm", "tab_based_iph_browser_agent.h", "tab_based_iph_browser_agent.mm", "utils.h", "utils.mm", ] deps = [ + ":features", "//base", "//components/feature_engagement/public", "//components/segmentation_platform/embedder/default_model", @@ -26,3 +25,14 @@ "//ios/chrome/browser/url_loading/model", ] } + +source_set("features") { + sources = [ + "features.h", + "features.mm", + ] + deps = [ + "//base", + "//ios/chrome/browser/shared/public/features:system_flags", + ] +}
diff --git a/ios/chrome/browser/main/model/browser_util.mm b/ios/chrome/browser/main/model/browser_util.mm index 604d28e..0ca3343 100644 --- a/ios/chrome/browser/main/model/browser_util.mm +++ b/ios/chrome/browser/main/model/browser_util.mm
@@ -55,7 +55,7 @@ MoveSnapshot(snapshot_tab_helper->GetSnapshotID(), source_browser, destination_browser); - int insertion_flags = flags; + WebStateList::InsertionFlags insertion_flags = flags; if (insertion_flags == WebStateList::InsertionFlags::INSERT_NO_FLAGS) { insertion_flags = WebStateList::INSERT_FORCE_INDEX; // TODO(crbug.com/1264451): Remove this workaround when it will not be @@ -65,9 +65,11 @@ } } - destination_browser->GetWebStateList()->InsertWebState( - destination_tab_index, std::move(web_state), insertion_flags, - WebStateOpener()); + WebStateList::InsertionParams params = + WebStateList::InsertionParams::ForDeprecationMigration( + insertion_flags, destination_tab_index); + destination_browser->GetWebStateList()->InsertWebState(std::move(web_state), + params); } void MoveTabFromBrowserToBrowser(Browser* source_browser,
diff --git a/ios/chrome/browser/shared/model/web_state_list/web_state_list.h b/ios/chrome/browser/shared/model/web_state_list/web_state_list.h index e56f6a4..497c8a7 100644 --- a/ios/chrome/browser/shared/model/web_state_list/web_state_list.h +++ b/ios/chrome/browser/shared/model/web_state_list/web_state_list.h
@@ -73,6 +73,13 @@ this->pinned = pin; return *this; } + + // To simplify migrating off of the deprecated `InsertWebState` member + // function, convert a set of insertion parameters to real InsertionParams. + static InsertionParams ForDeprecationMigration( + int insertion_flags, + int desired_index = kInvalidIndex, + WebStateOpener opener = WebStateOpener()); }; // Deprecated. Use InsertionParams.
diff --git a/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm b/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm index f513118..a33ebfe5 100644 --- a/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm +++ b/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm
@@ -33,6 +33,21 @@ } // namespace +WebStateList::InsertionParams +WebStateList::InsertionParams::ForDeprecationMigration(int insertion_flags, + int desired_index, + WebStateOpener opener) { + InsertionParams params = InsertionParams::Automatic(); + if (IsInsertionFlagSet(insertion_flags, INSERT_FORCE_INDEX)) { + params = InsertionParams::AtIndex(desired_index); + } + params.WithOpener(opener) + .InheritOpener(IsInsertionFlagSet(insertion_flags, INSERT_INHERIT_OPENER)) + .Activate(IsInsertionFlagSet(insertion_flags, INSERT_ACTIVATE)) + .Pinned(IsInsertionFlagSet(insertion_flags, INSERT_PINNED)); + return params; +} + WebStateList::ScopedBatchOperation::ScopedBatchOperation( WebStateList* web_state_list) : web_state_list_(web_state_list) { @@ -336,20 +351,8 @@ int insertion_flags, WebStateOpener opener) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - InsertionParams params = InsertionParams::Automatic(); - if (IsInsertionFlagSet(insertion_flags, INSERT_FORCE_INDEX)) { - params = InsertionParams::AtIndex(index); - } - params.WithOpener(opener); - if (IsInsertionFlagSet(insertion_flags, INSERT_INHERIT_OPENER)) { - params.InheritOpener(); - } - if (IsInsertionFlagSet(insertion_flags, INSERT_ACTIVATE)) { - params.Activate(); - } - if (IsInsertionFlagSet(insertion_flags, INSERT_PINNED)) { - params.Pinned(); - } + InsertionParams params = + InsertionParams::ForDeprecationMigration(insertion_flags, index, opener); return InsertWebState(std::move(web_state), params); }
diff --git a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_egtest.mm b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_egtest.mm index 64c300a..d600797 100644 --- a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_egtest.mm +++ b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_egtest.mm
@@ -518,16 +518,10 @@ // Tests that both the virtual card and the original card are shown // in the Payments Bottom Sheet. -// TODO(crbug.com/1524066): This test flakily crashes the browser. -- (void)DISABLED_testPaymentsBottomSheetShowsVirtualCard { +- (void)testPaymentsBottomSheetShowsVirtualCard { // Add a credit card enrolled in VCN to the Personal Data Manager. - [AutofillAppInterface saveMaskedCreditCardEnrolledInVirtualCard]; - - NSString* virtualCardAccessibleName = - @"Virtual card Mastercard ending in 2 1 0 9, , 1 of 3"; - NSString* creditCardAccessibleName = [NSString - stringWithFormat:@"Mastercard ending in 2 1 0 9, expires on %@, , 2 of 3", - ExpirationDateNSString()]; + NSString* enrolledCardNameAndLastFour = + [AutofillAppInterface saveMaskedCreditCardEnrolledInVirtualCard]; [self loadPaymentsPage]; @@ -537,11 +531,17 @@ // Confirm virtual card is displayed. [[EarlGrey - selectElementWithMatcher:grey_accessibilityID(virtualCardAccessibleName)] + selectElementWithMatcher:grey_accessibilityID([NSString + stringWithFormat:@"%@ %@", + enrolledCardNameAndLastFour, + @"Virtual card"])] assertWithMatcher:grey_sufficientlyVisible()]; // Confirm original card is displayed. [[EarlGrey - selectElementWithMatcher:grey_accessibilityID(creditCardAccessibleName)] + selectElementWithMatcher:grey_accessibilityID([NSString + stringWithFormat:@"%@ %@", + enrolledCardNameAndLastFour, + ExpirationDateNSString()])] assertWithMatcher:grey_sufficientlyVisible()]; // Dismiss the bottom sheet by tapping outside.
diff --git a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_mediator_unittest.mm b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_mediator_unittest.mm index 092ee31a..69bff74 100644 --- a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_mediator_unittest.mm +++ b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_mediator_unittest.mm
@@ -5,12 +5,9 @@ #import "ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_mediator.h" #import "components/autofill/core/browser/autofill_test_utils.h" -#import "components/autofill/core/browser/personal_data_manager.h" +#import "components/autofill/core/browser/test_personal_data_manager.h" #import "components/autofill/core/common/autofill_prefs.h" #import "components/autofill/ios/form_util/form_activity_params.h" -#import "components/prefs/pref_service.h" -#import "components/sync/test/test_sync_service.h" -#import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/shared/model/web_state_list/test/fake_web_state_list_delegate.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_opener.h" @@ -32,34 +29,18 @@ class PaymentsSuggestionBottomSheetMediatorTest : public PlatformTest { protected: PaymentsSuggestionBottomSheetMediatorTest() - : test_web_state_(std::make_unique<web::FakeWebState>()), - personal_data_manager_( - std::make_unique<autofill::PersonalDataManager>("en", - std::string())) { + : test_web_state_(std::make_unique<web::FakeWebState>()) { web_state_list_ = std::make_unique<WebStateList>(&web_state_list_delegate_); test_web_state_->SetCurrentURL(GURL("http://foo.com")); - TestChromeBrowserState::Builder builder; - chrome_browser_state_ = builder.Build(); - consumer_ = OCMProtocolMock(@protocol(PaymentsSuggestionBottomSheetConsumer)); } - ~PaymentsSuggestionBottomSheetMediatorTest() override { - if (personal_data_manager_) { - personal_data_manager_->Shutdown(); - } - personal_data_manager_.reset(); - } - void SetUp() override { - PrefService* pref_service = chrome_browser_state_->GetPrefs(); - autofill::prefs::SetAutofillProfileEnabled(pref_service, true); - autofill::prefs::SetAutofillPaymentMethodsEnabled(pref_service, true); - personal_data_manager_->SetPrefService(pref_service); - personal_data_manager_->SetSyncServiceForTest(&sync_service_); + personal_data_manager_.SetAutofillProfileEnabled(true); + personal_data_manager_.SetAutofillPaymentMethodsEnabled(true); } void TearDown() override { [mediator_ disconnect]; } @@ -73,7 +54,7 @@ mediator_ = [[PaymentsSuggestionBottomSheetMediator alloc] initWithWebStateList:web_state_list_.get() params:autofill::FormActivityParams() - personalDataManager:personal_data_manager_.get()]; + personalDataManager:&personal_data_manager_]; } // Add credit card to personal data manager. @@ -83,20 +64,14 @@ int64_t instrument_id = 0, autofill::CreditCard::RecordType record_type = autofill::CreditCard::RecordType::kMaskedServerCard) { - autofill::CreditCard card = autofill::CreditCard(); + autofill::CreditCard card; autofill::test::SetCreditCardInfo(&card, "Jane Doe", number.c_str(), autofill::test::NextMonth().c_str(), autofill::test::NextYear().c_str(), "1"); card.set_guid(guid); card.set_instrument_id(instrument_id); card.set_record_type(record_type); - - std::unique_ptr<autofill::CreditCard> server_credit_card = - std::make_unique<autofill::CreditCard>(card); - personal_data_manager_->server_credit_cards_.push_back( - std::move(server_credit_card)); - personal_data_manager_->NotifyPersonalDataObserver(); - + personal_data_manager_.AddServerCreditCard(card); return card; } @@ -105,7 +80,7 @@ void CreateMediatorWithSuggestions() { CreateMediator(); CreateCreditCard(kTestGuid); - personal_data_manager_->SetSyncingForTest(true); + personal_data_manager_.SetSyncingForTest(true); } // Create a mediator and make sure the personal data manager contains at least @@ -114,17 +89,15 @@ CreateMediator(); CreateCreditCard(kTestGuid, kTestNumber, 0, autofill::CreditCard::RecordType::kLocalCard); - personal_data_manager_->SetSyncingForTest(true); + personal_data_manager_.SetSyncingForTest(true); } web::WebTaskEnvironment task_environment_; std::unique_ptr<web::FakeWebState> test_web_state_; FakeWebStateListDelegate web_state_list_delegate_; std::unique_ptr<WebStateList> web_state_list_; - std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; - syncer::TestSyncService sync_service_; id consumer_; - std::unique_ptr<autofill::PersonalDataManager> personal_data_manager_; + autofill::TestPersonalDataManager personal_data_manager_; PaymentsSuggestionBottomSheetMediator* mediator_; };
diff --git a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm index 2fc8128a..46e56c4f 100644 --- a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm
@@ -557,7 +557,9 @@ // own is no longer a unique identifier, so we include the description. if (base::FeatureList::IsEnabled( autofill::features::kAutofillEnableVirtualCards)) { - cell.accessibilityIdentifier = [self accessibleCardNameAtRow:indexPath.row]; + cell.accessibilityIdentifier = + [NSString stringWithFormat:@"%@ %@", cell.textLabel.text, + [self descriptionAtRow:indexPath.row]]; } else { cell.accessibilityIdentifier = cell.textLabel.text; }
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm b/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm index 1dd45e9..0b524c7e 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm
@@ -123,7 +123,7 @@ _accountBookmarkModel.get()); NSString* text = bookmark_utils_ios::messageForAddingBookmarksInFolder( folderTitle, !IsLastUsedBookmarkFolderSet(_prefs), storageType, - /*count=*/1, _authenticationService, _syncService); + /*showCount=*/false, /*count=*/1, _authenticationService, _syncService); TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); MDCSnackbarMessage* message = [MDCSnackbarMessage messageWithText:text]; message.action = action; @@ -186,9 +186,12 @@ bookmarks::StorageType storageType = bookmark_utils_ios::GetBookmarkModelType( defaultFolder, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); - NSString* result = [self - messageForBulkAddingBookmarksWithStorageType:storageType - successfullyAddedBookmarks:successfullyAddedBookmarks]; + NSString* folderTitle = + bookmark_utils_ios::TitleForBookmarkNode(defaultFolder); + NSString* result = bookmark_utils_ios::messageForAddingBookmarksInFolder( + folderTitle, !IsLastUsedBookmarkFolderSet(_prefs), storageType, + /*showCount=*/true, successfullyAddedBookmarks, _authenticationService, + _syncService); TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); MDCSnackbarMessage* message = [MDCSnackbarMessage messageWithText:result]; @@ -216,8 +219,8 @@ bookmarks::StorageType storageType = bookmark_utils_ios::GetBookmarkModelType( folder, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); NSString* text = bookmark_utils_ios::messageForAddingBookmarksInFolder( - folderTitle, /*choosenByUser=*/YES, storageType, URLs.count, - _authenticationService, _syncService); + folderTitle, /*choosenByUser=*/YES, storageType, /*showCount=*/false, + URLs.count, _authenticationService, _syncService); TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); MDCSnackbarMessage* message = [MDCSnackbarMessage messageWithText:text]; message.category = bookmark_utils_ios::kBookmarksSnackbarCategory;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm b/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm index f9bc806..3cdeb39 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm
@@ -55,7 +55,8 @@ class BookmarkMediatorUnitTest : public BookmarkIOSUnitTestSupport, - public testing::WithParamInterface<std::tuple<int, bool, SignInStatus>> { + public testing::WithParamInterface< + std::tuple<int, bool, SignInStatus, bool>> { public: void SetUp() override { BookmarkIOSUnitTestSupport::SetUp(); @@ -74,9 +75,11 @@ // Number of bookmark saved. int GetBookmarkCountParam() { return std::get<0>(GetParam()); } - // Weather the bookmarks are saved in the default folder or not. + // Wether the bookmarks are saved in the default folder or not. bool GetFolderWasSelectedByUserParam() { return std::get<1>(GetParam()); } SignInStatus GetSignInStatusParam() { return std::get<2>(GetParam()); } + // Wether to display the number of bookmarks when it’s not 1. + bool GetDisplayTheNumberOfBookmarksParam() { return std::get<3>(GetParam()); } protected: // Signs in using `fakeIdentity1`. @@ -109,16 +112,20 @@ } // Returns `IDS_IOS_BOOKMARKS_BULK_SAVED` string with `count` value. - NSString* GetSavedToDeviceText(int count) { - return base::SysUTF16ToNSString( - l10n_util::GetPluralStringFUTF16(IDS_IOS_BOOKMARKS_BULK_SAVED, count)); + NSString* GetSavedToDeviceText(int count, bool show_count) { + return base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16( + (show_count) ? IDS_IOS_BOOKMARKS_BULK_SAVED : IDS_IOS_BOOKMARKS_SAVED, + count)); } // Returns `IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER` string with `count` and // `folder_name` value. - NSString* GetSavedToFolderText(int count, NSString* folder_name) { - std::u16string pattern = - l10n_util::GetStringUTF16(IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER); + NSString* GetSavedToFolderText(int count, + NSString* folder_name, + bool show_count) { + std::u16string pattern = l10n_util::GetStringUTF16( + (show_count) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER + : IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER); std::u16string message = base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "title", base::SysNSStringToUTF16(folder_name)); @@ -127,9 +134,10 @@ // Returns `IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT` string with `count` and // `email` value. - NSString* GetSavedToAccountText(int count, NSString* email) { - std::u16string pattern = - l10n_util::GetStringUTF16(IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT); + NSString* GetSavedToAccountText(int count, NSString* email, bool show_count) { + std::u16string pattern = l10n_util::GetStringUTF16( + (show_count) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT + : IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT); std::u16string message = base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "email", base::SysNSStringToUTF16(email)); return base::SysUTF16ToNSString(message); @@ -139,9 +147,11 @@ // `folder_name` and `email` value. NSString* GetSavedToFolderToAccountText(int count, NSString* folder_name, - NSString* email) { + NSString* email, + bool show_count) { std::u16string pattern = l10n_util::GetStringUTF16( - IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT_FOLDER); + (show_count) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT_FOLDER + : IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT_FOLDER); std::u16string message = base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "title", base::SysNSStringToUTF16(folder_name), "email", base::SysNSStringToUTF16(email)); @@ -150,9 +160,12 @@ // Returns `IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE` string with `count`, // `folder_name` and `email` value. - NSString* GetSavedLocallyOnlyText(int count, NSString* folder_name) { - std::u16string pattern = - l10n_util::GetStringUTF16(IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE); + NSString* GetSavedLocallyOnlyText(int count, + NSString* folder_name, + bool show_count) { + std::u16string pattern = l10n_util::GetStringUTF16( + (show_count) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER_TO_DEVICE + : IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE); std::u16string message = base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "title", base::SysNSStringToUTF16(folder_name)); @@ -180,7 +193,9 @@ SignInStatus::kSignedInOnlyWithLocalOrSyncableStorage, SignInStatus::kSignedInNoBookmarkSyncing, SignInStatus::kSignedInOnlyWithAccountStorage, - SignInStatus::KSignedInAndSync))); + SignInStatus::KSignedInAndSync), + // Whether or not the count should be displayed. + testing::Bool())); // Tests the snackbar message with all the different combinaisons with: // * One or two saved bookmarks @@ -193,6 +208,7 @@ NSString* expected_snackbar_message = nil; bookmarks::StorageType bookmark_storage_type = bookmarks::StorageType::kLocalOrSyncable; + bool show_count = GetDisplayTheNumberOfBookmarksParam(); switch (signed_in_status) { case SignInStatus::kSignedInNoBookmarkSyncing: SignInOnlyAndDisableBookmark(); @@ -200,8 +216,8 @@ case SignInStatus::kSignOut: expected_snackbar_message = (folder_was_selected_by_user) - ? GetSavedToFolderText(bookmark_count, kFolderName) - : GetSavedToDeviceText(bookmark_count); + ? GetSavedToFolderText(bookmark_count, kFolderName, show_count) + : GetSavedToDeviceText(bookmark_count, show_count); break; case SignInStatus::kSignedInOnlyWithLocalOrSyncableStorage: if (!folder_was_selected_by_user) { @@ -211,15 +227,15 @@ return; } expected_snackbar_message = - GetSavedLocallyOnlyText(bookmark_count, kFolderName); + GetSavedLocallyOnlyText(bookmark_count, kFolderName, show_count); SignInOnly(); break; case SignInStatus::kSignedInOnlyWithAccountStorage: expected_snackbar_message = (folder_was_selected_by_user) ? GetSavedToFolderToAccountText(bookmark_count, kFolderName, - kEmail) - : GetSavedToAccountText(bookmark_count, kEmail); + kEmail, show_count) + : GetSavedToAccountText(bookmark_count, kEmail, show_count); SignInOnly(); bookmark_storage_type = bookmarks::StorageType::kAccount; break; @@ -227,15 +243,15 @@ expected_snackbar_message = (folder_was_selected_by_user) ? GetSavedToFolderToAccountText(bookmark_count, kFolderName, - kEmail) - : GetSavedToAccountText(bookmark_count, kEmail); + kEmail, show_count) + : GetSavedToAccountText(bookmark_count, kEmail, show_count); SignInAndSync(); break; } NSString* const snackbar_message = bookmark_utils_ios::messageForAddingBookmarksInFolder( kFolderName, folder_was_selected_by_user, bookmark_storage_type, - bookmark_count, + show_count, bookmark_count, AuthenticationServiceFactory::GetForBrowserState( chrome_browser_state_.get()) ->GetWeakPtr(),
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h index e20aa86..81508283 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h
@@ -260,12 +260,14 @@ // `folderTitle`: The name of the folder. Assumed to be non-nil. // `chosenByUser`: whether this is the last folder in which the user moved a // bookmark since last time the set of model changed. -// `storageType` whether it is is on account storage, or local or syncable. +// `storageType`: whether it is is on account storage, or local or syncable. +// `showCount`: Display the number of moved bookmarks in the snackbar. // `count`: the number of bookmarks. NSString* messageForAddingBookmarksInFolder( NSString* folderTitle, bool chosenByUser, bookmarks::StorageType storageType, + bool showCount, int count, base::WeakPtr<AuthenticationService> authenticationService, raw_ptr<syncer::SyncService> syncService);
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm index d7d8ad12..563cff74 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
@@ -293,6 +293,7 @@ NSString* folderTitle, bool chosenByUser, bookmarks::StorageType storageType, + bool showCount, int count, base::WeakPtr<AuthenticationService> authenticationService, raw_ptr<syncer::SyncService> syncService) { @@ -309,13 +310,15 @@ // Also mentions the folder in which the bookmark is saved. std::u16string title = base::SysNSStringToUTF16(folderTitle); std::u16string pattern = l10n_util::GetStringUTF16( - IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT_FOLDER); + (showCount) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT_FOLDER + : IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT_FOLDER); return base::SysUTF16ToNSString( base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "title", title, "email", email)); } else { - std::u16string pattern = - l10n_util::GetStringUTF16(IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT); + std::u16string pattern = l10n_util::GetStringUTF16( + (showCount) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_INTO_ACCOUNT + : IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT); return base::SysUTF16ToNSString( base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "email", email)); @@ -332,7 +335,8 @@ CHECK(chosenByUser); std::u16string title = base::SysNSStringToUTF16(folderTitle); std::u16string pattern = l10n_util::GetStringUTF16( - IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE); + (showCount) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER_TO_DEVICE + : IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER_TO_DEVICE); std::u16string message = base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "title", title); @@ -344,14 +348,16 @@ // The user is signed-out. if (chosenByUser) { std::u16string title = base::SysNSStringToUTF16(folderTitle); - std::u16string pattern = - l10n_util::GetStringUTF16(IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER); + std::u16string pattern = l10n_util::GetStringUTF16( + (showCount) ? IDS_IOS_BOOKMARK_PAGE_BULK_SAVED_FOLDER + : IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER); return base::SysUTF16ToNSString( base::i18n::MessageFormatter::FormatWithNamedArgs( pattern, "count", count, "title", title)); } else { - return base::SysUTF16ToNSString( - l10n_util::GetPluralStringFUTF16(IDS_IOS_BOOKMARKS_BULK_SAVED, count)); + return base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16( + (showCount) ? IDS_IOS_BOOKMARKS_BULK_SAVED : IDS_IOS_BOOKMARKS_SAVED, + count)); } } @@ -391,7 +397,7 @@ text = messageForAddingBookmarksInFolder( title, /*chosenByUser =*/true, GetBookmarkModelType(folder, local_or_syncable_model, account_model), - /*count=*/1, authenticationService, syncService); + /*showCount=*/false, /*count=*/1, authenticationService, syncService); } return CreateUndoToastWithWrapper( wrapper, text, "MobileBookmarkManagerUpdatedBookmarkUndone"); @@ -641,8 +647,8 @@ destination_folder, local_model, account_model); NSString* text = messageForAddingBookmarksInFolder( TitleForBookmarkNode(destination_folder), - /*chosenByUser=*/true, storageType, count, authenticationService, - syncService); + /*chosenByUser=*/true, storageType, /*showCount=*/false, count, + authenticationService, syncService); return CreateUndoToastWithWrapper(wrapper, text, "MobileBookmarkManagerMoveToFolderUndone"); }
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 1498157..75734045 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -1295,7 +1295,12 @@ [_fakeStatusBarView setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) { if (base::FeatureList::IsEnabled(kModernTabStrip)) { - _fakeStatusBarView.backgroundColor = [UIColor colorNamed:kGrey200Color]; + _fakeStatusBarView.backgroundColor = + [UIColor colorNamed:kTabStripBackgroundColor]; + // Force the UserInterfaceStyle update in incognito. + _fakeStatusBarView.overrideUserInterfaceStyle = + _isOffTheRecord ? UIUserInterfaceStyleDark + : UIUserInterfaceStyleUnspecified; } else { _fakeStatusBarView.backgroundColor = UIColor.blackColor; }
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index f3efb65..f17c9cbc 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -48,21 +48,14 @@ "//components/feed/core/v2/public/ios:feed_ios_public", "//components/history/core/browser", "//components/ntp_tiles", - "//components/password_manager/core/browser/ui", "//components/password_manager/core/browser/ui:credential_ui_entry", "//components/pref_registry", "//components/prefs", - "//components/prefs/ios", "//components/reading_list/core", "//components/reading_list/ios", "//components/search_engines", "//components/segmentation_platform/public", - "//components/signin/public/identity_manager", - "//components/signin/public/identity_manager/objc", "//components/strings", - "//components/sync/base", - "//components/sync/base:features", - "//components/sync/service", "//components/url_formatter", "//ios/chrome/app:tests_hook", "//ios/chrome/app/application_delegate:app_state_header", @@ -110,7 +103,6 @@ "//ios/chrome/browser/shared/ui/util", "//ios/chrome/browser/signin/model", "//ios/chrome/browser/sync/model", - "//ios/chrome/browser/synced_sessions/model", "//ios/chrome/browser/ui/authentication/signin:constants", "//ios/chrome/browser/ui/content_suggestions/cells", "//ios/chrome/browser/ui/content_suggestions/cells:constants",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h index 10db1a3..51cae55 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h
@@ -9,6 +9,7 @@ class GURL; @class QuerySuggestionConfig; enum class SafetyCheckItemType; +@class TabResumptionItem; // Commands protocol allowing the ContentSuggestions ViewControllers to interact // with the coordinator layer, and from there to the rest of the application. @@ -19,7 +20,7 @@ - (void)openMostRecentTab; // Opens the displayed tab resumption item. -- (void)openTabResumptionItem; +- (void)openTabResumptionItem:(TabResumptionItem*)item; @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm index 4d4e33a2..210580c5 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
@@ -23,21 +23,14 @@ #import "components/feed/core/v2/public/ios/pref_names.h" #import "components/history/core/browser/features.h" #import "components/ntp_tiles/most_visited_sites.h" -#import "components/password_manager/core/browser/ui/credential_ui_entry.h" #import "components/pref_registry/pref_registry_syncable.h" -#import "components/prefs/ios/pref_observer_bridge.h" #import "components/search_engines/search_terms_data.h" #import "components/search_engines/template_url.h" #import "components/segmentation_platform/public/constants.h" #import "components/segmentation_platform/public/features.h" #import "components/segmentation_platform/public/segmentation_platform_service.h" -#import "components/signin/public/identity_manager/identity_manager.h" -#import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h" #import "components/strings/grit/components_strings.h" -#import "components/sync/base/user_selectable_type.h" -#import "components/sync/service/sync_user_settings.h" #import "components/url_formatter/elide_url.h" -#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h" #import "ios/chrome/browser/intents/intents_donation_helper.h" #import "ios/chrome/browser/net/model/crurl.h" #import "ios/chrome/browser/ntp/model/new_tab_page_tab_helper.h" @@ -59,9 +52,6 @@ #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/signin/model/authentication_service.h" #import "ios/chrome/browser/signin/model/authentication_service_factory.h" -#import "ios/chrome/browser/sync/model/session_sync_service_factory.h" -#import "ios/chrome/browser/sync/model/sync_observer_bridge.h" -#import "ios/chrome/browser/synced_sessions/model/synced_sessions_bridge.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_tile_view.h" @@ -86,6 +76,7 @@ #import "ios/chrome/browser/ui/content_suggestions/set_up_list/utils.h" #import "ios/chrome/browser/ui/content_suggestions/start_suggest_service_factory.h" #import "ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.h" +#import "ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper_delegate.h" #import "ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_item.h" #import "ios/chrome/browser/ui/favicon/favicon_attributes_provider.h" #import "ios/chrome/browser/ui/ntp/metrics/home_metrics.h" @@ -106,14 +97,8 @@ } // namespace -@interface ContentSuggestionsMediator () <IdentityManagerObserverBridgeDelegate, - MostVisitedTilesMediatorDelegate, - SyncObserverModelBridge, - PrefObserverDelegate, - SyncedSessionsObserver> { - std::unique_ptr<synced_sessions::SyncedSessionsObserverBridge> - _syncedSessionsObserver; -} +@interface ContentSuggestionsMediator () <MostVisitedTilesMediatorDelegate, + TabResumptionHelperDelegate> // Whether the contents section should be hidden completely. // Don't use PrefBackedBoolean or PrefMember as this value needs to be checked @@ -146,21 +131,10 @@ @end @implementation ContentSuggestionsMediator { - // Registrar for pref changes notifications. - PrefChangeRegistrar _prefChangeRegistrar; // Local State prefs. raw_ptr<PrefService> _localState; - // Used by SetUpList to get the sync status. - raw_ptr<syncer::SyncService> _syncService; - // Observes changes to signed-in status. - std::unique_ptr<signin::IdentityManagerObserverBridge> - _identityObserverBridge; - // Observer for sync service status changes. - std::unique_ptr<SyncObserverBridge> _syncObserverBridge; // Helper class for the tab resumption tile. std::unique_ptr<TabResumptionHelper> _tabResumptionHelper; - // Item displayed in the tab resumption tile. - TabResumptionItem* _tabResumptionItem; // The latest module ranking returned from the SegmentationService. NSArray<NSNumber*>* _magicStackOrderFromSegmentation; // YES if the module ranking has been received from the SegmentationService. @@ -205,17 +179,7 @@ _mostVisitedTilesMediator.contentSuggestionsDelegate = self.delegate; _mostVisitedTilesMediator.actionFactory = actionFactory; - _syncService = syncService; - BOOL isSetupListEnabled = set_up_list_utils::IsSetUpListActive(_localState); - if (IsTabResumptionEnabled() || isSetupListEnabled) { - _syncObserverBridge = - std::make_unique<SyncObserverBridge>(self, _syncService); - _identityObserverBridge = - std::make_unique<signin::IdentityManagerObserverBridge>( - identityManager, self); - } - if (isSetupListEnabled) { _setUpListMediator = [[SetUpListMediator alloc] initWithPrefService:prefService @@ -225,18 +189,10 @@ sceneState:browser->GetSceneState()]; } - if (IsTabResumptionEnabled() && - !tab_resumption_prefs::IsTabResumptionDisabled(_localState)) { - if (!IsTabResumptionEnabledForMostRecentTabOnly()) { - sync_sessions::SessionSyncService* sessionSyncService = - SessionSyncServiceFactory::GetForBrowserState( - browser->GetBrowserState()); - _syncedSessionsObserver = - std::make_unique<synced_sessions::SyncedSessionsObserverBridge>( - self, sessionSyncService); - } - - _tabResumptionHelper = std::make_unique<TabResumptionHelper>(browser); + if (IsTabResumptionEnabled()) { + _tabResumptionHelper = std::make_unique<TabResumptionHelper>( + browser, identityManager, _localState); + _tabResumptionHelper->SetDelegate(self); } _browser = browser; @@ -256,9 +212,10 @@ _setUpListMediator = nil; [_mostVisitedTilesMediator disconnect]; _mostVisitedTilesMediator = nil; - _syncObserverBridge.reset(); - _identityObserverBridge.reset(); - _syncedSessionsObserver.reset(); + if (_tabResumptionHelper) { + _tabResumptionHelper->SetDelegate(nullptr); + _tabResumptionHelper = nil; + } _localState = nullptr; } @@ -326,7 +283,7 @@ - (void)disableTabResumption { tab_resumption_prefs::DisableTabResumption(_localState); - [self hideTabResumption]; + [self removeTabResumptionModule]; } - (void)disableSafetyCheck:(ContentSuggestionsModuleType)type { @@ -346,25 +303,6 @@ [self indexForMagicStackModule:type]]; } -#pragma mark - IdentityManagerObserverBridgeDelegate - -// Called when a user changes the syncing state. -- (void)onPrimaryAccountChanged: - (const signin::PrimaryAccountChangeEvent&)event { - switch (event.GetEventTypeFor(signin::ConsentLevel::kSignin)) { - case signin::PrimaryAccountChangeEvent::Type::kCleared: { - if (IsTabResumptionEnabled()) { - // If the user is signed out, remove the tab resumption tile. - [self hideTabResumption]; - } - break; - } - case signin::PrimaryAccountChangeEvent::Type::kSet: - case signin::PrimaryAccountChangeEvent::Type::kNone: - break; - } -} - #pragma mark - ContentSuggestionsCommands - (void)openMostRecentTab { @@ -383,14 +321,14 @@ webStateList->ActivateWebStateAt(index); } -- (void)openTabResumptionItem { +- (void)openTabResumptionItem:(TabResumptionItem*)item { [self.contentSuggestionsMetricsRecorder recordTabResumptionTabOpened]; tab_resumption_prefs::SetTabResumptionLastOpenedTabURL( - _tabResumptionItem.tabURL, self.browser->GetBrowserState()->GetPrefs()); + item.tabURL, self.browser->GetBrowserState()->GetPrefs()); [self logMagicStackEngagementForType:ContentSuggestionsModuleType:: kTabResumption]; - switch (_tabResumptionItem.itemType) { + switch (item.itemType) { case TabResumptionItemType::kLastSyncedTab: [self.NTPMetricsDelegate distantTabResumptionOpened]; _tabResumptionHelper->OpenDistantTab(); @@ -398,14 +336,14 @@ case TabResumptionItemType::kMostRecentTab: { [self.NTPMetricsDelegate recentTabTileOpened]; web::NavigationManager::WebLoadParams webLoadParams = - web::NavigationManager::WebLoadParams(_tabResumptionItem.tabURL); + web::NavigationManager::WebLoadParams(item.tabURL); UrlLoadParams params = UrlLoadParams::SwitchToTab(webLoadParams); params.web_params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK; UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params); break; } } - [self hideTabResumption]; + [self removeTabResumptionModule]; } #pragma mark - ParcelTrackingMediatorDelegate @@ -450,9 +388,7 @@ #pragma mark - StartSurfaceRecentTabObserving - (void)mostRecentTabWasRemoved:(web::WebState*)webState { - if (IsTabResumptionEnabled() && _tabResumptionItem) { - [self hideTabResumption]; - } else { + if (!IsTabResumptionEnabled()) { [self hideRecentTabTile]; } } @@ -482,11 +418,20 @@ } } -#pragma mark - SyncedSessionsObserver +#pragma mark - TabResumptionHelperDelegate -- (void)onForeignSessionsChanged { - DCHECK(!IsTabResumptionEnabledForMostRecentTabOnly()); - [self showTabResumptionTile]; +- (void)tabResumptionHelperDidReceiveItem { + CHECK(IsTabResumptionEnabled()); + if (!self.consumer || + tab_resumption_prefs::IsTabResumptionDisabled(_localState)) { + return; + } + + [self showTabResumptionWithItem:_tabResumptionHelper->GetTabResumptionItem()]; +} + +- (void)removeTabResumptionModule { + [self.consumer hideTabResumption]; } #pragma mark - Private @@ -508,8 +453,11 @@ _latestMagicStackOrder = [self magicStackOrder]; [self.consumer setMagicStackOrder:_latestMagicStackOrder]; } - if (IsTabResumptionEnabled()) { - [self showTabResumptionTile]; + if (IsTabResumptionEnabled() && + _tabResumptionHelper->GetTabResumptionItem()) { + TabResumptionItem* item = _tabResumptionHelper->GetTabResumptionItem(); + item.commandHandler = self; + [self.consumer showTabResumptionWithItem:item]; } } if (self.returnToRecentTabItem) { @@ -569,7 +517,9 @@ // Magic Stack. - (NSArray<NSNumber*>*)magicStackOrder { NSMutableArray* magicStackModules = [NSMutableArray array]; - if (IsTabResumptionEnabled() && _tabResumptionItem) { + if (IsTabResumptionEnabled() && + !tab_resumption_prefs::IsTabResumptionDisabled(_localState) && + _tabResumptionHelper->GetTabResumptionItem()) { [magicStackModules addObject:@(int(ContentSuggestionsModuleType::kTabResumption))]; } @@ -629,7 +579,7 @@ case ContentSuggestionsModuleType::kTabResumption: if (!IsTabResumptionEnabled() || tab_resumption_prefs::IsTabResumptionDisabled(_localState) || - !_tabResumptionItem) { + !_tabResumptionHelper->GetTabResumptionItem()) { break; } // If ShouldHideIrrelevantModules() is enabled and it is not ranked as @@ -821,33 +771,6 @@ [_setUpListMediator showSetUpList]; } -// Shows the tab resumption tile if there is a `_tabResumptionItem` to present. -- (void)showTabResumptionTile { - if (!self.webState) { - return; - } - - CHECK(IsTabResumptionEnabled()); - if (!self.consumer || - tab_resumption_prefs::IsTabResumptionDisabled(_localState)) { - return; - } - - if (_tabResumptionItem) { - [self.consumer showTabResumptionWithItem:_tabResumptionItem]; - return; - } - - _tabResumptionHelper->SetCanSHowMostRecentItem( - NewTabPageTabHelper::FromWebState(self.webState) - ->ShouldShowStartSurface()); - - __weak __typeof(self) weakSelf = self; - _tabResumptionHelper->LastTabResumptionItem(^(TabResumptionItem* item) { - [weakSelf showTabResumptionWithItem:item]; - }); -} - // Shows the tab resumption tile with the given `item` configuration. - (void)showTabResumptionWithItem:(TabResumptionItem*)item { if (tab_resumption_prefs::IsLastOpenedURL( @@ -855,8 +778,7 @@ return; } - _tabResumptionItem = item; - _tabResumptionItem.commandHandler = self; + item.commandHandler = self; _latestMagicStackOrder = base::FeatureList::IsEnabled( segmentation_platform::features::kSegmentationPlatformIosModuleRanker) @@ -878,13 +800,7 @@ change.index = insertionIndex; [self.consumer updateMagicStackOrder:change]; } - [self.consumer showTabResumptionWithItem:_tabResumptionItem]; -} - -// Hides the tab resumption tile. -- (void)hideTabResumption { - [self.consumer hideTabResumption]; - _tabResumptionItem = nil; + [self.consumer showTabResumptionWithItem:item]; } // Returns the index rank of `moduleType`. @@ -946,27 +862,4 @@ self.contentSuggestionsPolicyEnabled->GetValue()->GetBool(); } -#pragma mark - PrefObserverDelegate - -- (void)onPreferenceChanged:(const std::string&)preferenceName { - if (IsTabResumptionEnabled()) { - if (_tabResumptionItem && - tab_resumption_prefs::IsTabResumptionDisabled(_localState)) { - [self hideTabResumption]; - } - } -} - -#pragma mark - SyncObserverModelBridge - -- (void)onSyncStateChanged { - if (IsTabResumptionEnabled()) { - // If tabs are not synced, hide the tab resumption tile. - if (!_syncService->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kTabs)) { - [self hideTabResumption]; - } - } -} - @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm index a6a90fce..54643d7 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm
@@ -495,6 +495,15 @@ {}); [mediator_ disconnect]; + + // Create NTP. + web_state_list_->InsertWebState(1, CreateWebState("chrome://newtab"), + WebStateList::INSERT_ACTIVATE, + WebStateOpener()); + web::WebState* ntp_web_state = web_state_list_->GetActiveWebState(); + mediator_.webState = ntp_web_state; + NewTabPageTabHelper::FromWebState(ntp_web_state)->SetShowStartSurface(true); + SetUpMediator(); consumer_ = OCMProtocolMock(@protocol(ContentSuggestionsConsumer)); mediator_.segmentationService =
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 913219f6..7fbcffb8 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -876,12 +876,6 @@ [self.audience didSelectSetUpListItem:view.type]; } -#pragma mark - TabResumptionViewDelegate methods - -- (void)tabResumptionViewTapped { - [self.suggestionCommandHandler openTabResumptionItem]; -} - #pragma mark - ContentSuggestionsSelectionActions - (void)contentSuggestionsElementTapped:(UIGestureRecognizer*)sender {
diff --git a/ios/chrome/browser/ui/content_suggestions/tab_resumption/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/tab_resumption/BUILD.gn index 1a1c9bf..5d1d28f 100644 --- a/ios/chrome/browser/ui/content_suggestions/tab_resumption/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/tab_resumption/BUILD.gn
@@ -4,6 +4,7 @@ source_set("tab_resumption") { sources = [ + "tab_resumption_helper_delegate.h", "tab_resumption_item.h", "tab_resumption_item.mm", "tab_resumption_view.h", @@ -39,6 +40,8 @@ "//components/sync_sessions", "//ios/chrome/browser/favicon/model", "//ios/chrome/browser/metrics/model:metrics_internal", + "//ios/chrome/browser/ntp/model", + "//ios/chrome/browser/ntp_tiles/model/tab_resumption:tab_resumption_prefs", "//ios/chrome/browser/sessions:session_util", "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/browser_state",
diff --git a/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.h b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.h index 67072b05..8b191da 100644 --- a/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.h +++ b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.h
@@ -5,18 +5,26 @@ #ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_TAB_RESUMPTION_TAB_RESUMPTION_HELPER_H_ #define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_TAB_RESUMPTION_TAB_RESUMPTION_HELPER_H_ -#import <Foundation/Foundation.h> -#import <UIKit/UIKit.h> - +#import "base/callback_list.h" #import "base/ios/block_types.h" +#import "base/scoped_observation.h" #import "components/sessions/core/session_id.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/sync/service/sync_service_observer.h" #import "ios/chrome/browser/favicon/model/favicon_loader.h" +#import "ios/chrome/browser/ui/start_surface/start_surface_recent_tab_browser_agent.h" #import "url/gurl.h" class Browser; class FaviconLoader; +class PrefService; class StartSurfaceRecentTabBrowserAgent; @class TabResumptionItem; +@protocol TabResumptionHelperDelegate; + +namespace base { +class Time; +} // namespace base namespace syncer { class SyncService; @@ -26,29 +34,75 @@ class SessionSyncService; } // namespace sync_sessions +namespace synced_sessions { +struct DistantSession; +struct DistantTab; +} // namespace synced_sessions + +namespace web { +class WebState; +} // namespace web + // Helper class to control the tab resumption feature. -class TabResumptionHelper { +class TabResumptionHelper : public signin::IdentityManager::Observer, + public syncer::SyncServiceObserver, + public StartSurfaceRecentTabObserver { public: TabResumptionHelper(const TabResumptionHelper&) = delete; TabResumptionHelper& operator=(const TabResumptionHelper&) = delete; - explicit TabResumptionHelper(Browser* browser); + explicit TabResumptionHelper(Browser* browser, + signin::IdentityManager* identity_manager, + PrefService* local_state); - // Type for completion block for GetLastTabResumptionItem(). - typedef void (^TabResumptionItemCompletionBlock)(TabResumptionItem*); + ~TabResumptionHelper() override; - // Tries to return the last available TabResumptionItem. - // If found, invokes `item_block_handler` and exits. - void LastTabResumptionItem( - TabResumptionItemCompletionBlock item_block_handler); - - // Sets `can_show_most_recent_item`. - void SetCanSHowMostRecentItem(const bool show); + // Tries to fetch the last available TabResumptionItem. + void LastTabResumptionItem(); // Opens the last synced tab from another device. void OpenDistantTab(); + // Sets the delegate for this helper. + void SetDelegate(id<TabResumptionHelperDelegate> delegate); + + TabResumptionItem* GetTabResumptionItem() { return tab_resumption_item_; } + private: + // Handles signal that the synced session has changed. + void ForeignSessionsChanged(); + + // Fetches the favicon for the given `item`. + void FetchFaviconForItem(TabResumptionItem* item, + FaviconLoader* favicon_loader); + + // Handles the result of a favicon fetch. + void OnFaviconForPageUrl(TabResumptionItem* item, + FaviconAttributes* attributes); + + // Creates a TabResumptionItem corresponding to the last active distant tab. + void LastSyncedTabItemFromLastActiveDistantTab( + const synced_sessions::DistantSession* session, + const synced_sessions::DistantTab* tab, + FaviconLoader* favicon_loader); + + // Creates a TabResumptionItem corresponding to the last synced tab. + void MostRecentTabItemFromWebState(web::WebState* web_state, + base::Time opened_time, + FaviconLoader* favicon_loader); + + // syncer::SyncServiceObserver. + void OnStateChanged(syncer::SyncService* sync) override; + // signin::IdentityManager::Observer. + void OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event_details) override; + // StartSurfaceBrowserAgentObserver. + void MostRecentTabRemoved(web::WebState* web_state) override; + void MostRecentTabFaviconUpdated(web::WebState* web_state, + UIImage* image) override {} + void MostRecentTabTitleUpdated(web::WebState* web_state, + const std::u16string& title) override {} + // Bool that tracks if a most recent tab item can be displayed. bool can_show_most_recent_item_ = true; // Last distant tab resumption item URL. @@ -61,6 +115,7 @@ // The owning Browser. raw_ptr<Browser> browser_ = nullptr; + raw_ptr<PrefService> local_state_ = nullptr; // Loads favicons. raw_ptr<FaviconLoader> favicon_loader_ = nullptr; // Browser Agent that manages the most recent WebState. @@ -70,6 +125,21 @@ raw_ptr<sync_sessions::SessionSyncService> session_sync_service_ = nullptr; // KeyedService responsible for sync state. raw_ptr<syncer::SyncService> sync_service_ = nullptr; + // CallbackListSubscription for the SessionSyncService method. + base::CallbackListSubscription foreign_session_updated_subscription_; + // The latest state of the item config for the Tab Resumption module. + TabResumptionItem* tab_resumption_item_ = nullptr; + base::ScopedObservation<syncer::SyncService, syncer::SyncServiceObserver> + scoped_observation_{this}; + base::ScopedObservation<signin::IdentityManager, + signin::IdentityManager::Observer> + identity_manager_observer_{this}; + base::ScopedObservation<StartSurfaceRecentTabBrowserAgent, + StartSurfaceRecentTabObserver> + start_surface_recent_tab_observer_{this}; + // The delegate for this helper class. + __weak id<TabResumptionHelperDelegate> delegate_ = nullptr; + base::WeakPtrFactory<TabResumptionHelper> weak_ptr_factory_{this}; }; #endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_TAB_RESUMPTION_TAB_RESUMPTION_HELPER_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.mm b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.mm index 7dd6528..fa02208 100644 --- a/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.mm +++ b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper.mm
@@ -6,12 +6,16 @@ #import "base/apple/foundation_util.h" #import "base/strings/sys_string_conversions.h" +#import "components/sync/base/user_selectable_type.h" #import "components/sync/service/sync_service.h" +#import "components/sync/service/sync_user_settings.h" #import "components/sync_sessions/open_tabs_ui_delegate.h" #import "components/sync_sessions/session_sync_service.h" #import "ios/chrome/browser/favicon/model/favicon_loader.h" #import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h" #import "ios/chrome/browser/metrics/model/new_tab_page_uma.h" +#import "ios/chrome/browser/ntp/model/new_tab_page_tab_helper.h" +#import "ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.h" #import "ios/chrome/browser/sessions/session_util.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" @@ -25,6 +29,7 @@ #import "ios/chrome/browser/synced_sessions/model/distant_tab.h" #import "ios/chrome/browser/synced_sessions/model/synced_sessions.h" #import "ios/chrome/browser/tabs/model/tab_sync_util.h" +#import "ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper_delegate.h" #import "ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_item.h" #import "ios/chrome/browser/ui/start_surface/start_surface_features.h" #import "ios/chrome/browser/ui/start_surface/start_surface_recent_tab_browser_agent.h" @@ -38,63 +43,13 @@ NSString* kStartSurfaceSceneEnterIntoBackgroundTime = @"StartSurfaceSceneEnterIntoBackgroundTime"; -// Fetches the favicon for the given `item` then asynchronously invokes -// `item_block_handler` and exits. -void FetchFaviconForItem( - TabResumptionItem* item, - FaviconLoader* favicon_loader, - TabResumptionHelper::TabResumptionItemCompletionBlock item_block_handler) { - favicon_loader->FaviconForPageUrl( - item.tabURL, kDesiredSmallFaviconSizePt, kMinFaviconSizePt, - /*fallback_to_google_server=*/true, ^(FaviconAttributes* attributes) { - if (!attributes.usesDefaultImage) { - item.faviconImage = attributes.faviconImage; - item_block_handler(item); - } - }); -} - -// Creates a TabResumptionItem corresponding to the last active distant tab then -// asynchronously invokes `item_block_handler` and exits. -void LastSyncedTabItemFromLastActiveDistantTab( - const synced_sessions::DistantSession* session, - const synced_sessions::DistantTab* tab, - FaviconLoader* favicon_loader, - TabResumptionHelper::TabResumptionItemCompletionBlock item_block_handler) { - CHECK(!IsTabResumptionEnabledForMostRecentTabOnly()); - - TabResumptionItem* tab_resumption_item = [[TabResumptionItem alloc] - initWithItemType:TabResumptionItemType::kLastSyncedTab]; - tab_resumption_item.sessionName = base::SysUTF8ToNSString(session->name); - tab_resumption_item.tabTitle = base::SysUTF16ToNSString(tab->title); - tab_resumption_item.syncedTime = tab->last_active_time; - tab_resumption_item.tabURL = tab->virtual_url; - - // Fetch the favicon. - FetchFaviconForItem(tab_resumption_item, favicon_loader, item_block_handler); -} - -// Creates a TabResumptionItem corresponding to the last synced tab then -// asynchronously invokes `item_block_handler` and exits. -void MostRecentTabItemFromWebState( - web::WebState* web_state, - base::Time opened_time, - FaviconLoader* favicon_loader, - TabResumptionHelper::TabResumptionItemCompletionBlock item_block_handler) { - TabResumptionItem* tab_resumption_item = [[TabResumptionItem alloc] - initWithItemType:TabResumptionItemType::kMostRecentTab]; - tab_resumption_item.tabTitle = - base::SysUTF16ToNSString(web_state->GetTitle()); - tab_resumption_item.syncedTime = opened_time; - tab_resumption_item.tabURL = web_state->GetLastCommittedURL(); - - // Fetch the favicon. - FetchFaviconForItem(tab_resumption_item, favicon_loader, item_block_handler); -} - } // namespace -TabResumptionHelper::TabResumptionHelper(Browser* browser) : browser_(browser) { +TabResumptionHelper::TabResumptionHelper( + Browser* browser, + signin::IdentityManager* identity_manager, + PrefService* local_state) + : browser_(browser), local_state_(local_state) { CHECK(browser_); CHECK(IsTabResumptionEnabled()); @@ -106,12 +61,27 @@ IOSChromeFaviconLoaderFactory::GetForBrowserState(browser_state); recent_tab_browser_agent_ = StartSurfaceRecentTabBrowserAgent::FromBrowser(browser_); + start_surface_recent_tab_observer_.Observe(recent_tab_browser_agent_); + + if (!IsTabResumptionEnabledForMostRecentTabOnly()) { + foreign_session_updated_subscription_ = + session_sync_service_->SubscribeToForeignSessionsChanged( + base::BindRepeating(&TabResumptionHelper::ForeignSessionsChanged, + base::Unretained(this))); + scoped_observation_.Observe(sync_service_); + identity_manager_observer_.Observe(identity_manager); + } } +TabResumptionHelper::~TabResumptionHelper() = default; + #pragma mark - Public methods -void TabResumptionHelper::LastTabResumptionItem( - TabResumptionItemCompletionBlock item_block_handler) { +void TabResumptionHelper::LastTabResumptionItem() { + if (tab_resumption_prefs::IsTabResumptionDisabled(local_state_)) { + return; + } + session_tag_ = ""; tab_id_ = SessionID::InvalidValue(); @@ -155,26 +125,26 @@ } } + web::WebState* active_web_state = + browser_->GetWebStateList()->GetActiveWebState(); + bool can_show_most_recent_item = + NewTabPageTabHelper::FromWebState(active_web_state) + ->ShouldShowStartSurface(); // If both times have not been updated, that means there is no item to return. if (most_recent_tab_opened_time == base::Time::UnixEpoch() && last_synced_tab_synced_time == base::Time::UnixEpoch()) { return; } else if (last_synced_tab_synced_time > most_recent_tab_opened_time) { CHECK(!IsTabResumptionEnabledForMostRecentTabOnly()); - LastSyncedTabItemFromLastActiveDistantTab(session, tab, favicon_loader_, - item_block_handler); + LastSyncedTabItemFromLastActiveDistantTab(session, tab, favicon_loader_); session_tag_ = session->tag; tab_id_ = tab->tab_id; - } else if (can_show_most_recent_item_) { + } else if (can_show_most_recent_item) { MostRecentTabItemFromWebState(most_recent_tab, most_recent_tab_opened_time, - favicon_loader_, item_block_handler); + favicon_loader_); } } -void TabResumptionHelper::SetCanSHowMostRecentItem(const bool show) { - can_show_most_recent_item_ = show; -} - void TabResumptionHelper::OpenDistantTab() { ChromeBrowserState* browser_state = browser_->GetBrowserState(); WebStateList* web_state_list = browser_->GetWebStateList(); @@ -199,3 +169,95 @@ std::move(web_state)); } } + +void TabResumptionHelper::SetDelegate( + id<TabResumptionHelperDelegate> delegate) { + delegate_ = delegate; + if (delegate_) { + LastTabResumptionItem(); + } +} + +void TabResumptionHelper::OnStateChanged(syncer::SyncService* sync) { + // If tabs are not synced, hide the tab resumption tile. + if (!sync_service_->GetUserSettings()->GetSelectedTypes().Has( + syncer::UserSelectableType::kTabs)) { + [delegate_ removeTabResumptionModule]; + } +} + +void TabResumptionHelper::OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event_details) { + switch (event_details.GetEventTypeFor(signin::ConsentLevel::kSignin)) { + case signin::PrimaryAccountChangeEvent::Type::kCleared: { + // If the user is signed out, remove the tab resumption tile. + [delegate_ removeTabResumptionModule]; + break; + } + default: + break; + } +} + +#pragma mark - Private + +void TabResumptionHelper::ForeignSessionsChanged() { + LastTabResumptionItem(); +} + +void TabResumptionHelper::FetchFaviconForItem(TabResumptionItem* item, + FaviconLoader* favicon_loader) { + favicon_loader->FaviconForPageUrl( + item.tabURL, kDesiredSmallFaviconSizePt, kMinFaviconSizePt, + /*fallback_to_google_server=*/true, + base::CallbackToBlock( + base::BindRepeating(&TabResumptionHelper::OnFaviconForPageUrl, + weak_ptr_factory_.GetWeakPtr(), item))); +} + +void TabResumptionHelper::OnFaviconForPageUrl(TabResumptionItem* item, + FaviconAttributes* attributes) { + if (!attributes.usesDefaultImage) { + item.faviconImage = attributes.faviconImage; + tab_resumption_item_ = item; + [delegate_ tabResumptionHelperDidReceiveItem]; + } +} + +void TabResumptionHelper::LastSyncedTabItemFromLastActiveDistantTab( + const synced_sessions::DistantSession* session, + const synced_sessions::DistantTab* tab, + FaviconLoader* favicon_loader) { + CHECK(!IsTabResumptionEnabledForMostRecentTabOnly()); + + TabResumptionItem* tab_resumption_item = [[TabResumptionItem alloc] + initWithItemType:TabResumptionItemType::kLastSyncedTab]; + tab_resumption_item.sessionName = base::SysUTF8ToNSString(session->name); + tab_resumption_item.tabTitle = base::SysUTF16ToNSString(tab->title); + tab_resumption_item.syncedTime = tab->last_active_time; + tab_resumption_item.tabURL = tab->virtual_url; + + // Fetch the favicon. + FetchFaviconForItem(tab_resumption_item, favicon_loader); +} + +void TabResumptionHelper::MostRecentTabItemFromWebState( + web::WebState* web_state, + base::Time opened_time, + FaviconLoader* favicon_loader) { + TabResumptionItem* tab_resumption_item = [[TabResumptionItem alloc] + initWithItemType:TabResumptionItemType::kMostRecentTab]; + tab_resumption_item.tabTitle = + base::SysUTF16ToNSString(web_state->GetTitle()); + tab_resumption_item.syncedTime = opened_time; + tab_resumption_item.tabURL = web_state->GetLastCommittedURL(); + + // Fetch the favicon. + FetchFaviconForItem(tab_resumption_item, favicon_loader); +} + +void TabResumptionHelper::MostRecentTabRemoved(web::WebState* web_state) { + if (tab_resumption_item_ && tab_resumption_item_.itemType == kMostRecentTab) { + [delegate_ removeTabResumptionModule]; + } +}
diff --git a/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper_delegate.h b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper_delegate.h new file mode 100644 index 0000000..7d2ed48 --- /dev/null +++ b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_helper_delegate.h
@@ -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. + +#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_TAB_RESUMPTION_TAB_RESUMPTION_HELPER_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_TAB_RESUMPTION_TAB_RESUMPTION_HELPER_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +// Delegate handling events from the TabResumptionHelper. +@protocol TabResumptionHelperDelegate + +// Signals that the TabResumptionHelper received a new item configuration. +- (void)tabResumptionHelperDidReceiveItem; + +// Signals that the Tab Resumption module should be removed. +- (void)removeTabResumptionModule; + +@end + +#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_TAB_RESUMPTION_TAB_RESUMPTION_HELPER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_view.mm b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_view.mm index 13cafc4..0a3f0bdc 100644 --- a/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_view.mm +++ b/ios/chrome/browser/ui/content_suggestions/tab_resumption/tab_resumption_view.mm
@@ -257,7 +257,7 @@ // Called when the view has been tapped. - (void)tabResumptionItemTapped:(UIGestureRecognizer*)sender { - [self.commandHandler openTabResumptionItem]; + [self.commandHandler openTabResumptionItem:_item]; } @end
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn index aaebe26..2e827f2 100644 --- a/ios/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -258,6 +258,8 @@ "//components/feature_engagement/public", "//components/strings:components_strings_grit", "//ios/chrome/app/strings", + "//ios/chrome/browser/iph_for_new_chrome_user/model:features", + "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/shared/public/features", "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant", "//ios/chrome/browser/ui/omnibox/popup:popup_accessibility_identifier_constants",
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm index 173b012..8dd44ee 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -14,6 +14,8 @@ #import "build/build_config.h" #import "components/feature_engagement/public/feature_constants.h" #import "components/strings/grit/components_strings.h" +#import "ios/chrome/browser/iph_for_new_chrome_user/model/features.h" +#import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h" #import "ios/chrome/browser/ui/omnibox/omnibox_app_interface.h" @@ -287,6 +289,14 @@ [ChromeEarlGrey clearPasteboard]; [ChromeEarlGrey clearBrowsingHistory]; + + [ChromeEarlGrey setBoolValue:NO forUserPref:prefs::kBottomOmnibox]; +} + +- (void)tearDown { + [super tearDown]; + + [ChromeEarlGrey setBoolValue:NO forUserPref:prefs::kBottomOmnibox]; } #pragma mark - Helpers @@ -558,6 +568,9 @@ if ([ChromeEarlGrey isIPadIdiom]) { EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (no bottom omnibox in tablet)"); } + + [ChromeEarlGrey setBoolValue:YES forUserPref:prefs::kBottomOmnibox]; + // Enable the IPH Demo Mode feature to ensure the IPH triggers AppLaunchConfiguration config = [self appConfigurationForTestCase]; config.additional_args.push_back( @@ -630,6 +643,10 @@ DefocusOmnibox(); + // Verify the omnibox is at the top. + [ChromeEarlGrey + waitForUIElementToAppearWithMatcher:chrome_test_util::OmniboxOnTop()]; + // Verify the share button IPH is shown. [ChromeEarlGrey waitForUIElementToAppearWithMatcher:grey_accessibilityID( @@ -766,22 +783,26 @@ if ([ChromeEarlGrey isIPadIdiom]) { EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (no bottom omnibox in tablet)"); } + + [ChromeEarlGrey setBoolValue:YES forUserPref:prefs::kBottomOmnibox]; + // Enable the IPH Demo Mode feature to ensure the IPH triggers AppLaunchConfiguration config = [self appConfigurationForTestCase]; config.additional_args.push_back( base::StringPrintf("--enable-features=%s:chosen_feature/" - "IPH_iOSShareToolbarItemFeature,IPHForSafariSwitcher", - feature_engagement::kIPHDemoMode.name)); + "IPH_iOSShareToolbarItemFeature", + feature_engagement::kIPHDemoMode.name) + + "," + std::string(kIPHForSafariSwitcher.name)); + // Force the conditions that allow the iph to show. config.additional_args.push_back("-ForceExperienceForDeviceSwitcher"); config.additional_args.push_back("SyncedAndFirstDevice"); [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config]; - GREYAssertTrue([ChromeEarlGrey isBottomOmniboxSteadyStateEnabled], - @"Test case should have ran in bottom omnibox environment"); - [self openPage1]; + [ChromeEarlGrey + waitForUIElementToAppearWithMatcher:chrome_test_util::OmniboxAtBottom()]; // Long pressing should allow copying. [[EarlGrey selectElementWithMatcher:chrome_test_util::DefocusedLocationView()] @@ -835,6 +856,10 @@ performAction:grey_tap()]; [ChromeEarlGrey verifyStringCopied:base::SysUTF8ToNSString(_URL1.spec())]; + // Verify the omnibox is at the top. + [ChromeEarlGrey + waitForUIElementToAppearWithMatcher:chrome_test_util::OmniboxOnTop()]; + // Verify the share button IPH is shown. GREYAssert([ChromeEarlGrey testUIElementAppearanceWithMatcher: chrome_test_util::TabShareButton()],
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn index 31f116e..a0116b1 100644 --- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -30,8 +30,6 @@ "autocomplete_controller_observer_bridge.mm", "omnibox_pedal_annotator.h", "omnibox_pedal_annotator.mm", - "omnibox_popup_container_view.h", - "omnibox_popup_container_view.mm", "omnibox_popup_coordinator.h", "omnibox_popup_coordinator.mm", "omnibox_popup_mediator+Testing.h",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.h deleted file mode 100644 index cb8568f3..0000000 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.h +++ /dev/null
@@ -1,15 +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. - -#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_CONTAINER_VIEW_H_ -#define IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_CONTAINER_VIEW_H_ - -#include <UIKit/UIKit.h> - -/// Container view for the popup view hierarchy. It overrides hit-testing so we -/// can dismiss hits on the PopupEmptySpaceView. -@interface OmniboxPopupContainerView : UIView -@end - -#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_CONTAINER_VIEW_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.mm deleted file mode 100644 index 03b5b15..0000000 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.mm +++ /dev/null
@@ -1,19 +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. - -#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.h" - -@implementation OmniboxPopupContainerView - -/// Ignore user interaction with itself or PopupEmptySpaceView. -- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event { - UIView* hitResult = [super hitTest:point withEvent:event]; - - if (hitResult == self) - return NULL; - - return hitResult; -} - -@end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm index 5d804c5..06f5f63 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
@@ -38,7 +38,6 @@ #import "ios/chrome/browser/ui/omnibox/popup/carousel/carousel_item_menu_provider.h" #import "ios/chrome/browser/ui/omnibox/popup/content_providing.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_pedal_annotator.h" -#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm index d74c3db..c473b39 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
@@ -11,7 +11,6 @@ #import "ios/chrome/browser/shared/ui/util/util_swift.h" #import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h" #import "ios/chrome/browser/ui/omnibox/popup/content_providing.h" -#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.h" #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -78,7 +77,7 @@ initWithStyle:incognito ? ToolbarStyle::kIncognito : ToolbarStyle::kNormal]; - UIView* containerView = [[OmniboxPopupContainerView alloc] init]; + UIView* containerView = [[UIView alloc] init]; [containerView addSubview:viewController.view]; _popupContainerView = containerView;
diff --git a/ios/chrome/browser/ui/settings/address_bar_preference/address_bar_preference_egtest.mm b/ios/chrome/browser/ui/settings/address_bar_preference/address_bar_preference_egtest.mm index 61ccb57f8..1562b137 100644 --- a/ios/chrome/browser/ui/settings/address_bar_preference/address_bar_preference_egtest.mm +++ b/ios/chrome/browser/ui/settings/address_bar_preference/address_bar_preference_egtest.mm
@@ -48,19 +48,6 @@ return grey_allOf(grey_selected(), BottomAddressBarOption(), nil); } -id<GREYMatcher> BottomOmnibox() { - return grey_allOf( - chrome_test_util::DefocusedLocationView(), - grey_ancestor(grey_kindOfClassName(@"SecondaryToolbarView")), - grey_sufficientlyVisible(), nil); -} - -id<GREYMatcher> TopOmnibox() { - return grey_allOf(chrome_test_util::DefocusedLocationView(), - grey_ancestor(grey_kindOfClassName(@"PrimaryToolbarView")), - grey_sufficientlyVisible(), nil); -} - } // namespace @interface AddressBarPreferenceTestCase : ChromeTestCase @@ -90,7 +77,7 @@ [ChromeEarlGrey loadURL:GURL("about:blank")]; // The address bar should be on top. - [[EarlGrey selectElementWithMatcher:TopOmnibox()] + [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxOnTop()] assertWithMatcher:grey_notNil()]; [self openAddressBarPreferenceSettingPage]; @@ -111,9 +98,9 @@ performAction:grey_tap()]; // The address bar should be now on bottom. - [[EarlGrey selectElementWithMatcher:BottomOmnibox()] + [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxAtBottom()] assertWithMatcher:grey_notNil()]; - [[EarlGrey selectElementWithMatcher:TopOmnibox()] + [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxOnTop()] assertWithMatcher:grey_nil()]; }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn index c493004..62f136af 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn
@@ -38,6 +38,8 @@ sources = [ "create_tab_group_view_controller.h", "create_tab_group_view_controller.mm", + "tab_group_snapshots_view.h", + "tab_group_snapshots_view.mm", "tab_group_view_controller.h", "tab_group_view_controller.mm", "tab_groups_commands.h",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm index fcdf6ac..61f4a2f02f 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm
@@ -11,6 +11,7 @@ #import "ios/chrome/browser/shared/ui/elements/top_aligned_image_view.h" #import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_creation_mutator.h" +#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_commands.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_constants.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -38,7 +39,6 @@ constexpr CGFloat kSnapshotViewMaxHeight = 190; constexpr CGFloat kSnapshotViewCornerRadius = 18; constexpr CGFloat kSnapshotViewVerticalMargin = 25; -constexpr CGFloat kOutsideSnapshotCornerRadius = 16; constexpr CGFloat kSingleSnapshotRatio = 0.75; } // namespace @@ -494,14 +494,9 @@ snapshotsBackground.opaque = NO; // TODO(crbug.com/1501837): Manage more than one snapshot and favicons. - // TODO(crbug.com/1501837): Manage favicons. - UIImage* snapshotImg = _snapshots.firstObject; - TopAlignedImageView* snapshotView = [[TopAlignedImageView alloc] init]; - snapshotView.image = snapshotImg; - snapshotView.translatesAutoresizingMaskIntoConstraints = NO; - snapshotView.layer.cornerRadius = kOutsideSnapshotCornerRadius; - snapshotView.contentMode = UIViewContentModeScaleAspectFill; - snapshotView.clipsToBounds = YES; + UIView* snapshotView = [[TabGroupSnapshotsView alloc] + initWithSnapshot:[self imageFromObject:_snapshots.firstObject] + favicon:[self imageFromObject:_favicons.firstObject]]; [snapshotsBackground addSubview:snapshotView]; @@ -540,4 +535,14 @@ _favicons = favicons; } +#pragma mark - Private Helpers + +// Returns the picture is it is a picture and nil if not. +- (UIImage*)imageFromObject:(id)object { + if ([object isKindOfClass:[NSNull class]]) { + return nil; + } + return object; +} + @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.h new file mode 100644 index 0000000..de01b6cc --- /dev/null +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.h
@@ -0,0 +1,18 @@ +// 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 IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_TAB_GROUPS_TAB_GROUP_SNAPSHOTS_VIEW_H_ +#define IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_TAB_GROUPS_TAB_GROUP_SNAPSHOTS_VIEW_H_ + +#import <UIKit/UIKit.h> + +// View controller that manages the tab group sample view with multiples +// snapshots. +@interface TabGroupSnapshotsView : UIView + +- (instancetype)initWithSnapshot:(UIImage*)snapshot favicon:(UIImage*)favicon; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_TAB_GROUPS_TAB_GROUP_SNAPSHOTS_VIEW_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.mm new file mode 100644 index 0000000..0729d5a --- /dev/null +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.mm
@@ -0,0 +1,88 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_snapshots_view.h" + +#import "base/check.h" +#import "ios/chrome/browser/shared/public/features/features.h" +#import "ios/chrome/browser/shared/ui/elements/top_aligned_image_view.h" +#import "ios/chrome/common/ui/util/constraints_ui_util.h" + +namespace { +constexpr CGFloat kFaviconSize = 16; +constexpr CGFloat kFaviconPadding = 8; +constexpr CGFloat kFaviconMargin = 4; +constexpr CGFloat kFaviconCornerRadius = 7; +constexpr CGFloat kSnapshotCornerRadius = 12; +constexpr CGFloat kSnapshotOverlayAlpha = 0.14; +} // namespace + +@implementation TabGroupSnapshotsView + +- (instancetype)initWithSnapshot:(UIImage*)snapshot favicon:(UIImage*)favicon { + CHECK(base::FeatureList::IsEnabled(kTabGroupsInGrid)) + << "You should not be able to create a tab group snapshot view outside " + "the Tab Groups experiment."; + self = [super init]; + if (self) { + UIView* finalView = self; + finalView.translatesAutoresizingMaskIntoConstraints = NO; + + TopAlignedImageView* snapshotView = [[TopAlignedImageView alloc] init]; + snapshotView.image = snapshot; + snapshotView.translatesAutoresizingMaskIntoConstraints = NO; + snapshotView.layer.cornerRadius = kSnapshotCornerRadius; + snapshotView.contentMode = UIViewContentModeScaleAspectFill; + snapshotView.clipsToBounds = YES; + + UIView* snapshotOverlay = [[UIView alloc] init]; + snapshotOverlay.translatesAutoresizingMaskIntoConstraints = NO; + snapshotOverlay.backgroundColor = + [UIColor colorWithRed:0 green:0 blue:0 alpha:kSnapshotOverlayAlpha]; + [snapshotView addSubview:snapshotOverlay]; + AddSameConstraints(snapshotOverlay, snapshotView); + + // Add a favicon only if there is one. + if (favicon) { + UIImageView* faviconImageView = [[UIImageView alloc] init]; + faviconImageView.translatesAutoresizingMaskIntoConstraints = NO; + faviconImageView.contentMode = UIViewContentModeScaleAspectFill; + faviconImageView.image = favicon; + + UIView* faviconBackground = [[UIView alloc] init]; + faviconBackground.translatesAutoresizingMaskIntoConstraints = NO; + faviconBackground.backgroundColor = UIColor.whiteColor; + faviconBackground.layer.cornerRadius = kFaviconCornerRadius; + faviconBackground.clipsToBounds = YES; + + [faviconBackground addSubview:faviconImageView]; + AddSameCenterConstraints(faviconBackground, faviconImageView); + + [snapshotView addSubview:faviconBackground]; + + [NSLayoutConstraint activateConstraints:@[ + [faviconImageView.widthAnchor constraintEqualToConstant:kFaviconSize], + [faviconImageView.heightAnchor constraintEqualToConstant:kFaviconSize], + [faviconBackground.widthAnchor + constraintEqualToAnchor:faviconImageView.widthAnchor + constant:kFaviconPadding], + [faviconBackground.heightAnchor + constraintEqualToAnchor:faviconImageView.heightAnchor + constant:kFaviconPadding], + [faviconBackground.trailingAnchor + constraintEqualToAnchor:snapshotView.trailingAnchor + constant:-kFaviconMargin], + [faviconBackground.bottomAnchor + constraintEqualToAnchor:snapshotView.bottomAnchor + constant:-kFaviconMargin], + ]]; + } + + [finalView addSubview:snapshotView]; + AddSameConstraints(finalView, snapshotView); + } + return self; +} + +@end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_cell.mm index a0b97c70..fed743a 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_cell.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_cell.mm
@@ -33,6 +33,7 @@ const CGFloat kSeparatorHeight = 18; const CGFloat kSeparatorHorizontalInset = 2; const CGFloat kSeparatorGradientWidth = 4; +const CGFloat kSeparatorBackgroundAlpha = 0.3; // Content view constants. const CGFloat kFaviconLeadingMargin = 10; @@ -348,9 +349,9 @@ // Updates view colors. - (void)updateColors { - UIColor* backgroundColor = self.selected - ? [UIColor colorNamed:kPrimaryBackgroundColor] - : [UIColor colorNamed:kGrey200Color]; + UIColor* backgroundColor = + self.selected ? [UIColor colorNamed:kGroupedSecondaryBackgroundColor] + : [UIColor colorNamed:kTabStripBackgroundColor]; // Needed to correctly update the `_titleGradientView` colors in incognito. backgroundColor = [backgroundColor resolvedColorWithTraitCollection:self.traitCollection]; @@ -639,9 +640,9 @@ // Returns a new gradient view. - (GradientView*)createGradientView { GradientView* gradientView = [[GradientView alloc] - initWithStartColor:[[UIColor colorNamed:kGrey200Color] + initWithStartColor:[[UIColor colorNamed:kTabStripBackgroundColor] colorWithAlphaComponent:0] - endColor:[UIColor colorNamed:kGrey200Color] + endColor:[UIColor colorNamed:kTabStripBackgroundColor] startPoint:CGPointMake(0.0f, 0.5f) endPoint:CGPointMake(1.0f, 0.5f)]; gradientView.translatesAutoresizingMaskIntoConstraints = NO; @@ -674,7 +675,8 @@ // Returns a new decoration view. - (UIView*)createDecorationView { UIView* tailView = [[UIView alloc] init]; - tailView.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; + tailView.backgroundColor = + [UIColor colorNamed:kGroupedSecondaryBackgroundColor]; tailView.translatesAutoresizingMaskIntoConstraints = NO; tailView.clipsToBounds = NO; tailView.hidden = YES; @@ -684,16 +686,24 @@ // Returns a new separator view. - (UIView*)createSeparatorView { UIView* separatorView = [[UIView alloc] init]; - separatorView.backgroundColor = [UIColor colorNamed:kGrey400Color]; + separatorView.backgroundColor = [UIColor colorNamed:kTabStripBackgroundColor]; separatorView.translatesAutoresizingMaskIntoConstraints = NO; separatorView.layer.cornerRadius = kSeparatorCornerRadius; + + UIView* backgroundView = [[UIView alloc] init]; + backgroundView.autoresizingMask = + UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + backgroundView.backgroundColor = [[UIColor colorNamed:kTextSecondaryColor] + colorWithAlphaComponent:kSeparatorBackgroundAlpha]; + [separatorView addSubview:backgroundView]; return separatorView; } // Returns a new selected border background view. - (UIView*)createSelectedBorderBackgroundView { UIView* backgroundView = [[UIView alloc] init]; - backgroundView.backgroundColor = [UIColor colorNamed:kGrey200Color]; + backgroundView.backgroundColor = + [UIColor colorNamed:kTabStripBackgroundColor]; backgroundView.translatesAutoresizingMaskIntoConstraints = NO; backgroundView.hidden = YES; return backgroundView;
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_constants.swift b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_constants.swift index d355b20..ae839c76 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_constants.swift +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_constants.swift
@@ -58,6 +58,7 @@ static let horizontalInset: CGFloat = 4 static let leadingInset: CGFloat = 6 static let bottomInset: CGFloat = 4 + static let backgroundColorAlpha: CGFloat = 0.3 } }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_decoration_view.swift b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_decoration_view.swift index a8dbf10..2d56639c 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_decoration_view.swift +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_decoration_view.swift
@@ -66,7 +66,10 @@ // Returns a new separator view. func createSeparatorView() -> UIView { let separatorView = UIView() - separatorView.backgroundColor = UIColor(named: kGrey400Color) + if let backgroundColor = UIColor(named: kTextSecondaryColor) { + separatorView.backgroundColor = backgroundColor.withAlphaComponent( + TabStripConstants.StaticSeparator.backgroundColorAlpha) + } separatorView.translatesAutoresizingMaskIntoConstraints = false separatorView.layer.cornerRadius = TabStripConstants.StaticSeparator.separatorCornerRadius return separatorView @@ -75,7 +78,7 @@ // Returns a new solid background view. func createSolidBackgroundView() -> UIView { let solidBackgroundView = UIView() - solidBackgroundView.backgroundColor = UIColor(named: kGrey200Color) + solidBackgroundView.backgroundColor = UIColor(named: kTabStripBackgroundColor) solidBackgroundView.translatesAutoresizingMaskIntoConstraints = false return solidBackgroundView }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_layout.swift b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_layout.swift index dde82cb0..438455a 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_layout.swift +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_layout.swift
@@ -321,8 +321,19 @@ var origin = layoutAttributes.frame.origin var horizontalInset: CGFloat = 0 - let staticSeparatorHorizontalInset = - tabCellSize.width - TabStripConstants.AnimatedSeparator.collapseHorizontalInsetThreshold + // Add a static separator horizontal inset only if the selected cell is the + // first or the last one. Otherwise, when the selected cell is anchored and + // a cell is scrolled behind, only one separator is displayed until the + // horizontal inset threshold is reached. + var staticSeparatorHorizontalInset: CGFloat = 0 + if let snapshot = dataSource?.snapshot() { + let itemCount = snapshot.itemIdentifiers.count + if indexPath.item == 0 || indexPath.item == itemCount - 1 { + staticSeparatorHorizontalInset = + tabCellSize.width - TabStripConstants.AnimatedSeparator.collapseHorizontalInsetThreshold + } + } + var hideLeftStaticSeparator = true var hideRightStaticSeparator = true
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_new_tab_button.swift b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_new_tab_button.swift index 869225f..ec8f0322 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_new_tab_button.swift +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_new_tab_button.swift
@@ -57,7 +57,7 @@ button.imageView?.contentMode = .center button.layer.cornerRadius = TabStripConstants.NewTabButton.cornerRadius - button.backgroundColor = UIColor(named: kPrimaryBackgroundColor) + button.backgroundColor = UIColor(named: kGroupedSecondaryBackgroundColor) button.translatesAutoresizingMaskIntoConstraints = false button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_view_controller.swift b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_view_controller.swift index 41d6de18..f3518451 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_view_controller.swift +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/ui/tab_strip_view_controller.swift
@@ -77,7 +77,7 @@ override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = UIColor(named: kGrey200Color) + view.backgroundColor = UIColor(named: kTabStripBackgroundColor) collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.clipsToBounds = true
diff --git a/ios/chrome/common/ui/colors/resources/BUILD.gn b/ios/chrome/common/ui/colors/resources/BUILD.gn index b4bcfede..6e7881c 100644 --- a/ios/chrome/common/ui/colors/resources/BUILD.gn +++ b/ios/chrome/common/ui/colors/resources/BUILD.gn
@@ -64,6 +64,7 @@ ":solid_white_color", ":static_blue_400_color", ":static_grey_300_color", + ":tab_strip_background_color", ":table_view_row_highlight_color", ":tertiary_background_color", ":text_primary_color", @@ -368,3 +369,7 @@ colorset("omnibox_keyboard_button_color") { sources = [ "omnibox_keyboard_button_color.colorset/Contents.json" ] } + +colorset("tab_strip_background_color") { + sources = [ "tab_strip_background_color.colorset/Contents.json" ] +}
diff --git a/ios/chrome/common/ui/colors/resources/tab_strip_background_color.colorset/Contents.json b/ios/chrome/common/ui/colors/resources/tab_strip_background_color.colorset/Contents.json new file mode 100644 index 0000000..a0478347 --- /dev/null +++ b/ios/chrome/common/ui/colors/resources/tab_strip_background_color.colorset/Contents.json
@@ -0,0 +1,38 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha": "1.000", + "red": "0xF1", + "green": "0xF3", + "blue": "0xF4" + } + } + }, + { + "idiom" : "universal", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha": "1.000", + "red": "0x20", + "green": "0x21", + "blue": "0x24" + } + } + } + ] +}
diff --git a/ios/chrome/common/ui/colors/semantic_color_names.h b/ios/chrome/common/ui/colors/semantic_color_names.h index 4167dc1..0c85d2b 100644 --- a/ios/chrome/common/ui/colors/semantic_color_names.h +++ b/ios/chrome/common/ui/colors/semantic_color_names.h
@@ -54,6 +54,8 @@ extern NSString* const kOmniboxKeyboardButtonColor; // Color for separator between omnibox suggestions. extern NSString* const kOmniboxSuggestionRowSeparatorColor; +// Background color for the tab strip surface. +extern NSString* const kTabStripBackgroundColor; // *************** // Standard Colors
diff --git a/ios/chrome/common/ui/colors/semantic_color_names.mm b/ios/chrome/common/ui/colors/semantic_color_names.mm index b5632f4..d60c173 100644 --- a/ios/chrome/common/ui/colors/semantic_color_names.mm +++ b/ios/chrome/common/ui/colors/semantic_color_names.mm
@@ -41,6 +41,7 @@ NSString* const kOmniboxKeyboardButtonColor = @"omnibox_keyboard_button_color"; NSString* const kOmniboxSuggestionRowSeparatorColor = @"omnibox_suggestion_row_separator_color"; +NSString* const kTabStripBackgroundColor = @"tab_strip_background_color"; #pragma mark - Standard Colors NSString* const kSolidBlackColor = @"solid_black_color";
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h index b0e9256..42c8c0e3 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.h +++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -132,6 +132,12 @@ // Returns a matcher for the omnibox. id<GREYMatcher> Omnibox(); +// Returns a matcher for the omnibox at the bottom. +id<GREYMatcher> OmniboxAtBottom(); + +// Returns a matcher for the omnibox on the top. +id<GREYMatcher> OmniboxOnTop(); + // Returns matcher for the omnibox popup list row views. id<GREYMatcher> OmniboxPopupRow();
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm index 024f1775..e513b99 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -161,6 +161,14 @@ return [ChromeMatchersAppInterface omnibox]; } +id<GREYMatcher> OmniboxAtBottom() { + return [ChromeMatchersAppInterface omniboxAtBottom]; +} + +id<GREYMatcher> OmniboxOnTop() { + return [ChromeMatchersAppInterface omniboxOnTop]; +} + id<GREYMatcher> OmniboxPopupRow() { return [ChromeMatchersAppInterface omniboxPopupRow]; }
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h index b146d43de..2ee07a7 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h +++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h
@@ -123,6 +123,12 @@ // Returns a matcher for the omnibox. + (id<GREYMatcher>)omnibox; +// Returns a matcher for the omnibox at the bottom. ++ (id<GREYMatcher>)omniboxAtBottom; + +// Returns a matcher for the omnibox on the top. ++ (id<GREYMatcher>)omniboxOnTop; + // Returns a matcher for the location view. + (id<GREYMatcher>)defocusedLocationView;
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm index e1e3aa1..31e5607 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -404,6 +404,19 @@ grey_userInteractionEnabled(), nil); } ++ (id<GREYMatcher>)omniboxAtBottom { + return grey_allOf( + [ChromeMatchersAppInterface defocusedLocationView], + grey_ancestor(grey_kindOfClassName(@"SecondaryToolbarView")), + grey_sufficientlyVisible(), nil); +} + ++ (id<GREYMatcher>)omniboxOnTop { + return grey_allOf([ChromeMatchersAppInterface defocusedLocationView], + grey_ancestor(grey_kindOfClassName(@"PrimaryToolbarView")), + grey_sufficientlyVisible(), nil); +} + + (id<GREYMatcher>)defocusedLocationView { return grey_kindOfClass([LocationBarSteadyView class]); }
diff --git a/ios_internal b/ios_internal index a2e9e8c..d7d7b06 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit a2e9e8cfd9bd77d59fc632ddb10190e30514189d +Subproject commit d7d7b06b764310290cab652eeb2701c6c515881f
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index e83e6668..77157d5 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -1651,6 +1651,18 @@ video_frame_is_pure_sw || video_frame->shared_image_format_type() == SharedImageFormatType::kLegacy; + // It is not possible for VideoFrames holding legacy mailboxes to reach this + // function. The reason is the following: + // * VideoFrames holding legacy mailboxes must have exactly one texture + // * By definition, they are not using multiplanar SharedImages (since they + // are not using SharedImage at all) + // * This function only has two entrypoints: One from + // CopyVideoFrameTexturesToGLTexture() that is conditional on the mailbox + // either having more than one texture or holding a multiplanar SharedImage, + // and one from CopyVideoFrameYUVDataToGLTexture(), which itself is a codepath + // that is used only when the VideoFrame has no textures. + DUMP_WILL_BE_CHECK(!video_frame_is_legacy_mailbox); + bool use_legacy_mailboxes_for_upload = yuv_rgb_conversion_not_supported || video_frame_is_legacy_mailbox || video_frame_is_pure_sw ||
diff --git a/net/BUILD.gn b/net/BUILD.gn index 04b8591..24c1b7a 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -795,6 +795,8 @@ "quic/quic_http_utils.h", "quic/quic_proxy_client_socket.cc", "quic/quic_proxy_client_socket.h", + "quic/quic_proxy_datagram_client_socket.cc", + "quic/quic_proxy_datagram_client_socket.h", "quic/quic_server_info.cc", "quic/quic_server_info.h", "quic/quic_session_key.cc",
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index 2d63fc0..a8903523 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -1179,16 +1179,6 @@ return max_entries_; } -// static -std::unique_ptr<HostCache> HostCache::CreateDefaultCache() { -#if defined(ENABLE_BUILT_IN_DNS) - const size_t kDefaultMaxEntries = 1000; -#else - const size_t kDefaultMaxEntries = 100; -#endif - return std::make_unique<HostCache>(kDefaultMaxEntries); -} - bool HostCache::EvictOneEntry(base::TimeTicks now) { DCHECK_LT(0u, entries_.size());
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index c3f9734..57b706f 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -476,9 +476,6 @@ int network_changes() const { return network_changes_; } const EntryMap& entries() const { return entries_; } - // Creates a default cache. - static std::unique_ptr<HostCache> CreateDefaultCache(); - private: FRIEND_TEST_ALL_PREFIXES(HostCacheTest, NoCache);
diff --git a/net/dns/host_resolver_dns_task.cc b/net/dns/host_resolver_dns_task.cc index ab5bb0fe..203d3c0a 100644 --- a/net/dns/host_resolver_dns_task.cc +++ b/net/dns/host_resolver_dns_task.cc
@@ -17,6 +17,7 @@ #include "net/dns/dns_transaction.h" #include "net/dns/dns_util.h" #include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_cache.h" #include "net/dns/host_resolver_internal_result.h" #include "net/dns/public/util.h" #include "third_party/abseil-cpp/absl/types/variant.h" @@ -134,6 +135,7 @@ HostResolverDnsTask::HostResolverDnsTask( DnsClient* client, absl::variant<url::SchemeHostPort, std::string> host, + NetworkAnonymizationKey anonymization_key, DnsQueryTypeSet query_types, ResolveContext* resolve_context, bool secure, @@ -145,6 +147,7 @@ const HostResolver::HttpsSvcbOptions& https_svcb_options) : client_(client), host_(std::move(host)), + anonymization_key_(std::move(anonymization_key)), resolve_context_(resolve_context->AsSafeRef()), secure_(secure), secure_dns_mode_(secure_dns_mode), @@ -696,6 +699,16 @@ CHECK(transactions_in_progress_.find(transaction_info) == transactions_in_progress_.end()); + if (base::FeatureList::IsEnabled(features::kUseHostResolverCache) && + resolve_context_->host_resolver_cache() != nullptr) { + for (const std::unique_ptr<HostResolverInternalResult>& result : + transaction_results) { + resolve_context_->host_resolver_cache()->Set( + result->Clone(), anonymization_key_, HostResolverSource::DNS, + secure_); + } + } + // TODO(crbug.com/1381506): Use new results type directly instead of // converting to HostCache::Entry. HostCache::Entry legacy_results(std::move(transaction_results),
diff --git a/net/dns/host_resolver_dns_task.h b/net/dns/host_resolver_dns_task.h index eb052b3..0c19757 100644 --- a/net/dns/host_resolver_dns_task.h +++ b/net/dns/host_resolver_dns_task.h
@@ -66,6 +66,7 @@ HostResolverDnsTask(DnsClient* client, absl::variant<url::SchemeHostPort, std::string> host, + NetworkAnonymizationKey anonymization_key, DnsQueryTypeSet query_types, ResolveContext* resolve_context, bool secure, @@ -196,6 +197,7 @@ const raw_ptr<DnsClient> client_; absl::variant<url::SchemeHostPort, std::string> host_; + NetworkAnonymizationKey anonymization_key_; base::SafeRef<ResolveContext> resolve_context_;
diff --git a/net/dns/host_resolver_manager_job.cc b/net/dns/host_resolver_manager_job.cc index 35fd239..794d6be 100644 --- a/net/dns/host_resolver_manager_job.cc +++ b/net/dns/host_resolver_manager_job.cc
@@ -641,9 +641,9 @@ // 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>( - resolver_->dns_client_.get(), key_.host, key_.query_types, - &*key_.resolve_context, secure, key_.secure_dns_mode, this, net_log_, - tick_clock_, !tasks_.empty() /* fallback_available */, + resolver_->dns_client_.get(), key_.host, key_.network_anonymization_key, + key_.query_types, &*key_.resolve_context, secure, key_.secure_dns_mode, + this, net_log_, tick_clock_, !tasks_.empty() /* fallback_available */, https_svcb_options_); dns_task_->StartNextTransaction(); // Schedule a second transaction, if needed. DoH queries can bypass the
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index 92795872..b8d59b14 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -63,6 +63,9 @@ #include "net/dns/dns_test_util.h" #include "net/dns/dns_util.h" #include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_cache.h" +#include "net/dns/host_resolver_internal_result.h" +#include "net/dns/host_resolver_internal_result_test_util.h" #include "net/dns/host_resolver_results_test_util.h" #include "net/dns/host_resolver_system_task.h" #include "net/dns/mock_host_resolver.h" @@ -110,6 +113,7 @@ using ::testing::Between; using ::testing::ByMove; using ::testing::Contains; +using ::testing::ElementsAre; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Not; @@ -13862,6 +13866,98 @@ HostResolverSource::ANY, NetworkAnonymizationKey()))); } +TEST_F(HostResolverManagerDnsTest, HostResolverCacheContainsTransactions) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kUseHostResolverCache, + features::kSplitHostCacheByNetworkIsolationKey}, + /*disabled_features=*/{}); + + ChangeDnsConfig(CreateValidDnsConfig()); + + const SchemefulSite kSite(GURL("https://site.test/")); + const auto kNetworkAnonymizationKey = + NetworkAnonymizationKey::CreateSameSite(kSite); + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("ok", 80), kNetworkAnonymizationKey, NetLogWithSource(), + absl::nullopt, resolve_context_.get())); + ASSERT_THAT(response.result_error(), IsOk()); + + // Expect separate transactions to be separately cached. + EXPECT_THAT( + resolve_context_->host_resolver_cache()->Lookup( + "ok", kNetworkAnonymizationKey, DnsQueryType::A, + HostResolverSource::DNS, /*secure=*/false), + Pointee(ExpectHostResolverInternalDataResult( + "ok", DnsQueryType::A, HostResolverInternalResult::Source::kDns, _, _, + ElementsAre(IPEndPoint(IPAddress::IPv4Localhost(), 0))))); + EXPECT_THAT( + resolve_context_->host_resolver_cache()->Lookup( + "ok", kNetworkAnonymizationKey, DnsQueryType::AAAA, + HostResolverSource::DNS, /*secure=*/false), + Pointee(ExpectHostResolverInternalDataResult( + "ok", DnsQueryType::AAAA, HostResolverInternalResult::Source::kDns, _, + _, ElementsAre(IPEndPoint(IPAddress::IPv6Localhost(), 0))))); +} + +TEST_F(HostResolverManagerDnsTest, HostResolverCacheContainsAliasChains) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kUseHostResolverCache, + features::kSplitHostCacheByNetworkIsolationKey}, + /*disabled_features=*/{}); + + constexpr base::StringPiece kHost = "host.test"; + + MockDnsClientRuleList rules; + DnsResponse a_response = BuildTestDnsResponse( + std::string(kHost), dns_protocol::kTypeA, + {BuildTestCnameRecord(std::string(kHost), "alias1.test"), + BuildTestCnameRecord("alias1.test", "alias2.test"), + BuildTestAddressRecord("alias2.test", IPAddress::IPv4Localhost())}); + AddDnsRule(&rules, std::string(kHost), dns_protocol::kTypeA, + std::move(a_response), + /*delay=*/false); + AddDnsRule(&rules, std::string(kHost), dns_protocol::kTypeAAAA, + MockDnsClientRule::ResultType::kEmpty, /*delay=*/false); + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + + const SchemefulSite kSite(GURL("https://site.test/")); + const auto kNetworkAnonymizationKey = + NetworkAnonymizationKey::CreateSameSite(kSite); + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair(kHost, 80), kNetworkAnonymizationKey, NetLogWithSource(), + absl::nullopt, resolve_context_.get())); + ASSERT_THAT(response.result_error(), IsOk()); + + // Expect each alias link and the result to be separately cached with the + // aliases cached under the original query type. + EXPECT_THAT( + resolve_context_->host_resolver_cache()->Lookup( + kHost, kNetworkAnonymizationKey, DnsQueryType::A, + HostResolverSource::DNS, /*secure=*/false), + Pointee(ExpectHostResolverInternalAliasResult( + std::string(kHost), DnsQueryType::A, + HostResolverInternalResult::Source::kDns, _, _, "alias1.test"))); + EXPECT_THAT( + resolve_context_->host_resolver_cache()->Lookup( + "alias1.test", kNetworkAnonymizationKey, DnsQueryType::A, + HostResolverSource::DNS, /*secure=*/false), + Pointee(ExpectHostResolverInternalAliasResult( + "alias1.test", DnsQueryType::A, + HostResolverInternalResult::Source::kDns, _, _, "alias2.test"))); + EXPECT_THAT(resolve_context_->host_resolver_cache()->Lookup( + "alias2.test", kNetworkAnonymizationKey, DnsQueryType::A, + HostResolverSource::DNS, /*secure=*/false), + Pointee(ExpectHostResolverInternalDataResult( + "alias2.test", DnsQueryType::A, + HostResolverInternalResult::Source::kDns, _, _, + ElementsAre(IPEndPoint(IPAddress::IPv4Localhost(), 0))))); +} + class HostResolverManagerBootstrapTest : public HostResolverManagerDnsTest { protected: using MockResult = MockDnsClientRule::ResultType;
diff --git a/net/dns/resolve_context.cc b/net/dns/resolve_context.cc index 01b1d6a..ac550f6c 100644 --- a/net/dns/resolve_context.cc +++ b/net/dns/resolve_context.cc
@@ -28,6 +28,7 @@ #include "net/dns/dns_session.h" #include "net/dns/dns_util.h" #include "net/dns/host_cache.h" +#include "net/dns/host_resolver_cache.h" #include "net/dns/public/dns_over_https_config.h" #include "net/dns/public/doh_provider_entry.h" #include "net/dns/public/secure_dns_mode.h" @@ -117,6 +118,29 @@ return histogram; } +#if defined(ENABLE_BUILT_IN_DNS) +constexpr size_t kDefaultCacheSize = 1000; +#else +constexpr size_t kDefaultCacheSize = 100; +#endif + +std::unique_ptr<HostCache> CreateHostCache(bool enable_caching) { + if (enable_caching) { + return std::make_unique<HostCache>(kDefaultCacheSize); + } else { + return nullptr; + } +} + +std::unique_ptr<HostResolverCache> CreateHostResolverCache( + bool enable_caching) { + if (enable_caching) { + return std::make_unique<HostResolverCache>(kDefaultCacheSize); + } else { + return nullptr; + } +} + } // namespace ResolveContext::ServerStats::ServerStats( @@ -130,7 +154,8 @@ ResolveContext::ResolveContext(URLRequestContext* url_request_context, bool enable_caching) : url_request_context_(url_request_context), - host_cache_(enable_caching ? HostCache::CreateDefaultCache() : nullptr), + host_cache_(CreateHostCache(enable_caching)), + host_resolver_cache_(CreateHostResolverCache(enable_caching)), isolation_info_(IsolationInfo::CreateTransient()) { max_fallback_period_ = GetMaxFallbackPeriod(); }
diff --git a/net/dns/resolve_context.h b/net/dns/resolve_context.h index 31e21a63..7cbbfd0 100644 --- a/net/dns/resolve_context.h +++ b/net/dns/resolve_context.h
@@ -30,6 +30,7 @@ class DnsServerIterator; class DohDnsServerIterator; class HostCache; +class HostResolverCache; class URLRequestContext; // Represents various states of the DoH auto-upgrade process. @@ -180,6 +181,9 @@ } HostCache* host_cache() { return host_cache_.get(); } + HostResolverCache* host_resolver_cache() { + return host_resolver_cache_.get(); + } // Invalidate or clear saved per-context cached data that is not expected to // stay valid between connections or sessions (eg the HostCache and DNS server @@ -299,6 +303,7 @@ raw_ptr<URLRequestContext> url_request_context_; std::unique_ptr<HostCache> host_cache_; + std::unique_ptr<HostResolverCache> host_resolver_cache_; // Current maximum server fallback period. Updated on connection change. base::TimeDelta max_fallback_period_;
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index 043ee12..ed8d371 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-02-05 12:54 UTC +# Last updated: 2024-02-06 12:53 UTC PinsListTimestamp -1707137643 +1707224034 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json index cd529be5..5db04c7 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-02-05 12:54 UTC +// Last updated: 2024-02-06 12:53 UTC // { "pinsets": [
diff --git a/net/log/net_log_source_type_list.h b/net/log/net_log_source_type_list.h index 85707816..7b11fd8 100644 --- a/net/log/net_log_source_type_list.h +++ b/net/log/net_log_source_type_list.h
@@ -49,3 +49,4 @@ SOURCE_TYPE(NETWORK_CHANGE_NOTIFIER) SOURCE_TYPE(QUIC_SESSION_POOL) SOURCE_TYPE(UDP_CLIENT_SOCKET) +SOURCE_TYPE(QUIC_PROXY_DATAGRAM_CLIENT_SOCKET)
diff --git a/net/quic/quic_proxy_datagram_client_socket.cc b/net/quic/quic_proxy_datagram_client_socket.cc new file mode 100644 index 0000000..357efa6 --- /dev/null +++ b/net/quic/quic_proxy_datagram_client_socket.cc
@@ -0,0 +1,152 @@ +// 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/quic/quic_proxy_datagram_client_socket.h" + +#include "net/base/net_errors.h" + +namespace net { + +// TODO(crbug.com/1524411) Add net log begin event to constructor. +QuicProxyDatagramClientSocket::QuicProxyDatagramClientSocket( + const NetLogWithSource& source_net_log, + url::SchemeHostPort destination) + : net_log_(NetLogWithSource::Make( + source_net_log.net_log(), + NetLogSourceType::QUIC_PROXY_DATAGRAM_CLIENT_SOCKET)), + destination_(std::move(destination)) {} + +QuicProxyDatagramClientSocket::~QuicProxyDatagramClientSocket() {} + +int QuicProxyDatagramClientSocket::ConnectViaStream( + const IPEndPoint& local_address, + const IPEndPoint& proxy_peer_address, + std::unique_ptr<QuicChromiumClientStream::Handle> stream, + CompletionOnceCallback callback) { + CHECK(!stream_); + local_address_ = local_address; + proxy_peer_address_ = proxy_peer_address; + stream_ = std::move(stream); + // TODO(crbug.com/1524411) Implement method. + return OK; +} + +int QuicProxyDatagramClientSocket::Connect(const IPEndPoint& address) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectAsync( + const IPEndPoint& address, + CompletionOnceCallback callback) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingDefaultNetworkAsync( + const IPEndPoint& address, + CompletionOnceCallback callback) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingNetwork( + handles::NetworkHandle network, + const IPEndPoint& address) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingDefaultNetwork( + const IPEndPoint& address) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingNetworkAsync( + handles::NetworkHandle network, + const IPEndPoint& address, + CompletionOnceCallback callback) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411) Implement method. +handles::NetworkHandle QuicProxyDatagramClientSocket::GetBoundNetwork() const { + return handles::kInvalidNetworkHandle; +} + +// TODO(crbug.com/1524411): Implement method. +void QuicProxyDatagramClientSocket::ApplySocketTag(const SocketTag& tag) {} + +int QuicProxyDatagramClientSocket::SetMulticastInterface( + uint32_t interface_index) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +void QuicProxyDatagramClientSocket::SetIOSNetworkServiceType( + int ios_network_service_type) {} + +void QuicProxyDatagramClientSocket::Close() {} + +int QuicProxyDatagramClientSocket::GetPeerAddress(IPEndPoint* address) const { + *address = proxy_peer_address_; + return OK; +} + +int QuicProxyDatagramClientSocket::GetLocalAddress(IPEndPoint* address) const { + *address = local_address_; + return OK; +} + +void QuicProxyDatagramClientSocket::UseNonBlockingIO() { + NOTREACHED(); +} + +int QuicProxyDatagramClientSocket::SetDoNotFragment() { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::SetRecvEcn() { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +void QuicProxyDatagramClientSocket::SetMsgConfirm(bool confirm) { + NOTREACHED(); +} + +const NetLogWithSource& QuicProxyDatagramClientSocket::NetLog() const { + return net_log_; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::Write( + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + const NetworkTrafficAnnotationTag& traffic_annotation) { + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::SetReceiveBufferSize(int32_t size) { + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::SetSendBufferSize(int32_t size) { + return ERR_NOT_IMPLEMENTED; +} + +} // namespace net
diff --git a/net/quic/quic_proxy_datagram_client_socket.h b/net/quic/quic_proxy_datagram_client_socket.h new file mode 100644 index 0000000..4192fb6 --- /dev/null +++ b/net/quic/quic_proxy_datagram_client_socket.h
@@ -0,0 +1,102 @@ +// 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_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ +#define NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ + +#include <stdint.h> + +#include "net/base/ip_endpoint.h" +#include "net/base/net_export.h" +#include "net/log/net_log.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/quic_chromium_client_stream.h" +#include "net/socket/datagram_client_socket.h" +#include "net/socket/udp_socket.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "url/scheme_host_port.h" + +namespace net { + +// A client socket that uses a QUIC proxy as the transport layer. +// +// Given that DatagramClientSocket class contains numerous methods tailored for +// UDP, many methods from DatagramClientSocket are left as stubs. +// ConnectViaStream is used to connect this socket over the provided QUIC stream +// to send and receive datagrams. +class NET_EXPORT_PRIVATE QuicProxyDatagramClientSocket + : public DatagramClientSocket { + public: + // Initializes a QuicProxyDatagramClientSocket with the provided network + // log (source_net_log) and destination URL. The destination parameter + // specifies the target server (including the scheme, hostname, and port + // number) to which datagrams will be sent. + QuicProxyDatagramClientSocket(const NetLogWithSource& source_net_log, + url::SchemeHostPort destination); + + QuicProxyDatagramClientSocket(const QuicProxyDatagramClientSocket&) = delete; + QuicProxyDatagramClientSocket& operator=( + const QuicProxyDatagramClientSocket&) = delete; + + ~QuicProxyDatagramClientSocket() override; + + // Connect this socket over the given QUIC stream, using the `destination_` + // and local and proxy peer addresses. The socket has no true peer + // address since it is connected over a proxy and the proxy performs the + // hostname resolution. Instead `proxy_peer_address_` is the peer to which the + // underlying socket is connected. + int ConnectViaStream(const IPEndPoint& local_address, + const IPEndPoint& proxy_peer_address, + std::unique_ptr<QuicChromiumClientStream::Handle> stream, + CompletionOnceCallback callback); + + // DatagramClientSocket implementation. + int Connect(const IPEndPoint& address) override; + int ConnectUsingNetwork(handles::NetworkHandle network, + const IPEndPoint& address) override; + int ConnectUsingDefaultNetwork(const IPEndPoint& address) override; + int ConnectAsync(const IPEndPoint& address, + CompletionOnceCallback callback) override; + int ConnectUsingNetworkAsync(handles::NetworkHandle network, + const IPEndPoint& address, + CompletionOnceCallback callback) override; + int ConnectUsingDefaultNetworkAsync(const IPEndPoint& address, + CompletionOnceCallback callback) override; + handles::NetworkHandle GetBoundNetwork() const override; + void ApplySocketTag(const SocketTag& tag) override; + int SetMulticastInterface(uint32_t interface_index) override; + void SetIOSNetworkServiceType(int ios_network_service_type) override; + + // DatagramSocket implementation. + void Close() override; + int GetPeerAddress(IPEndPoint* address) const override; + int GetLocalAddress(IPEndPoint* address) const override; + void UseNonBlockingIO() override; + int SetDoNotFragment() override; + int SetRecvEcn() override; + void SetMsgConfirm(bool confirm) override; + const NetLogWithSource& NetLog() const override; + + // Socket implementation. + int Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + int Write(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + const NetworkTrafficAnnotationTag& traffic_annotation) override; + int SetReceiveBufferSize(int32_t size) override; + int SetSendBufferSize(int32_t size) override; + + private: + NetLogWithSource net_log_; + IPEndPoint local_address_; + IPEndPoint proxy_peer_address_; + std::unique_ptr<QuicChromiumClientStream::Handle> stream_; + url::SchemeHostPort destination_; +}; + +} // namespace net + +#endif // NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_
diff --git a/remoting/resources/remoting_strings_mr.xtb b/remoting/resources/remoting_strings_mr.xtb index 98832886..1b9cb9d 100644 --- a/remoting/resources/remoting_strings_mr.xtb +++ b/remoting/resources/remoting_strings_mr.xtb
@@ -77,7 +77,7 @@ <translation id="4450893287417543264">पुन्हा दाखवू नका</translation> <translation id="4513946894732546136">फीडबॅक</translation> <translation id="4563926062592110512">डिस्कनेक्ट केलेला क्लायंट: <ph name="CLIENT_USERNAME" />.</translation> -<translation id="4618411825115957973"><ph name="URL_FORWARDER_NAME" /> योग्यरीत्या कॉंफिगर केलेला नाही. कृपया वेगळा डीफॉल्ट वेब ब्राउझर निवडा आणि त्यानंतर URL फॉरवर्ड करणे पुन्हा सुरू करा.</translation> +<translation id="4618411825115957973"><ph name="URL_FORWARDER_NAME" /> योग्यरीत्या कॉन्फिगर केलेला नाही. कृपया वेगळा डीफॉल्ट वेब ब्राउझर निवडा आणि त्यानंतर URL फॉरवर्ड करणे पुन्हा सुरू करा.</translation> <translation id="4635770493235256822">रिमोट डिव्हाइस</translation> <translation id="4660011489602794167">कीबोर्ड दाखवा</translation> <translation id="4703799847237267011">तुमचे Chromoting सेशन समाप्त झाले.</translation> @@ -171,7 +171,7 @@ '<ph name="SERVICE_SCRIPT_NAME" />' वर आधीच खूण केलेली असल्यास, ती काढा आणि त्यावर पुन्हा खूण करा.</translation> <translation id="8305209735512572429">वेब ऑथेंटिकेशन रिमोटिंगची प्रक्रिया</translation> <translation id="8383794970363966105">Chromoting वापरण्यासाठी, तुम्हाला आपल्या डिव्हाइसमध्ये एक Google खाते जोडणे आवश्यक असेल.</translation> -<translation id="8386846956409881180">अवैध OAuth क्रेडेंशियलसह होस्ट कॉंफिगर केला आहे.</translation> +<translation id="8386846956409881180">अवैध OAuth क्रेडेंशियलसह होस्ट कॉन्फिगर केला आहे.</translation> <translation id="8397385476380433240"><ph name="PRODUCT_NAME" /> ला परवानगी द्या</translation> <translation id="8406498562923498210">तुमच्या Chrome रिमोट डेस्कटॉप वातावरणात लाँच करण्यासाठी सेशन निवडा. (लक्षात घ्या की काही सेशन प्रकार Chrome रिमोट डेस्कटॉप आणि लोकल कन्सोलवर एकाच वेळी रन होण्यास कदाचित सपोर्ट करणार नाहीत.)</translation> <translation id="8428213095426709021">सेटिंग्ज</translation>
diff --git a/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc b/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc index 64b149d..57d56551 100644 --- a/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc +++ b/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
@@ -257,9 +257,11 @@ options->paths_to_clone.push_back( base::FilePath(base::kPackageRootDirectoryPath)); - // If /config/data/tzdata/icu/ exists then it contains up-to-date timezone + // If /config/tzdata/icu/ exists then it contains up-to-date timezone // data which should be provided to all sub-processes, for consistency. - const auto kIcuTimezoneDataPath = base::FilePath("/config/data/tzdata/icu"); + // LINT.IfChange(icu_time_zone_data_path) + const auto kIcuTimezoneDataPath = base::FilePath("/config/tzdata/icu"); + // LINT.ThenChange(//base/i18n/icu_util.cc:icu_time_zone_data_path) static bool icu_timezone_data_exists = base::PathExists(kIcuTimezoneDataPath); if (icu_timezone_data_exists) { options->paths_to_clone.push_back(kIcuTimezoneDataPath);
diff --git a/services/network/attribution/attribution_request_helper_unittest.cc b/services/network/attribution/attribution_request_helper_unittest.cc index 478ace65..a7274a4 100644 --- a/services/network/attribution/attribution_request_helper_unittest.cc +++ b/services/network/attribution/attribution_request_helper_unittest.cc
@@ -199,7 +199,7 @@ request->extra_request_headers().GetHeader( AttributionVerificationMediator::kReportVerificationHeader, &blind_messages_header); - std::vector<const std::string> blinded_messages = + const std::vector<std::string> blinded_messages = DeserializeStructuredHeaderListOfStrings(blind_messages_header); std::string expected_origin = "https://origin.example"; for (const auto& blinded_message : blinded_messages) {
diff --git a/services/network/attribution/attribution_test_utils.cc b/services/network/attribution/attribution_test_utils.cc index 444ec5e..bf469bb 100644 --- a/services/network/attribution/attribution_test_utils.cc +++ b/services/network/attribution/attribution_test_utils.cc
@@ -179,7 +179,7 @@ std::make_unique<AttributionVerificationMediatorMetricsRecorder>()); } -std::vector<const std::string> DeserializeStructuredHeaderListOfStrings( +std::vector<std::string> DeserializeStructuredHeaderListOfStrings( std::string_view header) { std::optional<net::structured_headers::List> parsed_list = net::structured_headers::ParseList(header); @@ -187,7 +187,7 @@ return {}; } - std::vector<const std::string> strings; + std::vector<std::string> strings; strings.reserve(parsed_list->size()); for (const auto& item : parsed_list.value()) { if (item.member_is_inner_list || item.member.size() != 1u ||
diff --git a/services/network/attribution/attribution_test_utils.h b/services/network/attribution/attribution_test_utils.h index f275297..a48436e 100644 --- a/services/network/attribution/attribution_test_utils.h +++ b/services/network/attribution/attribution_test_utils.h
@@ -116,7 +116,7 @@ std::string SerializeStructureHeaderListOfStrings( const std::vector<std::string>& strings); -std::vector<const std::string> DeserializeStructuredHeaderListOfStrings( +std::vector<std::string> DeserializeStructuredHeaderListOfStrings( std::string_view header); } // namespace network
diff --git a/services/network/attribution/attribution_verification_mediator_unittest.cc b/services/network/attribution/attribution_verification_mediator_unittest.cc index cc6b9db7..14071c1 100644 --- a/services/network/attribution/attribution_verification_mediator_unittest.cc +++ b/services/network/attribution/attribution_verification_mediator_unittest.cc
@@ -137,7 +137,7 @@ std::string verification_header; headers.GetHeader("Sec-Attribution-Reporting-Private-State-Token", &verification_header); - std::vector<const std::string> verification_headers = + const std::vector<std::string> verification_headers = DeserializeStructuredHeaderListOfStrings(verification_header); // Check that the message was blinded by the Cryptographer before being added ASSERT_EQ(verification_headers.size(), 1u);
diff --git a/testing/buildbot/chrome.gpu.fyi.json b/testing/buildbot/chrome.gpu.fyi.json index f67afbc..a93a4367 100644 --- a/testing/buildbot/chrome.gpu.fyi.json +++ b/testing/buildbot/chrome.gpu.fyi.json
@@ -20,7 +20,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", "name": "context_lost_passthrough_tests JACUZZI_RELEASE_LKGM", "resultdb": { @@ -50,7 +49,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", "name": "expected_color_pixel_passthrough_test JACUZZI_RELEASE_LKGM", "precommit_args": [ @@ -80,7 +78,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc", "name": "gpu_process_launch_tests JACUZZI_RELEASE_LKGM", "resultdb": { @@ -105,7 +102,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc", "name": "hardware_accelerated_feature_tests JACUZZI_RELEASE_LKGM", "resultdb": { @@ -134,7 +130,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc --force_high_performance_gpu", "name": "info_collection_tests JACUZZI_RELEASE_LKGM", "resultdb": { @@ -165,7 +160,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", "name": "pixel_skia_gold_passthrough_test JACUZZI_RELEASE_LKGM", "precommit_args": [ @@ -196,7 +190,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", "name": "screenshot_sync_passthrough_tests JACUZZI_RELEASE_LKGM", "resultdb": { @@ -222,7 +215,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc", "name": "trace_test JACUZZI_RELEASE_LKGM", "resultdb": { @@ -248,7 +240,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc", "name": "webcodecs_tests JACUZZI_RELEASE_LKGM", "resultdb": { @@ -276,7 +267,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc --use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu", "name": "webgl2_conformance_gles_passthrough_tests JACUZZI_RELEASE_LKGM", "resultdb": { @@ -304,7 +294,6 @@ ], "autotest_name": "chromium_Graphics", "cros_board": "jacuzzi", - "dut_pool": "chrome", "extra_browser_args": "--log-level=0 --js-flags=--expose-gc --use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu", "name": "webgl_conformance_gles_passthrough_tests JACUZZI_RELEASE_LKGM", "resultdb": {
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index 748c051..553b00c1 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -1677,7 +1677,6 @@ { "autotest_name": "chromium", "cros_board": "jacuzzi", - "dut_pool": "chrome", "name": "base_unittests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", @@ -1687,7 +1686,6 @@ { "autotest_name": "tast.chrome-from-gcs", "cros_board": "jacuzzi", - "dut_pool": "chrome", "name": "chrome_all_tast_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 20, "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", @@ -1702,7 +1700,6 @@ "autotest_name": "tast.chrome-from-gcs", "ci_only": true, "cros_board": "jacuzzi", - "dut_pool": "chrome", "experiment_percentage": 100, "name": "chrome_criticalstaging_tast_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 3, @@ -1718,7 +1715,6 @@ "autotest_name": "tast.chrome-from-gcs", "ci_only": true, "cros_board": "jacuzzi", - "dut_pool": "chrome", "experiment_percentage": 100, "name": "chrome_disabled_tast_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 2, @@ -1733,7 +1729,6 @@ { "autotest_name": "chromium", "cros_board": "jacuzzi", - "dut_pool": "chrome", "name": "chromeos_integration_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "test": "chromeos_integration_tests", "test_id_prefix": "ninja://chrome/test:chromeos_integration_tests/", @@ -1758,7 +1753,6 @@ "autotest_name": "chromium", "cros_board": "octopus", "cros_model": "casta", - "dut_pool": "chrome", "name": "base_unittests OCTOPUS_RELEASE_CHROME_FROM_TLS_LKGM", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", @@ -1769,7 +1763,6 @@ "autotest_name": "tast.chrome-from-gcs", "cros_board": "octopus", "cros_model": "casta", - "dut_pool": "chrome", "name": "chrome_all_tast_tests OCTOPUS_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 15, "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", @@ -1878,7 +1871,6 @@ { "autotest_name": "chromium", "cros_board": "volteer", - "dut_pool": "chrome", "name": "base_unittests VOLTEER_RELEASE_LKGM", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", @@ -1888,7 +1880,6 @@ { "autotest_name": "tast.chrome-from-gcs", "cros_board": "volteer", - "dut_pool": "chrome", "name": "chrome_all_tast_tests VOLTEER_RELEASE_LKGM", "shards": 15, "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", @@ -1903,7 +1894,6 @@ "autotest_name": "tast.chrome-from-gcs", "ci_only": true, "cros_board": "volteer", - "dut_pool": "chrome", "experiment_percentage": 100, "name": "chrome_criticalstaging_tast_tests VOLTEER_RELEASE_LKGM", "shards": 3, @@ -1919,7 +1909,6 @@ "autotest_name": "tast.chrome-from-gcs", "ci_only": true, "cros_board": "volteer", - "dut_pool": "chrome", "experiment_percentage": 100, "name": "chrome_disabled_tast_tests VOLTEER_RELEASE_LKGM", "shards": 2, @@ -1934,7 +1923,6 @@ { "autotest_name": "chromium", "cros_board": "volteer", - "dut_pool": "chrome", "name": "chromeos_integration_tests VOLTEER_RELEASE_LKGM", "test": "chromeos_integration_tests", "test_id_prefix": "ninja://chrome/test:chromeos_integration_tests/", @@ -2486,7 +2474,6 @@ { "autotest_name": "chromium", "cros_board": "strongbad", - "dut_pool": "chrome", "name": "chromeos_integration_tests STRONGBAD_RELEASE_LKGM", "test": "chromeos_integration_tests", "test_id_prefix": "ninja://chrome/test:chromeos_integration_tests/", @@ -2496,7 +2483,6 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "strongbad", - "dut_pool": "chrome", "name": "lacros_all_tast_tests STRONGBAD_RELEASE_LKGM", "resultdb": { "enable": true,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index f04d7bf..64bd0d48 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -1385,7 +1385,6 @@ "bucket": "chromiumos-image-archive", "cros_board": "trogdor", "cros_img": "trogdor-public/R123-15763.0.0", - "dut_pool": "chromium", "name": "chromeos_integration_tests TROGDOR_PUBLIC_LKGM", "test": "chromeos_integration_tests", "test_id_prefix": "ninja://chrome/test:chromeos_integration_tests/", @@ -1396,7 +1395,6 @@ "bucket": "chromiumos-image-archive", "cros_board": "trogdor", "cros_img": "trogdor-public/R123-15763.0.0", - "dut_pool": "chromium", "name": "lacros_all_tast_tests TROGDOR_PUBLIC_LKGM", "resultdb": { "enable": true, @@ -2964,6 +2962,7 @@ "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" }, { + "ci_only": true, "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 366e2a1..d907017 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -4652,7 +4652,6 @@ "autotest_name": "tast.chrome-from-gcs", "bucket": "chromiumos-image-archive", "cros_board": "jacuzzi", - "dut_pool": "chromium", "name": "chrome_all_tast_tests JACUZZI_CQ_PUBLIC_LKGM", "public_builder": "cros_test_platform_public", "public_builder_bucket": "testplatform-public", @@ -4670,7 +4669,6 @@ "bucket": "chromiumos-image-archive", "ci_only": true, "cros_board": "jacuzzi", - "dut_pool": "chromium", "experiment_percentage": 100, "name": "chrome_criticalstaging_tast_tests JACUZZI_CQ_PUBLIC_LKGM", "public_builder": "cros_test_platform_public", @@ -4689,7 +4687,6 @@ "bucket": "chromiumos-image-archive", "ci_only": true, "cros_board": "jacuzzi", - "dut_pool": "chromium", "experiment_percentage": 100, "name": "chrome_disabled_tast_tests JACUZZI_CQ_PUBLIC_LKGM", "public_builder": "cros_test_platform_public", @@ -4714,7 +4711,6 @@ "autotest_name": "tast.chrome-from-gcs", "bucket": "chromiumos-image-archive", "cros_board": "octopus", - "dut_pool": "chromium", "name": "chrome_all_tast_tests OCTOPUS_PUBLIC_LKGM", "shards": 15, "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS",
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 9dd26411..37a24e2 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -18834,7 +18834,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", "--enforce-browser-version", - "--jobs=4" + "--jobs=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" @@ -19031,8 +19031,8 @@ "--dont-restore-color-profile-after-test", "--test-machine-name", "${buildername}", - "--jobs=4", - "--git-revision=${got_revision}" + "--git-revision=${got_revision}", + "--jobs=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" @@ -19111,7 +19111,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--enforce-browser-version", - "--jobs=4" + "--jobs=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" @@ -19148,7 +19148,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--enforce-browser-version", - "--jobs=4" + "--jobs=2" ], "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/testing/buildbot/filters/win.win_arm64.services_webnn_unittests.filter b/testing/buildbot/filters/win.win_arm64.services_webnn_unittests.filter index 47d87b9..8e81094 100644 --- a/testing/buildbot/filters/win.win_arm64.services_webnn_unittests.filter +++ b/testing/buildbot/filters/win.win_arm64.services_webnn_unittests.filter
@@ -1,5 +1,6 @@ # crbug.com/1522972 -WebNNCommandRecorderTest.InitializeAndExecuteConvolutionOperator +-WebNNCommandRecorderTest.InitializeAndExecuteConvolutionOperatorWithCustomBuffers -WebNNGraphBuilderTest.BuildGraphWithReluAndConv2d -WebNNGraphBuilderTest.BuildSingleOperatorConv2d -WebNNGraphDMLImplTest.BuildAndComputeMultipleOperatorGemm @@ -20,4 +21,4 @@ -WebNNGraphDMLImplTest.BuildSingleOperatorBatchNormalization -WebNNGraphDMLImplTest.BuildSingleOperatorGemm -WebNNGraphDMLImplTest.BuildSingleOperatorInstanceNormalization --WebNNGraphDMLImplTest.BuildSingleOperatorLayerNormalization \ No newline at end of file +-WebNNGraphDMLImplTest.BuildSingleOperatorLayerNormalization
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json index 2195e1a..717eaecd 100644 --- a/testing/buildbot/internal.chromeos.fyi.json +++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1525,7 +1525,6 @@ { "autotest_name": "chromium", "cros_board": "jacuzzi", - "dut_pool": "chrome", "name": "base_unittests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", @@ -1535,7 +1534,6 @@ { "autotest_name": "tast.chrome-from-gcs", "cros_board": "jacuzzi", - "dut_pool": "chrome", "name": "chrome_all_tast_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 20, "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", @@ -1550,7 +1548,6 @@ "autotest_name": "tast.chrome-from-gcs", "ci_only": true, "cros_board": "jacuzzi", - "dut_pool": "chrome", "experiment_percentage": 100, "name": "chrome_criticalstaging_tast_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 3, @@ -1566,7 +1563,6 @@ "autotest_name": "tast.chrome-from-gcs", "ci_only": true, "cros_board": "jacuzzi", - "dut_pool": "chrome", "experiment_percentage": 100, "name": "chrome_disabled_tast_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 2, @@ -1581,7 +1577,6 @@ { "autotest_name": "chromium", "cros_board": "jacuzzi", - "dut_pool": "chrome", "name": "chromeos_integration_tests JACUZZI_RELEASE_CHROME_FROM_TLS_LKGM", "test": "chromeos_integration_tests", "test_id_prefix": "ninja://chrome/test:chromeos_integration_tests/", @@ -1601,7 +1596,6 @@ "autotest_name": "chromium", "cros_board": "octopus", "cros_model": "casta", - "dut_pool": "chrome", "name": "base_unittests OCTOPUS_RELEASE_CHROME_FROM_TLS_LKGM", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", @@ -1612,7 +1606,6 @@ "autotest_name": "tast.chrome-from-gcs", "cros_board": "octopus", "cros_model": "casta", - "dut_pool": "chrome", "name": "chrome_all_tast_tests OCTOPUS_RELEASE_CHROME_FROM_TLS_LKGM", "shards": 15, "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", @@ -1637,7 +1630,6 @@ { "autotest_name": "chromium", "cros_board": "trogdor", - "dut_pool": "chrome", "name": "base_unittests TROGDOR_RELEASE_LKGM", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", @@ -1647,7 +1639,6 @@ { "autotest_name": "tast.chrome-from-gcs", "cros_board": "trogdor", - "dut_pool": "chrome", "name": "chrome_all_tast_tests TROGDOR_RELEASE_LKGM", "shards": 20, "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", @@ -1661,7 +1652,6 @@ { "autotest_name": "chromium", "cros_board": "trogdor", - "dut_pool": "chrome", "name": "chromeos_integration_tests TROGDOR_RELEASE_LKGM", "test": "chromeos_integration_tests", "test_id_prefix": "ninja://chrome/test:chromeos_integration_tests/",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 8449bed..31a6e9a5 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -205,6 +205,11 @@ '--gtest_filter=-ConstructCompilerTest.DefaultParameters', ], }, + 'linux-chromeos-rel': { + # b/41493162: angle_unittests has a high failure rate. + # Re-enable cq when the issue is fixed. + 'ci_only': True, + }, }, }, 'ash_crosapi_tests': { @@ -2290,6 +2295,13 @@ }, 'context_lost_passthrough_tests': { 'modifications': { + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': [ + # TODO(crbug.com/41496675): Apply this via magic subustitutions if it + # helps with stability. + '--jobs=2', + ], + }, 'Win11 FYI arm64 Release (Qualcomm Adreno 690)': { 'args': [ # These devices have issues running these tests in parallel. @@ -2298,6 +2310,13 @@ }, }, 'replacements': { + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': { + # Magic substitution happens after regular replacement, so remove it + # now since we are manually applying the number of jobs above. + '$$MAGIC_SUBSTITUTION_GPUParallelJobs': None, + }, + }, 'Win11 FYI arm64 Release (Qualcomm Adreno 690)': { 'args': { # Magic substitution happens after regular replacement, so remove it @@ -3843,6 +3862,13 @@ '--extra-browser-args=--disable-wcg-for-test', ], }, + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': [ + # TODO(crbug.com/41496675): Apply this via magic subustitutions if it + # helps with stability. + '--jobs=2', + ], + }, 'android_optional_gpu_tests_rel': { 'args': [ # See above. @@ -3868,6 +3894,13 @@ '--git-revision': '${got_cr_revision}', }, }, + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': { + # Magic substitution happens after regular replacement, so remove it + # now since we are manually applying the number of jobs above. + '$$MAGIC_SUBSTITUTION_GPUParallelJobs': None, + }, + }, }, }, 'pixel_skia_gold_passthrough_test JACUZZI_RELEASE_LKGM': { @@ -4413,6 +4446,22 @@ 'shards': 2, }, }, + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': [ + # TODO(crbug.com/41496675): Apply this via magic subustitutions if it + # helps with stability. + '--jobs=2', + ], + }, + }, + 'replacements': { + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': { + # Magic substitution happens after regular replacement, so remove it + # now since we are manually applying the number of jobs above. + '$$MAGIC_SUBSTITUTION_GPUParallelJobs': None, + }, + }, }, 'remove_from': [ # crbug.com/1458020 for Mac Retina ASAN removal @@ -4704,6 +4753,26 @@ 'Mac FYI Retina ASAN (AMD)', ], }, + 'webcodecs_tests': { + 'modifications': { + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': [ + # TODO(crbug.com/41496675): Apply this via magic subustitutions if it + # helps with stability. + '--jobs=2', + ], + }, + }, + 'replacements': { + 'Win10 FYI x64 Experimental Release (Intel)': { + 'args': { + # Magic substitution happens after regular replacement, so remove it + # now since we are manually applying the number of jobs above. + '$$MAGIC_SUBSTITUTION_GPUParallelJobs': None, + }, + }, + }, + }, 'webdriver_wpt_tests': { 'modifications': { 'Linux Tests (dbg)(1)': {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 00e161f5..323be4d 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -121,7 +121,6 @@ 'cros_board': 'jacuzzi', 'use_lkgm': True, 'bucket': 'chromiumos-image-archive', - 'dut_pool': 'chromium', 'public_builder': 'cros_test_platform_public', 'public_builder_bucket': 'testplatform-public', }, @@ -131,7 +130,6 @@ 'skylab': { 'cros_board': 'jacuzzi', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_JACUZZI_RELEASE_LKGM': { @@ -139,7 +137,6 @@ 'skylab': { 'cros_board': 'jacuzzi', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_OCTOPUS_PUBLIC_LKGM': { @@ -148,7 +145,6 @@ 'cros_board': 'octopus', 'use_lkgm': True, 'bucket': 'chromiumos-image-archive', - 'dut_pool': 'chromium', }, }, 'CROS_OCTOPUS_RELEASE_CHROME_FROM_TLS_ASH_LKGM': { @@ -157,7 +153,6 @@ 'cros_board': 'octopus', 'cros_model': 'casta', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_PUFF_RELEASE_BETA': { @@ -197,7 +192,6 @@ 'skylab': { 'cros_board': 'strongbad', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_TROGDOR_PUBLIC_LKGM': { @@ -206,7 +200,6 @@ 'cros_board': 'trogdor', 'cros_img': 'trogdor-public/R123-15763.0.0', 'bucket': 'chromiumos-image-archive', - 'dut_pool': 'chromium', }, }, 'CROS_TROGDOR_RELEASE_ASH_LKGM': { @@ -214,7 +207,6 @@ 'skylab': { 'cros_board': 'trogdor', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'CROS_VOLTEER_PUBLIC_LKGM': { @@ -246,7 +238,6 @@ 'skylab': { 'cros_board': 'volteer', 'use_lkgm': True, - 'dut_pool': 'chrome', }, }, 'DISABLE_FIELD_TRIAL_CONFIG': {
diff --git a/testing/iossim/iossim.mm b/testing/iossim/iossim.mm index 384da81..7e5fbe37 100644 --- a/testing/iossim/iossim.mm +++ b/testing/iossim/iossim.mm
@@ -410,8 +410,10 @@ NSMutableArray* cmd_args, NSMutableArray* tests_filter, bool verbose) { - NSString* tempFilePath = [NSTemporaryDirectory() - stringByAppendingPathComponent:NSUUID.UUID.UUIDString]; + NSString* filename = + [NSUUID.UUID.UUIDString stringByAppendingString:@".xctestrun"]; + NSString* tempFilePath = + [NSTemporaryDirectory() stringByAppendingPathComponent:filename]; [NSFileManager.defaultManager createFileAtPath:tempFilePath contents:nil attributes:nil];
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9356053..b7e2c92 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -4540,6 +4540,28 @@ ] } ], + "ContentSettingsIndex": [ + { + "platforms": [ + "android", + "android_webview", + "chromeos", + "chromeos_lacros", + "fuchsia", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled_20240205", + "enable_features": [ + "IndexedHostContentSettingsMap" + ] + } + ] + } + ], "CookieAccessDetailsNotificationDeDuping": [ { "platforms": [ @@ -10018,28 +10040,6 @@ ] } ], - "IndexedHostContentSettingsMap": [ - { - "platforms": [ - "android", - "android_webview", - "chromeos", - "chromeos_lacros", - "fuchsia", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled_20240112", - "enable_features": [ - "IndexedHostContentSettingsMap" - ] - } - ] - } - ], "InputDeviceSettingsSplit": [ { "platforms": [ @@ -15126,21 +15126,6 @@ ] } ], - "QuickDeleteForAndroid": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "QuickDeleteForAndroid" - ] - } - ] - } - ], "QuotaDatabaseDisableFullFSync": [ { "platforms": [ @@ -17642,21 +17627,6 @@ ] } ], - "ShutdownConfirmationBubble": [ - { - "platforms": [ - "chromeos" - ], - "experiments": [ - { - "name": "Enabled_20220923", - "enable_features": [ - "ShutdownConfirmationBubble" - ] - } - ] - } - ], "SidePanelCompanionDesktopM116Plus": [ { "platforms": [
diff --git a/third_party/abseil-cpp/symbols_arm64_dbg.def b/third_party/abseil-cpp/symbols_arm64_dbg.def index 879a8c16..8bf75ce 100644 --- a/third_party/abseil-cpp/symbols_arm64_dbg.def +++ b/third_party/abseil-cpp/symbols_arm64_dbg.def
@@ -254,13 +254,6 @@ ??$?0V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ??$?0V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@FormatArgImpl@str_format_internal@absl@@QEAA@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$?0V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XV012@$0A@@?$Span@$$CBD@absl@@QEAA@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z - ??$?0V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@12@0@Z ??$?0VBufferRawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVBufferRawSink@12@@Z ??$?0VFILERawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVFILERawSink@12@@Z ??$?0VFallbackCrcMemcpyEngine@crc_internal@absl@@$0A@@?$default_delete@VCrcMemcpyEngine@crc_internal@absl@@@__Cr@std@@QEAA@AEBU?$default_delete@VFallbackCrcMemcpyEngine@crc_internal@absl@@@12@@Z @@ -297,15 +290,8 @@ ??$?8V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@__Cr@std@@YA_NAEBV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@$$T@Z ??$?8VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YA_NAEBV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@01@$$T@Z ??$?9PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$?9PEAPEAVCordzHandle@cord_internal@absl@@PEAPEAV012@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z ??$?9PEAPEAVLogSink@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@0@Z - ??$?9PEAPEAVLogSink@absl@@PEAPEAV01@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@0@Z - ??$?9PEAPEBVCordzHandle@cord_internal@absl@@PEAPEBV012@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$?9PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@PEAU0123@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$?9PEAUTransition@cctz@time_internal@absl@@PEAU0123@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z ??$?9PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$?9PEAUTransitionType@cctz@time_internal@absl@@PEAU0123@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$?9PEAUViableSubstitution@strings_internal@absl@@PEAU012@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$?9PEBQEAVLogSink@absl@@PEAPEAV01@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEBQEAVLogSink@absl@@@01@AEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@@Z ??$?9PEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z ??$?DH@absl@@YA?AVDuration@0@HV10@@Z @@ -354,13 +340,6 @@ ??$?RUTransitionType@cctz@time_internal@absl@@U0123@$0A@@__move_backward_trivial@__Cr@std@@QEBA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@12@PEAUTransitionType@cctz@time_internal@absl@@00@Z ??$?RUTransitionType@cctz@time_internal@absl@@U0123@$0A@@__move_trivial@__Cr@std@@QEBA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@12@PEAUTransitionType@cctz@time_internal@absl@@00@Z ??$?RV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@$0A@@?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@12@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@@Z - ??$?RV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAPEAVLogSink@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@12@00@Z ??$?RVDuration@absl@@V01@@?$__less@XX@__Cr@std@@QEBA_NAEBVDuration@absl@@0@Z ??$?RW4LogSeverity@absl@@AEBQEBDHAEAPEBD@?$AtomicHook@P6AXW4LogSeverity@absl@@PEBDHAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z@base_internal@absl@@QEBAX$$QEAW4LogSeverity@2@AEBQEBD$$QEAHAEAPEBD@Z ??$?RW4LogSeverity@absl@@AEBQEBDHAEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$AtomicHook@P6AXW4LogSeverity@absl@@PEBDHAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z@base_internal@absl@@QEBAX$$QEAW4LogSeverity@2@AEBQEBD$$QEAHAEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z @@ -852,13 +831,6 @@ ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PEAPEAVLogSink@absl@@PEAPEAV67@PEAPEAV67@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PEAUTransition@cctz@time_internal@absl@@PEAU6789@PEAU6789@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PEAUTransitionType@cctz@time_internal@absl@@PEAU6789@PEAU6789@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__distance@PEBUPayload@status_internal@absl@@@__Cr@std@@YA_JPEBUPayload@status_internal@absl@@0Urandom_access_iterator_tag@01@@Z ??$__distance@PEBUTransition@cctz@time_internal@absl@@@__Cr@std@@YA_JPEBUTransition@cctz@time_internal@absl@@0Urandom_access_iterator_tag@01@@Z ??$__distance@PEBVFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YA_JPEBVFormatArgImpl@str_format_internal@absl@@0Urandom_access_iterator_tag@01@@Z @@ -877,13 +849,6 @@ ??$__invoke@AEAUByUnixTime@Transition@cctz@time_internal@absl@@AEBU2345@AEBU2345@@__Cr@std@@YA_NAEAUByUnixTime@Transition@cctz@time_internal@absl@@AEBU3456@1@Z ??$__invoke@AEAU__identity@__Cr@std@@AEAPEAVLogSink@absl@@@__Cr@std@@YAAEAPEAVLogSink@absl@@AEAU__identity@01@AEAPEAV23@@Z ??$__invoke@AEAU__identity@__Cr@std@@AEBUTransition@cctz@time_internal@absl@@@__Cr@std@@YAAEBUTransition@cctz@time_internal@absl@@AEAU__identity@01@AEBU2345@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEAVCordzHandle@cord_internal@absl@@AEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEAVLogSink@absl@@AEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEBVCordzHandle@cord_internal@absl@@AEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@AEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUTransition@cctz@time_internal@absl@@AEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUTransitionType@cctz@time_internal@absl@@AEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUViableSubstitution@strings_internal@absl@@AEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@12@@Z ??$__launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z ??$__launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z ??$__launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAURefcountedRep@CrcCordState@crc_internal@absl@@PEAU2345@@Z @@ -895,13 +860,6 @@ ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAVLogSink@absl@@PEAPEAV45@PEAPEAV45@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV45678@PEAPEAPEBV45678@@__Cr@std@@YA?AU?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@01@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@PEAPEAU4567@@__Cr@std@@YA?AU?$pair@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@01@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z @@ -923,13 +881,6 @@ ??$__rewrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@V201@0@Z ??$__rewrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@V201@0@Z ??$__rewrap_iter@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@PEAPEAVLogSink@absl@@U?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@23@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@V201@PEAPEAVLogSink@absl@@@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@0@Z ??$__rewrap_range@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@PEAPEAPEBV12345@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@0@Z ??$__rewrap_range@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@PEAPEAU1234@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@0@Z ??$__rewrap_range@PEAPEAVLogSink@absl@@PEAPEAV12@PEAPEAV12@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0@Z @@ -937,13 +888,6 @@ ??$__rewrap_range@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@PEAU1234@@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@0@Z ??$__rewrap_range@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@PEBU1234@@__Cr@std@@YAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU2345@0@Z ??$__rewrap_range@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@0@Z ??$__to_address@$$CBUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU2345@@Z ??$__to_address@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z ??$__to_address@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@@Z @@ -956,15 +900,13 @@ ??$__to_address@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@@Z ??$__to_address@UViableSubstitution@strings_internal@absl@@@__Cr@std@@YAPEAUViableSubstitution@strings_internal@absl@@PEAU234@@Z ??$__to_address@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@X@__Cr@std@@YAPEAPEAVLogSink@absl@@AEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@PEAVCordzHandle@cord_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@AEAV?$allocator@PEAVCordzHandle@cord_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@PEAVLogSink@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@AEAV?$allocator@PEAVLogSink@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@PEBVCordzHandle@cord_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@AEAV?$allocator@PEBVCordzHandle@cord_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@UConversionItem@ParsedFormatBase@str_format_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@AEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@U4567@X@__Cr@std@@YAPEAUTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@01@PEAU2345@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@UTransition@cctz@time_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@U4567@X@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@PEAU2345@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@UTransitionType@cctz@time_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@UViableSubstitution@strings_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@V201@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@PEAVCordzHandle@cord_internal@absl@@@01@PEAPEAVCordzHandle@cord_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@PEAVLogSink@absl@@@__Cr@std@@YAXAEAV?$allocator@PEAVLogSink@absl@@@01@PEAPEAVLogSink@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@PEBVCordzHandle@cord_internal@absl@@@01@PEAPEBVCordzHandle@cord_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@UTransition@cctz@time_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@01@PEAUTransition@cctz@time_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@PEAUTransitionType@cctz@time_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@UViableSubstitution@strings_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@PEAUViableSubstitution@strings_internal@absl@@11@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU4567@PEAU4567@$0A@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0PEAU3456@@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU4567@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@$0A@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@V423@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@$0A@@__Cr@std@@YA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@01@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z @@ -977,13 +919,6 @@ ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PEAPEAVLogSink@absl@@PEAPEAV45@PEAPEAV45@$0A@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@PEAU4567@$0A@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@PEAU4567@$0A@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__unwrap_iter@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@U?$__unwrap_iter_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z ??$__unwrap_iter@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@U?$__unwrap_iter_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@@Z ??$__unwrap_iter@PEAPEAVLogSink@absl@@U?$__unwrap_iter_impl@PEAPEAVLogSink@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@@Z @@ -994,13 +929,6 @@ ??$__unwrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@V201@@Z ??$__unwrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@V201@@Z ??$__unwrap_iter@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@23@$0A@@__Cr@std@@YAPEAPEAVLogSink@absl@@V?$__wrap_iter@PEAPEAVLogSink@absl@@@01@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@@Z ??$__unwrap_range@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@YA?A?<auto>@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ??$__unwrap_range@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@YA?A?<auto>@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ??$__unwrap_range@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@YA?A?<auto>@@PEAPEAVLogSink@absl@@0@Z @@ -1008,22 +936,8 @@ ??$__unwrap_range@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YA?A?<auto>@@PEAUTransitionType@cctz@time_internal@absl@@0@Z ??$__unwrap_range@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@@__Cr@std@@YA?A?<auto>@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ??$__unwrap_range@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByCivilTime@Transition@cctz@time_internal@absl@@PEBU5678@PEBU5678@U5678@U__identity@23@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@$$QEAUByCivilTime@2345@$$QEAU__identity@01@@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByUnixTime@Transition@cctz@time_internal@absl@@PEBU5678@PEBU5678@U5678@U__identity@23@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@$$QEAUByUnixTime@2345@$$QEAU__identity@01@@Z - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ ??$advance@PEBUTransition@cctz@time_internal@absl@@_J@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXAEAPEBUTransition@cctz@time_internal@absl@@_J@Z ??$advance@PEBUTransition@cctz@time_internal@absl@@_J_JX@__Cr@std@@YAXAEAPEBUTransition@cctz@time_internal@absl@@_J@Z ??$assign@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0@Z @@ -1195,13 +1109,6 @@ ??$make_pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@01@$$QEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QEAPEAU3456@@Z ??$make_pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@01@$$QEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z ??$make_pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@__Cr@std@@YA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@01@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z - ??$make_pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$make_unique@ULogMessageData@LogMessage@log_internal@absl@@AEAPEBDAEAHAEAW4LogSeverity@4@VTime@4@@__Cr@std@@YA?AV?$unique_ptr@ULogMessageData@LogMessage@log_internal@absl@@U?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@@01@AEAPEBDAEAHAEAW4LogSeverity@absl@@$$QEAVTime@4@@Z ??$make_unique@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@$$V@__Cr@std@@YA?AV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@XZ ??$make_unique@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@AEAV12@@__Cr@std@@YA?AV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@AEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@Z @@ -1234,13 +1141,6 @@ ??$move@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@00@Z ??$move@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z ??$move@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z - ??$move@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@00@Z ??$move_backward@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z ??$move_backward@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@00@Z ??$move_backward@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z @@ -1493,13 +1393,6 @@ ??0?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAA@PEAUTransitionType@cctz@time_internal@absl@@@Z ??0?$optional@VCord@absl@@@__Cr@std@@QEAA@Unullopt_t@12@@Z ??0?$probe_seq@$07@container_internal@absl@@QEAA@_K0@Z - ??0?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAA@PEAPEAVCordzHandle@cord_internal@absl@@@Z - ??0?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEAA@PEAPEAVLogSink@absl@@@Z - ??0?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAA@PEAPEBVCordzHandle@cord_internal@absl@@@Z - ??0?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAA@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z - ??0?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEAA@PEAUTransition@cctz@time_internal@absl@@@Z - ??0?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAA@PEAUTransitionType@cctz@time_internal@absl@@@Z - ??0?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEAA@PEAUViableSubstitution@strings_internal@absl@@@Z ??0?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@__Cr@std@@QEAA@$$QEAV012@@Z ??0?$unordered_map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QEAA@XZ ??0?$unordered_set@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA@XZ @@ -1980,13 +1873,6 @@ ??D?$move_iterator@PEAUPayload@status_internal@absl@@@__Cr@std@@QEBA$$QEAUPayload@status_internal@absl@@XZ ??D?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEBA$$QEAUTransition@cctz@time_internal@absl@@XZ ??D?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEBA$$QEAUTransitionType@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAAEAPEAVCordzHandle@cord_internal@absl@@XZ - ??D?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEBAAEAPEAVLogSink@absl@@XZ - ??D?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAAEAPEBVCordzHandle@cord_internal@absl@@XZ - ??D?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEBAAEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ - ??D?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEBAAEAUTransition@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEBAAEAUTransitionType@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEBAAEAUViableSubstitution@strings_internal@absl@@XZ ??D?$unique_ptr@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QEBAAEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@12@XZ ??D?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QEBAAEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@12@XZ ??D?$unique_ptr@ULogMessageData@LogMessage@log_internal@absl@@U?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@@__Cr@std@@QEBAAEAULogMessageData@LogMessage@log_internal@absl@@XZ @@ -2011,13 +1897,6 @@ ??E?$move_iterator@PEAUPayload@status_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ ??E?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ ??E?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ ??EChunkIterator@Cord@absl@@QEAAAEAV012@XZ ??E__deque_range@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAAEAU0123@XZ ??Euint128@absl@@QEAAAEAV01@XZ @@ -3847,13 +3726,6 @@ ?__rewrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@V423@0@Z ?__rewrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@V423@0@Z ?__rewrap@?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@__Cr@std@@SA?AV?$__wrap_iter@PEAPEAVLogSink@absl@@@23@V423@PEAPEAVLogSink@absl@@@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@0@Z ?__rewrap@?$__unwrap_range_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@SA?A?<auto>@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@SA?A?<auto>@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@SA?A?<auto>@@PEAPEAVLogSink@absl@@0@Z @@ -3861,13 +3733,6 @@ ?__rewrap@?$__unwrap_range_impl@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@SA?A?<auto>@@PEAUTransitionType@cctz@time_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@@__Cr@std@@SA?A?<auto>@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@0@Z ?__segment@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@Z ?__segment@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEBQEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@@Z ?__size@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAAEA_KXZ @@ -3900,13 +3765,6 @@ ?__unwrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@V423@@Z ?__unwrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@V423@@Z ?__unwrap@?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@__Cr@std@@SAPEAPEAVLogSink@absl@@V?$__wrap_iter@PEAPEAVLogSink@absl@@@23@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@@Z ?__unwrap@?$__unwrap_range_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@SA?A?<auto>@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@SA?A?<auto>@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@SA?A?<auto>@@PEAPEAVLogSink@absl@@0@Z @@ -3914,13 +3772,6 @@ ?__unwrap@?$__unwrap_range_impl@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@SA?A?<auto>@@PEAUTransitionType@cctz@time_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@@__Cr@std@@SA?A?<auto>@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@0@Z ?__upcast@?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@XZ ?__upcast@?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@XZ ?align@detail@cctz@time_internal@absl@@YA?AUfields@1234@Uday_tag@1234@U51234@@Z @@ -3998,13 +3849,6 @@ ?base@?$move_iterator@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEGBAAEBQEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?base@?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransition@cctz@time_internal@absl@@XZ ?base@?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransitionType@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAPEAPEAVCordzHandle@cord_internal@absl@@XZ - ?base@?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEBAPEAPEAVLogSink@absl@@XZ - ?base@?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAPEAPEBVCordzHandle@cord_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEBAPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEBAPEAUTransition@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEBAPEAUTransitionType@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEBAPEAUViableSubstitution@strings_internal@absl@@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ ?begin@?$Span@$$CBI@absl@@QEBAPEBIXZ
diff --git a/third_party/abseil-cpp/symbols_arm64_rel.def b/third_party/abseil-cpp/symbols_arm64_rel.def index 00de0dd..4020964 100644 --- a/third_party/abseil-cpp/symbols_arm64_rel.def +++ b/third_party/abseil-cpp/symbols_arm64_rel.def
@@ -169,9 +169,6 @@ ??$__emplace_unique_key_args@PEBUCordRep@cord_internal@absl@@AEBQEBU123@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@0@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z ??$__for_each_segment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@23@@__Cr@std@@YAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@01@@Z - ??$__push_back_slow_path@AEBQEAVCordzHandle@cord_internal@absl@@@?$vector@PEAVCordzHandle@cord_internal@absl@@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEAVCordzHandle@cord_internal@absl@@AEBQEAV345@@Z - ??$__push_back_slow_path@AEBQEAVLogSink@absl@@@?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEAVLogSink@absl@@AEBQEAV34@@Z - ??$__push_back_slow_path@AEBQEBVCordzHandle@cord_internal@absl@@@?$vector@PEBVCordzHandle@cord_internal@absl@@V?$allocator@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEBVCordzHandle@cord_internal@absl@@AEBQEBV345@@Z ??$__rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z ??$__rehash@$00@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@AEAAX_K@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByCivilTime@Transition@cctz@time_internal@absl@@PEBU5678@PEBU5678@U5678@U__identity@23@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@$$QEAUByCivilTime@2345@$$QEAU__identity@01@@Z
diff --git a/third_party/abseil-cpp/symbols_x64_dbg.def b/third_party/abseil-cpp/symbols_x64_dbg.def index 67d893f3..05a84e0 100644 --- a/third_party/abseil-cpp/symbols_x64_dbg.def +++ b/third_party/abseil-cpp/symbols_x64_dbg.def
@@ -254,13 +254,6 @@ ??$?0V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ??$?0V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@FormatArgImpl@str_format_internal@absl@@QEAA@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$?0V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XV012@$0A@@?$Span@$$CBD@absl@@QEAA@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z - ??$?0V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@12@0@Z ??$?0VBufferRawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVBufferRawSink@12@@Z ??$?0VFILERawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVFILERawSink@12@@Z ??$?0VFallbackCrcMemcpyEngine@crc_internal@absl@@$0A@@?$default_delete@VCrcMemcpyEngine@crc_internal@absl@@@__Cr@std@@QEAA@AEBU?$default_delete@VFallbackCrcMemcpyEngine@crc_internal@absl@@@12@@Z @@ -297,15 +290,8 @@ ??$?8V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@__Cr@std@@YA_NAEBV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@$$T@Z ??$?8VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YA_NAEBV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@01@$$T@Z ??$?9PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$?9PEAPEAVCordzHandle@cord_internal@absl@@PEAPEAV012@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z ??$?9PEAPEAVLogSink@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@0@Z - ??$?9PEAPEAVLogSink@absl@@PEAPEAV01@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@0@Z - ??$?9PEAPEBVCordzHandle@cord_internal@absl@@PEAPEBV012@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$?9PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@PEAU0123@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$?9PEAUTransition@cctz@time_internal@absl@@PEAU0123@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z ??$?9PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$?9PEAUTransitionType@cctz@time_internal@absl@@PEAU0123@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$?9PEAUViableSubstitution@strings_internal@absl@@PEAU012@@__Cr@std@@YA_NAEBV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$?9PEBQEAVLogSink@absl@@PEAPEAV01@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEBQEAVLogSink@absl@@@01@AEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@@Z ??$?9PEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YA_NAEBV?$__wrap_iter@PEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z ??$?DH@absl@@YA?AVDuration@0@HV10@@Z @@ -354,13 +340,6 @@ ??$?RUTransitionType@cctz@time_internal@absl@@U0123@$0A@@__move_backward_trivial@__Cr@std@@QEBA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@12@PEAUTransitionType@cctz@time_internal@absl@@00@Z ??$?RUTransitionType@cctz@time_internal@absl@@U0123@$0A@@__move_trivial@__Cr@std@@QEBA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@12@PEAUTransitionType@cctz@time_internal@absl@@00@Z ??$?RV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@$0A@@?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@12@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@@Z - ??$?RV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAPEAVLogSink@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QEBA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@12@00@Z ??$?RVDuration@absl@@V01@@?$__less@XX@__Cr@std@@QEBA_NAEBVDuration@absl@@0@Z ??$?RW4LogSeverity@absl@@AEBQEBDHAEAPEBD@?$AtomicHook@P6AXW4LogSeverity@absl@@PEBDHAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z@base_internal@absl@@QEBAX$$QEAW4LogSeverity@2@AEBQEBD$$QEAHAEAPEBD@Z ??$?RW4LogSeverity@absl@@AEBQEBDHAEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$AtomicHook@P6AXW4LogSeverity@absl@@PEBDHAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z@base_internal@absl@@QEBAX$$QEAW4LogSeverity@2@AEBQEBD$$QEAHAEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z @@ -851,13 +830,6 @@ ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PEAPEAVLogSink@absl@@PEAPEAV67@PEAPEAV67@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PEAUTransition@cctz@time_internal@absl@@PEAU6789@PEAU6789@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PEAUTransitionType@cctz@time_internal@absl@@PEAU6789@PEAU6789@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__distance@PEBUPayload@status_internal@absl@@@__Cr@std@@YA_JPEBUPayload@status_internal@absl@@0Urandom_access_iterator_tag@01@@Z ??$__distance@PEBUTransition@cctz@time_internal@absl@@@__Cr@std@@YA_JPEBUTransition@cctz@time_internal@absl@@0Urandom_access_iterator_tag@01@@Z ??$__distance@PEBVFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YA_JPEBVFormatArgImpl@str_format_internal@absl@@0Urandom_access_iterator_tag@01@@Z @@ -876,13 +848,6 @@ ??$__invoke@AEAUByUnixTime@Transition@cctz@time_internal@absl@@AEBU2345@AEBU2345@@__Cr@std@@YA_NAEAUByUnixTime@Transition@cctz@time_internal@absl@@AEBU3456@1@Z ??$__invoke@AEAU__identity@__Cr@std@@AEAPEAVLogSink@absl@@@__Cr@std@@YAAEAPEAVLogSink@absl@@AEAU__identity@01@AEAPEAV23@@Z ??$__invoke@AEAU__identity@__Cr@std@@AEBUTransition@cctz@time_internal@absl@@@__Cr@std@@YAAEBUTransition@cctz@time_internal@absl@@AEAU__identity@01@AEBU2345@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEAVCordzHandle@cord_internal@absl@@AEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEAVLogSink@absl@@AEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEBVCordzHandle@cord_internal@absl@@AEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@AEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUTransition@cctz@time_internal@absl@@AEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUTransitionType@cctz@time_internal@absl@@AEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@@Z - ??$__iter_move@AEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAUViableSubstitution@strings_internal@absl@@AEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@12@@Z ??$__launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z ??$__launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z ??$__launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAURefcountedRep@CrcCordState@crc_internal@absl@@PEAU2345@@Z @@ -894,13 +859,6 @@ ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAVLogSink@absl@@PEAPEAV45@PEAPEAV45@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV45678@PEAPEAPEBV45678@@__Cr@std@@YA?AU?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@01@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@PEAPEAU4567@@__Cr@std@@YA?AU?$pair@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@01@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z @@ -922,13 +880,6 @@ ??$__rewrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@V201@0@Z ??$__rewrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@V201@0@Z ??$__rewrap_iter@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@PEAPEAVLogSink@absl@@U?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@23@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@V201@PEAPEAVLogSink@absl@@@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@0@Z ??$__rewrap_range@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@PEAPEAPEBV12345@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@0@Z ??$__rewrap_range@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@PEAPEAU1234@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@0@Z ??$__rewrap_range@PEAPEAVLogSink@absl@@PEAPEAV12@PEAPEAV12@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0@Z @@ -936,13 +887,6 @@ ??$__rewrap_range@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@PEAU1234@@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@0@Z ??$__rewrap_range@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@PEBU1234@@__Cr@std@@YAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU2345@0@Z ??$__rewrap_range@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@0@Z ??$__to_address@$$CBUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU2345@@Z ??$__to_address@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z ??$__to_address@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@@Z @@ -955,15 +899,13 @@ ??$__to_address@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@@Z ??$__to_address@UViableSubstitution@strings_internal@absl@@@__Cr@std@@YAPEAUViableSubstitution@strings_internal@absl@@PEAU234@@Z ??$__to_address@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@X@__Cr@std@@YAPEAPEAVLogSink@absl@@AEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@PEAVCordzHandle@cord_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@AEAV?$allocator@PEAVCordzHandle@cord_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@PEAVLogSink@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@AEAV?$allocator@PEAVLogSink@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@PEBVCordzHandle@cord_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@AEAV?$allocator@PEBVCordzHandle@cord_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@UConversionItem@ParsedFormatBase@str_format_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@AEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@U4567@X@__Cr@std@@YAPEAUTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@01@PEAU2345@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@UTransition@cctz@time_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@U4567@X@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@PEAU2345@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@UTransitionType@cctz@time_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@UViableSubstitution@strings_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@V201@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@PEAVCordzHandle@cord_internal@absl@@@01@PEAPEAVCordzHandle@cord_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@PEAVLogSink@absl@@@__Cr@std@@YAXAEAV?$allocator@PEAVLogSink@absl@@@01@PEAPEAVLogSink@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@PEBVCordzHandle@cord_internal@absl@@@01@PEAPEBVCordzHandle@cord_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@UTransition@cctz@time_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@01@PEAUTransition@cctz@time_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@PEAUTransitionType@cctz@time_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@UViableSubstitution@strings_internal@absl@@@__Cr@std@@YAXAEAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@PEAUViableSubstitution@strings_internal@absl@@11@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU4567@PEAU4567@$0A@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0PEAU3456@@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU4567@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@$0A@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@V423@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@$0A@@__Cr@std@@YA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@01@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z @@ -976,13 +918,6 @@ ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PEAPEAVLogSink@absl@@PEAPEAV45@PEAPEAV45@$0A@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PEAUTransition@cctz@time_internal@absl@@PEAU4567@PEAU4567@$0A@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@PEAU4567@$0A@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__unwrap_iter@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@U?$__unwrap_iter_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z ??$__unwrap_iter@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@U?$__unwrap_iter_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@@Z ??$__unwrap_iter@PEAPEAVLogSink@absl@@U?$__unwrap_iter_impl@PEAPEAVLogSink@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@@Z @@ -993,13 +928,6 @@ ??$__unwrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@V201@@Z ??$__unwrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@V201@@Z ??$__unwrap_iter@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@23@$0A@@__Cr@std@@YAPEAPEAVLogSink@absl@@V?$__wrap_iter@PEAPEAVLogSink@absl@@@01@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@@Z ??$__unwrap_range@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@YA?A?<auto>@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ??$__unwrap_range@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@YA?A?<auto>@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ??$__unwrap_range@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@YA?A?<auto>@@PEAPEAVLogSink@absl@@0@Z @@ -1007,22 +935,8 @@ ??$__unwrap_range@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YA?A?<auto>@@PEAUTransitionType@cctz@time_internal@absl@@0@Z ??$__unwrap_range@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@@__Cr@std@@YA?A?<auto>@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ??$__unwrap_range@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByCivilTime@Transition@cctz@time_internal@absl@@PEBU5678@PEBU5678@U5678@U__identity@23@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@$$QEAUByCivilTime@2345@$$QEAU__identity@01@@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByUnixTime@Transition@cctz@time_internal@absl@@PEBU5678@PEBU5678@U5678@U__identity@23@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@$$QEAUByUnixTime@2345@$$QEAU__identity@01@@Z - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ ??$advance@PEBUTransition@cctz@time_internal@absl@@_J@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXAEAPEBUTransition@cctz@time_internal@absl@@_J@Z ??$advance@PEBUTransition@cctz@time_internal@absl@@_J_JX@__Cr@std@@YAXAEAPEBUTransition@cctz@time_internal@absl@@_J@Z ??$assign@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0@Z @@ -1194,13 +1108,6 @@ ??$make_pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@01@$$QEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QEAPEAU3456@@Z ??$make_pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@01@$$QEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z ??$make_pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@__Cr@std@@YA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@01@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z - ??$make_pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@$$QEAV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$make_unique@ULogMessageData@LogMessage@log_internal@absl@@AEAPEBDAEAHAEAW4LogSeverity@4@VTime@4@@__Cr@std@@YA?AV?$unique_ptr@ULogMessageData@LogMessage@log_internal@absl@@U?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@@01@AEAPEBDAEAHAEAW4LogSeverity@absl@@$$QEAVTime@4@@Z ??$make_unique@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@$$V@__Cr@std@@YA?AV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@XZ ??$make_unique@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@AEAV12@@__Cr@std@@YA?AV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@AEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@Z @@ -1233,13 +1140,6 @@ ??$move@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@00@Z ??$move@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z ??$move@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z - ??$move@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@01@V201@00@Z ??$move_backward@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z ??$move_backward@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@00@Z ??$move_backward@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z @@ -1492,13 +1392,6 @@ ??0?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAA@PEAUTransitionType@cctz@time_internal@absl@@@Z ??0?$optional@VCord@absl@@@__Cr@std@@QEAA@Unullopt_t@12@@Z ??0?$probe_seq@$0BA@@container_internal@absl@@QEAA@_K0@Z - ??0?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAA@PEAPEAVCordzHandle@cord_internal@absl@@@Z - ??0?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEAA@PEAPEAVLogSink@absl@@@Z - ??0?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAA@PEAPEBVCordzHandle@cord_internal@absl@@@Z - ??0?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAA@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z - ??0?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEAA@PEAUTransition@cctz@time_internal@absl@@@Z - ??0?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAA@PEAUTransitionType@cctz@time_internal@absl@@@Z - ??0?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEAA@PEAUViableSubstitution@strings_internal@absl@@@Z ??0?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@__Cr@std@@QEAA@$$QEAV012@@Z ??0?$unordered_map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QEAA@XZ ??0?$unordered_set@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA@XZ @@ -1978,13 +1871,6 @@ ??D?$move_iterator@PEAUPayload@status_internal@absl@@@__Cr@std@@QEBA$$QEAUPayload@status_internal@absl@@XZ ??D?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEBA$$QEAUTransition@cctz@time_internal@absl@@XZ ??D?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEBA$$QEAUTransitionType@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAAEAPEAVCordzHandle@cord_internal@absl@@XZ - ??D?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEBAAEAPEAVLogSink@absl@@XZ - ??D?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAAEAPEBVCordzHandle@cord_internal@absl@@XZ - ??D?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEBAAEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ - ??D?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEBAAEAUTransition@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEBAAEAUTransitionType@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEBAAEAUViableSubstitution@strings_internal@absl@@XZ ??D?$unique_ptr@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QEBAAEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@12@XZ ??D?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QEBAAEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@12@XZ ??D?$unique_ptr@ULogMessageData@LogMessage@log_internal@absl@@U?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@@__Cr@std@@QEBAAEAULogMessageData@LogMessage@log_internal@absl@@XZ @@ -2009,13 +1895,6 @@ ??E?$move_iterator@PEAUPayload@status_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ ??E?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ ??E?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ - ??E?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEAAAEAV012@XZ ??EChunkIterator@Cord@absl@@QEAAAEAV012@XZ ??E__deque_range@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAAEAU0123@XZ ??Euint128@absl@@QEAAAEAV01@XZ @@ -3845,13 +3724,6 @@ ?__rewrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@V423@0@Z ?__rewrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@V423@0@Z ?__rewrap@?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@__Cr@std@@SA?AV?$__wrap_iter@PEAPEAVLogSink@absl@@@23@V423@PEAPEAVLogSink@absl@@@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@0@Z ?__rewrap@?$__unwrap_range_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@SA?A?<auto>@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@SA?A?<auto>@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@SA?A?<auto>@@PEAPEAVLogSink@absl@@0@Z @@ -3859,13 +3731,6 @@ ?__rewrap@?$__unwrap_range_impl@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@SA?A?<auto>@@PEAUTransitionType@cctz@time_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@@__Cr@std@@SA?A?<auto>@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@0@Z ?__segment@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@Z ?__segment@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEBQEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@@Z ?__size@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAAEA_KXZ @@ -3898,13 +3763,6 @@ ?__unwrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@V423@@Z ?__unwrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@V423@@Z ?__unwrap@?$__unwrap_iter_impl@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@$00@__Cr@std@@SAPEAPEAVLogSink@absl@@V?$__wrap_iter@PEAPEAVLogSink@absl@@@23@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEAVLogSink@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@V423@@Z ?__unwrap@?$__unwrap_range_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@SA?A?<auto>@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@SA?A?<auto>@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PEAPEAVLogSink@absl@@PEAPEAV12@@__Cr@std@@SA?A?<auto>@@PEAPEAVLogSink@absl@@0@Z @@ -3912,13 +3770,6 @@ ?__unwrap@?$__unwrap_range_impl@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__Cr@std@@SA?A?<auto>@@PEAUTransitionType@cctz@time_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@@__Cr@std@@SA?A?<auto>@@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEAVLogSink@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@23@0@Z ?__upcast@?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@XZ ?__upcast@?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@XZ ?_mm_cmpgt_epi8_fixed@container_internal@absl@@YA?AT__m128i@@T3@0@Z @@ -3997,13 +3848,6 @@ ?base@?$move_iterator@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEGBAAEBQEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?base@?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransition@cctz@time_internal@absl@@XZ ?base@?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransitionType@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAPEAPEAVCordzHandle@cord_internal@absl@@XZ - ?base@?$reverse_iterator@PEAPEAVLogSink@absl@@@__Cr@std@@QEBAPEAPEAVLogSink@absl@@XZ - ?base@?$reverse_iterator@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@QEBAPEAPEBVCordzHandle@cord_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEBAPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEBAPEAUTransition@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEBAPEAUTransitionType@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QEBAPEAUViableSubstitution@strings_internal@absl@@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ ?begin@?$Span@$$CBI@absl@@QEBAPEBIXZ
diff --git a/third_party/abseil-cpp/symbols_x64_rel.def b/third_party/abseil-cpp/symbols_x64_rel.def index 9efb7f4..b1bda62 100644 --- a/third_party/abseil-cpp/symbols_x64_rel.def +++ b/third_party/abseil-cpp/symbols_x64_rel.def
@@ -163,7 +163,6 @@ ??$__push_back_slow_path@AEBQEAVCordzHandle@cord_internal@absl@@@?$vector@PEAVCordzHandle@cord_internal@absl@@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEAVCordzHandle@cord_internal@absl@@AEBQEAV345@@Z ??$__push_back_slow_path@AEBQEAVLogSink@absl@@@?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEAVLogSink@absl@@AEBQEAV34@@Z ??$__push_back_slow_path@AEBQEBVCordzHandle@cord_internal@absl@@@?$vector@PEBVCordzHandle@cord_internal@absl@@V?$allocator@PEBVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEBVCordzHandle@cord_internal@absl@@AEBQEBV345@@Z - ??$__push_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@$$QEAU3456@@Z ??$__rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z ??$__rehash@$00@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@AEAAX_K@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByCivilTime@Transition@cctz@time_internal@absl@@PEBU5678@PEBU5678@U5678@U__identity@23@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@$$QEAUByCivilTime@2345@$$QEAU__identity@01@@Z @@ -471,7 +470,6 @@ ?ConvertFloatImpl@str_format_internal@absl@@YA_NMAEBVFormatConversionSpecImpl@12@PEAVFormatSinkImpl@12@@Z ?ConvertFloatImpl@str_format_internal@absl@@YA_NNAEBVFormatConversionSpecImpl@12@PEAVFormatSinkImpl@12@@Z ?ConvertFloatImpl@str_format_internal@absl@@YA_NOAEBVFormatConversionSpecImpl@12@PEAVFormatSinkImpl@12@@Z - ?ConvertOne@ParsedFormatConsumer@ParsedFormatBase@str_format_internal@absl@@QEAA_NAEBUUnboundConversion@34@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?CopyCordToString@absl@@YAXAEBVCord@1@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ?CopyPrefix@CordRepBtree@cord_internal@absl@@AEAA?AUCopyResult@123@_K_N@Z ?CopySuffix@CordRepBtree@cord_internal@absl@@AEAA?AUCopyResult@123@_K@Z @@ -1250,6 +1248,7 @@ ?push_back@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEBQEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z ?push_back@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEBQEBVImpl@time_zone@cctz@time_internal@absl@@@Z ?push_back@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAX$$QEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z + ?push_back@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z ?push_back@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEBUTransition@cctz@time_internal@absl@@@Z ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEBQEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAX$$QEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
diff --git a/third_party/abseil-cpp/symbols_x86_dbg.def b/third_party/abseil-cpp/symbols_x86_dbg.def index 3be7253..f07d208 100644 --- a/third_party/abseil-cpp/symbols_x86_dbg.def +++ b/third_party/abseil-cpp/symbols_x86_dbg.def
@@ -254,13 +254,6 @@ ??$?0V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QAE@PAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ??$?0V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@FormatArgImpl@str_format_internal@absl@@QAE@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$?0V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XV012@$0A@@?$Span@$$CBD@absl@@QAE@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z - ??$?0V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$reverse_iterator@PAPAVLogSink@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@12@0@Z - ??$?0V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V012@$0A@@?$pair@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@12@0@Z ??$?0VBufferRawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QAE@PAVBufferRawSink@12@@Z ??$?0VFILERawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QAE@PAVFILERawSink@12@@Z ??$?0VFallbackCrcMemcpyEngine@crc_internal@absl@@$0A@@?$default_delete@VCrcMemcpyEngine@crc_internal@absl@@@__Cr@std@@QAE@ABU?$default_delete@VFallbackCrcMemcpyEngine@crc_internal@absl@@@12@@Z @@ -297,15 +290,8 @@ ??$?8V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@__Cr@std@@YA_NABV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@$$T@Z ??$?8VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YA_NABV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@01@$$T@Z ??$?9PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@YA_NABV?$__wrap_iter@PAPAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$?9PAPAVCordzHandle@cord_internal@absl@@PAPAV012@@__Cr@std@@YA_NABV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@0@Z ??$?9PAPAVLogSink@absl@@@__Cr@std@@YA_NABV?$__wrap_iter@PAPAVLogSink@absl@@@01@0@Z - ??$?9PAPAVLogSink@absl@@PAPAV01@@__Cr@std@@YA_NABV?$reverse_iterator@PAPAVLogSink@absl@@@01@0@Z - ??$?9PAPBVCordzHandle@cord_internal@absl@@PAPBV012@@__Cr@std@@YA_NABV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$?9PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@PAU0123@@__Cr@std@@YA_NABV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$?9PAUTransition@cctz@time_internal@absl@@PAU0123@@__Cr@std@@YA_NABV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@0@Z ??$?9PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@YA_NABV?$__wrap_iter@PAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$?9PAUTransitionType@cctz@time_internal@absl@@PAU0123@@__Cr@std@@YA_NABV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$?9PAUViableSubstitution@strings_internal@absl@@PAU012@@__Cr@std@@YA_NABV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$?9PBQAVLogSink@absl@@PAPAV01@@__Cr@std@@YA_NABV?$__wrap_iter@PBQAVLogSink@absl@@@01@ABV?$__wrap_iter@PAPAVLogSink@absl@@@01@@Z ??$?9PBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YA_NABV?$__wrap_iter@PBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z ??$?DH@absl@@YA?AVDuration@0@HV10@@Z @@ -354,13 +340,6 @@ ??$?RUTransitionType@cctz@time_internal@absl@@U0123@$0A@@__move_backward_trivial@__Cr@std@@QBE?AU?$pair@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@12@PAUTransitionType@cctz@time_internal@absl@@00@Z ??$?RUTransitionType@cctz@time_internal@absl@@U0123@$0A@@__move_trivial@__Cr@std@@QBE?AU?$pair@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@12@PAUTransitionType@cctz@time_internal@absl@@00@Z ??$?RV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@12@$0A@@?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@12@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@12@@Z - ??$?RV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PAPAVLogSink@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@12@00@Z - ??$?RV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V012@V012@@?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@QBE?AU?$pair@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@12@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@12@00@Z ??$?RVDuration@absl@@V01@@?$__less@XX@__Cr@std@@QBE_NABVDuration@absl@@0@Z ??$?RW4LogSeverity@absl@@ABQBDHAAPBD@?$AtomicHook@P6AXW4LogSeverity@absl@@PBDHABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z@base_internal@absl@@QBEX$$QAW4LogSeverity@2@ABQBD$$QAHAAPBD@Z ??$?RW4LogSeverity@absl@@ABQBDHAAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$AtomicHook@P6AXW4LogSeverity@absl@@PBDHABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z@base_internal@absl@@QBEX$$QAW4LogSeverity@2@ABQBD$$QAHAAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z @@ -851,13 +830,6 @@ ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PAPAVLogSink@absl@@PAPAV67@PAPAV67@@__Cr@std@@YA?AU?$pair@PAPAVLogSink@absl@@PAPAV12@@01@PAPAVLogSink@absl@@00@Z ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PAUTransition@cctz@time_internal@absl@@PAU6789@PAU6789@@__Cr@std@@YA?AU?$pair@PAUTransition@cctz@time_internal@absl@@PAU1234@@01@PAUTransition@cctz@time_internal@absl@@00@Z ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@PAUTransitionType@cctz@time_internal@absl@@PAU6789@PAU6789@@__Cr@std@@YA?AU?$pair@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@01@PAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PAPAVLogSink@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPAVLogSink@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__dispatch_copy_or_move@U_ClassicAlgPolicy@__Cr@std@@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@23@U__move_trivial@23@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@V623@V623@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__distance@PBUPayload@status_internal@absl@@@__Cr@std@@YAHPBUPayload@status_internal@absl@@0Urandom_access_iterator_tag@01@@Z ??$__distance@PBUTransition@cctz@time_internal@absl@@@__Cr@std@@YAHPBUTransition@cctz@time_internal@absl@@0Urandom_access_iterator_tag@01@@Z ??$__distance@PBVFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YAHPBVFormatArgImpl@str_format_internal@absl@@0Urandom_access_iterator_tag@01@@Z @@ -876,13 +848,6 @@ ??$__invoke@AAUByUnixTime@Transition@cctz@time_internal@absl@@ABU2345@ABU2345@@__Cr@std@@YA_NAAUByUnixTime@Transition@cctz@time_internal@absl@@ABU3456@1@Z ??$__invoke@AAU__identity@__Cr@std@@AAPAVLogSink@absl@@@__Cr@std@@YAAAPAVLogSink@absl@@AAU__identity@01@AAPAV23@@Z ??$__invoke@AAU__identity@__Cr@std@@ABUTransition@cctz@time_internal@absl@@@__Cr@std@@YAABUTransition@cctz@time_internal@absl@@AAU__identity@01@ABU2345@@Z - ??$__iter_move@AAV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAPAVCordzHandle@cord_internal@absl@@AAV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@12@@Z - ??$__iter_move@AAV?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAPAVLogSink@absl@@AAV?$reverse_iterator@PAPAVLogSink@absl@@@12@@Z - ??$__iter_move@AAV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAPBVCordzHandle@cord_internal@absl@@AAV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@12@@Z - ??$__iter_move@AAV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAUConversionItem@ParsedFormatBase@str_format_internal@absl@@AAV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@@Z - ??$__iter_move@AAV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAUTransition@cctz@time_internal@absl@@AAV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@12@@Z - ??$__iter_move@AAV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAUTransitionType@cctz@time_internal@absl@@AAV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@12@@Z - ??$__iter_move@AAV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAUViableSubstitution@strings_internal@absl@@AAV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@12@@Z ??$__launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PBU201@@Z ??$__launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PAU201@@Z ??$__launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPAURefcountedRep@CrcCordState@crc_internal@absl@@PAU2345@@Z @@ -894,13 +859,6 @@ ??$__move@U_ClassicAlgPolicy@__Cr@std@@PAPAVLogSink@absl@@PAPAV45@PAPAV45@@__Cr@std@@YA?AU?$pair@PAPAVLogSink@absl@@PAPAV12@@01@PAPAVLogSink@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PAUTransition@cctz@time_internal@absl@@PAU4567@PAU4567@@__Cr@std@@YA?AU?$pair@PAUTransition@cctz@time_internal@absl@@PAU1234@@01@PAUTransition@cctz@time_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PAUTransitionType@cctz@time_internal@absl@@PAU4567@PAU4567@@__Cr@std@@YA?AU?$pair@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@01@PAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PAPAVLogSink@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPAVLogSink@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__move@U_ClassicAlgPolicy@__Cr@std@@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@V423@V423@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV45678@PAPAPBV45678@@__Cr@std@@YA?AU?$pair@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@01@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU4567@PAPAU4567@@__Cr@std@@YA?AU?$pair@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@@01@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@00@Z ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PAUTransition@cctz@time_internal@absl@@PAU4567@PAU4567@@__Cr@std@@YA?AU?$pair@PAUTransition@cctz@time_internal@absl@@PAU1234@@01@PAUTransition@cctz@time_internal@absl@@00@Z @@ -922,13 +880,6 @@ ??$__rewrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@V201@0@Z ??$__rewrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@V201@0@Z ??$__rewrap_iter@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@PAPAVLogSink@absl@@U?$__unwrap_iter_impl@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@$00@23@@__Cr@std@@YA?AV?$__wrap_iter@PAPAVLogSink@absl@@@01@V201@PAPAVLogSink@absl@@@Z - ??$__rewrap_iter@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVLogSink@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_iter@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@23@@__Cr@std@@YA?AV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@V201@0@Z ??$__rewrap_range@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@PAPAPBV12345@@__Cr@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@0@Z ??$__rewrap_range@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@PAPAU1234@@__Cr@std@@YAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU2345@0@Z ??$__rewrap_range@PAPAVLogSink@absl@@PAPAV12@PAPAV12@@__Cr@std@@YAPAPAVLogSink@absl@@PAPAV23@0@Z @@ -936,13 +887,6 @@ ??$__rewrap_range@PAUTransitionType@cctz@time_internal@absl@@PAU1234@PAU1234@@__Cr@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@0@Z ??$__rewrap_range@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@PBU1234@@__Cr@std@@YAPBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU2345@0@Z ??$__rewrap_range@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVLogSink@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@V201@0@Z - ??$__rewrap_range@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@V201@0@Z ??$__to_address@$$CBUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU2345@@Z ??$__to_address@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@@Z ??$__to_address@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU2345@@Z @@ -955,15 +899,13 @@ ??$__to_address@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@@Z ??$__to_address@UViableSubstitution@strings_internal@absl@@@__Cr@std@@YAPAUViableSubstitution@strings_internal@absl@@PAU234@@Z ??$__to_address@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@X@__Cr@std@@YAPAPAVLogSink@absl@@ABV?$__wrap_iter@PAPAVLogSink@absl@@@01@@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PAVCordzHandle@cord_internal@absl@@@__Cr@std@@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@V423@PAVCordzHandle@cord_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@AAV?$allocator@PAVCordzHandle@cord_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PAVLogSink@absl@@@__Cr@std@@V?$reverse_iterator@PAPAVLogSink@absl@@@23@V423@PAVLogSink@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PAPAVLogSink@absl@@@01@AAV?$allocator@PAVLogSink@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@PBVCordzHandle@cord_internal@absl@@@__Cr@std@@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@V423@PBVCordzHandle@cord_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@AAV?$allocator@PBVCordzHandle@cord_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@UConversionItem@ParsedFormatBase@str_format_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@AAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@PAUTransition@cctz@time_internal@absl@@PAU4567@U4567@X@__Cr@std@@YAPAUTransition@cctz@time_internal@absl@@AAV?$allocator@UTransition@cctz@time_internal@absl@@@01@PAU2345@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@V423@UTransition@cctz@time_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@AAV?$allocator@UTransition@cctz@time_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@PAUTransitionType@cctz@time_internal@absl@@PAU4567@U4567@X@__Cr@std@@YAPAUTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@PAU2345@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@V423@UTransitionType@cctz@time_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@V201@11@Z - ??$__uninitialized_allocator_move_if_noexcept@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@V423@UViableSubstitution@strings_internal@absl@@X@__Cr@std@@YA?AV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@AAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@V201@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PAVCordzHandle@cord_internal@absl@@@__Cr@std@@PAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXAAV?$allocator@PAVCordzHandle@cord_internal@absl@@@01@PAPAVCordzHandle@cord_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PAVLogSink@absl@@@__Cr@std@@PAVLogSink@absl@@@__Cr@std@@YAXAAV?$allocator@PAVLogSink@absl@@@01@PAPAVLogSink@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@PBVCordzHandle@cord_internal@absl@@@__Cr@std@@PBVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXAAV?$allocator@PBVCordzHandle@cord_internal@absl@@@01@PAPBVCordzHandle@cord_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YAXAAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@UTransition@cctz@time_internal@absl@@@__Cr@std@@YAXAAV?$allocator@UTransition@cctz@time_internal@absl@@@01@PAUTransition@cctz@time_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAXAAV?$allocator@UTransitionType@cctz@time_internal@absl@@@01@PAUTransitionType@cctz@time_internal@absl@@11@Z + ??$__uninitialized_allocator_relocate@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@UViableSubstitution@strings_internal@absl@@@__Cr@std@@YAXAAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@PAUViableSubstitution@strings_internal@absl@@11@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU4567@PAU4567@$0A@@__Cr@std@@YA?AU?$pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@@01@PBUPrefixCrc@CrcCordState@crc_internal@absl@@0PAU3456@@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU4567@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@$0A@@__Cr@std@@YA?AU?$pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@01@PBUPrefixCrc@CrcCordState@crc_internal@absl@@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__copy_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__copy_trivial@23@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@23@V423@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@$0A@@__Cr@std@@YA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@01@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@@Z @@ -976,13 +918,6 @@ ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PAPAVLogSink@absl@@PAPAV45@PAPAV45@$0A@@__Cr@std@@YA?AU?$pair@PAPAVLogSink@absl@@PAPAV12@@01@PAPAVLogSink@absl@@00@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PAUTransition@cctz@time_internal@absl@@PAU4567@PAU4567@$0A@@__Cr@std@@YA?AU?$pair@PAUTransition@cctz@time_internal@absl@@PAU1234@@01@PAUTransition@cctz@time_internal@absl@@00@Z ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@PAUTransitionType@cctz@time_internal@absl@@PAU4567@PAU4567@$0A@@__Cr@std@@YA?AU?$pair@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@01@PAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PAPAVLogSink@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPAVLogSink@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@00@Z - ??$__unwrap_and_dispatch@U?$__overload@U?$__move_loop@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@U__move_trivial@23@@__Cr@std@@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@V423@V423@$0A@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@00@Z ??$__unwrap_iter@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@U?$__unwrap_iter_impl@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@@Z ??$__unwrap_iter@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@U?$__unwrap_iter_impl@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU2345@@Z ??$__unwrap_iter@PAPAVLogSink@absl@@U?$__unwrap_iter_impl@PAPAVLogSink@absl@@$00@__Cr@std@@$0A@@__Cr@std@@YAPAPAVLogSink@absl@@PAPAV23@@Z @@ -993,13 +928,6 @@ ??$__unwrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@V201@@Z ??$__unwrap_iter@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@U?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@V201@@Z ??$__unwrap_iter@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@$00@23@$0A@@__Cr@std@@YAPAPAVLogSink@absl@@V?$__wrap_iter@PAPAVLogSink@absl@@@01@@Z - ??$__unwrap_iter@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVLogSink@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@V201@@Z - ??$__unwrap_iter@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@U?$__unwrap_iter_impl@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@23@$0A@@__Cr@std@@YA?AV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@V201@@Z ??$__unwrap_range@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@__Cr@std@@YA?A?<auto>@@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@0@Z ??$__unwrap_range@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@@__Cr@std@@YA?A?<auto>@@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ??$__unwrap_range@PAPAVLogSink@absl@@PAPAV12@@__Cr@std@@YA?A?<auto>@@PAPAVLogSink@absl@@0@Z @@ -1007,22 +935,8 @@ ??$__unwrap_range@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@__Cr@std@@YA?A?<auto>@@PAUTransitionType@cctz@time_internal@absl@@0@Z ??$__unwrap_range@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@@__Cr@std@@YA?A?<auto>@@PBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ??$__unwrap_range@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PAPAVLogSink@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$__unwrap_range@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?A?<auto>@@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByCivilTime@Transition@cctz@time_internal@absl@@PBU5678@PBU5678@U5678@U__identity@23@@__Cr@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@0ABU2345@$$QAUByCivilTime@2345@$$QAU__identity@01@@Z ??$__upper_bound@U_ClassicAlgPolicy@__Cr@std@@UByUnixTime@Transition@cctz@time_internal@absl@@PBU5678@PBU5678@U5678@U__identity@23@@__Cr@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@0ABU2345@$$QAUByUnixTime@2345@$$QAU__identity@01@@Z - ??$__validate_iter_reference@AAV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AAV?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AAV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AAV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AAV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AAV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ - ??$__validate_iter_reference@AAV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXXZ ??$advance@PBUTransition@cctz@time_internal@absl@@H@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAXAAPBUTransition@cctz@time_internal@absl@@H@Z ??$advance@PBUTransition@cctz@time_internal@absl@@HHX@__Cr@std@@YAXAAPBUTransition@cctz@time_internal@absl@@H@Z ??$assign@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@$0A@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@0@Z @@ -1194,13 +1108,6 @@ ??$make_pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@@__Cr@std@@YA?AU?$pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@@01@$$QAPBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QAPAU3456@@Z ??$make_pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@__Cr@std@@YA?AU?$pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@01@$$QAPBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@@Z ??$make_pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@__Cr@std@@YA?AU?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@01@$$QAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@$$QAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@@Z - ??$make_pair@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@$$QAV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@01@$$QAV?$reverse_iterator@PAPAVLogSink@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@01@$$QAV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@01@$$QAV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@01@$$QAV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@01@$$QAV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@0@Z - ??$make_pair@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AU?$pair@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@01@$$QAV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@0@Z ??$make_unique@ULogMessageData@LogMessage@log_internal@absl@@AAPBDAAHAAW4LogSeverity@4@VTime@4@@__Cr@std@@YA?AV?$unique_ptr@ULogMessageData@LogMessage@log_internal@absl@@U?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@@01@AAPBDAAHAAW4LogSeverity@absl@@$$QAVTime@4@@Z ??$make_unique@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@$$V@__Cr@std@@YA?AV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@XZ ??$make_unique@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@AAV12@@__Cr@std@@YA?AV?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@01@AAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@Z @@ -1233,13 +1140,6 @@ ??$move@PAPAVLogSink@absl@@PAPAV12@@__Cr@std@@YAPAPAVLogSink@absl@@PAPAV23@00@Z ??$move@PAUTransition@cctz@time_internal@absl@@PAU1234@@__Cr@std@@YAPAUTransition@cctz@time_internal@absl@@PAU2345@00@Z ??$move@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@__Cr@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@00@Z - ??$move@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAPAVLogSink@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@V201@00@Z - ??$move@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@YA?AV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@01@V201@00@Z ??$move_backward@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@__Cr@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@00@Z ??$move_backward@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@@__Cr@std@@YAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU2345@00@Z ??$move_backward@PAUTransition@cctz@time_internal@absl@@PAU1234@@__Cr@std@@YAPAUTransition@cctz@time_internal@absl@@PAU2345@00@Z @@ -1492,13 +1392,6 @@ ??0?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QAE@PAUTransitionType@cctz@time_internal@absl@@@Z ??0?$optional@VCord@absl@@@__Cr@std@@QAE@Unullopt_t@12@@Z ??0?$probe_seq@$0BA@@container_internal@absl@@QAE@II@Z - ??0?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@QAE@PAPAVCordzHandle@cord_internal@absl@@@Z - ??0?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@QAE@PAPAVLogSink@absl@@@Z - ??0?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@QAE@PAPBVCordzHandle@cord_internal@absl@@@Z - ??0?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QAE@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z - ??0?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QAE@PAUTransition@cctz@time_internal@absl@@@Z - ??0?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QAE@PAUTransitionType@cctz@time_internal@absl@@@Z - ??0?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QAE@PAUViableSubstitution@strings_internal@absl@@@Z ??0?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@@__Cr@std@@QAE@$$QAV012@@Z ??0?$unordered_map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QAE@XZ ??0?$unordered_set@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAE@XZ @@ -1978,13 +1871,6 @@ ??D?$move_iterator@PAUPayload@status_internal@absl@@@__Cr@std@@QBE$$QAUPayload@status_internal@absl@@XZ ??D?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QBE$$QAUTransition@cctz@time_internal@absl@@XZ ??D?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QBE$$QAUTransitionType@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@QBEAAPAVCordzHandle@cord_internal@absl@@XZ - ??D?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@QBEAAPAVLogSink@absl@@XZ - ??D?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@QBEAAPBVCordzHandle@cord_internal@absl@@XZ - ??D?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QBEAAUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ - ??D?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QBEAAUTransition@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QBEAAUTransitionType@cctz@time_internal@absl@@XZ - ??D?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QBEAAUViableSubstitution@strings_internal@absl@@XZ ??D?$unique_ptr@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QBEAAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@12@XZ ??D?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QBEAAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@12@XZ ??D?$unique_ptr@ULogMessageData@LogMessage@log_internal@absl@@U?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@@__Cr@std@@QBEAAULogMessageData@LogMessage@log_internal@absl@@XZ @@ -2009,13 +1895,6 @@ ??E?$move_iterator@PAUPayload@status_internal@absl@@@__Cr@std@@QAEAAV012@XZ ??E?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QAEAAV012@XZ ??E?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QAEAAV012@XZ - ??E?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@QAEAAV012@XZ - ??E?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@QAEAAV012@XZ - ??E?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@QAEAAV012@XZ - ??E?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QAEAAV012@XZ - ??E?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QAEAAV012@XZ - ??E?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QAEAAV012@XZ - ??E?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QAEAAV012@XZ ??EChunkIterator@Cord@absl@@QAEAAV012@XZ ??E__deque_range@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEAAU0123@XZ ??Euint128@absl@@QAEAAV01@XZ @@ -3845,13 +3724,6 @@ ?__rewrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@V423@0@Z ?__rewrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@23@V423@0@Z ?__rewrap@?$__unwrap_iter_impl@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@$00@__Cr@std@@SA?AV?$__wrap_iter@PAPAVLogSink@absl@@@23@V423@PAPAVLogSink@absl@@@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAPAVLogSink@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@V423@0@Z - ?__rewrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@V423@0@Z ?__rewrap@?$__unwrap_range_impl@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@__Cr@std@@SA?A?<auto>@@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@@__Cr@std@@SA?A?<auto>@@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PAPAVLogSink@absl@@PAPAV12@@__Cr@std@@SA?A?<auto>@@PAPAVLogSink@absl@@0@Z @@ -3859,13 +3731,6 @@ ?__rewrap@?$__unwrap_range_impl@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@__Cr@std@@SA?A?<auto>@@PAUTransitionType@cctz@time_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@@__Cr@std@@SA?A?<auto>@@PBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__rewrap@?$__unwrap_range_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAPAVLogSink@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@0@Z - ?__rewrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@0@Z ?__segment@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@__Cr@std@@SAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@Z ?__segment@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@@__Cr@std@@SAPBQBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@23@@Z ?__size@?$deque@PBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEAAIXZ @@ -3898,13 +3763,6 @@ ?__unwrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@V423@@Z ?__unwrap@?$__unwrap_iter_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@23@V423@@Z ?__unwrap@?$__unwrap_iter_impl@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@$00@__Cr@std@@SAPAPAVLogSink@absl@@V?$__wrap_iter@PAPAVLogSink@absl@@@23@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAPAVLogSink@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@V423@@Z - ?__unwrap@?$__unwrap_iter_impl@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@$0A@@__Cr@std@@SA?AV?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@V423@@Z ?__unwrap@?$__unwrap_range_impl@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@__Cr@std@@SA?A?<auto>@@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@@__Cr@std@@SA?A?<auto>@@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PAPAVLogSink@absl@@PAPAV12@@__Cr@std@@SA?A?<auto>@@PAPAVLogSink@absl@@0@Z @@ -3912,13 +3770,6 @@ ?__unwrap@?$__unwrap_range_impl@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@__Cr@std@@SA?A?<auto>@@PAUTransitionType@cctz@time_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@@__Cr@std@@SA?A?<auto>@@PBUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z ?__unwrap@?$__unwrap_range_impl@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAPAVLogSink@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@23@0@Z - ?__unwrap@?$__unwrap_range_impl@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@V123@@__Cr@std@@SA?A?<auto>@@V?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@23@0@Z ?__upcast@?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@QAEPAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@23@XZ ?__upcast@?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@QAEPAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@23@XZ ?_mm_cmpgt_epi8_fixed@container_internal@absl@@YA?AT__m128i@@T3@0@Z @@ -3997,13 +3848,6 @@ ?base@?$move_iterator@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QGBEABQAPAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?base@?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QGBEABQAUTransition@cctz@time_internal@absl@@XZ ?base@?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QGBEABQAUTransitionType@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@QBEPAPAVCordzHandle@cord_internal@absl@@XZ - ?base@?$reverse_iterator@PAPAVLogSink@absl@@@__Cr@std@@QBEPAPAVLogSink@absl@@XZ - ?base@?$reverse_iterator@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@QBEPAPBVCordzHandle@cord_internal@absl@@XZ - ?base@?$reverse_iterator@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QBEPAUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ - ?base@?$reverse_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QBEPAUTransition@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QBEPAUTransitionType@cctz@time_internal@absl@@XZ - ?base@?$reverse_iterator@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@QBEPAUViableSubstitution@strings_internal@absl@@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QAEPAUPayload@status_internal@2@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QBEPBUPayload@status_internal@2@XZ ?begin@?$Span@$$CBI@absl@@QBEPBIXZ
diff --git a/third_party/blink/public/mojom/mediastream/media_stream.mojom b/third_party/blink/public/mojom/mediastream/media_stream.mojom index 34744b5..28214d7 100644 --- a/third_party/blink/public/mojom/mediastream/media_stream.mojom +++ b/third_party/blink/public/mojom/mediastream/media_stream.mojom
@@ -316,15 +316,6 @@ CapturedWheelAction action) => (CapturedSurfaceControlResult result); - // Retrieves the zoom level from the captured tab. - // - // |device_id| identifies the captured tab. - // |zoom_level| will contain the zoom level if the request is successful. - // |result| reports if the call was successful or what type of error occurred. - [EnableIfNot=is_android_or_ios] - GetZoomLevel(mojo_base.mojom.UnguessableToken device_id) - => (int32? zoom_level, CapturedSurfaceControlResult result); - // Sets the zoom level of the captured tab. // // |device_id| identifies the captured tab.
diff --git a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h index 2f30782..d593c2e 100644 --- a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h +++ b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
@@ -190,15 +190,6 @@ int wheel_delta_y, base::OnceCallback<void(DOMException*)> callback); - // Retrieves the zoom level from the captured tab. - // - // `callback` is used to report the result. - // `callback.zoom_level` has the zoom level or nullopt in case of failure. - // `callback.error` has the error message upon failure. (Empty otherwise.) - virtual void GetZoomLevel( - base::OnceCallback<void(std::optional<int> zoom_level, - const String& error)> callback); - // Sets the zoom level for the captured tab. // // `zoom_level` is the requested zoom level and must be among the values
diff --git a/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc b/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc index 4f246abe..56decaae2 100644 --- a/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc +++ b/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc
@@ -60,13 +60,19 @@ return true; } -} // namespace +const unsigned char* GetCachedTracingFlags() { + DEFINE_STATIC_LOCAL( + const unsigned char*, tracing_enabled, + (TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT( + "devtools.timeline.invalidationTracking")))); + return tracing_enabled; +} -static const unsigned char* g_tracing_enabled = nullptr; +} // namespace #define TRACE_STYLE_INVALIDATOR_INVALIDATION_SELECTORPART_IF_ENABLED( \ element, reason, invalidationSet, singleSelectorPart) \ - if (UNLIKELY(*g_tracing_enabled)) \ + if (UNLIKELY(*GetCachedTracingFlags())) \ TRACE_STYLE_INVALIDATOR_INVALIDATION_SELECTORPART( \ element, reason, invalidationSet, singleSelectorPart); @@ -109,11 +115,6 @@ other.attributes_); } -void InvalidationSet::CacheTracingFlag() { - g_tracing_enabled = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( - TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking")); -} - InvalidationSet::InvalidationSet(InvalidationType type) : type_(static_cast<unsigned>(type)), invalidates_self_(false),
diff --git a/third_party/blink/renderer/core/css/invalidation/invalidation_set.h b/third_party/blink/renderer/core/css/invalidation/invalidation_set.h index f002305..d5c4445 100644 --- a/third_party/blink/renderer/core/css/invalidation/invalidation_set.h +++ b/third_party/blink/renderer/core/css/invalidation/invalidation_set.h
@@ -117,8 +117,6 @@ return GetType() == InvalidationType::kInvalidateNthSiblings; } - static void CacheTracingFlag(); - bool InvalidatesElement(Element&) const; bool InvalidatesTagName(Element&) const;
diff --git a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc index 25edf33..11e38af8 100644 --- a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc +++ b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
@@ -18,10 +18,6 @@ namespace blink { -PendingInvalidations::PendingInvalidations() { - InvalidationSet::CacheTracingFlag(); -} - void PendingInvalidations::ScheduleInvalidationSetsForNode( const InvalidationLists& invalidation_lists, ContainerNode& node) {
diff --git a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h index 0ecaceb..5680db9c 100644 --- a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h +++ b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h
@@ -65,7 +65,7 @@ DISALLOW_NEW(); public: - PendingInvalidations(); + PendingInvalidations() = default; PendingInvalidations(const PendingInvalidations&) = delete; PendingInvalidations& operator=(const PendingInvalidations&) = delete; ~PendingInvalidations() {}
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index ca890ff..0112f57 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -5350,7 +5350,7 @@ // Remove focus from the existing focus node (if any) if (old_focused_element) { old_focused_element->SetFocused(false, params.type); - old_focused_element->SetHasFocusWithinUpToAncestor(false, ancestor); + old_focused_element->SetHasFocusWithinUpToAncestor(false, ancestor, true); DisplayLockUtilities::ElementLostFocus(old_focused_element); @@ -5426,7 +5426,7 @@ if (focused_element_ == nullptr) { return false; } - focused_element_->SetHasFocusWithinUpToAncestor(true, ancestor); + focused_element_->SetHasFocusWithinUpToAncestor(true, ancestor, true); DisplayLockUtilities::ElementGainedFocus(focused_element_.Get()); // Element::setFocused for frames can dispatch events.
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 9f3cca1..5af705e1 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -6363,11 +6363,33 @@ PseudoStateChanged(CSSSelector::kPseudoFocusWithin); } -void Element::SetHasFocusWithinUpToAncestor(bool flag, Element* ancestor) { - for (Element* element = this; element && element != ancestor; +void Element::SetHasFocusWithinUpToAncestor(bool flag, + Element* ancestor, + bool need_snap_container_search) { + bool reached_ancestor = false; + for (Element* element = this; + element && (need_snap_container_search || !reached_ancestor); element = FlatTreeTraversal::ParentElement(*element)) { - element->SetHasFocusWithin(flag); - element->FocusWithinStateChanged(); + if (!reached_ancestor && element != ancestor) { + element->SetHasFocusWithin(flag); + element->FocusWithinStateChanged(); + } + // If |ancestor| or any of its ancestors is a snap container, that snap + // container needs to know which one of its descendants newly gained or lost + // focus even if its own HasFocusWithin state has not changed. + if (element != this && need_snap_container_search) { + if (const auto* box = element->GetLayoutBoxForScrolling()) { + if (box->Style() && !box->Style()->GetScrollSnapType().is_none) { + if (GetDocument().GetFrame() && GetDocument().GetFrame()->View()) { + // Tag the enclosing snap container for an update so it can be + // updated with focus information. + GetDocument().GetFrame()->View()->AddPendingSnapUpdate( + box->GetScrollableArea()); + } + } + } + } + reached_ancestor |= element == ancestor; } }
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index 64c9c7e9..5eb1904 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -850,7 +850,9 @@ void Focus(const FocusOptions*); virtual void SetFocused(bool received, mojom::blink::FocusType); - void SetHasFocusWithinUpToAncestor(bool, Element* ancestor); + void SetHasFocusWithinUpToAncestor(bool, + Element* ancestor, + bool need_snap_container_search = false); void FocusStateChanged(); void FocusVisibleStateChanged(); void FocusWithinStateChanged();
diff --git a/third_party/blink/renderer/core/frame/device_single_window_event_controller.h b/third_party/blink/renderer/core/frame/device_single_window_event_controller.h index d60f66f1..55a9aca 100644 --- a/third_party/blink/renderer/core/frame/device_single_window_event_controller.h +++ b/third_party/blink/renderer/core/frame/device_single_window_event_controller.h
@@ -42,6 +42,10 @@ virtual const AtomicString& EventTypeName() const = 0; virtual bool IsNullEvent(Event*) const = 0; + void set_needs_checking_null_events(bool enabled) { + needs_checking_null_events_ = enabled; + } + private: bool needs_checking_null_events_; };
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc index a7c27cc..64a5705 100644 --- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc +++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
@@ -256,6 +256,8 @@ snap_area_data.must_snap = (area_style->ScrollSnapStop() == EScrollSnapStop::kAlways); + snap_area_data.has_focus_within = snap_area.GetNode()->HasFocusWithin(); + snap_area_data.element_id = CompositorElementIdFromDOMNodeId(snap_area.GetNode()->GetDomNodeId());
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc index 6c22d9f9..6f467d53 100644 --- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
@@ -445,7 +445,7 @@ cc::SnapStrictness::kMandatory), gfx::RectF(10, 10, width - 20, height - 20), max_position); cc::SnapAreaData expected_area(cc::ScrollSnapAlign(cc::SnapAlignment::kStart), - gfx::RectF(192, 192, 116, 116), false, + gfx::RectF(192, 192, 116, 116), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); @@ -480,7 +480,7 @@ cc::SnapStrictness::kMandatory), gfx::RectF(10, 10, width - 20, height - 20), max_position); cc::SnapAreaData expected_area(cc::ScrollSnapAlign(cc::SnapAlignment::kStart), - gfx::RectF(192, 192, 116, 116), false, + gfx::RectF(192, 192, 116, 116), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); @@ -541,7 +541,7 @@ gfx::RectF(0, 0, width, height), max_position); cc::SnapAreaData expected_area(cc::ScrollSnapAlign(cc::SnapAlignment::kStart), - gfx::RectF(200, 200, 100, 100), false, + gfx::RectF(200, 200, 100, 100), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); @@ -588,7 +588,7 @@ // rect.height = area.height + // 2 * (area.padding + area.border + area.scroll-margin) cc::SnapAreaData expected_area(cc::ScrollSnapAlign(cc::SnapAlignment::kStart), - gfx::RectF(208, 208, 144, 144), false, + gfx::RectF(208, 208, 144, 144), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); @@ -623,7 +623,7 @@ cc::SnapStrictness::kMandatory), gfx::RectF(10, 10, width - 20, height - 20), max_position); cc::SnapAreaData expected_area(cc::ScrollSnapAlign(cc::SnapAlignment::kStart), - gfx::RectF(208, 208, 84, 84), false, + gfx::RectF(208, 208, 84, 84), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); @@ -669,7 +669,7 @@ gfx::RectF(16, 10, width - 28, height - 24), max_position); cc::SnapAreaData expected_area( cc::ScrollSnapAlign(cc::SnapAlignment::kCenter), - gfx::RectF(192, 198, 112, 108), false, cc::ElementId(10)); + gfx::RectF(192, 198, 112, 108), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); EXPECT_EQ_CONTAINER(expected_container, actual_container); @@ -705,7 +705,7 @@ // The area is scaled from center, so it pushes the area's top-left corner to // (50, 50). cc::SnapAreaData expected_area(cc::ScrollSnapAlign(cc::SnapAlignment::kEnd), - gfx::RectF(42, 42, 416, 416), false, + gfx::RectF(42, 42, 416, 416), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); @@ -744,7 +744,7 @@ // and 'end' should align to the left. cc::SnapAreaData expected_area( cc::ScrollSnapAlign(cc::SnapAlignment::kStart, cc::SnapAlignment::kEnd), - gfx::RectF(192, 192, 116, 116), false, cc::ElementId(10)); + gfx::RectF(192, 192, 116, 116), false, false, cc::ElementId(10)); expected_container.AddSnapAreaData(expected_area); EXPECT_EQ_CONTAINER(expected_container, actual_container);
diff --git a/third_party/blink/renderer/core/paint/text_painter.cc b/third_party/blink/renderer/core/paint/text_painter.cc index 19e6a5a6..0da0a2ef 100644 --- a/third_party/blink/renderer/core/paint/text_painter.cc +++ b/third_party/blink/renderer/core/paint/text_painter.cc
@@ -241,18 +241,45 @@ if (!fragment_paint_info.shape_result) { return; } + DCHECK_LE(fragment_paint_info.from, fragment_paint_info.text.length()); + DCHECK_LE(fragment_paint_info.to, fragment_paint_info.text.length()); + GraphicsContextStateSaver state_saver(graphics_context_, false); UpdateGraphicsContext(graphics_context_, text_style, state_saver, shadow_mode); // TODO(layout-dev): Handle combine text here or elsewhere. - PaintInternalFragment<kPaintText>(fragment_paint_info, node_id, - auto_dark_mode); + if (svg_text_paint_state_.has_value()) { + const AutoDarkMode svg_text_auto_dark_mode( + DarkModeFilter::ElementRole::kSVG, + auto_dark_mode.enabled && + !svg_text_paint_state_->IsRenderingClipPathAsMaskImage()); + PaintSvgTextFragment(fragment_paint_info, node_id, svg_text_auto_dark_mode); + } else { + graphics_context_.DrawText(font_, fragment_paint_info, + gfx::PointF(text_origin_), node_id, + auto_dark_mode); + } if (!emphasis_mark_.empty()) { if (text_style.emphasis_mark_color != text_style.fill_color) graphics_context_.SetFillColor(text_style.emphasis_mark_color); - PaintInternalFragment<kPaintEmphasisMark>(fragment_paint_info, node_id, - auto_dark_mode); + graphics_context_.DrawEmphasisMarks( + font_, fragment_paint_info, emphasis_mark_, + gfx::PointF(text_origin_) + gfx::Vector2dF(0, emphasis_mark_offset_), + auto_dark_mode); + } + + // TODO(sohom): SubstringContainsOnlyWhitespaceOrEmpty() does not check + // for all whitespace characters as defined in the spec definition of + // whitespace. See https://w3c.github.io/paint-timing/#non-empty + // In particular 0xb and 0xc are not checked. + if (!fragment_paint_info.text.SubstringContainsOnlyWhitespaceOrEmpty( + fragment_paint_info.from, fragment_paint_info.to)) { + graphics_context_.GetPaintController().SetTextPainted(); + } + + if (!font_.ShouldSkipDrawing()) { + PaintTimingDetector::NotifyTextPaint(visual_rect_); } } @@ -360,47 +387,6 @@ } } -template <TextPainter::PaintInternalStep step> -void TextPainter::PaintInternalFragment( - const TextFragmentPaintInfo& fragment_paint_info, - DOMNodeId node_id, - const AutoDarkMode& auto_dark_mode) { - DCHECK(fragment_paint_info.from <= fragment_paint_info.text.length()); - DCHECK(fragment_paint_info.to <= fragment_paint_info.text.length()); - - if (step == kPaintEmphasisMark) { - graphics_context_.DrawEmphasisMarks( - font_, fragment_paint_info, emphasis_mark_, - gfx::PointF(text_origin_) + gfx::Vector2dF(0, emphasis_mark_offset_), - auto_dark_mode); - } else { - DCHECK(step == kPaintText); - if (svg_text_paint_state_.has_value()) { - const AutoDarkMode svg_text_auto_dark_mode( - DarkModeFilter::ElementRole::kSVG, - auto_dark_mode.enabled && - !svg_text_paint_state_->IsRenderingClipPathAsMaskImage()); - PaintSvgTextFragment(fragment_paint_info, node_id, - svg_text_auto_dark_mode); - } else { - graphics_context_.DrawText(font_, fragment_paint_info, - gfx::PointF(text_origin_), node_id, - auto_dark_mode); - } - - // TODO(sohom): SubstringContainsOnlyWhitespaceOrEmpty() does not check - // for all whitespace characters as defined in the spec definition of - // whitespace. See https://w3c.github.io/paint-timing/#non-empty - // In particular 0xb and 0xc are not checked. - if (!fragment_paint_info.text.SubstringContainsOnlyWhitespaceOrEmpty( - fragment_paint_info.from, fragment_paint_info.to)) - graphics_context_.GetPaintController().SetTextPainted(); - - if (!font_.ShouldSkipDrawing()) - PaintTimingDetector::NotifyTextPaint(visual_rect_); - } -} - void TextPainter::ClipDecorationsStripe( const TextFragmentPaintInfo& fragment_paint_info, float upper,
diff --git a/third_party/blink/renderer/core/paint/text_painter.h b/third_party/blink/renderer/core/paint/text_painter.h index 6bae395..340383c3 100644 --- a/third_party/blink/renderer/core/paint/text_painter.h +++ b/third_party/blink/renderer/core/paint/text_painter.h
@@ -108,11 +108,6 @@ float dilation) override; private: - template <PaintInternalStep step> - void PaintInternalFragment(const TextFragmentPaintInfo&, - DOMNodeId node_id, - const AutoDarkMode& auto_dark_mode); - void PaintSvgTextFragment(const TextFragmentPaintInfo&, DOMNodeId node_id, const AutoDarkMode& auto_dark_mode);
diff --git a/third_party/blink/renderer/core/paint/text_painter_base.h b/third_party/blink/renderer/core/paint/text_painter_base.h index ef7ab1ca..113008f 100644 --- a/third_party/blink/renderer/core/paint/text_painter_base.h +++ b/third_party/blink/renderer/core/paint/text_painter_base.h
@@ -95,8 +95,6 @@ float stripe_width, float dilation) = 0; - enum PaintInternalStep { kPaintText, kPaintEmphasisMark }; - GraphicsContext& graphics_context_; const Font& font_; const LineRelativeOffset text_origin_;
diff --git a/third_party/blink/renderer/core/timing/background_tracing_helper.cc b/third_party/blink/renderer/core/timing/background_tracing_helper.cc index 37a3c75d..b330d63 100644 --- a/third_party/blink/renderer/core/timing/background_tracing_helper.cc +++ b/third_party/blink/renderer/core/timing/background_tracing_helper.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/timing/background_tracing_helper.h" +#include "base/containers/span.h" #include "base/feature_list.h" #include "base/hash/md5.h" #include "base/rand_util.h" @@ -274,7 +275,7 @@ // static uint32_t BackgroundTracingHelper::MD5Hash32(base::StringPiece string) { base::MD5Digest digest; - base::MD5Sum(string.data(), string.size(), &digest); + base::MD5Sum(base::as_byte_span(string), &digest); uint32_t value; DCHECK_GE(sizeof(digest.a), sizeof(value)); memcpy(&value, digest.a, sizeof(value));
diff --git a/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h b/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h index 1239cd6..184bb58 100644 --- a/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h +++ b/third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h
@@ -39,13 +39,6 @@ // Returns true if this object represents IDL null. bool IsNull() const { return !full_ && !small_data_; } - bool IsFull() const { return full_; } - - DOMArrayBufferView* Full() const { - DCHECK(IsFull()); - return full_; - } - // WARNING: The pointer returned by baseAddressMaybeOnStack() may point to // temporary storage that is only valid during the life-time of the // FlexibleArrayBufferView object. @@ -60,6 +53,8 @@ } private: + bool IsFull() const { return full_; } + void SetContents(v8::Local<v8::ArrayBufferView> array_buffer_view) { DCHECK(IsNull()); size_t size = array_buffer_view->ByteLength();
diff --git a/third_party/blink/renderer/modules/device_orientation/BUILD.gn b/third_party/blink/renderer/modules/device_orientation/BUILD.gn index 598f54db..fd6f67a1 100644 --- a/third_party/blink/renderer/modules/device_orientation/BUILD.gn +++ b/third_party/blink/renderer/modules/device_orientation/BUILD.gn
@@ -41,6 +41,5 @@ "//services/device/public/cpp/generic_sensor", "//services/device/public/mojom:generic_sensor", "//third_party/blink/renderer/modules/permissions", - "//third_party/blink/renderer/modules/sensor", ] }
diff --git a/third_party/blink/renderer/modules/device_orientation/DEPS b/third_party/blink/renderer/modules/device_orientation/DEPS index 8554a7c..6cd295a 100644 --- a/third_party/blink/renderer/modules/device_orientation/DEPS +++ b/third_party/blink/renderer/modules/device_orientation/DEPS
@@ -7,12 +7,10 @@ "+services/device/public/cpp/generic_sensor/sensor_reading.h", "+services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer.h", "+services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h", - "+ui/gfx/geometry/angle_conversions.h", "-third_party/blink/renderer/modules", "+third_party/blink/renderer/modules/device_orientation", "+third_party/blink/renderer/modules/event_modules.h", "+third_party/blink/renderer/modules/event_target_modules.h", "+third_party/blink/renderer/modules/modules_export.h", "+third_party/blink/renderer/modules/permissions", - "+third_party/blink/renderer/modules/sensor/sensor_inspector_agent.h", ]
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc index 775db78..90d87783 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
@@ -144,6 +144,20 @@ DidUpdateData(); } +void DeviceOrientationController::RestartPumpIfNeeded() { + if (!orientation_event_pump_ || !has_event_listener_) { + return; + } + // We do this to make sure that existing connections to + // device::mojom::blink::Sensor instances are dropped and GetSensor() is + // called again, so that e.g. the virtual sensors are used when added, or the + // real ones are used again when the virtual sensors are removed. + StopUpdating(); + set_needs_checking_null_events(/*enabled=*/true); + orientation_event_pump_.Clear(); + StartUpdating(); +} + void DeviceOrientationController::Trace(Visitor* visitor) const { visitor->Trace(override_orientation_data_); visitor->Trace(orientation_event_pump_);
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h index 0c59306..feb100f 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h +++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h
@@ -38,6 +38,8 @@ void SetOverride(DeviceOrientationData*); void ClearOverride(); + void RestartPumpIfNeeded(); + void Trace(Visitor*) const override; static void LogToConsolePolicyFeaturesDisabled(
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.cc index 0de0a77..630aa8ac 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.cc
@@ -5,28 +5,32 @@ #include "third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/inspector/inspected_frames.h" #include "third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h" -#include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h" -#include "third_party/blink/renderer/modules/sensor/sensor_inspector_agent.h" namespace blink { +namespace { + +constexpr char kInspectorConsoleMessage[] = + "A reload is required so that the existing AbsoluteOrientationSensor " + "and RelativeOrientationSensor objects on this page use the overridden " + "values that have been provided. To return to the normal behavior, you can " + "either close the inspector or disable the orientation override, and then " + "reload."; + +} // namespace + DeviceOrientationInspectorAgent::~DeviceOrientationInspectorAgent() = default; DeviceOrientationInspectorAgent::DeviceOrientationInspectorAgent( InspectedFrames* inspected_frames) : inspected_frames_(inspected_frames), - sensor_agent_(MakeGarbageCollected<SensorInspectorAgent>( - inspected_frames->Root()->DomWindow())), - enabled_(&agent_state_, /*default_value=*/false), - alpha_(&agent_state_, /*default_value=*/0.0), - beta_(&agent_state_, /*default_value=*/0.0), - gamma_(&agent_state_, /*default_value=*/0.0) {} + enabled_(&agent_state_, /*default_value=*/false) {} void DeviceOrientationInspectorAgent::Trace(Visitor* visitor) const { visitor->Trace(inspected_frames_); - visitor->Trace(sensor_agent_); InspectorBaseAgent::Trace(visitor); } @@ -39,13 +43,19 @@ DeviceOrientationInspectorAgent::setDeviceOrientationOverride(double alpha, double beta, double gamma) { + if (!enabled_.Get()) { + Controller().RestartPumpIfNeeded(); + + // If the device orientation override is switching to being enabled, warn + // about the effect it has on existing AbsoluteOrientationSensor and + // RelativeOrientationSensor instances. + inspected_frames_->Root()->DomWindow()->AddConsoleMessage( + MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kJavaScript, + mojom::blink::ConsoleMessageLevel::kInfo, + kInspectorConsoleMessage)); + } enabled_.Set(true); - alpha_.Set(alpha); - beta_.Set(beta); - gamma_.Set(gamma); - Controller().SetOverride( - DeviceOrientationData::Create(alpha, beta, gamma, false)); - sensor_agent_->SetOrientationSensorOverride(alpha, beta, gamma); return protocol::Response::Success(); } @@ -56,29 +66,17 @@ protocol::Response DeviceOrientationInspectorAgent::disable() { agent_state_.ClearAllFields(); - if (!inspected_frames_->Root()->DomWindow()->IsContextDestroyed()) - Controller().ClearOverride(); - sensor_agent_->Disable(); + if (!inspected_frames_->Root()->DomWindow()->IsContextDestroyed()) { + Controller().RestartPumpIfNeeded(); + } return protocol::Response::Success(); } void DeviceOrientationInspectorAgent::Restore() { - if (!enabled_.Get()) + if (!enabled_.Get()) { return; - Controller().SetOverride(DeviceOrientationData::Create( - alpha_.Get(), beta_.Get(), gamma_.Get(), false)); - sensor_agent_->SetOrientationSensorOverride(alpha_.Get(), beta_.Get(), - gamma_.Get()); -} - -void DeviceOrientationInspectorAgent::DidCommitLoadForLocalFrame( - LocalFrame* frame) { - if (frame == inspected_frames_->Root()) { - // New document in main frame - apply override there. - // No need to cleanup previous one, as it's already gone. - sensor_agent_->DidCommitLoadForLocalFrame(frame); - Restore(); } + Controller().RestartPumpIfNeeded(); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.h index 21151044..9c57acf 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.h +++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_inspector_agent.h
@@ -13,8 +13,15 @@ class DeviceOrientationController; class InspectedFrames; -class SensorInspectorAgent; +// This is the Blink part of the implementation of the DeviceOrientation CDP +// domain. Handling of this domain begins in DeviceOrientationHandler in +// content and reaches this class after initial processing. +// +// The code here is responsible for showing DevTools messages and restarting +// DeviceOrientationEventPump as necessary when overrides are enabled or +// disabled so that the Mojo connections are torn down and reestablished if +// required. class MODULES_EXPORT DeviceOrientationInspectorAgent final : public InspectorBaseAgent<protocol::DeviceOrientation::Metainfo> { public: @@ -36,17 +43,12 @@ protocol::Response disable() override; void Restore() override; - void DidCommitLoadForLocalFrame(LocalFrame*) override; private: DeviceOrientationController& Controller(); Member<InspectedFrames> inspected_frames_; - Member<SensorInspectorAgent> sensor_agent_; InspectorAgentState::Boolean enabled_; - InspectorAgentState::Double alpha_; - InspectorAgentState::Double beta_; - InspectorAgentState::Double gamma_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.cc index 24c065e..dd66030 100644 --- a/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.cc +++ b/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.cc
@@ -179,19 +179,6 @@ wheel_delta_y, std::move(callback)); } -void BrowserCaptureMediaStreamTrack::GetZoomLevel( - base::OnceCallback<void(std::optional<int>, const String&)> callback) { - const base::expected<MediaStreamVideoSource*, DOMException*> native_source = - GetNativeVideoSource(Component()); - if (!native_source.has_value()) { - // Note that BrowserCaptureMediaStreamTrack::GetZoomLevel() will shortly - // be removed (by m123), so this translation back to String is temporary. - std::move(callback).Run(std::nullopt, native_source.error()->message()); - return; - } - native_source.value()->GetZoomLevel(std::move(callback)); -} - void BrowserCaptureMediaStreamTrack::SetZoomLevel( int zoom_level, base::OnceCallback<void(DOMException*)> callback) {
diff --git a/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.h b/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.h index a03d777f..16024c89 100644 --- a/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.h +++ b/third_party/blink/renderer/modules/mediastream/browser_capture_media_stream_track.h
@@ -42,8 +42,6 @@ int wheel_delta_x, int wheel_delta_y, base::OnceCallback<void(DOMException*)> callback) override; - void GetZoomLevel(base::OnceCallback<void(std::optional<int>, const String&)> - callback) override; void SetZoomLevel(int zoom_level, base::OnceCallback<void(DOMException*)> callback) override;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.h b/third_party/blink/renderer/modules/mediastream/media_stream_track.h index 221923e..d46a333 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track.h +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.h
@@ -162,16 +162,6 @@ int wheel_delta_y, base::OnceCallback<void(DOMException*)> callback) = 0; - // When called on a "live" video track associated with tab-capture, - // returns the zoom level of the capture tab's viewport. - // This is subject to a permission policy on the capturing origin. - // - // If successful, |callback| is invoked with the zoom level in percentage - // points and an empty string. - // If unsuccessful, it is invoked with `std::nullopt` and an error message. - virtual void GetZoomLevel( - base::OnceCallback<void(std::optional<int>, const String&)> callback) = 0; - // When called on a "live" video track associated with tab-capture, asks to // set the zoom level on the captured tab's viewport. This is subject to a // permission policy on the capturing origin.
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc index 73eac83..3fa5351 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc
@@ -933,11 +933,6 @@ DOMExceptionCode::kNotSupportedError, "Unsupported.")); } -void MediaStreamTrackImpl::GetZoomLevel( - base::OnceCallback<void(std::optional<int>, const String&)> callback) { - std::move(callback).Run(std::nullopt, "Unsupported."); -} - void MediaStreamTrackImpl::SetZoomLevel( int zoom_level, base::OnceCallback<void(DOMException*)> callback) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h index fac5b24..638351bb 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h
@@ -134,8 +134,6 @@ int wheel_delta_x, int wheel_delta_y, base::OnceCallback<void(DOMException*)> callback) override; - void GetZoomLevel(base::OnceCallback<void(std::optional<int>, const String&)> - callback) override; void SetZoomLevel(int zoom_level, base::OnceCallback<void(DOMException*)> callback) override; #endif
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc index 2ddd382..b48951fb 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
@@ -69,17 +69,6 @@ CapturedSurfaceControlResult result) { std::move(callback).Run(CscResultToDOMException(result)); } - -void OnGetZoomLevelResult( - base::OnceCallback<void(std::optional<int>, const String&)> callback, - std::optional<int> zoom_level, - CapturedSurfaceControlResult result) { - // Note that OnGetZoomLevelResult() will shortly be removed (by m123), - // so this translation back to String is temporary. - const DOMException* const exception = CscResultToDOMException(result); - std::move(callback).Run(zoom_level, - /*error=*/exception ? exception->message() : ""); -} #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) } // namespace @@ -277,22 +266,6 @@ WTF::BindOnce(&OnCapturedSurfaceControlResult, std::move(callback))); } -void MediaStreamVideoCapturerSource::GetZoomLevel( - base::OnceCallback<void(std::optional<int>, const String&)> callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - const std::optional<base::UnguessableToken>& session_id = - device().serializable_session_id(); - if (!session_id.has_value()) { - std::move(callback).Run(std::nullopt, "Missing session ID."); - return; - } - - GetMediaStreamDispatcherHost()->GetZoomLevel( - session_id.value(), - WTF::BindOnce(&OnGetZoomLevelResult, std::move(callback))); -} - void MediaStreamVideoCapturerSource::SetZoomLevel( int zoom_level, base::OnceCallback<void(DOMException*)> callback) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h index bf82fab..b8d7bbcc 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
@@ -99,8 +99,6 @@ int wheel_delta_x, int wheel_delta_y, base::OnceCallback<void(DOMException*)> callback) override; - void GetZoomLevel(base::OnceCallback<void(std::optional<int>, const String&)> - callback) override; void SetZoomLevel(int zoom_level, base::OnceCallback<void(DOMException*)> callback) override; void ApplySubCaptureTarget(
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc index f97adf43..8dfa935 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
@@ -580,11 +580,6 @@ DOMExceptionCode::kNotSupportedError, "Unsupported.")); } -void MediaStreamVideoSource::GetZoomLevel( - base::OnceCallback<void(std::optional<int>, const String&)> callback) { - std::move(callback).Run(false, "Unsupported."); -} - void MediaStreamVideoSource::SetZoomLevel( int zoom_level, base::OnceCallback<void(DOMException*)> callback) {
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h index d2fddad..56a70ca 100644 --- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h +++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
@@ -94,11 +94,6 @@ (override)); MOCK_METHOD(void, - GetZoomLevel, - (base::OnceCallback<void(std::optional<int>, const String&)>), - (override)); - - MOCK_METHOD(void, SetZoomLevel, (int, base::OnceCallback<void(DOMException*)>), (override));
diff --git a/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h b/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h index 90d5403..3408f925 100644 --- a/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h +++ b/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h
@@ -61,8 +61,6 @@ void(const base::UnguessableToken&, mojom::blink::CapturedWheelActionPtr, SendWheelCallback)); - MOCK_METHOD2(GetZoomLevel, - void(const base::UnguessableToken&, GetZoomLevelCallback)); MOCK_METHOD3(SetZoomLevel, void(const base::UnguessableToken&, int32_t,
diff --git a/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.cc index d9f8da55a..9c466f5 100644 --- a/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.cc +++ b/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.cc
@@ -325,11 +325,6 @@ NOTREACHED_NORETURN(); } -void TransferredMediaStreamTrack::GetZoomLevel( - base::OnceCallback<void(std::optional<int>, const String&)> callback) { - NOTREACHED_NORETURN(); -} - void TransferredMediaStreamTrack::SetZoomLevel( int zoom_level, base::OnceCallback<void(DOMException*)> callback) {
diff --git a/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.h b/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.h index 120b4d1..afcf49f1 100644 --- a/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.h +++ b/third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.h
@@ -91,8 +91,6 @@ int wheel_delta_x, int wheel_delta_y, base::OnceCallback<void(DOMException*)> callback) override; - void GetZoomLevel(base::OnceCallback<void(std::optional<int>, const String&)> - callback) override; void SetZoomLevel(int zoom_level, base::OnceCallback<void(DOMException*)> callback) override; #endif
diff --git a/third_party/blink/renderer/modules/sensor/BUILD.gn b/third_party/blink/renderer/modules/sensor/BUILD.gn index 320d015..5b90970 100644 --- a/third_party/blink/renderer/modules/sensor/BUILD.gn +++ b/third_party/blink/renderer/modules/sensor/BUILD.gn
@@ -28,16 +28,12 @@ "sensor.h", "sensor_error_event.cc", "sensor_error_event.h", - "sensor_inspector_agent.cc", - "sensor_inspector_agent.h", "sensor_provider_proxy.cc", "sensor_provider_proxy.h", "sensor_proxy.cc", "sensor_proxy.h", "sensor_proxy_impl.cc", "sensor_proxy_impl.h", - "sensor_proxy_inspector_impl.cc", - "sensor_proxy_inspector_impl.h", "sensor_reading_remapper.cc", "sensor_reading_remapper.h", ]
diff --git a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc b/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc deleted file mode 100644 index 29297fd..0000000 --- a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/sensor/sensor_inspector_agent.h" - -#include "third_party/blink/renderer/core/frame/local_dom_window.h" -#include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/inspector/console_message.h" -#include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h" -#include "third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h" -#include "third_party/blink/renderer/platform/bindings/exception_code.h" -#include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/wtf/math_extras.h" - -namespace blink { - -SensorInspectorAgent::SensorInspectorAgent(LocalDOMWindow* window) - : provider_(SensorProviderProxy::From(window)) {} - -void SensorInspectorAgent::Trace(Visitor* visitor) const { - visitor->Trace(provider_); -} - -namespace { - -void FillQuaternion(double alpha, - double beta, - double gamma, - device::SensorReadingQuat* reading) { - double half_x_angle = Deg2rad(beta) * 0.5; - double half_y_angle = Deg2rad(gamma) * 0.5; - double half_z_angle = Deg2rad(alpha) * 0.5; - - double cos_z = cos(half_z_angle); - double sin_z = sin(half_z_angle); - double cos_y = cos(half_y_angle); - double sin_y = sin(half_y_angle); - double cos_x = cos(half_x_angle); - double sin_x = sin(half_x_angle); - - reading->x = sin_x * cos_y * cos_z - cos_x * sin_y * sin_z; - reading->y = cos_x * sin_y * cos_z + sin_x * cos_y * sin_z; - reading->z = cos_x * cos_y * sin_z + sin_x * sin_y * cos_z; - reading->w = cos_x * cos_y * cos_z - sin_x * sin_y * sin_z; -} - -void PopulateOrientationReading(double alpha, - double beta, - double gamma, - device::SensorReading* reading) { - FillQuaternion(alpha, beta, gamma, &reading->orientation_quat); - reading->orientation_quat.timestamp = - base::TimeTicks::Now().since_origin().InSecondsF(); -} - -const char kInspectorConsoleMessage[] = - "A reload is required so that the existing AbsoluteOrientationSensor and " - "RelativeOrientationSensor objects on this page use the overridden " - "values that have been provided. Close the inspector and reload again " - "to return to the normal behavior."; - -} // namespace - -void SensorInspectorAgent::DidCommitLoadForLocalFrame(LocalFrame* frame) { - LocalDOMWindow* current_window = provider_->GetSupplementable(); - LocalDOMWindow* new_window = frame->DomWindow(); - if (current_window != new_window) { - // We need to manually reset |provider_| to drop the strong reference it - // has to an old window that would otherwise be prevented from being - // deleted. - bool inspector_mode = provider_->inspector_mode(); - provider_ = SensorProviderProxy::From(new_window); - provider_->set_inspector_mode(inspector_mode); - } -} - -void SensorInspectorAgent::SetOrientationSensorOverride(double alpha, - double beta, - double gamma) { - if (!provider_->inspector_mode()) { - if (LocalDOMWindow* window = provider_->GetSupplementable()) { - auto* console_message = MakeGarbageCollected<ConsoleMessage>( - mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kInfo, kInspectorConsoleMessage); - window->AddConsoleMessage(console_message); - } - provider_->set_inspector_mode(true); - } - - using device::mojom::blink::SensorType; - SensorProxy* absolute = - provider_->GetSensorProxy(SensorType::ABSOLUTE_ORIENTATION_QUATERNION); - SensorProxy* relative = - provider_->GetSensorProxy(SensorType::RELATIVE_ORIENTATION_QUATERNION); - - if (!absolute && !relative) - return; - - device::SensorReading reading; - PopulateOrientationReading(alpha, beta, gamma, &reading); - - if (absolute) - absolute->SetReadingForInspector(reading); - if (relative) - relative->SetReadingForInspector(reading); -} - -void SensorInspectorAgent::Disable() { - provider_->set_inspector_mode(false); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.h b/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.h deleted file mode 100644 index 84a81133..0000000 --- a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_INSPECTOR_AGENT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_INSPECTOR_AGENT_H_ - -#include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/heap/member.h" - -namespace blink { - -class LocalDOMWindow; -class LocalFrame; -class SensorProviderProxy; - -class SensorInspectorAgent : public GarbageCollected<SensorInspectorAgent> { - public: - explicit SensorInspectorAgent(LocalDOMWindow* window); - - SensorInspectorAgent(const SensorInspectorAgent&) = delete; - SensorInspectorAgent& operator=(const SensorInspectorAgent&) = delete; - - virtual void Trace(Visitor*) const; - - void DidCommitLoadForLocalFrame(LocalFrame* frame); - - void SetOrientationSensorOverride(double alpha, double beta, double gamma); - - void Disable(); - - private: - Member<SensorProviderProxy> provider_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_INSPECTOR_AGENT_H_
diff --git a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc index a3fa4cc8..1bdcbe21 100644 --- a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc +++ b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
@@ -6,15 +6,12 @@ #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h" -#include "third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h" namespace blink { // SensorProviderProxy SensorProviderProxy::SensorProviderProxy(LocalDOMWindow& window) - : Supplement<LocalDOMWindow>(window), - sensor_provider_(&window), - inspector_mode_(false) {} + : Supplement<LocalDOMWindow>(window), sensor_provider_(&window) {} void SensorProviderProxy::InitializeIfNeeded() { if (sensor_provider_.is_bound()) @@ -56,13 +53,8 @@ Page* page) { DCHECK(!GetSensorProxy(type)); - SensorProxy* sensor = - inspector_mode_ - ? static_cast<SensorProxy*>( - MakeGarbageCollected<SensorProxyInspectorImpl>(type, this, - page)) - : static_cast<SensorProxy*>( - MakeGarbageCollected<SensorProxyImpl>(type, this, page)); + SensorProxy* sensor = static_cast<SensorProxy*>( + MakeGarbageCollected<SensorProxyImpl>(type, this, page)); sensor_proxies_.insert(sensor); return sensor;
diff --git a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h index 29aaa98..76866ff 100644 --- a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h +++ b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
@@ -39,9 +39,6 @@ void GetSensor(device::mojom::blink::SensorType, mojom::blink::WebSensorProviderProxy::GetSensorCallback); - void set_inspector_mode(bool flag) { inspector_mode_ = flag; } - bool inspector_mode() const { return inspector_mode_; } - void Trace(Visitor*) const override; private: @@ -56,7 +53,6 @@ HeapHashSet<WeakMember<SensorProxy>> sensor_proxies_; HeapMojoRemote<mojom::blink::WebSensorProvider> sensor_provider_; - bool inspector_mode_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/sensor/sensor_proxy.h b/third_party/blink/renderer/modules/sensor/sensor_proxy.h index d19cb14c..c13a38a 100644 --- a/third_party/blink/renderer/modules/sensor/sensor_proxy.h +++ b/third_party/blink/renderer/modules/sensor/sensor_proxy.h
@@ -58,7 +58,6 @@ device::mojom::blink::SensorConfigurationPtr) = 0; virtual double GetDefaultFrequency() const = 0; virtual std::pair<double, double> GetFrequencyLimits() const = 0; - virtual void SetReadingForInspector(const device::SensorReading&) {} virtual void ReportError(DOMExceptionCode code, const String& description); // Getters.
diff --git a/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc b/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc deleted file mode 100644 index acb07773..0000000 --- a/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h" - -#include "services/device/public/cpp/generic_sensor/sensor_traits.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h" -#include "third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/wtf/functional.h" -#include "third_party/blink/renderer/platform/wtf/math_extras.h" - -namespace blink { - -SensorProxyInspectorImpl::SensorProxyInspectorImpl( - device::mojom::blink::SensorType sensor_type, - SensorProviderProxy* provider, - Page* page) - : SensorProxy(sensor_type, provider, page) {} - -SensorProxyInspectorImpl::~SensorProxyInspectorImpl() {} - -void SensorProxyInspectorImpl::Trace(Visitor* visitor) const { - SensorProxy::Trace(visitor); -} - -void SensorProxyInspectorImpl::Initialize() { - if (state_ != kUninitialized) - return; - - state_ = kInitializing; - - auto callback = WTF::BindOnce(&SensorProxyInspectorImpl::OnSensorCreated, - WrapWeakPersistent(this)); - - sensor_provider_proxy() - ->GetSupplementable() - ->GetTaskRunner(TaskType::kSensor) - ->PostTask(FROM_HERE, std::move(callback)); -} - -void SensorProxyInspectorImpl::AddConfiguration( - device::mojom::blink::SensorConfigurationPtr configuration, - base::OnceCallback<void(bool)> callback) { - DCHECK(IsInitialized()); - std::move(callback).Run(true); -} - -void SensorProxyInspectorImpl::RemoveConfiguration( - device::mojom::blink::SensorConfigurationPtr configuration) { - DCHECK(IsInitialized()); -} - -double SensorProxyInspectorImpl::GetDefaultFrequency() const { - DCHECK(IsInitialized()); - return device::GetSensorDefaultFrequency(type_); -} - -std::pair<double, double> SensorProxyInspectorImpl::GetFrequencyLimits() const { - DCHECK(IsInitialized()); - return {1.0, device::GetSensorMaxAllowedFrequency(type_)}; -} - -void SensorProxyInspectorImpl::Suspend() { - suspended_ = true; -} - -void SensorProxyInspectorImpl::Resume() { - suspended_ = false; -} - -void SensorProxyInspectorImpl::SetReadingForInspector( - const device::SensorReading& reading) { - if (!ShouldProcessReadings()) - return; - - reading_ = reading; - for (Observer* observer : observers_) - observer->OnSensorReadingChanged(); -} - -void SensorProxyInspectorImpl::ReportError(DOMExceptionCode code, - const String& message) { - state_ = kUninitialized; - reading_ = device::SensorReading(); - SensorProxy::ReportError(code, message); -} - -void SensorProxyInspectorImpl::OnSensorCreated() { - DCHECK_EQ(kInitializing, state_); - - state_ = kInitialized; - - UpdateSuspendedStatus(); - - for (Observer* observer : observers_) - observer->OnSensorInitialized(); -} - -bool SensorProxyInspectorImpl::ShouldProcessReadings() const { - return IsInitialized() && !suspended_; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h b/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h deleted file mode 100644 index 53af614..0000000 --- a/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_PROXY_INSPECTOR_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_PROXY_INSPECTOR_IMPL_H_ - -#include "third_party/blink/renderer/modules/sensor/sensor_proxy.h" - -namespace blink { - -class SensorProxyInspectorImpl final : public SensorProxy { - public: - SensorProxyInspectorImpl(device::mojom::blink::SensorType sensor_type, - SensorProviderProxy* provider, - Page* page); - - SensorProxyInspectorImpl(const SensorProxyInspectorImpl&) = delete; - SensorProxyInspectorImpl& operator=(const SensorProxyInspectorImpl&) = delete; - - ~SensorProxyInspectorImpl() override; - - void Trace(Visitor*) const override; - - private: - // SensorProxy overrides. - void Initialize() override; - void AddConfiguration(device::mojom::blink::SensorConfigurationPtr, - base::OnceCallback<void(bool)>) override; - void RemoveConfiguration( - device::mojom::blink::SensorConfigurationPtr) override; - double GetDefaultFrequency() const override; - std::pair<double, double> GetFrequencyLimits() const override; - void SetReadingForInspector(const device::SensorReading&) override; - - void ReportError(DOMExceptionCode, const String&) override; - - private: - void OnSensorCreated(); - - // Returns 'true' if readings should be propagated to Observers - // (i.e. proxy is initialized, not suspended); - // returns 'false' otherwise. - bool ShouldProcessReadings() const; - - void Suspend() override; - void Resume() override; - - bool suspended_ = false; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_PROXY_INSPECTOR_IMPL_H_
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc index ecd4b37..1ec7506 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -225,6 +225,9 @@ case WGPURequestDeviceStatus_Error: case WGPURequestDeviceStatus_Unknown: + default: + // TODO(dawn:1987): Remove the default case after handling + // InstanceDropped. if (dawn_device) { // Immediately force the device to be lost. auto* device_lost_info = MakeGarbageCollected<GPUDeviceLostInfo>( @@ -245,8 +248,6 @@ StringFromASCIIAndUTF8(error_message)); } break; - default: - NOTREACHED(); } }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc index 1e3b44e..142fd5e 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -407,7 +407,11 @@ "The size is out of range"); break; default: - NOTREACHED(); + // TODO(dawn:1987): Remove the default case after handling + // InstanceDropped. + resolver->RejectWithDOMException(DOMExceptionCode::kAbortError, + "Device is lost"); + break; } }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc index 86dd72f..fa82cb9 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -404,16 +404,15 @@ case WGPUCreatePipelineAsyncStatus_InternalError: case WGPUCreatePipelineAsyncStatus_DeviceLost: case WGPUCreatePipelineAsyncStatus_DeviceDestroyed: - case WGPUCreatePipelineAsyncStatus_Unknown: { + case WGPUCreatePipelineAsyncStatus_Unknown: + default: { + // TODO(dawn:1987): Remove the default case after handling + // InstanceDropped. resolver->Reject(GPUPipelineError::Create( script_state->GetIsolate(), StringFromASCIIAndUTF8(message), V8GPUPipelineErrorReason::Enum::kInternal)); break; } - - default: { - NOTREACHED(); - } } }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc index 7b8f6578..2a043df 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -392,13 +392,14 @@ "Unknown failure in onSubmittedWorkDone"); break; case WGPUQueueWorkDoneStatus_DeviceLost: + default: + // TODO(dawn:1987): Remove the default case after handling + // InstanceDropped. resolver->RejectWithDOMException( DOMExceptionCode::kOperationError, "Device lost during onSubmittedWorkDone (do not use this error for " "recovery - it is NOT guaranteed to happen on device loss)"); break; - default: - NOTREACHED(); } }
diff --git a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist index c7acd737..bb05799 100644 --- a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist +++ b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
@@ -117,6 +117,66 @@ ../../web_tests/external/wpt/fonts/pass.woff ../../web_tests/external/wpt/fonts/sileot-webfont.woff ../../web_tests/external/wpt/fonts/tcu-font.woff +../../web_tests/images/bmp-suite/bad/badbitcount.bmp +../../web_tests/images/bmp-suite/bad/badbitssize.bmp +../../web_tests/images/bmp-suite/bad/baddens1.bmp +../../web_tests/images/bmp-suite/bad/baddens2.bmp +../../web_tests/images/bmp-suite/bad/badfilesize.bmp +../../web_tests/images/bmp-suite/bad/badheadersize.bmp +../../web_tests/images/bmp-suite/bad/badpalettesize.bmp +../../web_tests/images/bmp-suite/bad/badplanes.bmp +../../web_tests/images/bmp-suite/bad/badrle.bmp +../../web_tests/images/bmp-suite/bad/badrle4.bmp +../../web_tests/images/bmp-suite/bad/badrle4bis.bmp +../../web_tests/images/bmp-suite/bad/badrle4ter.bmp +../../web_tests/images/bmp-suite/bad/badrlebis.bmp +../../web_tests/images/bmp-suite/bad/badrleter.bmp +../../web_tests/images/bmp-suite/bad/badwidth.bmp +../../web_tests/images/bmp-suite/bad/pal8badindex.bmp +../../web_tests/images/bmp-suite/bad/reallybig.bmp +../../web_tests/images/bmp-suite/bad/rgb16-880.bmp +../../web_tests/images/bmp-suite/bad/rletopdown.bmp +../../web_tests/images/bmp-suite/bad/shortfile.bmp +../../web_tests/images/bmp-suite/good/pal1.bmp +../../web_tests/images/bmp-suite/good/pal1bg.bmp +../../web_tests/images/bmp-suite/good/pal1wb.bmp +../../web_tests/images/bmp-suite/good/pal4.bmp +../../web_tests/images/bmp-suite/good/pal4gs.bmp +../../web_tests/images/bmp-suite/good/pal4rle.bmp +../../web_tests/images/bmp-suite/good/pal8-0.bmp +../../web_tests/images/bmp-suite/good/pal8.bmp +../../web_tests/images/bmp-suite/good/pal8gs.bmp +../../web_tests/images/bmp-suite/good/pal8nonsquare.bmp +../../web_tests/images/bmp-suite/good/pal8os2.bmp +../../web_tests/images/bmp-suite/good/pal8rle.bmp +../../web_tests/images/bmp-suite/good/pal8topdown.bmp +../../web_tests/images/bmp-suite/good/pal8v4.bmp +../../web_tests/images/bmp-suite/good/pal8v5.bmp +../../web_tests/images/bmp-suite/good/pal8w124.bmp +../../web_tests/images/bmp-suite/good/pal8w125.bmp +../../web_tests/images/bmp-suite/good/pal8w126.bmp +../../web_tests/images/bmp-suite/good/rgb16-565.bmp +../../web_tests/images/bmp-suite/good/rgb16-565pal.bmp +../../web_tests/images/bmp-suite/good/rgb16.bmp +../../web_tests/images/bmp-suite/good/rgb16bfdef.bmp +../../web_tests/images/bmp-suite/good/rgb24.bmp +../../web_tests/images/bmp-suite/good/rgb24pal.bmp +../../web_tests/images/bmp-suite/good/rgb32.bmp +../../web_tests/images/bmp-suite/good/rgb32bf.bmp +../../web_tests/images/bmp-suite/good/rgb32bfdef.bmp +../../web_tests/images/bmp-suite/reference/pal1.png +../../web_tests/images/bmp-suite/reference/pal1bg.png +../../web_tests/images/bmp-suite/reference/pal4.png +../../web_tests/images/bmp-suite/reference/pal4gs.png +../../web_tests/images/bmp-suite/reference/pal8.png +../../web_tests/images/bmp-suite/reference/pal8gs.png +../../web_tests/images/bmp-suite/reference/pal8nonsquare-e.png +../../web_tests/images/bmp-suite/reference/pal8w124.png +../../web_tests/images/bmp-suite/reference/pal8w125.png +../../web_tests/images/bmp-suite/reference/pal8w126.png +../../web_tests/images/bmp-suite/reference/rgb16-565.png +../../web_tests/images/bmp-suite/reference/rgb16.png +../../web_tests/images/bmp-suite/reference/rgb24.png ../../web_tests/images/resources/0colors.ico ../../web_tests/images/resources/0x0.bmp ../../web_tests/images/resources/12-55.jpg @@ -322,6 +382,7 @@ ../../web_tests/images/resources/invalid-animated-webp2.webp ../../web_tests/images/resources/invalid-animated-webp3.webp ../../web_tests/images/resources/invalid-animated-webp4.webp +../../web_tests/images/resources/invalid-bitmap-offset.bmp ../../web_tests/images/resources/invalid.jpg ../../web_tests/images/resources/invalid_vp8_vp8x.webp ../../web_tests/images/resources/jpeg-height-exif-orientation.jpg
diff --git a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.globlist b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.globlist index 77e147cf..a1608090 100644 --- a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.globlist +++ b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.globlist
@@ -17,6 +17,8 @@ ../../web_tests/external/wpt/fonts/**/*.woff -../../web_tests/external/wpt/fonts/CSSTest/** ../../web_tests/images/resources/** +../../web_tests/images/bmp-suite/**/*.bmp +../../web_tests/images/bmp-suite/**/*.png ../../web_tests/third_party/**/*.ttf ../../web_tests/third_party/**/*.otf # pop(ignore-relative)
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc index 96639040..468369b 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -436,7 +436,7 @@ BufferSlice next_slice; unsigned run_start_index = slice.start_character_index; for (const BufferSlice* current_slice = &slice;;) { - auto run = ShapeResult::RunInfo::Create( + auto* run = MakeGarbageCollected<ShapeResult::RunInfo>( current_font, direction, canvas_rotation, script, run_start_index, current_slice->num_glyphs, current_slice->num_characters); unsigned next_start_glyph;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc index d46c565..4f020840 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -65,7 +65,7 @@ ASSERT_SIZE(HarfBuzzRunGlyphData, SameSizeAsHarfBuzzRunGlyphData); -struct SameSizeAsRunInfo : public RefCounted<SameSizeAsRunInfo> { +struct SameSizeAsRunInfo { struct GlyphDataCollection { void* pointers[2]; unsigned integer; @@ -166,7 +166,7 @@ return; unsigned result_start_index = StartIndex(); - for (const scoped_refptr<RunInfo>& run : runs_) { + for (const Member<RunInfo>& run : runs_) { if (!run) continue; DCHECK_GE(run->start_index_, result_start_index); @@ -423,13 +423,19 @@ direction_(other.direction_), has_vertical_offsets_(other.has_vertical_offsets_), is_applied_spacing_(other.is_applied_spacing_) { - runs_.reserve(other.runs_.size()); + runs_.ReserveInitialCapacity(other.runs_.size()); for (const auto& run : other.runs_) - runs_.push_back(run->Create(*run.get())); + runs_.push_back(MakeGarbageCollected<RunInfo>(*run)); } ShapeResult::~ShapeResult() = default; +void ShapeResult::Trace(Visitor* visitor) const { + visitor->Trace(deprecated_ink_bounds_); + visitor->Trace(runs_); + visitor->Trace(character_position_); +} + size_t ShapeResult::ByteSize() const { size_t self_byte_size = sizeof(*this); for (unsigned i = 0; i < runs_.size(); ++i) { @@ -460,10 +466,10 @@ const RunInfo* run = nullptr; const HarfBuzzRunGlyphData* glyph_data = nullptr; if (IsLtr()) { - run = runs_.front().get(); + run = runs_.front().Get(); glyph_data = &run->glyph_data_.front(); } else { - run = runs_.back().get(); + run = runs_.back().Get(); glyph_data = &run->glyph_data_.back(); } return glyph_data->safe_to_break_before && @@ -581,8 +587,7 @@ unsigned characters_so_far = IsRtl() ? NumCharacters() : 0; float current_x = 0; - for (const scoped_refptr<RunInfo>& run_ptr : runs_) { - const RunInfo* run = run_ptr.get(); + for (const Member<RunInfo>& run : runs_) { if (!run) continue; if (IsRtl()) @@ -721,7 +726,7 @@ bool ShapeResult::HasFallbackFonts() const { const SimpleFontData* primary_font = PrimaryFont(); - for (const scoped_refptr<RunInfo>& run : runs_) { + for (const Member<RunInfo>& run : runs_) { if (run->font_data_ != primary_font) { return true; } @@ -1172,11 +1177,10 @@ ShapeResult* sub_range = SubRange(start_offset, break_offset); // Remove the auto-spacing from the last glyph. - for (const scoped_refptr<RunInfo>& run : base::Reversed(sub_range->runs_)) { + for (const Member<RunInfo>& run : base::Reversed(sub_range->runs_)) { if (UNLIKELY(!run->NumGlyphs())) { continue; } - DCHECK(run->HasOneRef()); // Ensure it's copied and thus safe to modify. HarfBuzzRunGlyphData& last_glyph = run->glyph_data_.back(); DCHECK(PrimaryFont()); const float width = TextAutoSpace::GetSpacingWidth(*PrimaryFont()); @@ -1438,13 +1442,12 @@ run->CheckConsistency(); } -void ShapeResult::InsertRun(scoped_refptr<ShapeResult::RunInfo> run_to_insert, +void ShapeResult::InsertRun(ShapeResult::RunInfo* run, unsigned start_glyph, unsigned num_glyphs, unsigned* next_start_glyph, hb_buffer_t* harfbuzz_buffer) { DCHECK_GT(num_glyphs, 0u); - scoped_refptr<ShapeResult::RunInfo> run(std::move(run_to_insert)); const hb_glyph_info_t* glyph_infos = hb_buffer_get_glyph_infos(harfbuzz_buffer, nullptr); @@ -1460,47 +1463,41 @@ if (run->IsHorizontal()) { // Inserting a horizontal run into a horizontal or vertical result. - ComputeGlyphPositions<true>(run.get(), start_glyph, num_glyphs, - harfbuzz_buffer); + ComputeGlyphPositions<true>(run, start_glyph, num_glyphs, harfbuzz_buffer); } else { // Inserting a vertical run to a vertical result. - ComputeGlyphPositions<false>(run.get(), start_glyph, num_glyphs, - harfbuzz_buffer); + ComputeGlyphPositions<false>(run, start_glyph, num_glyphs, harfbuzz_buffer); } width_ += run->width_; num_glyphs_ += run->NumGlyphs(); DCHECK_GE(num_glyphs_, run->NumGlyphs()); - InsertRun(std::move(run)); + InsertRun(run); } -void ShapeResult::InsertRun(scoped_refptr<ShapeResult::RunInfo> run) { +void ShapeResult::InsertRun(ShapeResult::RunInfo* run) { // The runs are stored in result->m_runs in visual order. For LTR, we place // the run to be inserted before the next run with a bigger character start // index. - const auto ltr_comparer = [](scoped_refptr<RunInfo>& run, - unsigned start_index) { + const auto ltr_comparer = [](Member<RunInfo>& run, unsigned start_index) { return run->start_index_ < start_index; }; // For RTL, we place the run before the next run with a lower character // index. Otherwise, for both directions, at the end. - const auto rtl_comparer = [](scoped_refptr<RunInfo>& run, - unsigned start_index) { + const auto rtl_comparer = [](Member<RunInfo>& run, unsigned start_index) { return run->start_index_ > start_index; }; - Vector<scoped_refptr<RunInfo>>::iterator iterator = std::lower_bound( + auto* it = std::lower_bound( runs_.begin(), runs_.end(), run->start_index_, HB_DIRECTION_IS_FORWARD(run->direction_) ? ltr_comparer : rtl_comparer); - if (iterator != runs_.end()) { - runs_.insert(static_cast<wtf_size_t>(iterator - runs_.begin()), - std::move(run)); + if (it != runs_.end()) { + runs_.insert(static_cast<wtf_size_t>(it - runs_.begin()), run); + } else { + // If we didn't find an existing slot to place it, append. + runs_.push_back(run); } - - // If we didn't find an existing slot to place it, append. - if (run) - runs_.push_back(std::move(run)); } ShapeResult::RunInfo* ShapeResult::InsertRunForTesting( @@ -1508,7 +1505,7 @@ unsigned num_characters, TextDirection direction, Vector<uint16_t> safe_break_offsets) { - auto run = RunInfo::Create( + auto* run = MakeGarbageCollected<RunInfo>( nullptr, blink::IsLtr(direction) ? HB_DIRECTION_LTR : HB_DIRECTION_RTL, CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index, num_characters, num_characters); @@ -1521,9 +1518,8 @@ if (IsRtl()) run->glyph_data_.Reverse(); num_glyphs_ += run->NumGlyphs(); - RunInfo* run_ptr = run.get(); - InsertRun(std::move(run)); - return run_ptr; + InsertRun(run); + return run; } // Moves runs at (run_size_before, end) to the front of |runs_|. @@ -1536,22 +1532,22 @@ if (runs_.size() == run_size_before + 1) { if (!run_size_before) return; - scoped_refptr<RunInfo> new_run(std::move(runs_.back())); - runs_.Shrink(runs_.size() - 1); - runs_.push_front(std::move(new_run)); + RunInfo* new_run = runs_.back(); + runs_.pop_back(); + runs_.push_front(new_run); return; } // |push_front| is O(n) that we should not call it multiple times. // Create a new list in the correct order and swap it. - Vector<scoped_refptr<RunInfo>> new_runs; + HeapVector<Member<RunInfo>> new_runs; new_runs.ReserveInitialCapacity(runs_.size()); for (unsigned i = run_size_before; i < runs_.size(); i++) - new_runs.push_back(std::move(runs_[i])); + new_runs.push_back(runs_[i]); // Then append existing runs. for (unsigned i = 0; i < run_size_before; i++) - new_runs.push_back(std::move(runs_[i])); + new_runs.push_back(runs_[i]); runs_.swap(new_runs); } @@ -1636,16 +1632,16 @@ unsigned end = std::min(end_offset, run_end) - run_start; DCHECK(end > start); - if (scoped_refptr<RunInfo> sub_run = run->CreateSubRun(start, end)) { + if (RunInfo* sub_run = run->CreateSubRun(start, end)) { sub_run->start_index_ += index_diff; target->width_ += sub_run->width_; target->num_glyphs_ += sub_run->glyph_data_.size(); - if (auto merged_run = + if (auto* merged_run = should_merge ? target->runs_.back()->MergeIfPossible(*sub_run) - : scoped_refptr<RunInfo>()) { - target->runs_.back() = std::move(merged_run); + : nullptr) { + target->runs_.back() = merged_run; } else { - target->runs_.push_back(std::move(sub_run)); + target->runs_.push_back(sub_run); } } should_merge = false; @@ -1768,7 +1764,7 @@ float advance = font->TabWidth(font_data, tab_size, position); do { unsigned run_length = std::min(length, HarfBuzzRunGlyphData::kMaxGlyphs); - scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create( + RunInfo* run = MakeGarbageCollected<RunInfo>( font_data, hb_direction, CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index, run_length, run_length); float start_position = position; @@ -1782,7 +1778,7 @@ } run->width_ = position - start_position; result->width_ += run->width_; - result->runs_.push_back(std::move(run)); + result->runs_.push_back(run); DCHECK_GE(length, run_length); length -= run_length; start_index += run_length; @@ -1806,7 +1802,7 @@ font_data->PlatformData().IsVerticalAnyUpright(); hb_direction_t hb_direction = blink::IsLtr(direction) ? HB_DIRECTION_LTR : HB_DIRECTION_RTL; - scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create( + RunInfo* run = MakeGarbageCollected<RunInfo>( font_data, hb_direction, CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index, length, length); result->width_ = run->width_ = width; @@ -1816,7 +1812,7 @@ run->glyph_data_[i] = {font_data->SpaceGlyph(), index, true, width}; width = 0; } - result->runs_.push_back(std::move(run)); + result->runs_.push_back(run); return result; } @@ -1832,7 +1828,7 @@ hb_direction_t hb_direction = HB_DIRECTION_LTR; unsigned glyph_index = 0; - scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create( + RunInfo* run = MakeGarbageCollected<RunInfo>( font->PrimaryFont(), hb_direction, CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index, 1 /* num_glyph */, num_characters); run->glyph_data_[glyph_index] = {glyph_variant, 0 /* character index */, @@ -1842,7 +1838,7 @@ result->width_ = run->width_; result->num_glyphs_ = run->NumGlyphs(); - result->runs_.push_back(std::move(run)); + result->runs_.push_back(run); return result; } @@ -1864,7 +1860,7 @@ hb_direction_t hb_direction = is_horizontal_assembly ? HB_DIRECTION_LTR : HB_DIRECTION_TTB; - scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create( + RunInfo* run = MakeGarbageCollected<RunInfo>( font->PrimaryFont(), hb_direction, CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index, assembly_parameters.glyph_count, num_characters); @@ -1906,7 +1902,7 @@ result->width_ = run->width_; result->num_glyphs_ = run->NumGlyphs(); - result->runs_.push_back(std::move(run)); + result->runs_.push_back(run); return result; } @@ -2038,9 +2034,7 @@ return; } - Vector<ShapeResultCharacterData> character_position(num_characters_); - character_position_.swap(character_position); - + character_position_ = HeapVector<ShapeResultCharacterData>(num_characters_); RecalcCharacterPositions(); } @@ -2280,14 +2274,14 @@ for (const auto& run : runs_) { if (run->glyph_data_.HasNonZeroOffsets()) { if (run->IsHorizontal()) - ComputeRunInkBounds<true, true>(*run.get(), run_advance, &ink_bounds); + ComputeRunInkBounds<true, true>(*run, run_advance, &ink_bounds); else - ComputeRunInkBounds<false, true>(*run.get(), run_advance, &ink_bounds); + ComputeRunInkBounds<false, true>(*run, run_advance, &ink_bounds); } else { if (run->IsHorizontal()) - ComputeRunInkBounds<true, false>(*run.get(), run_advance, &ink_bounds); + ComputeRunInkBounds<true, false>(*run, run_advance, &ink_bounds); else - ComputeRunInkBounds<false, false>(*run.get(), run_advance, &ink_bounds); + ComputeRunInkBounds<false, false>(*run, run_advance, &ink_bounds); } run_advance += run->width_; }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h index 1eba5ed..e0718f13 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -41,6 +41,7 @@ #include "third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" +#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" #include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/text/text_direction.h" @@ -49,7 +50,6 @@ #include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/blink/renderer/platform/wtf/ref_counted.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -149,7 +149,7 @@ TextDirection); ShapeResult(const ShapeResult&); - void Trace(Visitor* visitor) const { visitor->Trace(deprecated_ink_bounds_); } + void Trace(Visitor*) const; static ShapeResult* CreateEmpty(const ShapeResult& other) { return MakeGarbageCollected<ShapeResult>(other.primary_font_, 0, 0, @@ -474,12 +474,12 @@ // Inserts as many glyphs as possible as a RunInfo, and sets // |next_start_glyph| to the start index of the remaining glyphs to be // inserted. - void InsertRun(scoped_refptr<ShapeResult::RunInfo>, + void InsertRun(ShapeResult::RunInfo*, unsigned start_glyph, unsigned num_glyphs, unsigned* next_start_glyph, hb_buffer_t*); - void InsertRun(scoped_refptr<ShapeResult::RunInfo>); + void InsertRun(ShapeResult::RunInfo*); void ReorderRtlRuns(unsigned run_size_before); template <bool is_horizontal_run, bool has_non_zero_glyph_offsets> @@ -488,7 +488,7 @@ gfx::RectF* ink_bounds) const; // Common signatures with ShapeResultView, to templatize algorithms. - const Vector<scoped_refptr<RunInfo>>& RunsOrParts() const { return runs_; } + const HeapVector<Member<RunInfo>>& RunsOrParts() const { return runs_; } unsigned StartIndexOffsetForRun() const { return 0; } // The total width. This is the sum of `RunInfo::width_`. @@ -501,7 +501,7 @@ // TODO(eae): Remove once LayoutNG lands. https://crbug.com/591099 Member<DeprecatedInkBounds> deprecated_ink_bounds_ = nullptr; - Vector<scoped_refptr<RunInfo>> runs_; + HeapVector<Member<RunInfo>> runs_; // Stores x-positions for quick mapping between offsets and x-positions. // Unlike the RunInfo and GlyphData, which operates in glyph order, this @@ -509,7 +509,7 @@ // advance for each character. Allowing constant time mapping from character // index to x-position and O(log n) time, using binary search, from // x-position to character index. - mutable Vector<ShapeResultCharacterData> character_position_; + mutable HeapVector<ShapeResultCharacterData> character_position_; scoped_refptr<const SimpleFontData> primary_font_; unsigned start_index_;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h index 68b8afd..e0882dfd 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -48,25 +48,9 @@ class SimpleFontData; -struct ShapeResult::RunInfo final : public RefCounted<ShapeResult::RunInfo> { - USING_FAST_MALLOC(RunInfo); - +struct ShapeResult::RunInfo final + : public GarbageCollected<ShapeResult::RunInfo> { public: - static scoped_refptr<RunInfo> Create(const SimpleFontData* font, - hb_direction_t dir, - CanvasRotationInVertical canvas_rotation, - hb_script_t script, - unsigned start_index, - unsigned num_glyphs, - unsigned num_characters) { - return base::AdoptRef(new RunInfo(font, dir, canvas_rotation, script, - start_index, num_glyphs, num_characters)); - } - - static scoped_refptr<RunInfo> Create(const RunInfo& other) { - return base::AdoptRef(new RunInfo(other)); - } - RunInfo(const SimpleFontData* font, hb_direction_t dir, CanvasRotationInVertical canvas_rotation, @@ -95,6 +79,8 @@ direction_(other.direction_), canvas_rotation_(other.canvas_rotation_) {} + void Trace(Visitor*) const {} + unsigned NumGlyphs() const { return glyph_data_.size(); } bool IsLtr() const { return HB_DIRECTION_IS_FORWARD(direction_); } bool IsRtl() const { return HB_DIRECTION_IS_BACKWARD(direction_); } @@ -134,7 +120,7 @@ // Creates a new RunInfo instance representing a subset of the current run. // Returns |nullptr| if there are no glyphs in the specified range. - scoped_refptr<RunInfo> CreateSubRun(unsigned start, unsigned end) { + RunInfo* CreateSubRun(unsigned start, unsigned end) { DCHECK(end > start); unsigned number_of_characters = std::min(end - start, num_characters_); auto glyphs = FindGlyphDataRange(start, end); @@ -143,9 +129,9 @@ if (UNLIKELY(!number_of_glyphs)) return nullptr; - auto run = - Create(font_data_.get(), direction_, canvas_rotation_, script_, - start_index_ + start, number_of_glyphs, number_of_characters); + auto* run = MakeGarbageCollected<RunInfo>( + font_data_.get(), direction_, canvas_rotation_, script_, + start_index_ + start, number_of_glyphs, number_of_characters); run->glyph_data_.CopyFromRange(glyphs); @@ -163,14 +149,14 @@ // Returns new |RunInfo| if |this| and |other| are merged. Otherwise returns // null. - scoped_refptr<RunInfo> MergeIfPossible(const RunInfo& other) const { + RunInfo* MergeIfPossible(const RunInfo& other) const { if (!CanMerge(other)) return nullptr; DCHECK_LT(start_index_, other.start_index_); - auto run = - Create(font_data_.get(), direction_, canvas_rotation_, script_, - start_index_, glyph_data_.size() + other.glyph_data_.size(), - num_characters_ + other.num_characters_); + auto* run = MakeGarbageCollected<RunInfo>( + font_data_.get(), direction_, canvas_rotation_, script_, start_index_, + glyph_data_.size() + other.glyph_data_.size(), + num_characters_ + other.num_characters_); // Note: We populate |graphemes_| on demand, e.g. hit testing. const int index_adjust = other.start_index_ - start_index_; if (UNLIKELY(IsRtl())) {
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc index a61d3ab..23951e0 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
@@ -17,13 +17,12 @@ namespace blink { -ShapeResultView::RunInfoPart::RunInfoPart( - scoped_refptr<const ShapeResult::RunInfo> run, - GlyphDataRange range, - unsigned start_index, - unsigned offset, - unsigned num_characters, - float width) +ShapeResultView::RunInfoPart::RunInfoPart(const ShapeResult::RunInfo* run, + GlyphDataRange range, + unsigned start_index, + unsigned offset, + unsigned num_characters, + float width) : run_(run), range_(range), start_index_(start_index), @@ -31,6 +30,10 @@ num_characters_(num_characters), width_(width) {} +void ShapeResultView::RunInfoPart::Trace(Visitor* visitor) const { + visitor->Trace(run_); +} + unsigned ShapeResultView::RunInfoPart::PreviousSafeToBreakOffset( unsigned offset) const { if (offset >= NumCharacters()) @@ -159,7 +162,7 @@ const Segment& segment) { return static_cast<unsigned>(base::ranges::count_if( result.RunsOrParts(), [&result, &segment](const auto& run_or_part) { - return !!RunInfoPart::ComputeStartEnd(*run_or_part.get(), result, + return !!RunInfoPart::ComputeStartEnd(*run_or_part.Get(), result, segment); })); } @@ -171,21 +174,15 @@ num_glyphs_(0), direction_(static_cast<unsigned>(data.direction)), has_vertical_offsets_(data.has_vertical_offsets), - char_index_offset_(data.char_index_offset), - num_parts_(data.num_parts) {} - -ShapeResultView::~ShapeResultView() { - for (auto& part : Parts()) - part.~RunInfoPart(); -} + char_index_offset_(data.char_index_offset) {} ShapeResult* ShapeResultView::CreateShapeResult() const { ShapeResult* new_result = MakeGarbageCollected<ShapeResult>( primary_font_, start_index_ + char_index_offset_, num_characters_, Direction()); - new_result->runs_.reserve(num_parts_); + new_result->runs_.ReserveInitialCapacity(parts_.size()); for (const auto& part : RunsOrParts()) { - auto new_run = ShapeResult::RunInfo::Create( + auto* new_run = MakeGarbageCollected<ShapeResult::RunInfo>( part.run_->font_data_.get(), part.run_->direction_, part.run_->canvas_rotation_, part.run_->script_, part.start_index_, part.NumGlyphs(), part.num_characters_); @@ -200,7 +197,7 @@ new_run->width_ = part.width_; new_run->num_characters_ = part.num_characters_; new_run->CheckConsistency(); - new_result->runs_.push_back(std::move(new_run)); + new_result->runs_.push_back(new_run); } new_result->num_glyphs_ = num_glyphs_; @@ -211,12 +208,8 @@ } template <class ShapeResultType> -ShapeResultView::RunInfoPart* ShapeResultView::PopulateRunInfoParts( - const ShapeResultType& other, - const Segment& segment, - RunInfoPart* part) { - DCHECK_GE(part, Parts().data()); - +void ShapeResultView::PopulateRunInfoParts(const ShapeResultType& other, + const Segment& segment) { // Compute the diff of index and the number of characters from the source // ShapeResult and given offsets, because computing them from runs/parts can // be inaccurate when all characters in a run/part are missing. @@ -228,7 +221,7 @@ std::max(segment.start_index, other.StartIndex()); for (const auto& run_or_part : other.RunsOrParts()) { - const auto* const run = run_or_part.get(); + const auto* const run = run_or_part.Get(); const auto part_start_end = RunInfoPart::ComputeStartEnd(*run, other, segment); if (!part_start_end) @@ -266,46 +259,24 @@ // Adjust start_index for runs to be continuous. const unsigned part_start_index = run_start + range_start + index_diff; const unsigned part_offset = range_start; - SECURITY_DCHECK(part + 1 <= Parts().data() + num_parts_); - new (part) RunInfoPart(run->GetRunInfo(), range, part_start_index, - part_offset, part_characters, part_width); - ++part; + parts_.emplace_back(run->GetRunInfo(), range, part_start_index, part_offset, + part_characters, part_width); num_glyphs_ += range.end - range.begin; width_ += part_width; } - return part; } -ShapeResultView::RunInfoPart* ShapeResultView::PopulateRunInfoParts( - const Segment& segment, - RunInfoPart* part) { +void ShapeResultView::PopulateRunInfoParts(const Segment& segment) { if (segment.result) { DCHECK(!segment.view); - return PopulateRunInfoParts(*segment.result, segment, part); - } - if (segment.view) { + PopulateRunInfoParts(*segment.result, segment); + } else if (segment.view) { DCHECK(!segment.result); - return PopulateRunInfoParts(*segment.view, segment, part); + PopulateRunInfoParts(*segment.view, segment); + } else { + NOTREACHED(); } - NOTREACHED(); - return nullptr; -} - -base::span<ShapeResultView::RunInfoPart> ShapeResultView::Parts() { - return {reinterpret_cast<ShapeResultView::RunInfoPart*>(parts_), num_parts_}; -} - -base::span<const ShapeResultView::RunInfoPart> ShapeResultView::Parts() const { - return {reinterpret_cast<const ShapeResultView::RunInfoPart*>(parts_), - num_parts_}; -} - -// static -constexpr size_t ShapeResultView::AdditionalByteSize(wtf_size_t num_parts) { - static_assert(sizeof(ShapeResultView) % alignof(RunInfoPart) == 0, - "We have RunInfoPart as flexible array in ShapeResultView"); - return sizeof(RunInfoPart) * num_parts; } ShapeResultView* ShapeResultView::Create(base::span<const Segment> segments) { @@ -313,24 +284,22 @@ InitData data; data.Populate(segments); - ShapeResultView* out = MakeGarbageCollected<ShapeResultView>( - AdditionalBytes(AdditionalByteSize(data.num_parts)), data); + ShapeResultView* out = MakeGarbageCollected<ShapeResultView>(data); DCHECK_EQ(out->num_characters_, 0u); DCHECK_EQ(out->num_glyphs_, 0u); DCHECK_EQ(out->width_, 0); + out->parts_.ReserveInitialCapacity(data.num_parts); // Segments are in logical order, runs and parts are in visual order. // Iterate over segments back-to-front for RTL. - RunInfoPart* part = out->Parts().data(); if (out->IsLtr()) { for (auto& segment : segments) - part = out->PopulateRunInfoParts(segment, part); + out->PopulateRunInfoParts(segment); } else { for (auto& segment : base::Reversed(segments)) - part = out->PopulateRunInfoParts(segment, part); + out->PopulateRunInfoParts(segment); } - CHECK_EQ(part, out->Parts().data() + out->num_parts_); - + DCHECK_EQ(data.num_parts, out->parts_.size()); return out; } @@ -354,16 +323,15 @@ InitData data; data.Populate(*result); - ShapeResultView* out = MakeGarbageCollected<ShapeResultView>( - AdditionalBytes(AdditionalByteSize(data.num_parts)), data); + ShapeResultView* out = MakeGarbageCollected<ShapeResultView>(data); DCHECK_EQ(out->num_characters_, 0u); DCHECK_EQ(out->num_glyphs_, 0u); DCHECK_EQ(out->width_, 0); + out->parts_.ReserveInitialCapacity(data.num_parts); const Segment segment = {result, 0, std::numeric_limits<unsigned>::max()}; - RunInfoPart* const part = - out->PopulateRunInfoParts(segment, out->Parts().data()); - CHECK_EQ(part, out->Parts().data() + out->num_parts_); + out->PopulateRunInfoParts(segment); + DCHECK_EQ(data.num_parts, out->parts_.size()); return out; } @@ -506,7 +474,7 @@ void* context) const { auto total_advance = initial_advance; - for (const auto& part : Parts()) { + for (const auto& part : parts_) { if (part.HasGlyphOffsets()) { total_advance = ForEachGlyphImpl<true>( total_advance, from, to, index_offset, glyph_callback, context, part); @@ -650,7 +618,7 @@ gfx::RectF ink_bounds; float run_advance = 0.0f; - for (const auto& part : Parts()) { + for (const auto& part : parts_) { if (part.HasGlyphOffsets()) { if (part.run_->IsHorizontal()) { ComputePartInkBounds<true, true>(part, run_advance, &ink_bounds); @@ -672,7 +640,7 @@ void ShapeResultView::ExpandRangeToIncludePartialGlyphs(unsigned* from, unsigned* to) const { - for (const auto& part : Parts()) { + for (const auto& part : parts_) { unsigned part_offset = char_index_offset_ + part.start_index_ - part.offset_; part.run_->ExpandRangeToIncludePartialGlyphs(
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h index a5d3283..f5df04a 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
@@ -108,9 +108,9 @@ explicit ShapeResultView(const InitData& data); ShapeResultView(const ShapeResultView&) = delete; ShapeResultView& operator=(const ShapeResultView&) = delete; - ~ShapeResultView(); + ~ShapeResultView() = default; - void Trace(Visitor*) const {} + void Trace(Visitor* visitor) const { visitor->Trace(parts_); } ShapeResult* CreateShapeResult() const; @@ -158,17 +158,19 @@ void ExpandRangeToIncludePartialGlyphs(unsigned* from, unsigned* to) const; - private: - // Note: We allocate |RunInfoPart| in flexible array in |ShapeResultView|. struct RunInfoPart { + DISALLOW_NEW(); + public: - RunInfoPart(scoped_refptr<const ShapeResult::RunInfo> run, + RunInfoPart(const ShapeResult::RunInfo* run, GlyphDataRange range, unsigned start_index, unsigned offset, unsigned num_characters, float width); + PLATFORM_EXPORT void Trace(Visitor*) const; + using const_iterator = const HarfBuzzRunGlyphData*; const_iterator begin() const { return range_.begin; } const_iterator end() const { return range_.end; } @@ -203,7 +205,7 @@ unsigned PreviousSafeToBreakOffset(unsigned offset) const; // Common signatures with RunInfo, to templatize algorithms. - const ShapeResult::RunInfo* GetRunInfo() const { return run_.get(); } + const ShapeResult::RunInfo* GetRunInfo() const { return run_.Get(); } const GlyphDataRange& GetGlyphDataRange() const { return range_; } GlyphDataRange FindGlyphDataRange(unsigned start_character_index, unsigned end_character_index) const; @@ -212,7 +214,7 @@ // The helper function for implementing |PopulateRunInfoParts()| for // handling iterating over |Vector<scoped_refptr<RunInfo>>| and // |base::span<RunInfoPart>|. - const RunInfoPart* get() const { return this; } + const RunInfoPart* Get() const { return this; } template <typename RunType, typename ShapeResultType> static unsigned ComputeStart(const RunType& run, @@ -250,7 +252,7 @@ return {{part_start, part_end}}; } - scoped_refptr<const ShapeResult::RunInfo> run_; + Member<const ShapeResult::RunInfo> run_; GlyphDataRange range_; // Start index for partial run, adjusted to ensure that runs are continuous. @@ -263,14 +265,14 @@ float width_; }; - RunInfoPart* PopulateRunInfoParts(const Segment& segment, RunInfoPart* part); + private: + void PopulateRunInfoParts(const Segment& segment); // Populates |parts_[]| and accumulates |num_characters_|, |num_glyphs_| and // |width_| from runs in |result|. template <class ShapeResultType> - RunInfoPart* PopulateRunInfoParts(const ShapeResultType& result, - const Segment& segment, - RunInfoPart* part); + void PopulateRunInfoParts(const ShapeResultType& result, + const Segment& segment); unsigned CharacterIndexOffsetForGlyphData(const RunInfoPart&) const; @@ -280,18 +282,10 @@ gfx::RectF* ink_bounds) const; // Common signatures with ShapeResult, to templatize algorithms. - base::span<const RunInfoPart> RunsOrParts() const { return Parts(); } - - base::span<RunInfoPart> Parts(); - - base::span<const RunInfoPart> Parts() const; + base::span<const RunInfoPart> RunsOrParts() const { return parts_; } unsigned StartIndexOffsetForRun() const { return char_index_offset_; } - // Returns byte size, aka allocation size, of |ShapeResultView| with - // |num_parts| count of |RunInfoPart| in flexible array member. - static constexpr size_t AdditionalByteSize(wtf_size_t num_parts); - scoped_refptr<const SimpleFontData> const primary_font_; const unsigned start_index_; @@ -314,14 +308,7 @@ // with ShapeResult::SubRange const unsigned char_index_offset_; - const wtf_size_t num_parts_; - - // TODO(yosin): We should declare |RunInfoPart| in this file to avoid using - // dummy struct. - // Note: To avoid declaring |RunInfoPart| here, we use dummy struct. - struct { - void* alignment; - } parts_[]; + HeapVector<RunInfoPart, 1> parts_; private: friend class ShapeResult; @@ -344,4 +331,7 @@ } // namespace blink +WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS( + blink::ShapeResultView::RunInfoPart) + #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_VIEW_H_
diff --git a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc index 1d4c0bb..038d9f7fc 100644 --- a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc +++ b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc
@@ -101,6 +101,19 @@ decoder->DecodeFrameBufferAtIndex(0); } +// Verify that decoding this image does not crash. +TEST(BMPImageDecoderTest, invalidBitmapOffset) { + static constexpr char kBmpFile[] = + "/images/resources/invalid-bitmap-offset.bmp"; + scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile); + ASSERT_TRUE(data.get()); + + std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder(); + decoder->SetData(data.get(), true); + decoder->DecodeFrameBufferAtIndex(0); + EXPECT_TRUE(decoder->Failed()); +} + // Verify that decoding an image with an unnecessary EOF marker does not crash. TEST(BMPImageDecoderTest, allowEOFWhenPastEndOfImage) { static constexpr char kBmpFile[] = "/images/resources/unnecessary-eof.bmp"; @@ -154,7 +167,30 @@ // "good" category, the test description states "not sure that the gamma // and chromaticity values in this file are sensible, because I can’t find // any detailed documentation of them" so a slight deviation seems fine. - // {"good/pal8v4", "pal8"}, + // {"good", "pal8v4", "pal8"}, + + // Bad images do not have a reference; we just need to verify that we can + // parse them without crashing. + {"bad", "badbitcount", nullptr}, + {"bad", "badbitssize", nullptr}, + {"bad", "baddens1", nullptr}, + {"bad", "baddens2", nullptr}, + {"bad", "badfilesize", nullptr}, + {"bad", "badheadersize", nullptr}, + {"bad", "badpalettesize", nullptr}, + {"bad", "badplanes", nullptr}, + {"bad", "badrle", nullptr}, + {"bad", "badrle4", nullptr}, + {"bad", "badrle4bis", nullptr}, + {"bad", "badrle4ter", nullptr}, + {"bad", "badrlebis", nullptr}, + {"bad", "badrleter", nullptr}, + {"bad", "badwidth", nullptr}, + {"bad", "pal8badindex", nullptr}, + {"bad", "reallybig", nullptr}, + {"bad", "rgb16-880", nullptr}, + {"bad", "rletopdown", nullptr}, + {"bad", "shortfile", nullptr}, }; for (const BMPSuiteEntry& entry : kBMPSuiteEntries) { @@ -168,6 +204,13 @@ std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder(); decoder->SetData(data.get(), /*all_data_received=*/true); ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); + if (!entry.png) { + // If there is no reference image, decoding the image without a crash is + // considered a success. + continue; + } + + // Verify that the BMP decoded successfully. ASSERT_EQ(ImageFrame::kFrameComplete, frame->GetStatus()); ASSERT_FALSE(decoder->Failed());
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.cc index 91558fe4..a3a8cf4a 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.cc
@@ -84,9 +84,9 @@ // Calculate MD5 sum. base::MD5Digest actual_digest; SkBitmap bitmap = frame_buffer->Bitmap(); - base::MD5Sum(bitmap.getPixels(), - bitmap.width() * bitmap.height() * sizeof(uint32_t), - &actual_digest); + auto bytes = base::make_span(static_cast<const uint8_t*>(bitmap.getPixels()), + bitmap.computeByteSize()); + base::MD5Sum(bytes, &actual_digest); // Read the MD5 sum off disk. std::string file_bytes;
diff --git a/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc b/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc index 3a3ff288..bb9c90d7 100644 --- a/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc +++ b/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc
@@ -425,9 +425,20 @@ // when the IEND chunk is found. This ensures that only complete frames are // reported, unless there is an error in the stream. char read_buffer[kPngReadBufferSize]; - while (reader.size() >= read_offset_ + 8) { - const png_byte* chunk = - ReadAsConstPngBytep(reader, read_offset_, 8, read_buffer); + for (;;) { + constexpr wtf_size_t kChunkHeaderSize = 8; + wtf_size_t chunk_start_offset; + if (!base::CheckAdd(read_offset_, kChunkHeaderSize) + .AssignIfValid(&chunk_start_offset)) { + // Overflow. + return false; + } + if (reader.size() < chunk_start_offset) { + // Insufficient data to decode the next chunk header. + break; + } + const png_byte* chunk = ReadAsConstPngBytep(reader, read_offset_, + kChunkHeaderSize, read_buffer); const wtf_size_t length = png_get_uint_32(chunk); if (length > PNG_UINT_31_MAX) { return false; @@ -435,7 +446,7 @@ wtf_size_t chunk_end_offset; if (!base::CheckAdd(read_offset_, base::CheckAdd(12, length)) .AssignIfValid(&chunk_end_offset)) { - // Overflow + // Overflow. return false; } @@ -572,14 +583,20 @@ } if (!parsed_signature_) { - if (reader.size() < read_offset_ + 8) { + constexpr wtf_size_t kNumSignatureBytes = 8; + wtf_size_t signature_end_offset; + if (!base::CheckAdd(read_offset_, kNumSignatureBytes) + .AssignIfValid(&signature_end_offset)) { + return false; + } + if (reader.size() < signature_end_offset) { return true; } - - const png_byte* chunk = - ReadAsConstPngBytep(reader, read_offset_, 8, read_buffer); - png_process_data(png_, info_, const_cast<png_byte*>(chunk), 8); - read_offset_ += 8; + const png_byte* chunk = ReadAsConstPngBytep( + reader, read_offset_, kNumSignatureBytes, read_buffer); + png_process_data(png_, info_, const_cast<png_byte*>(chunk), + kNumSignatureBytes); + read_offset_ = signature_end_offset; parsed_signature_ = true; new_frame_.start_offset = 0; }
diff --git a/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc b/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc index 236bf9d0..c6db51b 100644 --- a/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc +++ b/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
@@ -147,11 +147,11 @@ DCHECK(it->address.IsIPv6()); iface_addr = rtc::InterfaceAddress(ip_address, it->ip_address_attributes); - // Only allow non-private, non-deprecated IPv6 addresses which don't - // contain MAC. + // Only allow non-link-local, non-loopback, non-deprecated IPv6 addresses + // which don't contain MAC. if (rtc::IPIsMacBased(iface_addr) || (it->ip_address_attributes & net::IP_ADDRESS_ATTRIBUTE_DEPRECATED) || - rtc::IPIsPrivate(iface_addr)) { + rtc::IPIsLinkLocal(iface_addr) || rtc::IPIsLoopback(iface_addr)) { continue; }
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc b/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc index 0c85244..c033046 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc
@@ -69,7 +69,7 @@ ->estimated_capture_clock_offset.has_value()) { return std::nullopt; } - return webrtc::UQ32x32ToInt64Ms( + return webrtc::Q32x32ToInt64Ms( source_.absolute_capture_time()->estimated_capture_clock_offset.value()); }
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc b/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc index 31f0a39..105ab03 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source_test.cc
@@ -25,6 +25,7 @@ constexpr uint64_t kQ32x32Time1000ms = kUint64One << 32; constexpr uint64_t kQ32x32Time1250ms = kQ32x32Time1000ms | kUint64One << 30; constexpr uint64_t kQ32x32Time1500ms = kQ32x32Time1000ms | kUint64One << 31; +constexpr int64_t kQ32x32TimeNegative500ms = -(kUint64One << 31); } // namespace @@ -94,4 +95,16 @@ EXPECT_EQ(rtc_rtp_source.SenderCaptureTimeOffset(), 1500); } +TEST(RtcRtpSource, AbsoluteCaptureTimeSetAndReturnedWithNegativeOffset) { + constexpr webrtc::AbsoluteCaptureTime kAbsCaptureTime{ + .absolute_capture_timestamp = kQ32x32Time1250ms, + .estimated_capture_clock_offset = kQ32x32TimeNegative500ms}; + webrtc::RtpSource rtp_source( + kTimestamp, kSourceId, kSourceType, kRtpTimestamp, + /*extensions=*/{.absolute_capture_time = kAbsCaptureTime}); + RTCRtpSource rtc_rtp_source(rtp_source); + EXPECT_EQ(rtc_rtp_source.CaptureTimestamp(), 1250); + EXPECT_EQ(rtc_rtp_source.SenderCaptureTimeOffset(), -500); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 90832c44..da0795ec 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2816,7 +2816,7 @@ }, { name: "PageRevealEvent", - status: "experimental", + status: "stable", implied_by: ["ViewTransitionOnNavigation"], }, {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 15320627..9394404 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -211,6 +211,14 @@ crbug.com/1497170 external/wpt/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html [ Failure Pass ] crbug.com/1497170 external/wpt/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html [ Failure Pass ] +crbug.com/324053529 css3/filters/effect-reference-composite-hw.html [ Failure Pass ] +crbug.com/324053529 svg/batik/filters/feTile.svg [ Failure Pass ] +crbug.com/324053529 [ Linux ] compositing/reflections/masked-reflection-on-composited.html [ Failure Pass ] +crbug.com/324053529 [ Linux ] css3/filters/effect-all-on-background-hw.html [ Failure Pass ] +crbug.com/324053529 [ Linux ] css3/blending/effect-background-blend-mode-stacking.html [ Failure Pass ] +crbug.com/324053529 [ Mac ] virtual/scalefactor200/css3/filters/effect-reference-subregion-hw.html [ Failure Pass ] +crbug.com/324053529 [ Win ] virtual/scalefactor200/css3/filters/effect-reference-subregion-hw.html [ Failure Pass ] + # --- END Skia roll test suppresions @@ -2564,6 +2572,27 @@ crbug.com/626703 external/wpt/css/printing/table-overflow-quirks-frameset-crash-print.html [ Crash Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Win11-arm64 ] external/wpt/webtransport/echo-large-bidirectional-streams.https.any.sharedworker.html [ Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/fenced-frame-mparch/external/wpt/fenced-frame/frame-navigation.https.html [ Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/pna-workers-disabled/external/wpt/fetch/private-network-access/redirect.tentative.https.window.html [ Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/batch_normalization.https.any.html [ Crash ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/batch_normalization.https.any.worker.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv2d.https.any.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv2d.https.any.worker.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv_transpose2d.https.any.html [ Crash ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv_transpose2d.https.any.worker.html [ Crash ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/gemm.https.any.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/gemm.https.any.worker.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/instance_normalization.https.any.html [ Crash ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/instance_normalization.https.any.worker.html [ Crash ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/layer_normalization.https.any.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/layer_normalization.https.any.worker.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/matmul.https.any.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/matmul.https.any.worker.html [ Crash ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/pooling.https.any.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/pooling.https.any.worker.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/reduction.https.any.html [ Crash Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/reduction.https.any.worker.html [ Crash Timeout ] crbug.com/626703 external/wpt/mathml/relations/html5-tree/href-click-001.tentative.html [ Failure ] crbug.com/626703 external/wpt/mathml/relations/html5-tree/href-click-002.tentative.html [ Failure ] crbug.com/626703 external/wpt/mathml/relations/html5-tree/link-color-001.tentative.html [ Failure ] @@ -2871,8 +2900,7 @@ crbug.com/626703 [ Mac11 ] virtual/fenced-frame-mparch/external/wpt/fenced-frame/opaque-ad-sizes-exact-size.https.html [ Skip Timeout ] crbug.com/626703 [ Linux ] virtual/fenced-frame-mparch/external/wpt/fenced-frame/opaque-ad-sizes-special-cases.https.html [ Skip Timeout ] crbug.com/626703 [ Mac11 ] virtual/fenced-frame-mparch/external/wpt/fenced-frame/opaque-ad-sizes-special-cases.https.html [ Skip Timeout ] -crbug.com/626703 [ Win11 ] virtual/pending-beacon/external/wpt/pending-beacon/pending_beacon-sendonhidden.tentative.https.window.html [ Timeout ] -crbug.com/626703 [ Win10.20h2 ] virtual/pending-beacon/external/wpt/pending-beacon/pending_beacon-sendonhidden.tentative.https.window.html [ Timeout ] +crbug.com/626703 [ Win ] virtual/pending-beacon/external/wpt/pending-beacon/pending_beacon-sendonhidden.tentative.https.window.html [ Timeout ] crbug.com/626703 [ Debug Linux ] external/wpt/css/css-backgrounds/background-clip-padding-box-with-border-radius.html [ Failure ] crbug.com/626703 [ Debug Linux ] virtual/threaded/external/wpt/css/css-backgrounds/background-clip-padding-box-with-border-radius.html [ Failure ] crbug.com/626703 external/wpt/css/css-rhythm/block-step-size-establishes-independent-formatting-context-list-item.html [ Failure ] @@ -6715,3 +6743,6 @@ crbug.com/41496645 [ Linux ] external/wpt/css/css-contain/content-visibility/content-visibility-with-top-layer-008.html [ Failure Pass ] crbug.com/323752584 [ Win11-arm64 ] external/wpt/webnn/* [ Failure Pass ] crbug.com/41490297 virtual/speculation-rules-prerender-target-hint/external/wpt/speculation-rules/prerender/prerender-while-prerender.html [ Failure Pass ] + +# Gardener: 2024-02-06 +crbug.com/41491793 [ Mac ] virtual/disable-intersection-optimization/external/wpt/html/semantics/embedded-content/the-img-element/srcset/avoid-reload-on-resize.html [ Failure Pass ]
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 4b37a90..a5f36c3 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
@@ -378771,7 +378771,7 @@ [] ], "idlharness.window-expected.txt": [ - "db85b36f9dcc831238f52dac204840a402061749", + "1b543275c7840ecb3f3066948224367cac5baee7", [] ], "resources": { @@ -398231,11 +398231,11 @@ [] ], "idlharness.https.any-expected.txt": [ - "b1834d004289306e931c008bca6dc6e971c93684", + "162dc8882c16acf1f6f777e9c471a87a95b1e3bb", [] ], "idlharness.https.any.worker-expected.txt": [ - "2ecd4f6c825c84aeb700560ccd1a2e56ba089a5e", + "b74775ec1657afae222557d1379d1fa627978b02", [] ], "instance_normalization.https.any-expected.txt": [ @@ -477913,7 +477913,7 @@ ] ], "user-invalid.html": [ - "12a3b83862c014efffc46ea41ea804b2cfd6d7ed", + "5f8fa5811aff1b0cf333f5dc5bd173c6507b8810", [ null, { @@ -477922,7 +477922,7 @@ ] ], "user-valid.html": [ - "009286f0eb52aceaeea62d8f8e8acd741ab96555", + "7a12eb237d34af1645730435f44509a9af882677", [ null, { @@ -567060,28 +567060,28 @@ ] ] }, - "field-sizing-input-number.tentative.html": [ + "field-sizing-input-number.html": [ "859d35197b05ee31f350d157604308f5309ad372", [ null, {} ] ], - "field-sizing-input-text.tentative.html": [ + "field-sizing-input-text.html": [ "f421ad602c9391debca69ef282e8014271d7a4ec", [ null, {} ] ], - "field-sizing-select.tentative.html": [ + "field-sizing-select.html": [ "d55898105e8f6884dc61bddf8b8dcf91cf62c3c0", [ null, {} ] ], - "field-sizing-textarea.tentative.html": [ + "field-sizing-textarea.html": [ "f8d90dc659b119133cce6f651e7331d83c35fd3c", [ null, @@ -567105,7 +567105,7 @@ ] ], "input-text-size.html": [ - "7f2948280c072d120baf84cd56e540190911951b", + "fb3008df08f98f08bfa443fe1fb69cdc31a87a43", [ null, {} @@ -567119,7 +567119,7 @@ ] ], "textarea-cols-rows.html": [ - "012c5aa153dc34541c02899da8f30bb0524d3f47", + "6ad24a2eb8b399dacbc20b988932df7ba895db35", [ null, {} @@ -591667,7 +591667,7 @@ ] ], "loaf-source-location-redirect.html": [ - "a6bfd68f809af6bfeaf16a4c8feb86388ebfab09", + "c0bb96b1ec5bd982c0266d2c0da26060e2ccc2e5", [ null, { @@ -591676,7 +591676,7 @@ ] ], "loaf-source-location.html": [ - "cdd4bb4bbc9ec7f5f1a4b985aa005253c1d00726", + "51e85656443b9d4325ac7f073611b162289507b8", [ null, { @@ -591685,7 +591685,7 @@ ] ], "loaf-stream-source-location.html": [ - "79fb418f829b70970d643d217eaa91d0fb34b693", + "0fd30859d738dec410b9b8d20c0c9ba8c2f61294", [ null, {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element.html new file mode 100644 index 0000000..f15a291 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element.html
@@ -0,0 +1,128 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="help" href="https://drafts.csswg.org/css-scroll-snap" /> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/dom/events/scrolling/scroll_support.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> + <script src="resources/common.js" ></script> + </head> + <body> + <style> + .scroller { + overflow: scroll; + position: relative; + height: 400px; + width: 400px; + border:solid 1px black; + scroll-snap-type: y mandatory; + } + .no-snap { scroll-snap-align: none } + .scroller div:focus { + border: solid 1px red; + } + .large-space { + height: 300vh; + width: 300vw; + } + .target { + scroll-snap-align: start; + position: absolute; + width: 100px; + height: 100px; + border: solid 1px black; + } + .top { + top: 0px; + } + .left { + left: 0px; + } + .right { + left: 200px; + } + .bottom { + top: 200px; + } + </style> + <div id="scroller" class="scroller"> + <div class="large-space no-snap" tabindex="1" id="space"></div> + <div id="topleft" tabindex="1" class="top left target">top left</div> + <div id="topright" tabindex="1" class="top right target">top right</div> + <div id="bottomleft" tabindex="1" class="bottom left target">bottom left</div> + <div id="bottomright" tabindex="1" class="bottom right target">bottom right</div> + </div> + <script> + window.onload = () => { + const bottomright = document.getElementById("bottomright"); + const bottomleft = document.getElementById("bottomleft"); + const scroller = document.getElementById("scroller"); + + async function commonInitialization() { + await waitForCompositorCommit(); + assert_equals(scroller.scrollTop, 0, "snapped to top row"); + } + + promise_test(async (t) => { + await commonInitialization(); + + focusAndAssert(bottomright); + await runScrollSnapSelectionVerificationTest(t, scroller, + [bottomright, + bottomleft], + /*expected_target=*/bottomright, "y"); + + focusAndAssert(bottomleft); + await runScrollSnapSelectionVerificationTest(t, scroller, + [bottomright, + bottomleft], + /*expected_target=*/bottomleft, "y"); + }, "scroller selects focused target from aligned choices on snap"); + + promise_test(async (t) => { + t.add_cleanup(() => { + bottomright.style.left = "200px"; + }) + await commonInitialization(); + + // Move bottomright out of the snapport. + bottomright.style.left = "500px"; + + // Set focus on bottomright without scrolling to it. + focusAndAssert(bottomright, true); + await runScrollSnapSelectionVerificationTest(t, scroller, + [bottomright, + bottomleft], + /*expected_target=*/bottomleft, "y"); + }, "out-of-viewport focused element is not the selected snap target."); + + promise_test(async(t) => { + t.add_cleanup(() => { + bottomleft.style.top = "200px"; + }); + await commonInitialization(); + + // Set focus on bottomright without scrolling to it. + focusAndAssert(bottomright, true); + + // Move bottomleft below bottomright. + bottomleft.style.top = "400px"; + + // Snap to bottomleft. + scroller.scrollTop = bottomleft.offsetTop; + + // Test that if bottomright is also shifted so that it is aligned with + // bottomleft, bottomleft remains the selected snap target, despite + // bottomright's having focus. + await runLayoutSnapSeletionVerificationTest(t, scroller, [bottomright], + bottomleft, "y"); + }, "scroller follows selected snap target through layout shift," + + "regardless of focus"); + + } + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-nested-containers.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-nested-containers.html new file mode 100644 index 0000000..a6a0873 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-nested-containers.html
@@ -0,0 +1,109 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="help" href="https://drafts.csswg.org/css-scroll-snap" /> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/dom/events/scrolling/scroll_support.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> + <script src="resources/common.js" ></script> + </head> + <body> + <style> + .snap { + scroll-snap-align: start; + } + .placeholder { + height: 40%; + width: 40%; + position: absolute; + top: 0px; + border: solid 1px black; + } + .right { + left: 50%; + } + .container { + position: relative; + border: solid 1px blue; + overflow: scroll; + scroll-snap-type: y mandatory; + } + .bigcontainer { + height: 1000px; + width: 1000px; + } + .smallcontainer { + height: 400px; + width: 400px; + position: absolute; + border: solid 1px blue; + top: 500px; + overflow: scroll; + scroll-snap-type: y mandatory; + } + .large-space { + height: 300vh; + width: 300vw; + position: absolute; + } + .target { + top: 50%; + width: 40%; + height: 40%; + position: absolute; + border: solid 1px red; + } + .target:focus { + border:solid 2px green; + } + </style> + <div class="bigcontainer container" id="outercontainer"> + <div class="large-space"></div> + <div id="leftplaceholder" class="snap placeholder">LPH (outer)</div> + <div id="rightplaceholder" class="snap placeholder right">RPH (outer)</div> + <div id="leftcontainer" class="snap smallcontainer"> + <div class="large-space"></div> + <div class="snap placeholder"></div> + <div class="snap placeholder right"></div> + <div id="lefttarget1" tabindex="1" class="snap target"></div> + <div id="lefttarget2" tabindex="1" class="snap target right"></div> + </div> + <div id="rightcontainer" class="snap smallcontainer right"> + <div class="large-space"></div> + <div class="snap placeholder"></div> + <div class="snap placeholder right"></div> + <div id="righttarget1" tabindex="1" class="snap target"></div> + <div id="righttarget2" tabindex="1" class="snap target right"></div> + </div> + </div> + <script> + // This test verifies that a snap container (outer) which contains another + // snap container (inner) snaps with awareness of focus on children of the + // inner container, i.e. outer should prefer to select the snap area whose + // child has focus even if there is an intermediate snap container between + // the child and outer. + window.onload = () => { + const lefttarget1 = document.getElementById("lefttarget1"); + const righttarget1 = document.getElementById("righttarget1"); + const leftcontainer = document.getElementById("leftcontainer"); + const rightcontainer = document.getElementById("rightcontainer"); + const outercontainer = document.getElementById("outercontainer"); + + promise_test(async (t) => { + await waitForCompositorCommit(); + + focusAndAssert(lefttarget1, /*preventScroll=*/true); + await runScrollSnapSelectionVerificationTest(t, outercontainer, + [leftcontainer, rightcontainer], leftcontainer, "y"); + + focusAndAssert(righttarget1, /*preventScroll=*/true); + await runScrollSnapSelectionVerificationTest(t, outercontainer, + [leftcontainer, rightcontainer], rightcontainer, "y"); + }, "Snap container prefers focused nested snap target."); + } + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/resources/common.js b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/resources/common.js new file mode 100644 index 0000000..6ceec91 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/resources/common.js
@@ -0,0 +1,148 @@ +// Utility functions for scroll snap tests which verify User-Agents' snap point +// selection logic when multiple snap targets are aligned. +// It depends on methods in /resources/testdriver-actions.js and +// /dom/event/scrolling/scroll_support.js so html files using these functions +// should include those files as <script>s. + +// This function should be used by scroll snap WPTs wanting to test snap target +// selection when scrolling to multiple aligned targets. +// It assumes scroll-snap-align: start alignment and tries to align to the list +// of snap targets provided, |elements|, which are all expected to be at the +// same offset. +async function scrollToAlignedElementsInAxis(scroller, elements, axis) { + let target_offset_y = null; + let target_offset_x = null; + if (axis == "y") { + for (const e of elements) { + if (target_offset_y) { + assert_equals(e.offsetTop, target_offset_y, + `${e.id} is at y offset ${target_offset_y}`); + } else { + target_offset_y = e.offsetTop; + } + } + assert_equals(); + } else { + for (const e of elements) { + if (target_offset_x) { + assert_equals(e.offsetLeft, target_offset_x, + `${e.id} is at x offset ${target_offset_x}`); + } else { + target_offset_x = e.offsetLeft; + } + } + } + assert_not_equals(target_offset_x || target_offset_y, null); + + const scrollend_promise = waitForScrollendEventNoTimeout(scroller); + await new test_driver.Actions().scroll(0, 0, + (target_offset_x || 0) - scroller.scrollLeft, + (target_offset_y || 0) - scroller.scrollTop, + { origin: scroller }) + .send(); + await scrollend_promise; + if (axis == "y") { + assert_equals(scroller.scrollTop, target_offset_y, "vertical scroll done"); + } else { + assert_equals(scroller.scrollLeft,target_offset_x, "horizontal scroll done"); + } +} + +// This function verifies the snap target that a scroller picked by triggerring +// a layout change and observing which target is followed. Tests using this +// method should ensure that there is at least 100px of room to scroll in the +// desired axis. +// It assumes scroll-snap-align: start alignment. +function verifySelectedSnapTarget(scroller, expected_snap_target, axis) { + // Save initial style. + const initial_left = getComputedStyle(expected_snap_target).left; + const initial_top = getComputedStyle(expected_snap_target).top; + if (axis == "y") { + // Move the expected snap target along the y axis. + const initial_scroll_top = scroller.scrollTop; + const target_top = expected_snap_target.offsetTop + 100; + expected_snap_target.style.top = `${target_top}px`; + assert_equals(scroller.scrollTop, expected_snap_target.offsetTop, + `scroller followed ${expected_snap_target.id} after layout change`); + assert_not_equals(scroller.scrollTop, initial_scroll_top, + "scroller actually scrolled in y axis"); + } else { + // Move the expected snap target along the y axis. + const initial_scroll_left = scroller.scrollLeft; + const target_left = expected_snap_target.offsetLeft + 100; + expected_snap_target.style.left = `${target_left}px`; + assert_equals(scroller.scrollLeft, expected_snap_target.offsetLeft, + `scroller followed ${expected_snap_target.id} after layout change`); + assert_not_equals(scroller.scrollLeft, initial_scroll_left, + "scroller actually scrolled in x axis"); + } + // Undo style changes. + expected_snap_target.style.top = initial_top; + expected_snap_target.style.left = initial_left; +} + +// This is a utility function for tests which verify that the correct element +// is snapped to when snapping at the end of a scroll. +async function runScrollSnapSelectionVerificationTest(t, scroller, aligned_elements, + expected_target, axis) { + // Save initial scroll offset. + const initial_scroll_left = scroller.scrollLeft; + const initial_scroll_top = scroller.scrollTop; + await scrollToAlignedElementsInAxis(scroller, aligned_elements, axis); + verifySelectedSnapTarget(scroller, expected_target, axis); + // Restore initial scroll offsets. + const scrollend_promise = new Promise((resolve) => { + scroller.addEventListener("scrollend", resolve); + }); + scroller.scrollTo(initial_scroll_left, initial_scroll_top); + await scrollend_promise; +} + +// This is a utility function for tests verifying that a layout shift does not +// cause a scroller to change its selected snap target. +// It assumes the element to be aligned have scroll-snap-align: start. +// It tries to align the list of snap targets provided, |elements| with the +// current snap target. +function shiftLayoutToAlignElements(elements, target, axis) { + for (let element of elements) { + if (axis == "y") { + element.style.top = `${target.offsetTop}px`; + } else { + element.style.left = `${target.offsetLeft}px`; + } + } +} + +// This is a utility function for tests verifying that a layout shift does not +// cause a scroller to change its selected snap target. +// It assumes scroll-snap-align: start alignment. +async function runLayoutSnapSeletionVerificationTest(t, scroller, elements_to_align, + expected_target, axis) { + // Save initial scroll offsets and position. + const initial_scroll_left = scroller.scrollLeft; + const initial_scroll_top = scroller.scrollTop; + let initial_tops = []; + for (const element of elements_to_align) { + initial_tops.push(getComputedStyle(element).top); + } + + shiftLayoutToAlignElements(elements_to_align, expected_target, axis); + verifySelectedSnapTarget(scroller, expected_target, axis); + + // Restore initial scroll offset and position states. + let num_elements = initial_tops.length; + for (let i = 0; i < num_elements; i++) { + elements_to_align[i].style.top = initial_tops[i]; + } + // Restore initial scroll offsets. + const scrollend_promise = new Promise((resolve) => { + scroller.addEventListener("scrollend", resolve); + }); + scroller.scrollTo(initial_scroll_left, initial_scroll_top); + await scrollend_promise; +} + +function focusAndAssert(element, preventScroll=false) { + element.focus({preventScroll: preventScroll}); + assert_equals(document.activeElement, element); +}
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/direct-from-seller-signals.py b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/direct-from-seller-signals.py index e94b9c5..14f5ce1 100644 --- a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/direct-from-seller-signals.py +++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/direct-from-seller-signals.py
@@ -1,5 +1,7 @@ import json +from fledge.tentative.resources import fledge_http_server_util + # Script to return hardcoded "Ad-Auction-Signals" header to test header-based # directFromSellerSignals. Requires a "Sec-Ad-Auction-Fetch" header with value # of b"?1" in the request, otherwise returns a 400 response. @@ -10,160 +12,133 @@ # For all positive test cases, header "Buyer-Origin" is required to be the # origin in perBuyerSignals, otherwise return 400 response. def main(request, response): - # Append CORS headers if needed. - if b"origin" in request.headers: - response.headers.set(b"Access-Control-Allow-Origin", - request.headers.get(b"origin")) + if fledge_http_server_util.handle_cors_headers_and_preflight(request, response): + return - if b"credentials" in request.headers: - response.headers.set(b"Access-Control-Allow-Credentials", - request.headers.get(b"credentials")) + # Return 400 if there is no "Sec-Ad-Auction-Fetch" header. + if ("Sec-Ad-Auction-Fetch" not in request.headers or + request.headers.get("Sec-Ad-Auction-Fetch") != b"?1"): + response.status = (400, b"Bad Request") + response.headers.set(b"Content-Type", b"text/plain") + return "Failed to get Sec-Ad-Auction-Fetch in headers or its value is not \"?1\"." - # Handle CORS preflight requests. - if request.method == u"OPTIONS": - if not b"Access-Control-Request-Method" in request.headers: - response.status = (400, b"Bad Request") - response.headers.set(b"Content-Type", b"text/plain") - return "Failed to get access-control-request-method in preflight!" + # Return 500 to test http error. + if ("Negative-Test-Option" in request.headers and + request.headers.get("Negative-Test-Option") == b"HTTP Error"): + response.status = (500, b"Internal Error") + response.headers.set(b"Content-Type", b"text/plain") + return "Test http error with 500 response." - if not b"Access-Control-Request-Headers" in request.headers: - response.status = (400, b"Bad Request") - response.headers.set(b"Content-Type", b"text/plain") - return "Failed to get access-control-request-headers in preflight!" - - response.headers.set(b"Access-Control-Allow-Methods", - request.headers[b"Access-Control-Request-Method"]) - - response.headers.set(b"Access-Control-Allow-Headers", - request.headers[b"Access-Control-Request-Headers"]) - - response.status = (204, b"No Content") - return - - # Return 400 if there is no "Sec-Ad-Auction-Fetch" header. - if ("Sec-Ad-Auction-Fetch" not in request.headers or - request.headers.get("Sec-Ad-Auction-Fetch") != b"?1"): - response.status = (400, b"Bad Request") - response.headers.set(b"Content-Type", b"text/plain") - return "Failed to get Sec-Ad-Auction-Fetch in headers or its value is not \"?1\"." - - # Return 500 to test http error. - if ("Negative-Test-Option" in request.headers and - request.headers.get("Negative-Test-Option") == b"HTTP Error"): - response.status = (500, b"Internal Error") - response.headers.set(b"Content-Type", b"text/plain") - return "Test http error with 500 response." - - # Return 200 but without "Ad-Auction-Signals" header. - if ("Negative-Test-Option" in request.headers and - request.headers.get("Negative-Test-Option") == b"No Ad-Auction-Signals Header"): - response.status = (200, b"OK") - response.headers.set(b"Content-Type", b"text/plain") - return "Test 200 response without \"Ad-Auction-Signals\" header." - - # Return 200 but with invalid json in "Ad-Auction-Signals" header. - if ("Negative-Test-Option" in request.headers and - request.headers.get("Negative-Test-Option") == b"Invalid Json"): - response.status = (200, b"OK") - response.headers.set("Ad-Auction-Signals", b"[{\"adSlot\": \"adSlot\", \"sellerSignals\": \"sellerSignals\", \"auctionSignals\":}]") - response.headers.set(b"Content-Type", b"text/plain") - return "Test 200 response with invalid json in \"Ad-Auction-Signals\" header." - - # Return 404 but with valid "Ad-Auction-Signals" header to test network error. - if ("Negative-Test-Option" in request.headers and - request.headers.get("Negative-Test-Option") == b"Network Error"): - response.status = (404, b"Not Found") - adAuctionSignals = json.dumps( - [{ - "adSlot": "adSlot", - "sellerSignals": "sellerSignals", - "auctionSignals": "auctionSignals" - }]) - response.headers.set("Ad-Auction-Signals", adAuctionSignals) - response.headers.set(b"Content-Type", b"text/plain") - return "Test network error with 400 response code and valid \"Ad-Auction-Signals\" header." - - # For positive test cases, buyer-origin is required, otherwise return 400. - if "Buyer-Origin" not in request.headers: - response.status = (400, "Bad Request") - response.headers.set(b"Content-Type", b"text/plain") - return "Failed to get Buyer-Origin in headers." - + # Return 200 but without "Ad-Auction-Signals" header. + if ("Negative-Test-Option" in request.headers and + request.headers.get("Negative-Test-Option") == b"No Ad-Auction-Signals Header"): response.status = (200, b"OK") - buyerOrigin = request.headers.get("Buyer-Origin").decode('utf-8') + response.headers.set(b"Content-Type", b"text/plain") + return "Test 200 response without \"Ad-Auction-Signals\" header." - altResponse = request.headers.get("Alternative-Response") + # Return 200 but with invalid json in "Ad-Auction-Signals" header. + if ("Negative-Test-Option" in request.headers and + request.headers.get("Negative-Test-Option") == b"Invalid Json"): + response.status = (200, b"OK") + response.headers.set("Ad-Auction-Signals", b"[{\"adSlot\": \"adSlot\", \"sellerSignals\": \"sellerSignals\", \"auctionSignals\":}]") + response.headers.set(b"Content-Type", b"text/plain") + return "Test 200 response with invalid json in \"Ad-Auction-Signals\" header." - if altResponse == b"Overwrite adSlot/1": - adAuctionSignals = json.dumps( + # Return 404 but with valid "Ad-Auction-Signals" header to test network error. + if ("Negative-Test-Option" in request.headers and + request.headers.get("Negative-Test-Option") == b"Network Error"): + response.status = (404, b"Not Found") + adAuctionSignals = json.dumps( [{ - "adSlot": "adSlot/1", - "sellerSignals": "altSellerSignals/1", + "adSlot": "adSlot", + "sellerSignals": "sellerSignals", + "auctionSignals": "auctionSignals" }]) - elif altResponse == b"Overwrite adSlot/1 v2": - adAuctionSignals = json.dumps( - [{ - "adSlot": "adSlot/1", - "sellerSignals": "altV2SellerSignals/1", - }]) - elif altResponse == b"Two keys with same values": - adAuctionSignals = json.dumps( - [{ - "adSlot": "adSlot/1", - "sellerSignals": "sameSellerSignals", - "auctionSignals": "sameAuctionSignals", - "perBuyerSignals": { buyerOrigin: "samePerBuyerSignals" } - }, - { - "adSlot": "adSlot/2", - "sellerSignals": "sameSellerSignals", - "auctionSignals": "sameAuctionSignals", - "perBuyerSignals": { buyerOrigin: "samePerBuyerSignals" } - }]) - elif altResponse == b"Duplicate adSlot/1": - adAuctionSignals = json.dumps( - [{ - "adSlot": "adSlot/1", - "sellerSignals": "firstSellerSignals/1", - }, - { - "adSlot": "adSlot/2", - "sellerSignals": "nonDupSellerSignals/2", - }, - { - "adSlot": "adSlot/1", - "sellerSignals": "secondSellerSignals/1", - }]) - else: - adAuctionSignals = json.dumps( - [{ - "adSlot": "adSlot/0", - }, - { - "adSlot": "adSlot/1", - "sellerSignals": "sellerSignals/1", - }, - { - "adSlot": "adSlot/2", - "auctionSignals": "auctionSignals/2", - }, - { - "adSlot": "adSlot/3", - "perBuyerSignals": { buyerOrigin: "perBuyerSignals/3" } - }, - { - "adSlot": "adSlot/4", - "sellerSignals": "sellerSignals/4", - "auctionSignals": "auctionSignals/4", - "perBuyerSignals": { buyerOrigin: "perBuyerSignals/4" } - }, - { - "adSlot": "adSlot/5", - "sellerSignals": "sellerSignals/5", - "auctionSignals": "auctionSignals/5", - "perBuyerSignals": { "mismatchOrigin": "perBuyerSignals/5" } - }]) - response.headers.set("Ad-Auction-Signals", adAuctionSignals) response.headers.set(b"Content-Type", b"text/plain") - return + return "Test network error with 400 response code and valid \"Ad-Auction-Signals\" header." + + # For positive test cases, buyer-origin is required, otherwise return 400. + if "Buyer-Origin" not in request.headers: + response.status = (400, "Bad Request") + response.headers.set(b"Content-Type", b"text/plain") + return "Failed to get Buyer-Origin in headers." + + response.status = (200, b"OK") + buyerOrigin = request.headers.get("Buyer-Origin").decode('utf-8') + + altResponse = request.headers.get("Alternative-Response") + + if altResponse == b"Overwrite adSlot/1": + adAuctionSignals = json.dumps( + [{ + "adSlot": "adSlot/1", + "sellerSignals": "altSellerSignals/1", + }]) + elif altResponse == b"Overwrite adSlot/1 v2": + adAuctionSignals = json.dumps( + [{ + "adSlot": "adSlot/1", + "sellerSignals": "altV2SellerSignals/1", + }]) + elif altResponse == b"Two keys with same values": + adAuctionSignals = json.dumps( + [{ + "adSlot": "adSlot/1", + "sellerSignals": "sameSellerSignals", + "auctionSignals": "sameAuctionSignals", + "perBuyerSignals": { buyerOrigin: "samePerBuyerSignals" } + }, + { + "adSlot": "adSlot/2", + "sellerSignals": "sameSellerSignals", + "auctionSignals": "sameAuctionSignals", + "perBuyerSignals": { buyerOrigin: "samePerBuyerSignals" } + }]) + elif altResponse == b"Duplicate adSlot/1": + adAuctionSignals = json.dumps( + [{ + "adSlot": "adSlot/1", + "sellerSignals": "firstSellerSignals/1", + }, + { + "adSlot": "adSlot/2", + "sellerSignals": "nonDupSellerSignals/2", + }, + { + "adSlot": "adSlot/1", + "sellerSignals": "secondSellerSignals/1", + }]) + else: + adAuctionSignals = json.dumps( + [{ + "adSlot": "adSlot/0", + }, + { + "adSlot": "adSlot/1", + "sellerSignals": "sellerSignals/1", + }, + { + "adSlot": "adSlot/2", + "auctionSignals": "auctionSignals/2", + }, + { + "adSlot": "adSlot/3", + "perBuyerSignals": { buyerOrigin: "perBuyerSignals/3" } + }, + { + "adSlot": "adSlot/4", + "sellerSignals": "sellerSignals/4", + "auctionSignals": "auctionSignals/4", + "perBuyerSignals": { buyerOrigin: "perBuyerSignals/4" } + }, + { + "adSlot": "adSlot/5", + "sellerSignals": "sellerSignals/5", + "auctionSignals": "auctionSignals/5", + "perBuyerSignals": { "mismatchOrigin": "perBuyerSignals/5" } + }]) + + response.headers.set("Ad-Auction-Signals", adAuctionSignals) + response.headers.set(b"Content-Type", b"text/plain") + return
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge_http_server_util.py b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge_http_server_util.py index a5c9c97..162c93e 100644 --- a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge_http_server_util.py +++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge_http_server_util.py
@@ -1,7 +1,18 @@ -# Takes a map of header names to list of values that are all binary strings -# and returns an otherwise identical map where keys and values have both been -# converted to ASCII strings. -def headersToAscii(headers): +"""Utility functions shared across multiple endpoints.""" + + +def headers_to_ascii(headers): + """Converts a header map with binary values to one with ASCII values. + + Takes a map of header names to list of values that are all binary strings + and returns an otherwise identical map where keys and values have both been + converted to ASCII strings. + + Args: + headers: header map from binary key to binary value + + Returns header map from ASCII string key to ASCII string value + """ header_map = {} for pair in headers.items(): values = [] @@ -9,3 +20,48 @@ values.append(value.decode("ASCII")) header_map[pair[0].decode("ASCII")] = values return header_map + + +def handle_cors_headers_and_preflight(request, response): + """Applies CORS logic common to many entrypoints. + + Args: + request: the wptserve Request that was passed to main + response: the wptserve Response that was passed to main + + Returns True if the request is a CORS preflight, which is entirely handled by + this function, so that the calling function should immediately return. + """ + # Append CORS headers if needed + if b"origin" in request.headers: + response.headers.set(b"Access-Control-Allow-Origin", + request.headers.get(b"origin")) + + if b"credentials" in request.headers: + response.headers.set(b"Access-Control-Allow-Credentials", + request.headers.get(b"credentials")) + + # Handle CORS preflight requests. + if not request.method == u"OPTIONS": + return False + + if not b"Access-Control-Request-Method" in request.headers: + response.status = (400, b"Bad Request") + response.headers.set(b"Content-Type", b"text/plain") + response.content = "Failed to get access-control-request-method in preflight!" + return True + + if not b"Access-Control-Request-Headers" in request.headers: + response.status = (400, b"Bad Request") + response.headers.set(b"Content-Type", b"text/plain") + response.content = "Failed to get access-control-request-headers in preflight!" + return True + + response.headers.set(b"Access-Control-Allow-Methods", + request.headers[b"Access-Control-Request-Method"]) + + response.headers.set(b"Access-Control-Allow-Headers", + request.headers[b"Access-Control-Request-Headers"]) + + response.status = (204, b"No Content") + return True
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request-tracker.py b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request-tracker.py index 9fe20bf..c449d2a 100644 --- a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request-tracker.py +++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request-tracker.py
@@ -1,11 +1,12 @@ +import json import mimetypes import os -import json -import wptserve.stash -from fledge.tentative.resources.fledge_http_server_util import headersToAscii +from fledge.tentative.resources import fledge_http_server_util +import wptserve.stash from wptserve.utils import isomorphic_decode, isomorphic_encode + # Test server that tracks requests it has previously seen, keyed by a token. # # All requests have a "dispatch" field indicating what to do, and a "uuid" @@ -92,7 +93,7 @@ if server_state["trackedHeaders"] != None: server_state["errors"].append("Second track_headers request received.") else: - server_state["trackedHeaders"] = headersToAscii(request.headers) + server_state["trackedHeaders"] = fledge_http_server_util.headers_to_ascii(request.headers) stash.put(uuid, server_state) return simple_response(request, response, 200, b"OK", b"")
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-bidding-signals.py b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-bidding-signals.py index 5ec487f..45bede2 100644 --- a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-bidding-signals.py +++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-bidding-signals.py
@@ -1,6 +1,8 @@ import json from urllib.parse import unquote_plus -from fledge.tentative.resources.fledge_http_server_util import headersToAscii + +from fledge.tentative.resources import fledge_http_server_util + # Script to generate trusted bidding signals. The response depends on the # keys and interestGroupNames - some result in entire response failures, others @@ -103,7 +105,7 @@ elif key == "hostname": value = request.GET.first(b"hostname", b"not-found").decode("ASCII") elif key == "headers": - value = headersToAscii(request.headers) + value = fledge_http_server_util.headers_to_ascii(request.headers) elif key == "slotSize": value = request.GET.first(b"slotSize", b"not-found").decode("ASCII") elif key == "allSlotsRequestedSizes":
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-scoring-signals.py b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-scoring-signals.py index fc6ec790..80488a5 100644 --- a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-scoring-signals.py +++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-scoring-signals.py
@@ -1,6 +1,8 @@ import json from urllib.parse import unquote_plus, urlparse -from fledge.tentative.resources.fledge_http_server_util import headersToAscii + +from fledge.tentative.resources import fledge_http_server_util + # Script to generate trusted scoring signals. The responses depends on the # query strings in the ads Urls - some result in entire response failures, @@ -119,7 +121,7 @@ elif signalsParam == "hostname": value = request.GET.first(b"hostname", b"not-found").decode("ASCII") elif signalsParam == "headers": - value = headersToAscii(request.headers) + value = fledge_http_server_util.headers_to_ascii(request.headers) if addValue: if urlList["type"] not in responseBody: responseBody[urlList["type"]] = {}
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-number.tentative.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-number.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-number.tentative.html rename to third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-number.html
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-text.tentative.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-text.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-text.tentative.html rename to third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-input-text.html
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-select.tentative.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-select.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-select.tentative.html rename to third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-select.html
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-textarea.tentative.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-textarea.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-textarea.tentative.html rename to third_party/blink/web_tests/external/wpt/html/rendering/widgets/field-sizing-textarea.html
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-text-size.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-text-size.html index 7f294828..fb3008d 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-text-size.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-text-size.html
@@ -13,6 +13,7 @@ <input id="size20" size="20"> <input id="size21" size="21"> <input id="computed" style="border:none; padding:0;" size="19"> +<input id="computedNone" style="display:none" size="17"> <script> test(() => { @@ -34,6 +35,11 @@ const computedString = getComputedStyle(computed).width; assert_equals(computed.offsetWidth, parseInt(computedString.substring(0, computedString.length - 2))); -}, 'Size attribute value affects computed style'); +}, 'Size attribute value affects layout-dependent computed style'); + +test(() => { + const computedString = getComputedStyle(computedNone).width; + assert_equals(computedString, 'auto'); +}, 'Size attribute value is not a presentational hint'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/textarea-cols-rows.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/textarea-cols-rows.html index 012c5aa..6ad24a2 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/textarea-cols-rows.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/textarea-cols-rows.html
@@ -8,6 +8,7 @@ <textarea id="missing"></textarea> <textarea id="invalid" cols="-1" rows="-1"></textarea> <textarea id="computed" style="border:none; padding:0;" cols="19" rows="5"></textarea> +<textarea id="computedNone" style="display:none" cols="17" rows="7"></textarea> <textarea id="cols0" cols="0"></textarea> <textarea id="cols1" cols="1"></textarea> @@ -52,6 +53,12 @@ const computedHeight = getComputedStyle(computed).height; assert_equals(computed.offsetHeight, parseInt(computedHeight.substring(0, computedHeight.length - 2))); -}, 'Cols/rows attribute values affect computed style'); +}, 'Cols/rows attribute values affect layout-dependent computed style'); + +test(() => { + const computedNoneStyle = getComputedStyle(computedNone); + assert_equals(computedNoneStyle.width, 'auto'); + assert_equals(computedNoneStyle.height, 'auto'); +}, 'Cols/rows attribute values are not presentational hints'); </script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/device-orientation-success-expected.txt b/third_party/blink/web_tests/http/tests/devtools/device-orientation-success-expected.txt index 99e2615..57e9458d 100644 --- a/third_party/blink/web_tests/http/tests/devtools/device-orientation-success-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/device-orientation-success-expected.txt
@@ -1,7 +1,9 @@ Test device orientation -Running: setUpDeviceOrientation +Running: setDeviceOrientationOverrideViaEmulationDomain + +Running: removeEmulationDomainSensorOverride Running: firstOrientationOverride @@ -10,12 +12,12 @@ Running: secondOrientationOverride Running: clearOverride -device-orientation-success.js:32 alpha: 1.1 beta: 2.2 gamma: 3.3 -device-orientation-success.js:32 alpha: 20 beta: 30 gamma: 40 -inspected-page.html:1 A reload is required so that the existing AbsoluteOrientationSensor and RelativeOrientationSensor objects on this page use the overridden values that have been provided. Close the inspector and reload again to return to the normal behavior. -device-orientation-success.js:32 alpha: 90 beta: 0 gamma: 0 -device-orientation-success.js:39 quaternion: 0.000000,0.000000,0.707107,0.707107 -device-orientation-success.js:32 alpha: 1.1 beta: 2.2 gamma: 3.3 +device-orientation-success.js:35 alpha: 1.100000 beta: 2.200000 gamma: 3.300000 +empty.html:1 A reload is required so that the existing AbsoluteOrientationSensor and RelativeOrientationSensor objects on this page use the overridden values that have been provided. To return to the normal behavior, you can either close the inspector or disable the orientation override, and then reload. +device-orientation-success.js:35 alpha: 20.000000 beta: 30.000000 gamma: 40.000000 +device-orientation-success.js:41 quaternion: 0.182531,0.367707,0.244718,0.878400 +device-orientation-success.js:35 alpha: 90.000000 beta: 0.000000 gamma: 0.000000 +device-orientation-success.js:41 quaternion: 0.000000,0.000000,0.707107,0.707107 Running: reloadPageAndOverride Page reloaded.
diff --git a/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js b/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js index 0d85620..b506ff3 100644 --- a/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js +++ b/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js
@@ -2,83 +2,121 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {TestRunner} from 'test_runner'; import {ConsoleTestRunner} from 'console_test_runner'; +import {TestRunner} from 'test_runner'; (async function() { TestRunner.addResult(`Test device orientation\n`); await TestRunner.addScriptTag('/resources/testharness.js'); - await TestRunner.evaluateInPagePromise(` - var sensorProvider = null; - var mockAlpha = 1.1; - var mockBeta = 2.2; - var mockGamma = 3.3; + // The page we navigate to does not really matter, we just want an origin we + // control to pass to invoke_grantPermissions() below. + await TestRunner.navigatePromise( + 'https://devtools.test:8443/devtools/network/resources/empty.html'); + await TestRunner.BrowserAgent.invoke_grantPermissions({ + origin: 'https://devtools.test:8443', + permissions: ['sensors'], + }); - async function setUpDeviceOrientation() + await TestRunner.evaluateInPagePromise(` + const orientationSensor = new RelativeOrientationSensor; + + function setUpDeviceOrientation() { - const {sensorMocks, setMockSensorDataForType} = - await import('/resources/sensor-helpers.js'); - sensorProvider = sensorMocks(); - let mockDataPromise = setMockSensorDataForType( - sensorProvider, - "RelativeOrientationEulerAngles", - [mockBeta, mockGamma, mockAlpha]); window.addEventListener("deviceorientation", handler); - return mockDataPromise; + } + + function round(num) + { + return num.toFixed(6); } function handler(evt) { - console.log("alpha: " + evt.alpha + " beta: " + evt.beta + " gamma: " + evt.gamma); + console.log("alpha: " + round(evt.alpha) + " beta: " + round(evt.beta) + " gamma: " + round(evt.gamma)); } function setUpOrientationSensor() { - let orientationSensor = new RelativeOrientationSensor(); orientationSensor.onreading = () => console.log("quaternion: " - + orientationSensor.quaternion[0].toFixed(6) + ',' - + orientationSensor.quaternion[1].toFixed(6) + ',' - + orientationSensor.quaternion[2].toFixed(6) + ',' - + orientationSensor.quaternion[3].toFixed(6)); + + round(orientationSensor.quaternion[0]) + ',' + + round(orientationSensor.quaternion[1]) + ',' + + round(orientationSensor.quaternion[2]) + ',' + + round(orientationSensor.quaternion[3])); orientationSensor.start(); } function cleanUpDeviceOrientation() { + orientationSensor.stop(); window.removeEventListener("deviceorientation", handler); - sensorProvider.reset(); return new Promise(done => setTimeout(done, 0)); } `); TestRunner.runTestSuite([ - async function setUpDeviceOrientation(next) { - await TestRunner.evaluateInPageAsync('setUpDeviceOrientation()'); + // The first two steps verify that it is possible to control the Device + // Orientation API via the Emulation domain as well. + // + // They also verify that in this case no console message about reloading + // DevTools is shown. + // + // It is not possible to use the DeviceOrientation domain if the + // "relative-orientation" sensor is overridden via the Emulation domain, so + // we need to tear down the setup as well. The event listener will stop + // receiving readings. + async function setDeviceOrientationOverrideViaEmulationDomain(next) { + await TestRunner.EmulationAgent.setSensorOverrideEnabled( + true, 'relative-orientation'); + await TestRunner.EmulationAgent.setSensorOverrideReadings( + 'relative-orientation', { + // This is equivalent to alpha=1.1, beta=2.2, gamma=3.3. + quaternion: {x: 0.0189123, y: 0.0289715, z: 0.0101462, w: 0.9993498} + }); + await TestRunner.evaluateInPage('setUpDeviceOrientation()'); ConsoleTestRunner.addConsoleSniffer(next); }, - function firstOrientationOverride(next) { - ConsoleTestRunner.addConsoleSniffer(next); - TestRunner.DeviceOrientationAgent.setDeviceOrientationOverride(20, 30, 40); + async function removeEmulationDomainSensorOverride(next) { + await TestRunner.EmulationAgent.setSensorOverrideEnabled( + false, 'relative-orientation'); + next(); }, - function setUpOrientationSensor(next) { + // Now override the device orientatio data via the DeviceOrientation + // domain. We need to wait for 2 console messages: the console warning from + // DeviceOrientationInspectorAgent and the console.log() call from + // handler(). + async function firstOrientationOverride(next) { + ConsoleTestRunner.waitUntilNthMessageReceived(2, next); + await TestRunner.DeviceOrientationAgent.setDeviceOrientationOverride( + 20, 30, 40); + }, + + // Add a RelativeOrientationSensor to verify that it is also controlled by + // the same virtual sensor. We wait until its onreading event handler is + // invoked. + async function setUpOrientationSensor(next) { // The devtools inspector window needs to be focused to hear about // sensor changes. if (window.testRunner) testRunner.focusDevtoolsSecondaryWindow(); - TestRunner.evaluateInPage('setUpOrientationSensor()', next); + ConsoleTestRunner.addConsoleSniffer(next); + await TestRunner.evaluateInPage('setUpOrientationSensor()'); }, - function secondOrientationOverride(next) { - ConsoleTestRunner.addConsoleSniffer(next); - TestRunner.DeviceOrientationAgent.setDeviceOrientationOverride(90, 0, 0); + // Change the orientation values again to check that both handler() and + // |orientationSensor|'s onreading event handler are called (which is why + // we need to wait for 2 messages). + async function secondOrientationOverride(next) { + ConsoleTestRunner.waitUntilNthMessageReceived(2, next); + await TestRunner.DeviceOrientationAgent.setDeviceOrientationOverride( + 90, 0, 0); }, async function clearOverride(next) { - await TestRunner.DeviceOrientationAgent.clearDeviceOrientationOverride(); await TestRunner.evaluateInPageAsync('cleanUpDeviceOrientation()'); + await TestRunner.DeviceOrientationAgent.clearDeviceOrientationOverride(); await ConsoleTestRunner.dumpConsoleMessages(); next(); }, @@ -88,11 +126,12 @@ // changes. async function reloadPageAndOverride(next) { // First, enable DeviceOrientationAgent again. - TestRunner.DeviceOrientationAgent.setDeviceOrientationOverride(1, 2, 3); + await TestRunner.DeviceOrientationAgent.setDeviceOrientationOverride( + 1, 2, 3); // Reload the page. DeviceOrientationInspectorAgent::Restore() will call - // SensorInspectorAgent::SetOrientationSensorOverride() again, and we do - // not want any new console messages. + // DeviceOrientationInspectorAgent::SetOrientationSensorOverride() again, + // and we do not want any new console messages. // The console message from the call to setDeviceOrientationOverride() // above is lost with the reload, but we do not care. await TestRunner.reloadPagePromise();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/base-usage-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/base-usage-expected.txt new file mode 100644 index 0000000..f740315f40 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/base-usage-expected.txt
@@ -0,0 +1,16 @@ +Tests DeviceOrientation.SetDeviceOrientationOverride() basic usage +PASS: Overriding with first set of values +[ + [0] : 1 + [1] : 2 + [2] : 3 + [3] : false +] +PASS: Overriding with new set of values +[ + [0] : 42 + [1] : 34 + [2] : -90 + [3] : false +] +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/base-usage.js b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/base-usage.js new file mode 100644 index 0000000..a57ec99 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/base-usage.js
@@ -0,0 +1,33 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + 'Tests DeviceOrientation.SetDeviceOrientationOverride() basic usage'); + + async function waitAndLogEvent() { + testRunner.log(await session.evaluateAsync(` + new Promise(resolve => { + window.addEventListener('deviceorientation', event => { + resolve([event.alpha, event.beta, event.gamma, event.absolute]); + }, { once: true }); + }) + `)); + } + + await dp.Browser.grantPermissions( + {origin: location.origin, permissions: ['sensors']}); + + testRunner.expectedSuccess( + 'Overriding with first set of values', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: 3})); + + await waitAndLogEvent(); + + testRunner.expectedSuccess( + 'Overriding with new set of values', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 42, beta: 34, gamma: -90})); + + await waitAndLogEvent(); + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/clear-override-without-setting-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/clear-override-without-setting-expected.txt new file mode 100644 index 0000000..c015b8c6 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/clear-override-without-setting-expected.txt
@@ -0,0 +1,3 @@ +Tests that ClearDeviceOrientationOverride() works without SetDeviceOrientationOverride() +PASS: ClearDeviceOrientationOverride() works +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/clear-override-without-setting.js b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/clear-override-without-setting.js new file mode 100644 index 0000000..6897907 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/clear-override-without-setting.js
@@ -0,0 +1,13 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + 'Tests that ClearDeviceOrientationOverride() works without SetDeviceOrientationOverride()'); + + await dp.Browser.grantPermissions( + {origin: location.origin, permissions: ['sensors']}); + + testRunner.expectedSuccess( + 'ClearDeviceOrientationOverride() works', + await dp.DeviceOrientation.clearDeviceOrientationOverride()); + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/device-orientation-overrides-persist-across-navigations-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/device-orientation-overrides-persist-across-navigations-expected.txt new file mode 100644 index 0000000..26561d4 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/device-orientation-overrides-persist-across-navigations-expected.txt
@@ -0,0 +1,13 @@ +Tests that device orientation overrides persist across navigations +PASS: Created sensor override + +Navigating to a different URL + +Adding event listener and waiting for orientation data +[ + [0] : 1 + [1] : 2 + [2] : 3 + [3] : false +] +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/device-orientation-overrides-persist-across-navigations.js b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/device-orientation-overrides-persist-across-navigations.js new file mode 100644 index 0000000..b943752 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/device-orientation-overrides-persist-across-navigations.js
@@ -0,0 +1,27 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + 'Tests that device orientation overrides persist across navigations'); + + await dp.Browser.grantPermissions( + {origin: location.origin, permissions: ['sensors']}); + + testRunner.expectedSuccess( + 'Created sensor override', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: 3})); + + testRunner.log('\nNavigating to a different URL'); + await session.navigate('./resources/simple.html'); + + testRunner.log('\nAdding event listener and waiting for orientation data'); + + testRunner.log(await session.evaluateAsync(` + new Promise(resolve => { + window.addEventListener('deviceorientation', event => { + resolve([event.alpha, event.beta, event.gamma, event.absolute]); + }, { once: true }); + }) + `)); + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/emulation-domain-interaction-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/emulation-domain-interaction-expected.txt new file mode 100644 index 0000000..e7e4b28 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/emulation-domain-interaction-expected.txt
@@ -0,0 +1,14 @@ +Tests that the DeviceOrientation and Emulationd domains cannot override the same sensor at the same time + +Creating virtual sensor via Emulation domain +PASS: Attempting to create the same virtual sensor via DeviceOrientation domain fails + +Removing virtual sensor created via Emulation domain + +Creating virtual sensor via DeviceOrientation domain +PASS: DeviceOrientation.SetDeviceOrientationOverride() works + +Attempting to create sensor via Emulation domain +PASS: Virtual sensor is already overridden +PASS: Calling Emulation.getVirtualSensorInformation fails +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/emulation-domain-interaction.js b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/emulation-domain-interaction.js new file mode 100644 index 0000000..fa57d43 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/emulation-domain-interaction.js
@@ -0,0 +1,43 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + 'Tests that the DeviceOrientation and Emulationd domains cannot override the same sensor at the same time'); + + await dp.Browser.grantPermissions( + {origin: location.origin, permissions: ['sensors']}); + + testRunner.log('\nCreating virtual sensor via Emulation domain'); + + await dp.Emulation.setSensorOverrideEnabled( + {type: 'relative-orientation', enabled: true}); + + testRunner.expectedError( + 'Attempting to create the same virtual sensor via DeviceOrientation domain fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: 3})); + + testRunner.log('\nRemoving virtual sensor created via Emulation domain'); + + await dp.Emulation.setSensorOverrideEnabled( + {type: 'relative-orientation', enabled: false}); + + testRunner.log('\nCreating virtual sensor via DeviceOrientation domain'); + testRunner.expectedSuccess( + 'DeviceOrientation.SetDeviceOrientationOverride() works', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: 3})); + + testRunner.log('\nAttempting to create sensor via Emulation domain'); + testRunner.expectedError( + 'Virtual sensor is already overridden', + await dp.Emulation.setSensorOverrideEnabled( + {type: 'relative-orientation', enabled: true})); + + // This is supposed to fail because the virtual sensor is not being + // overridden by the Emulation domain handler. + testRunner.expectedError( + 'Calling Emulation.getVirtualSensorInformation fails', + await dp.Emulation.getVirtualSensorInformation( + {type: 'relative-orientation'})); + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/event-listener-in-frame-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/event-listener-in-frame-expected.txt new file mode 100644 index 0000000..57904e1 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/event-listener-in-frame-expected.txt
@@ -0,0 +1,11 @@ +Tests that device orientation overrides affect event listeners in iframes +PASS: Created sensor override + +Adding event listener in iframe and waiting for orientation data +[ + [0] : 1 + [1] : 2 + [2] : 3 + [3] : false +] +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/event-listener-in-frame.js b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/event-listener-in-frame.js new file mode 100644 index 0000000..15b798c --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/event-listener-in-frame.js
@@ -0,0 +1,30 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + 'Tests that device orientation overrides affect event listeners in iframes'); + + await dp.Browser.grantPermissions( + {origin: location.origin, permissions: ['sensors']}); + + testRunner.expectedSuccess( + 'Created sensor override', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: 3})); + + testRunner.log( + '\nAdding event listener in iframe and waiting for orientation data'); + + testRunner.log(await session.evaluateAsync(` + new Promise(resolve => { + const iframe = document.createElement('iframe'); + iframe.src = '/resources/blank.html'; + iframe.onload = () => { + iframe.contentWindow.addEventListener('deviceorientation', event => { + resolve([event.alpha, event.beta, event.gamma, event.absolute]); + }, { once: true }); + } + document.body.appendChild(iframe); + }) + `)); + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/parameter-validation-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/parameter-validation-expected.txt new file mode 100644 index 0000000..be302787 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/parameter-validation-expected.txt
@@ -0,0 +1,17 @@ +Tests that values passed to SetDeviceOrientationOverride() are validated + +Testing alpha in range [0, 360) +PASS: alpha < 0 fails +PASS: alpha == 360 fails +PASS: alpha > 360 fails + +Testing beta in range [-180, 180) +PASS: beta < -180 fails +PASS: beta == 180 fails +PASS: beta > 180 fails + +Testing gamma in range [-90, 90) +PASS: gamma < -90 fails +PASS: gamma == 90 fails +PASS: gamma > 90 fails +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/parameter-validation.js b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/parameter-validation.js new file mode 100644 index 0000000..6c8defc --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/device-orientation/parameter-validation.js
@@ -0,0 +1,51 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + 'Tests that values passed to SetDeviceOrientationOverride() are validated'); + + await dp.Browser.grantPermissions( + {origin: location.origin, permissions: ['sensors']}); + + testRunner.log('\nTesting alpha in range [0, 360)'); + testRunner.expectedError( + 'alpha < 0 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: -0.1, beta: 2, gamma: 3})); + testRunner.expectedError( + 'alpha == 360 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 360, beta: 2, gamma: 3})); + testRunner.expectedError( + 'alpha > 360 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 361, beta: 2, gamma: 3})); + + testRunner.log('\nTesting beta in range [-180, 180)'); + testRunner.expectedError( + 'beta < -180 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: -180.1, gamma: 3})); + testRunner.expectedError( + 'beta == 180 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 180, gamma: 3})); + testRunner.expectedError( + 'beta > 180 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 181, gamma: 3})); + + testRunner.log('\nTesting gamma in range [-90, 90)'); + testRunner.expectedError( + 'gamma < -90 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: -90.1})); + testRunner.expectedError( + 'gamma == 90 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: 90})); + testRunner.expectedError( + 'gamma > 90 fails', + await dp.DeviceOrientation.setDeviceOrientationOverride( + {alpha: 1, beta: 2, gamma: 90.1})); + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/resources/sensor-helpers.js b/third_party/blink/web_tests/http/tests/resources/sensor-helpers.js deleted file mode 100644 index f4e1bae..0000000 --- a/third_party/blink/web_tests/http/tests/resources/sensor-helpers.js +++ /dev/null
@@ -1,540 +0,0 @@ -import {ReportingMode, Sensor, SensorClientRemote, SensorReceiver, SensorRemote, SensorType} from '/gen/services/device/public/mojom/sensor.mojom.m.js'; -import {SensorCreationResult, SensorInitParams_READ_BUFFER_SIZE_FOR_TESTS} from '/gen/services/device/public/mojom/sensor_provider.mojom.m.js'; -import {WebSensorProvider, WebSensorProviderReceiver} from '/gen/third_party/blink/public/mojom/sensor/web_sensor_provider.mojom.m.js'; - -// Default sensor frequency in default configurations. -const DEFAULT_FREQUENCY = 5; - -// A "sliding window" that iterates over |data| and returns one item at a -// time, advancing and wrapping around as needed. |data| must be an array of -// arrays. -class RingBuffer { - constructor(data) { - this.bufferPosition_ = 0; - // Validate |data|'s format and deep-copy every element. - this.data_ = Array.from(data, element => { - if (!Array.isArray(element)) { - throw new TypeError('Every |data| element must be an array.'); - } - return Array.from(element); - }) - } - - next() { - const value = this.data_[this.bufferPosition_]; - this.bufferPosition_ = (this.bufferPosition_ + 1) % this.data_.length; - return { done: false, value: value }; - } - - reset() { - this.bufferPosition_ = 0; - } - - [Symbol.iterator]() { - return this; - } -} - -export function sensorMocks() { - // Class that mocks Sensor interface defined in sensor.mojom - class MockSensor { - constructor(sensorRequest, buffer, reportingMode) { - this.client_ = null; - this.startShouldFail_ = false; - this.notifyOnReadingChange_ = true; - this.reportingMode_ = reportingMode; - this.sensorReadingTimerId_ = null; - this.readingData_ = null; - this.suspendCalled_ = null; - this.resumeCalled_ = null; - this.addConfigurationCalled_ = null; - this.removeConfigurationCalled_ = null; - this.requestedFrequencies_ = []; - this.buffer_ = buffer; - this.resetBuffer(); - this.receiver_ = new SensorReceiver(this); - this.receiver_.$.bindHandle(sensorRequest.handle); - } - - // device.mojom.Sensor implementation - // Mojo functions that return a value must be async and return an object - // whose keys match the names declared in Mojo. - - // GetDefaultConfiguration() => (SensorConfiguration configuration) - // Returns default configuration. - async getDefaultConfiguration() { - return { frequency: DEFAULT_FREQUENCY }; - } - - // AddConfiguration(SensorConfiguration configuration) => (bool success) - // Adds configuration for the sensor and starts reporting fake data - // through setSensorReading function. - async addConfiguration(configuration) { - assert_not_equals(configuration, null, "Invalid sensor configuration."); - - this.requestedFrequencies_.push(configuration.frequency); - // Sort using descending order. - this.requestedFrequencies_.sort( - (first, second) => { return second - first }); - - if (!this.startShouldFail_ ) - this.startReading(); - - if (this.addConfigurationCalled_ != null) - this.addConfigurationCalled_(this); - - return { success: !this.startShouldFail_ }; - } - - // RemoveConfiguration(SensorConfiguration configuration) - // Removes sensor configuration from the list of active configurations and - // stops notification about sensor reading changes if - // requestedFrequencies_ is empty. - removeConfiguration(configuration) { - if (this.removeConfigurationCalled_ != null) { - this.removeConfigurationCalled_(this); - } - - const index = this.requestedFrequencies_.indexOf(configuration.frequency); - if (index == -1) - return; - - this.requestedFrequencies_.splice(index, 1); - if (this.requestedFrequencies_.length === 0) - this.stopReading(); - } - - // Suspend() - suspend() { - this.stopReading(); - if (this.suspendCalled_ != null) { - this.suspendCalled_(this); - } - } - - // Resume() - resume() { - assert_equals(this.sensorReadingTimerId_, null); - this.startReading(); - if (this.resumeCalled_ != null) { - this.resumeCalled_(this); - } - } - - // ConfigureReadingChangeNotifications(bool enabled) - // Configures whether to report a reading change when in ON_CHANGE - // reporting mode. - configureReadingChangeNotifications(notifyOnReadingChange) { - this.notifyOnReadingChange_ = notifyOnReadingChange; - } - - // Mock functions - - // Resets mock Sensor state. - reset() { - this.stopReading(); - - this.startShouldFail_ = false; - this.notifyOnReadingChange_ = true; - this.readingData_ = null; - this.requestedFrequencies_ = []; - this.suspendCalled_ = null; - this.resumeCalled_ = null; - this.addConfigurationCalled_ = null; - this.removeConfigurationCalled_ = null; - this.resetBuffer(); - this.receiver_.$.close(); - } - - // Zeroes shared buffer. - resetBuffer() { - this.buffer_.fill(0); - } - - // Sets fake data that is used to deliver sensor reading updates. - async setSensorReading(readingData) { - this.readingData_ = new RingBuffer(readingData); - return this; - } - - // Sets flag that forces sensor to fail when addConfiguration is invoked. - setStartShouldFail(shouldFail) { - this.startShouldFail_ = shouldFail; - } - - // Returns resolved promise if suspend() was called, rejected otherwise. - suspendCalled() { - return new Promise(resolve => { - this.suspendCalled_ = resolve; - }); - } - - // Returns resolved promise if resume() was called, rejected otherwise. - resumeCalled() { - return new Promise(resolve => { - this.resumeCalled_ = resolve; - }); - } - - // Resolves promise when addConfiguration() is called. - addConfigurationCalled() { - return new Promise(resolve => { - this.addConfigurationCalled_ = resolve; - }); - } - - // Resolves promise when removeConfiguration() is called. - removeConfigurationCalled() { - return new Promise(resolve => { - this.removeConfigurationCalled_ = resolve; - }); - } - - startReading() { - if (this.readingData_ != null) { - this.stopReading(); - const maxFrequencyUsed = this.requestedFrequencies_[0]; - const timeout = (1 / maxFrequencyUsed) * 1000; - this.sensorReadingTimerId_ = window.setInterval(() => { - if (this.readingData_) { - // |buffer_| is a TypedArray, so we need to make sure we pass an - // array to set(). - const reading = this.readingData_.next().value; - assert_true(Array.isArray(reading), "The readings passed to " + - "setSensorReading() must arrays."); - this.buffer_.set(reading, 2); - - // For all tests sensor reading should have monotonically - // increasing timestamp in seconds. - this.buffer_[1] = window.performance.now() * 0.001; - } - if (this.reportingMode_ === ReportingMode.ON_CHANGE && - this.notifyOnReadingChange_) { - this.client_.sensorReadingChanged(); - } - }, timeout); - } - } - - stopReading() { - if (this.sensorReadingTimerId_ != null) { - window.clearInterval(this.sensorReadingTimerId_); - this.sensorReadingTimerId_ = null; - } - this.buffer_.fill(0); - if (this.readingData_ !== null) { - this.readingData_.reset(); - } - } - - getSamplingFrequency() { - assert_true(this.requestedFrequencies_.length > 0); - return this.requestedFrequencies_[0]; - } - } - - // This class aggregates information about a given sensor type that is used by - // MockSensorProvider when it is asked to create a new MockSensor. - class SensorTypeSettings { - constructor(mojoSensorType) { - this.mojoSensorType_ = mojoSensorType; - assert_greater_than_equal(mojoSensorType, SensorType.MIN_VALUE); - assert_less_than_equal(mojoSensorType, SensorType.MAX_VALUE); - - this.shouldDenyRequests_ = false; - this.unavailable_ = false; - } - - get mojoSensorType() { - return this.mojoSensorType_; - } - - get shouldDenyRequests() { - return this.shouldDenyRequests_; - } - - set shouldDenyRequests(deny) { - this.shouldDenyRequests_ = deny; - } - - get unavailable() { - return this.unavailable_; - } - - set unavailable(is_unavailable) { - this.unavailable_ = is_unavailable; - } - } - - // Maps a given device.mojom.SensorType enum value to a suitable name as a - // string. - function getSensorTypeName(mojoSensorType) { - switch (mojoSensorType) { - case SensorType.ACCELEROMETER: - return 'Accelerometer'; - case SensorType.LINEAR_ACCELERATION: - return 'LinearAccelerationSensor'; - case SensorType.AMBIENT_LIGHT: - return 'AmbientLightSensor'; - case SensorType.GRAVITY: - return 'GravitySensor'; - case SensorType.GYROSCOPE: - return 'Gyroscope'; - case SensorType.MAGNETOMETER: - return 'Magnetometer'; - case SensorType.ABSOLUTE_ORIENTATION_QUATERNION: - return 'AbsoluteOrientationSensor'; - case SensorType.ABSOLUTE_ORIENTATION_EULER_ANGLES: - return 'AbsoluteOrientationEulerAngles'; - case SensorType.RELATIVE_ORIENTATION_QUATERNION: - return 'RelativeOrientationSensor'; - case SensorType.RELATIVE_ORIENTATION_EULER_ANGLES: - return 'RelativeOrientationEulerAngles'; - } - } - - // Class that mocks the WebSensorProvider interface defined in - // web_sensor_provider.mojom - class MockSensorProvider { - constructor() { - this.readingSizeInBytes_ = - Number(SensorInitParams_READ_BUFFER_SIZE_FOR_TESTS); - this.sharedBufferSizeInBytes_ = - this.readingSizeInBytes_ * (SensorType.MAX_VALUE + 1); - let rv = Mojo.createSharedBuffer(this.sharedBufferSizeInBytes_); - assert_equals( - rv.result, Mojo.RESULT_OK, 'Failed to create shared buffer'); - const handle = rv.handle; - rv = handle.mapBuffer(0, this.sharedBufferSizeInBytes_); - assert_equals(rv.result, Mojo.RESULT_OK, 'Failed to map shared buffer'); - this.shmemArrayBuffer_ = rv.buffer; - rv = handle.duplicateBufferHandle({readOnly: true}); - assert_equals( - rv.result, Mojo.RESULT_OK, 'Failed to duplicate shared buffer'); - this.readOnlySharedBufferHandle_ = rv.handle; - this.activeSensors_ = new Map(); - this.resolveFuncs_ = new Map(); - this.isContinuous_ = false; - this.maxFrequency_ = 60; - this.minFrequency_ = 1; - this.resetSensorTypeSettings(); - this.receiver_ = new WebSensorProviderReceiver(this); - this.interceptor_ = - new MojoInterfaceInterceptor(WebSensorProvider.$interfaceName); - this.interceptor_.oninterfacerequest = - e => this.receiver_.$.bindHandle(e.handle); - this.interceptor_.start(); - } - - // blink.mojom.SensorProvider implementation - // Mojo functions that return a value must be async and return an object - // whose keys match the names declared in Mojo. - - // GetSensor(SensorType type) => (SensorCreationResult result, - // SensorInitParams? init_params) - // Returns initialized Sensor proxy to the client. - async getSensor(mojoSensorType) { - const sensorSettings = this.sensorTypeSettings_.get(getSensorTypeName(mojoSensorType)); - if (sensorSettings.unavailable) { - return {result: SensorCreationResult.ERROR_NOT_AVAILABLE, - initParams: null}; - } - if (sensorSettings.shouldDenyRequests) { - return {result: SensorCreationResult.ERROR_NOT_ALLOWED, - initParams: null}; - } - - const offset = mojoSensorType * this.readingSizeInBytes_; - const reportingMode = this.isContinuous_ ? - ReportingMode.CONTINUOUS : ReportingMode.ON_CHANGE; - - const sensorPtr = new SensorRemote(); - if (!this.activeSensors_.has(mojoSensorType)) { - const shmemView = new Float64Array( - this.shmemArrayBuffer_, offset, - this.readingSizeInBytes_ / Float64Array.BYTES_PER_ELEMENT); - const mockSensor = new MockSensor( - sensorPtr.$.bindNewPipeAndPassReceiver(), shmemView, reportingMode); - this.activeSensors_.set(mojoSensorType, mockSensor); - this.activeSensors_.get(mojoSensorType).client_ = new SensorClientRemote(); - } - - const rv = this.readOnlySharedBufferHandle_.duplicateBufferHandle( - {readOnly: true}); - - assert_equals(rv.result, Mojo.RESULT_OK); - - const defaultConfig = { frequency: DEFAULT_FREQUENCY }; - // Consider sensor traits to meet assertions in C++ code (see - // services/device/public/cpp/generic_sensor/sensor_traits.h) - if (mojoSensorType == SensorType.AMBIENT_LIGHT || - mojoSensorType == SensorType.MAGNETOMETER) { - this.maxFrequency_ = Math.min(10, this.maxFrequency_); - } - - const client = this.activeSensors_.get(mojoSensorType).client_; - const initParams = { - sensor: sensorPtr, - clientReceiver: client.$.bindNewPipeAndPassReceiver(), - memory: {buffer: rv.handle}, - bufferOffset: BigInt(offset), - mode: reportingMode, - defaultConfiguration: defaultConfig, - minimumFrequency: this.minFrequency_, - maximumFrequency: this.maxFrequency_ - }; - - if (this.resolveFuncs_.has(mojoSensorType)) { - for (let resolveFunc of this.resolveFuncs_.get(mojoSensorType)) { - resolveFunc(this.activeSensors_.get(mojoSensorType)); - } - this.resolveFuncs_.delete(mojoSensorType); - } - - return {result: SensorCreationResult.SUCCESS, initParams}; - } - - // Mock functions - - // Returns a SensorTypeSettings instance corresponding to the name |type|, a - // string. - getSensorTypeSettings(type) { - return this.sensorTypeSettings_.get(type); - } - - // Recreates |this.sensorTypeSettings_| with a new map and values reset to - // their defaults. - resetSensorTypeSettings() { - this.sensorTypeSettings_ = new Map([ - ['Accelerometer', new SensorTypeSettings(SensorType.ACCELEROMETER)], - ['LinearAccelerationSensor', new SensorTypeSettings(SensorType.LINEAR_ACCELERATION)], - ['AmbientLightSensor', new SensorTypeSettings(SensorType.AMBIENT_LIGHT)], - ['GravitySensor', new SensorTypeSettings(SensorType.GRAVITY)], - ['Gyroscope', new SensorTypeSettings(SensorType.GYROSCOPE)], - ['Magnetometer', new SensorTypeSettings(SensorType.MAGNETOMETER)], - ['AbsoluteOrientationSensor', new SensorTypeSettings(SensorType.ABSOLUTE_ORIENTATION_QUATERNION)], - ['AbsoluteOrientationEulerAngles', new SensorTypeSettings(SensorType.ABSOLUTE_ORIENTATION_EULER_ANGLES)], - ['RelativeOrientationSensor', new SensorTypeSettings(SensorType.RELATIVE_ORIENTATION_QUATERNION)], - ['RelativeOrientationEulerAngles', new SensorTypeSettings(SensorType.RELATIVE_ORIENTATION_EULER_ANGLES)] - ]); - } - - // Resets state of mock SensorProvider between test runs. - reset() { - for (const sensor of this.activeSensors_.values()) { - sensor.reset(); - } - this.activeSensors_.clear(); - this.resolveFuncs_.clear(); - this.resetSensorTypeSettings(); - this.maxFrequency_ = 60; - this.minFrequency_ = 1; - this.isContinuous_ = false; - this.receiver_.$.close(); - this.interceptor_.stop(); - } - - // Returns mock sensor that was created in getSensor to the layout test. - getCreatedSensor(sensorName) { - const type = this.sensorTypeSettings_.get(sensorName).mojoSensorType; - - if (this.activeSensors_.has(type)) { - return Promise.resolve(this.activeSensors_.get(type)); - } - - return new Promise(resolve => { - if (!this.resolveFuncs_.has(type)) { - this.resolveFuncs_.set(type, []); - } - this.resolveFuncs_.get(type).push(resolve); - }); - } - - // Forces sensor to use |reportingMode| as an update mode. - setContinuousReportingMode() { - this.isContinuous_ = true; - } - - // Sets the maximum frequency for a concrete sensor. - setMaximumSupportedFrequency(frequency) { - this.maxFrequency_ = frequency; - } - - // Sets the minimum frequency for a concrete sensor. - setMinimumSupportedFrequency(frequency) { - this.minFrequency_ = frequency; - } - } - - return new MockSensorProvider(); -} - -export function sensor_test(func, name, properties) { - promise_test(async t => { - const sensorProvider = sensorMocks(); - - // Clean up and reset mock sensor stubs asynchronously, so that the blink - // side closes its proxies and notifies JS sensor objects before new test is - // started. - try { - await func(t, sensorProvider); - } finally { - sensorProvider.reset(); - await new Promise(resolve => { setTimeout(resolve, 0); }); - }; - }, name, properties); -} - -export async function setMockSensorDataForType(sensorProvider, sensorType, mockDataArray) { - const createdSensor = await sensorProvider.getCreatedSensor(sensorType); - return createdSensor.setSensorReading([mockDataArray]); -} - -// Returns a promise that will be resolved when an event equal to the given -// event is fired. -export function waitForEvent(expectedEvent, targetWindow = window) { - const stringify = (thing, targetWindow) => { - if (thing instanceof targetWindow.Object && thing.constructor !== targetWindow.Object) { - let str = '{'; - for (let key of Object.keys(Object.getPrototypeOf(thing))) { - str += JSON.stringify(key) + ': ' + stringify(thing[key], targetWindow) + ', '; - } - return str + '}'; - } else if (thing instanceof Number) { - return thing.toFixed(6); - } - return JSON.stringify(thing); - }; - - return new Promise((resolve, reject) => { - let events = []; - let timeoutId = null; - - const expectedEventString = stringify(expectedEvent, window); - function listener(event) { - const eventString = stringify(event, targetWindow); - if (eventString === expectedEventString) { - targetWindow.clearTimeout(timeoutId); - targetWindow.removeEventListener(expectedEvent.type, listener); - resolve(); - } else { - events.push(eventString); - } - } - targetWindow.addEventListener(expectedEvent.type, listener); - - timeoutId = targetWindow.setTimeout(() => { - targetWindow.removeEventListener(expectedEvent.type, listener); - let errorMessage = 'Timeout waiting for expected event: ' + expectedEventString; - if (events.length == 0) { - errorMessage += ', no events were fired'; - } else { - errorMessage += ', received events: ' - for (let event of events) { - errorMessage += event + ', '; - } - } - reject(errorMessage); - }, 500); - }); -}
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badbitcount.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badbitcount.bmp new file mode 100644 index 0000000..d4fa4e8 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badbitcount.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badbitssize.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badbitssize.bmp new file mode 100644 index 0000000..0a99a605 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badbitssize.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/baddens1.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/baddens1.bmp new file mode 100644 index 0000000..a6150a6 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/baddens1.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/baddens2.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/baddens2.bmp new file mode 100644 index 0000000..f2c1dfb6 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/baddens2.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badfilesize.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badfilesize.bmp new file mode 100644 index 0000000..da52cb51 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badfilesize.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badheadersize.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badheadersize.bmp new file mode 100644 index 0000000..2a4083a6 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badheadersize.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badpalettesize.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badpalettesize.bmp new file mode 100644 index 0000000..7d9d1b74 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badpalettesize.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badplanes.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badplanes.bmp new file mode 100644 index 0000000..92d2855b --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badplanes.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badrle.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badrle.bmp new file mode 100644 index 0000000..cbf8fdc --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badrle.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badrle4.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badrle4.bmp new file mode 100644 index 0000000..632787a7 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badrle4.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badrle4bis.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badrle4bis.bmp new file mode 100644 index 0000000..130b7e6 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badrle4bis.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badrle4ter.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badrle4ter.bmp new file mode 100644 index 0000000..8107a33 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badrle4ter.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badrlebis.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badrlebis.bmp new file mode 100644 index 0000000..893eb11 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badrlebis.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badrleter.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badrleter.bmp new file mode 100644 index 0000000..04d5874 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badrleter.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/badwidth.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/badwidth.bmp new file mode 100644 index 0000000..9fca005 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/badwidth.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/pal8badindex.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/pal8badindex.bmp new file mode 100644 index 0000000..efe16c0 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/pal8badindex.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/reallybig.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/reallybig.bmp new file mode 100644 index 0000000..101e0b49 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/reallybig.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/rgb16-880.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/rgb16-880.bmp new file mode 100644 index 0000000..72e7ce0 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/rgb16-880.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/rletopdown.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/rletopdown.bmp new file mode 100644 index 0000000..21a909fd --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/rletopdown.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/bmp-suite/bad/shortfile.bmp b/third_party/blink/web_tests/images/bmp-suite/bad/shortfile.bmp new file mode 100644 index 0000000..7396079 --- /dev/null +++ b/third_party/blink/web_tests/images/bmp-suite/bad/shortfile.bmp Binary files differ
diff --git a/third_party/blink/web_tests/images/resources/invalid-bitmap-offset.bmp b/third_party/blink/web_tests/images/resources/invalid-bitmap-offset.bmp new file mode 100644 index 0000000..cc8105b4 --- /dev/null +++ b/third_party/blink/web_tests/images/resources/invalid-bitmap-offset.bmp Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/external/wpt/webcodecs/audio-encoder-codec-specific.https.any-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/external/wpt/webcodecs/audio-encoder-codec-specific.https.any-expected.txt new file mode 100644 index 0000000..4365495 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/external/wpt/webcodecs/audio-encoder-codec-specific.https.any-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[PRECONDITION_FAILED] Test the AAC bitrateMode flag works. + AAC CBR not supported +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt index d594720e..b1e61c4 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -162,6 +162,7 @@ PASS oldChildWindow.onoffline is newChildWindow.onoffline PASS oldChildWindow.ononline is newChildWindow.ononline PASS oldChildWindow.onpagehide is newChildWindow.onpagehide +PASS oldChildWindow.onpagereveal is newChildWindow.onpagereveal PASS oldChildWindow.onpageshow is newChildWindow.onpageshow PASS oldChildWindow.onpause is newChildWindow.onpause PASS oldChildWindow.onplay is newChildWindow.onplay
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt index 95953ba9..6ecdda3 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -124,6 +124,7 @@ PASS childWindow.onoffline is null PASS childWindow.ononline is null PASS childWindow.onpagehide is null +PASS childWindow.onpagereveal is null PASS childWindow.onpageshow is null PASS childWindow.onpause is null PASS childWindow.onplay is null
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt index 8c29df8..7297792 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -124,6 +124,7 @@ PASS childWindow.onoffline is null PASS childWindow.ononline is null PASS childWindow.onpagehide is null +PASS childWindow.onpagereveal is null PASS childWindow.onpageshow is null PASS childWindow.onpause is null PASS childWindow.onplay is null
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index a79c1603..c184070c 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -6051,6 +6051,9 @@ attribute @@toStringTag getter constraint method constructor +interface PageRevealEvent : Event + attribute @@toStringTag + method constructor interface PageTransitionEvent : Event attribute @@toStringTag getter persisted @@ -11405,6 +11408,7 @@ getter onoffline getter ononline getter onpagehide + getter onpagereveal getter onpageshow getter onpause getter onplay @@ -11620,6 +11624,7 @@ setter onoffline setter ononline setter onpagehide + setter onpagereveal setter onpageshow setter onpause setter onplay
diff --git a/third_party/cardboard/BUILD.gn b/third_party/cardboard/BUILD.gn index e21c316..078740b5 100644 --- a/third_party/cardboard/BUILD.gn +++ b/third_party/cardboard/BUILD.gn
@@ -97,6 +97,8 @@ "src/sdk/screen_params.h", "src/sdk/screen_params/android/screen_params.cc", "src/sdk/sensors/accelerometer_data.h", + "src/sdk/sensors/android/device_accelerometer_sensor.cc", + "src/sdk/sensors/android/device_gyroscope_sensor.cc", "src/sdk/sensors/android/sensor_event_producer.cc", "src/sdk/sensors/device_accelerometer_sensor.h", "src/sdk/sensors/device_gyroscope_sensor.h", @@ -132,10 +134,6 @@ "src/sdk/util/vectorutils.cc", "src/sdk/util/vectorutils.h", "src_overrides/sdk/jni_utils/android/jni_utils.cc", - - # TODO(crbug.com/1497732): Remove override once changes have been upstreamed. - "src_overrides/sdk/sensors/android/device_accelerometer_sensor.cc", - "src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc", ] deps = [
diff --git a/third_party/cardboard/README.chromium b/third_party/cardboard/README.chromium index f61e678..987d983 100644 --- a/third_party/cardboard/README.chromium +++ b/third_party/cardboard/README.chromium
@@ -1,7 +1,7 @@ Name: Cardboard SDK Short Name: cardboard URL: https://github.com/googlevr/cardboard -Version: 1.22.0 +Version: 1.23.0 License: Apache 2.0 License File: LICENSE Security Critical: yes @@ -16,4 +16,3 @@ * Created local proguard-rules.pro to create more scoped proto-specific rules * Created local override for LoadJClass in jni_utils to leaverage //base JNI loading due to splits. * Created local configuration header file with the OpenGL ES 2.0 binding customization required by setting the CARDBOARD_USE_CUSTOM_GL_BINDINGS buildflag. -* Created local override for sdk/sensors/android/device_accelerometer_sensor.cc and device_gyroscope_sensor.cc to support updating minimum SDK version to 26 due to deprecated ASensorManager_getInstance() function. See crbug.com/1497732.
diff --git a/third_party/cardboard/src b/third_party/cardboard/src index 5c9f306..c8842698 160000 --- a/third_party/cardboard/src +++ b/third_party/cardboard/src
@@ -1 +1 @@ -Subproject commit 5c9f3066dc14962d1dec9a32ec9d3668641c408d +Subproject commit c8842698f4a9d63cce865e7d6cb75773a4673496
diff --git a/third_party/cardboard/src_overrides/sdk/sensors/android/device_accelerometer_sensor.cc b/third_party/cardboard/src_overrides/sdk/sensors/android/device_accelerometer_sensor.cc deleted file mode 100644 index dca6cf5..0000000 --- a/third_party/cardboard/src_overrides/sdk/sensors/android/device_accelerometer_sensor.cc +++ /dev/null
@@ -1,177 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "third_party/cardboard/src/sdk/sensors/device_accelerometer_sensor.h" - -#include <android/looper.h> -#include <android/sensor.h> -#include <stddef.h> - -#include <memory> -#include <mutex> // NOLINT - -#include "third_party/cardboard/src/sdk/util/logging.h" - -// Workaround to avoid the inclusion of "android_native_app_glue.h. -#ifndef LOOPER_ID_USER -#define LOOPER_ID_USER 3 -#endif - -namespace cardboard { - -namespace { - -// Creates an Android sensor event queue for the current thread. -static ASensorEventQueue* CreateSensorQueue(ASensorManager* sensor_manager) { - ALooper* event_looper = ALooper_forThread(); - - if (event_looper == nullptr) { - event_looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); - CARDBOARD_LOGI( - "AccelerometerSensor: Created new event looper for accelerometer " - "sensor capture thread."); - } - - return ASensorManager_createEventQueue(sensor_manager, event_looper, - LOOPER_ID_USER, nullptr, nullptr); -} - -const ASensor* InitSensor(ASensorManager* sensor_manager) { - return ASensorManager_getDefaultSensor(sensor_manager, - ASENSOR_TYPE_ACCELEROMETER); -} - -bool PollLooper(int timeout_ms, int* num_events) { - void* source = nullptr; - const int looper_id = ALooper_pollAll(timeout_ms, NULL, num_events, - reinterpret_cast<void**>(&source)); - if (looper_id != LOOPER_ID_USER) { - return false; - } - if (*num_events <= 0) { - return false; - } - return true; -} - -class SensorEventQueueReader { - public: - SensorEventQueueReader(ASensorManager* manager, const ASensor* sensor) - : manager_(manager), - sensor_(sensor), - queue_(CreateSensorQueue(manager_)) {} - - ~SensorEventQueueReader() { - ASensorManager_destroyEventQueue(manager_, queue_); - } - - bool Start() { - ASensorEventQueue_enableSensor(queue_, sensor_); - const int min_delay = ASensor_getMinDelay(sensor_); - // Set sensor capture rate to the highest possible sampling rate. - ASensorEventQueue_setEventRate(queue_, sensor_, min_delay); - return true; - } - - void Stop() { ASensorEventQueue_disableSensor(queue_, sensor_); } - - bool WaitForEvent(int timeout_ms, ASensorEvent* event) { - int num_events; - if (!PollLooper(timeout_ms, &num_events)) { - return false; - } - return (ASensorEventQueue_getEvents(queue_, event, 1) > 0); - } - - bool ReadEvent(ASensorEvent* event) { - return (ASensorEventQueue_getEvents(queue_, event, 1) > 0); - } - - private: - ASensorManager* manager_; // Owned by android library. - const ASensor* sensor_; // Owned by android library. - ASensorEventQueue* queue_; // Owned by this. -}; - -void ParseAccelerometerEvent(const ASensorEvent& event, - AccelerometerData* sample) { - sample->sensor_timestamp_ns = event.timestamp; - sample->system_timestamp = event.timestamp; - // The event values in ASensorEvent (event, acceleration and - // magnetic) are all in the same union type so they can be - // accessed by event. - sample->data = {event.vector.x, event.vector.y, event.vector.z}; -} - -} // namespace - -// This struct holds android specific sensor information. -struct DeviceAccelerometerSensor::SensorInfo { - SensorInfo() : sensor_manager(nullptr), sensor(nullptr) {} - - ASensorManager* sensor_manager; - const ASensor* sensor; - std::unique_ptr<SensorEventQueueReader> reader; -}; - -DeviceAccelerometerSensor::DeviceAccelerometerSensor() - : sensor_info_(new SensorInfo()) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - sensor_info_->sensor_manager = ASensorManager_getInstance(); -#pragma clang diagnostic pop - sensor_info_->sensor = InitSensor(sensor_info_->sensor_manager); - if (!sensor_info_->sensor) { - return; - } - - sensor_info_->reader = - std::unique_ptr<SensorEventQueueReader>(new SensorEventQueueReader( - sensor_info_->sensor_manager, sensor_info_->sensor)); -} - -DeviceAccelerometerSensor::~DeviceAccelerometerSensor() {} - -void DeviceAccelerometerSensor::PollForSensorData( - int timeout_ms, - std::vector<AccelerometerData>* results) const { - results->clear(); - ASensorEvent event; - if (!sensor_info_->reader->WaitForEvent(timeout_ms, &event)) { - return; - } - do { - AccelerometerData sample; - ParseAccelerometerEvent(event, &sample); - results->push_back(sample); - } while (sensor_info_->reader->ReadEvent(&event)); -} - -bool DeviceAccelerometerSensor::Start() { - if (!sensor_info_->reader) { - CARDBOARD_LOGE("Could not start accelerometer sensor"); - return false; - } - return sensor_info_->reader->Start(); -} - -void DeviceAccelerometerSensor::Stop() { - if (!sensor_info_->reader) { - return; - } - sensor_info_->reader->Stop(); -} - -} // namespace cardboard
diff --git a/third_party/cardboard/src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc b/third_party/cardboard/src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc deleted file mode 100644 index 69d64ab..0000000 --- a/third_party/cardboard/src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc +++ /dev/null
@@ -1,229 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "third_party/cardboard/src/sdk/sensors/device_gyroscope_sensor.h" - -#include <android/looper.h> -#include <android/sensor.h> -#include <stddef.h> - -#include <memory> - -#include "third_party/cardboard/src/sdk/sensors/accelerometer_data.h" -#include "third_party/cardboard/src/sdk/sensors/gyroscope_data.h" -#include "third_party/cardboard/src/sdk/util/logging.h" - -// Workaround to avoid the inclusion of "android_native_app_glue.h. -#ifndef LOOPER_ID_USER -#define LOOPER_ID_USER 3 -#endif - -namespace cardboard { - -namespace { - -// Creates an Android sensor event queue for the current thread. -static ASensorEventQueue* CreateSensorQueue(ASensorManager* sensor_manager) { - ALooper* event_looper = ALooper_forThread(); - - if (event_looper == nullptr) { - event_looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); - CARDBOARD_LOGI( - "AccelerometerSensor: Created new event looper for gyroscope sensor " - "capture thread."); - } - - return ASensorManager_createEventQueue(sensor_manager, event_looper, - LOOPER_ID_USER, nullptr, nullptr); -} - -// Initialize Gyroscope sensor on Android. If available we try to -// request a SENSOR_TYPE_GYROSCOPE_UNCALIBRATED. -// Since both seem to be using the same underlying code this will work if the -// same integer is used as the mode as in java. -// The reason for using the uncalibrated gyroscope is that the regular -// gyro is calibrated with a bias offset in the system. As we cannot influence -// the behavior of this algorithm and it will affect the gyro while moving, -// it is safer to initialize to the uncalibrated one and handle the gyro bias -// estimation in Cardboard SDK. -enum PrivateSensors { - // This is not defined in the native public sensors API, but it is in java. - // If we define this here and it gets defined later in NDK this should - // not compile. - // It is defined in AOSP in hardware/libhardware/include/hardware/sensors.h - ASENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14, - ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED = 16, - ASENSOR_TYPE_ADDITIONAL_INFO = 33, -}; - -static const ASensor* GetUncalibratedGyroscope(ASensorManager* sensor_manager) { - return ASensorManager_getDefaultSensor(sensor_manager, - ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED); -} - -const ASensor* InitSensor(ASensorManager* sensor_manager) { - const ASensor* gyro = GetUncalibratedGyroscope(sensor_manager); - if (gyro != nullptr) { - CARDBOARD_LOGI("Android Gyro Sensor: ASENSOR_TYPE_GYRO_UNCALIBRATED"); - return gyro; - } - CARDBOARD_LOGI("Android Gyro Sensor: ASENSOR_TYPE_GYROSCOPE"); - return ASensorManager_getDefaultSensor(sensor_manager, - ASENSOR_TYPE_GYROSCOPE); -} - -bool PollLooper(int timeout_ms, int* num_events) { - void* source = nullptr; - const int looper_id = ALooper_pollAll(timeout_ms, NULL, num_events, - reinterpret_cast<void**>(&source)); - if (looper_id != LOOPER_ID_USER) { - return false; - } - if (*num_events <= 0) { - return false; - } - return true; -} - -class SensorEventQueueReader { - public: - SensorEventQueueReader(ASensorManager* manager, const ASensor* sensor) - : manager_(manager), - sensor_(sensor), - queue_(CreateSensorQueue(manager_)) {} - - ~SensorEventQueueReader() { - ASensorManager_destroyEventQueue(manager_, queue_); - } - - bool Start() { - ASensorEventQueue_enableSensor(queue_, sensor_); - const int min_delay = ASensor_getMinDelay(sensor_); - // Set sensor capture rate to the highest possible sampling rate. - ASensorEventQueue_setEventRate(queue_, sensor_, min_delay); - return true; - } - - void Stop() { ASensorEventQueue_disableSensor(queue_, sensor_); } - - bool WaitForEvent(int timeout_ms, ASensorEvent* event) { - int num_events; - if (!PollLooper(timeout_ms, &num_events)) { - return false; - } - return (ASensorEventQueue_getEvents(queue_, event, 1) > 0); - } - - bool ReadEvent(ASensorEvent* event) { - return (ASensorEventQueue_getEvents(queue_, event, 1) > 0); - } - - private: - ASensorManager* manager_; // Owned by android library. - const ASensor* sensor_; // Owned by android library. - ASensorEventQueue* queue_; // Owned by this. -}; - -} // namespace - -// This struct holds android gyroscope specific sensor information. -struct DeviceGyroscopeSensor::SensorInfo { - SensorInfo() : sensor_manager(nullptr), sensor(nullptr) {} - ASensorManager* sensor_manager; - const ASensor* sensor; - std::unique_ptr<SensorEventQueueReader> reader; -}; - -namespace { - -bool ParseGyroEvent(const ASensorEvent& event, GyroscopeData* sample) { - if (event.type == ASENSOR_TYPE_ADDITIONAL_INFO) { - CARDBOARD_LOGI("ParseGyroEvent discarding additional info sensor event"); - return false; - } - - sample->sensor_timestamp_ns = event.timestamp; - sample->system_timestamp = event.timestamp; // Clock::time_point(); - // The event values in ASensorEvent (event, acceleration and - // magnetic) are all in the same union type so they can be - // accessed by event. - if (event.type == ASENSOR_TYPE_GYROSCOPE) { - sample->data = {event.vector.x, event.vector.y, event.vector.z}; - return true; - } else if (event.type == ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED) { - // This is a special case when it is possible to initialize to - // ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED - sample->data = {event.vector.x, event.vector.y, event.vector.z}; - return true; - } else { - CARDBOARD_LOGE("ParseGyroEvent discarding unexpected sensor event type %d", - event.type); - } - - return false; -} - -} // namespace - -DeviceGyroscopeSensor::DeviceGyroscopeSensor() - : sensor_info_(new SensorInfo()) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - sensor_info_->sensor_manager = ASensorManager_getInstance(); -#pragma clang diagnostic pop - sensor_info_->sensor = InitSensor(sensor_info_->sensor_manager); - if (!sensor_info_->sensor) { - return; - } - - sensor_info_->reader = - std::unique_ptr<SensorEventQueueReader>(new SensorEventQueueReader( - sensor_info_->sensor_manager, sensor_info_->sensor)); -} - -DeviceGyroscopeSensor::~DeviceGyroscopeSensor() {} - -void DeviceGyroscopeSensor::PollForSensorData( - int timeout_ms, - std::vector<GyroscopeData>* results) const { - results->clear(); - ASensorEvent event; - if (!sensor_info_->reader->WaitForEvent(timeout_ms, &event)) { - return; - } - do { - GyroscopeData sample; - if (ParseGyroEvent(event, &sample)) { - results->push_back(sample); - } - } while (sensor_info_->reader->ReadEvent(&event)); -} - -bool DeviceGyroscopeSensor::Start() { - if (!sensor_info_->reader) { - CARDBOARD_LOGE("Could not start gyroscope sensor."); - return false; - } - return sensor_info_->reader->Start(); -} - -void DeviceGyroscopeSensor::Stop() { - if (!sensor_info_->reader) { - return; - } - sensor_info_->reader->Stop(); -} - -} // namespace cardboard
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index a7a1e5e..dfd5d19 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit a7a1e5eaa6ed285b51271a665bfda91bc8fe7a3f +Subproject commit dfd5d19b1692bb48558f9ee13f1248aed2251886
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index d27a6b8..ecca9b5 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit d27a6b83a969ae8c9a02df0e03e5756a1f4c521a +Subproject commit ecca9b5d5bc1e729ccb20fc4c3ca68da163bcb06
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 3a11358..7128b4c 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 3a113586c2d333056dc944e92db447ddaa492762 +Subproject commit 7128b4c8c6619ee48f9dd33a4ed13be79b107a26
diff --git a/third_party/libc++/src b/third_party/libc++/src index 3c2f388..6024b26 160000 --- a/third_party/libc++/src +++ b/third_party/libc++/src
@@ -1 +1 @@ -Subproject commit 3c2f3884e62e17b137ede3e2f3e7214ef294e2c9 +Subproject commit 6024b26887625fef52ea0f227d888c4b815488be
diff --git a/third_party/perfetto b/third_party/perfetto index 786ec3a..5cafd5f 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 786ec3a414ad41aa627a88b83c7fd9bae5d59136 +Subproject commit 5cafd5f37c15d474540c4a3439129381f4184f39
diff --git a/third_party/skia b/third_party/skia index c29a207..7bba745 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit c29a20702356a118d09d173755d66315b16127cf +Subproject commit 7bba745c06f2b61b147716b112a9f8b565212113
diff --git a/third_party/webrtc b/third_party/webrtc index 1188d08..310c9d4 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 1188d0849f18baf91ab0061781ea1a521363b8bd +Subproject commit 310c9d4cbe0f3d7bbf3e5bcc2a2a92c8c350372f
diff --git a/tools/code_coverage/coverage_consts.py b/tools/code_coverage/coverage_consts.py index d19fa6d..9c42fb8 100755 --- a/tools/code_coverage/coverage_consts.py +++ b/tools/code_coverage/coverage_consts.py
@@ -325,6 +325,7 @@ 'pffft_complex_fuzzer', 'pffft_real_fuzzer', 'pickle_fuzzer', + 'pix_code_validator_fuzzer', 'policy_schema_fuzzer', 'preg_parser_fuzzer', 'process_doc_fuzzer',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index d88c2729..f9b82cb 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -4576,6 +4576,7 @@ </action> <action name="AvatarToolbarButtonHighlighted"> + <obsolete>Removed in M123</obsolete> <owner>siyua@chromium.org</owner> <owner>droger@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 105c53ac..b28df94 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2467,6 +2467,9 @@ </enum> <enum name="BreakageIndicatorType"> + <obsolete> + Deprecated 02/2024. + </obsolete> <int value="0" label="User Reload"/> <int value="1" label="HTTP Error"/> <int value="2" label="Uncaught JS Error"/> @@ -15008,6 +15011,7 @@ label="Profile menu of installable chrome://password-manager WebUI)"/> <int value="36" label="Launch from system tray Calendar"/> <int value="37" label="Installer"/> + <int value="38" label="First run"/> </enum> <enum name="LcppHintStatus">
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml index d4e19ec2..3b761f92 100644 --- a/tools/metrics/histograms/metadata/apps/histograms.xml +++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -2088,6 +2088,7 @@ <variant name=".FromDiscoverTabNotification" summary="From Discover Tab notification."/> <variant name=".FromFileManager" summary="From FileManager."/> + <variant name=".FromFirstRun" summary="From first run."/> <variant name=".FromFullRestore" summary="From full restore."/> <variant name=".FromInstalledNotification" summary="From installed notification."/>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index 6dec92a..653748b 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -3311,18 +3311,6 @@ </summary> </histogram> -<histogram name="Autofill.PageLoadsWithOfferIconShowing.{OfferType}" - enum="BooleanShown" expires_after="2023-07-01"> - <owner>meiliang@chromium.org</owner> - <owner>chrome-shopping@google.com</owner> - <summary> - Emits true if the offer notification icon is currently being shown in the - omnibox after a page navigation for {OfferType}. Doesn't emit any other - value. - </summary> - <token key="OfferType" variants="Autofill.OfferNotification.Type"/> -</histogram> - <histogram name="Autofill.PaymentMethods.CheckoutFlow.ReauthUsage.{CardType}.{AuthenticationMethod}" enum="MandatoryReauthAuthEvent" expires_after="2024-07-01">
diff --git a/tools/metrics/histograms/metadata/commerce/histograms.xml b/tools/metrics/histograms/metadata/commerce/histograms.xml index 9f2d8495..952553a 100644 --- a/tools/metrics/histograms/metadata/commerce/histograms.xml +++ b/tools/metrics/histograms/metadata/commerce/histograms.xml
@@ -443,13 +443,14 @@ </histogram> <histogram name="Commerce.PriceInsights.BuyingOptionsClicked" - enum="PriceInsightsPriceBucket" expires_after="2024-01-03"> + enum="PriceInsightsPriceBucket" expires_after="2024-08-06"> <owner>zhiyuancai@chromium.org</owner> <owner>ayman@chromium.org</owner> <owner>chrome-shopping@google.com</owner> <summary> Records the current price bucket of the product when the user clicks - "Buying Options" in the price insights side panel. + "Buying Options" in the price insights side panel. This histogram + was expired from 2024-01-03 to 2024-02-06. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/cros_audio/histograms.xml b/tools/metrics/histograms/metadata/cros_audio/histograms.xml index ecd53f9..eeb24272 100644 --- a/tools/metrics/histograms/metadata/cros_audio/histograms.xml +++ b/tools/metrics/histograms/metadata/cros_audio/histograms.xml
@@ -60,7 +60,7 @@ </histogram> <histogram name="ChromeOS.CrosAudioConfig.DeviceChange" - enum="AudioDeviceChange" expires_after="2024-02-14"> + enum="AudioDeviceChange" expires_after="2024-06-30"> <owner>gavinwill@chromium.org</owner> <owner>cros-peripherals@google.com</owner> <summary> @@ -94,7 +94,7 @@ </histogram> <histogram name="ChromeOS.CrosAudioConfig.InputMuteStateChange" - enum="AudioMuteButtonAction" expires_after="2024-02-14"> + enum="AudioMuteButtonAction" expires_after="2024-06-30"> <owner>gavinwill@chromium.org</owner> <owner>cros-peripherals@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/enterprise/enums.xml b/tools/metrics/histograms/metadata/enterprise/enums.xml index 150d729f..935eb98 100644 --- a/tools/metrics/histograms/metadata/enterprise/enums.xml +++ b/tools/metrics/histograms/metadata/enterprise/enums.xml
@@ -2025,6 +2025,8 @@ <int value="1208" label="ToolbarAvatarLabelSettings"/> <int value="1209" label="DeviceWeeklyScheduledSuspend"/> <int value="1210" label="RemoteAccessHostAllowUrlForwarding"/> + <int value="1211" label="ScreenCaptureLocation"/> + <int value="1212" label="AllowDomainsForAppsList"/> </enum> <enum name="EnterprisePoliciesSources">
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml index 64920b2..4a865bb 100644 --- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml +++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -2629,7 +2629,7 @@ </histogram> <histogram name="SafeBrowsing.V4GetHash.CacheFullyHit" enum="BooleanCacheHit" - expires_after="2024-02-20"> + expires_after="2024-08-20"> <owner>thefrog@chromium.org</owner> <owner>chrome-counter-abuse-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml index 455b23f..bbb8326 100644 --- a/tools/metrics/histograms/metadata/security/histograms.xml +++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -292,7 +292,7 @@ </histogram> <histogram name="Security.JSONParser.ParsingTime" units="microseconds" - expires_after="M124"> + expires_after="M126"> <owner>djmitche@chromium.org</owner> <owner>chrome-platform-security@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/signin/enums.xml b/tools/metrics/histograms/metadata/signin/enums.xml index 681060f..499c1ea 100644 --- a/tools/metrics/histograms/metadata/signin/enums.xml +++ b/tools/metrics/histograms/metadata/signin/enums.xml
@@ -766,6 +766,7 @@ </int> <int value="19" label="LogoutTabHelper::DidFinishNavigation"/> <int value="20" label="ForceSigninReauthWithDifferentAccount"/> + <int value="21" label="AccountReconcilor::RevokeTokensNotInCookies"/> </enum> <enum name="SyncErrorPromptUIAction">
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml index 77bf49b..c5d5dd5 100644 --- a/tools/metrics/histograms/metadata/tab/histograms.xml +++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1944,6 +1944,33 @@ </summary> </histogram> +<histogram name="Tabs.TabSearch.TimeToShow.{WarmUpLevel}" units="ms" + expires_after="2024-12-31"> + <owner>kerenzhu@chromium.org</owner> + <owner>dayeung@chromium.org</owner> + <owner>tluk@chromium.org</owner> + <owner>robliao@chromium.org</owner> + <summary> + This tracks the time between when the Tab Search WebUI bubble widget is + first created and when it is first shown to users as reported by the bubble + widget's ui compositor. This metric is only logged for the specific warm-up + level. The warm-up level indicates the readiness of the browser when it was + about to show this WebUI. + + This metric is emitted when the bubble window is first revealed. + </summary> + <token key="WarmUpLevel"> + <variant name="DedicatedRenderer" + summary="Uses a renderer that already hosts other top chrome WebUIs"/> + <variant name="NavigatedWebContents" + summary="Uses a WebContents that has already navigated to this WebUI"/> + <variant name="NoRenderer" summary="No renderer can be used"/> + <variant name="RedirectedRenderer" + summary="Uses a redirected WebContents. Note: currently not used"/> + <variant name="SpareRenderer" summary="Uses a spare renderer"/> + </token> +</histogram> + <histogram name="Tabs.TabSearch.WebUI.IndexOf{Action}In{State}List" units="tabs" expires_after="2024-12-31"> <owner>tluk@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index c32a280..daf22b3 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -26006,6 +26006,12 @@ </event> <event name="ThirdPartyCookies.BreakageIndicator"> + <obsolete> + Deprecated 02/2024. Replaced with: + ThirdPartyCookies.BreakageIndicator.HTTPError, + ThirdPartyCookies.BreakageIndicator.UncaughtJSError, + ThirdPartyCookies.BreakageIndicator.UserReload. + </obsolete> <owner>3pcd-core@google.com</owner> <owner>kurtosis-team@google.com</owner> <owner>johannhof@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 334338b8..66b6700 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@ "full_remote_path": "perfetto-luci-artifacts/v42.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "7de412f93bacd7427c6db87ceb751aad749a23e6", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/786ec3a414ad41aa627a88b83c7fd9bae5d59136/trace_processor_shell.exe" + "hash": "31468bd5ec994f6006287d6837440dd3d9c1dbae", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/5cafd5f37c15d474540c4a3439129381f4184f39/trace_processor_shell.exe" }, "linux_arm": { "hash": "46739eeb4b8f2a65a8a0aac57743767e6407f7bb", @@ -21,8 +21,8 @@ "full_remote_path": "perfetto-luci-artifacts/v42.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "20b7c0fc1a3dcfd10f7b4c6f3d9df15f60bf7baa", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/786ec3a414ad41aa627a88b83c7fd9bae5d59136/trace_processor_shell" + "hash": "c7481c40de05cdcb66abaefe76c43dd2a058328c", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/5cafd5f37c15d474540c4a3439129381f4184f39/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/process_perf_results.pydeps b/tools/perf/process_perf_results.pydeps index d30d042d..c84c7140 100644 --- a/tools/perf/process_perf_results.pydeps +++ b/tools/perf/process_perf_results.pydeps
@@ -552,6 +552,10 @@ contrib/power/stories.py contrib/power/top_sites_story.py contrib/power/wakeups.py +contrib/shared_storage/__init__.py +contrib/shared_storage/page_set.py +contrib/shared_storage/pages.py +contrib/shared_storage/shared_storage.py contrib/system_health_scroll_jank/__init__.py contrib/system_health_scroll_jank/janky_story_set.py contrib/system_health_scroll_jank/system_health_scroll_jank.py
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 1f843f9f..043046d 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -150,7 +150,7 @@ <item id="password_protection_request" added_in_milestone="62" content_hash_code="01869413" os_list="linux,windows,chromeos,android" file_path="components/safe_browsing/core/browser/password_protection/password_protection_request.cc" /> <item id="password_requirements_spec_fetch" added_in_milestone="69" content_hash_code="005550dc" os_list="linux,windows,chromeos,android" file_path="components/password_manager/core/browser/generation/password_requirements_spec_fetcher_impl.cc" /> <item id="payment_manifest_downloader" added_in_milestone="62" content_hash_code="01266484" os_list="linux,windows,chromeos,android" file_path="components/payments/core/payment_manifest_downloader.cc" /> - <item id="payments_sync_cards" added_in_milestone="62" content_hash_code="035e86b1" os_list="linux,windows,chromeos,android" file_path="components/autofill/core/browser/payments/payments_network_interface.cc" /> + <item id="payments_sync_cards" added_in_milestone="62" content_hash_code="027dd4a5" os_list="linux,windows,chromeos,android" file_path="components/autofill/core/browser/payments/payments_network_interface_base.cc" /> <item id="pdf_plugin_placeholder" added_in_milestone="63" content_hash_code="0101fbd5" os_list="linux,windows,chromeos" file_path="chrome/browser/plugins/plugin_observer.cc" /> <item id="per_user_topic_registration_request" added_in_milestone="68" content_hash_code="0367425f" os_list="linux,windows,chromeos,android" file_path="components/invalidation/impl/per_user_topic_subscription_request.cc" /> <item id="permission_predictions" added_in_milestone="88" content_hash_code="0556d9f7" os_list="linux,windows,chromeos,android" file_path="components/permissions/prediction_service/prediction_service.cc" />
diff --git a/ui/aura/DIR_METADATA b/ui/aura/DIR_METADATA index b6a6331..d20312e2 100644 --- a/ui/aura/DIR_METADATA +++ b/ui/aura/DIR_METADATA
@@ -1,3 +1,6 @@ monorail: { component: "UI>Aura" } +buganizer_public: { + component_id: 1456113 +}
diff --git a/ui/aura/gestures/DIR_METADATA b/ui/aura/gestures/DIR_METADATA index 0164239..ba506cb 100644 --- a/ui/aura/gestures/DIR_METADATA +++ b/ui/aura/gestures/DIR_METADATA
@@ -2,3 +2,6 @@ component: "UI>Input" } team_email: "input-dev@chromium.org" +buganizer_public: { + component_id: 1457729 +}
diff --git a/ui/aura_extra/DIR_METADATA b/ui/aura_extra/DIR_METADATA index b6a6331..d20312e2 100644 --- a/ui/aura_extra/DIR_METADATA +++ b/ui/aura_extra/DIR_METADATA
@@ -1,3 +1,6 @@ monorail: { component: "UI>Aura" } +buganizer_public: { + component_id: 1456113 +}
diff --git a/ui/base/clipboard/DIR_METADATA b/ui/base/clipboard/DIR_METADATA index 7d0a14e..060c29b7 100644 --- a/ui/base/clipboard/DIR_METADATA +++ b/ui/base/clipboard/DIR_METADATA
@@ -1,12 +1,7 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Blink>DataTransfer" } -team_email: "storage-dev@chromium.org" \ No newline at end of file +team_email: "storage-dev@chromium.org" +buganizer_public: { + component_id: 1456484 +}
diff --git a/ui/base/cursor/DIR_METADATA b/ui/base/cursor/DIR_METADATA index f343444..b95192f 100644 --- a/ui/base/cursor/DIR_METADATA +++ b/ui/base/cursor/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Internals>Input" } +buganizer_public: { + component_id: 1456650 +}
diff --git a/ui/base/data_transfer_policy/DIR_METADATA b/ui/base/data_transfer_policy/DIR_METADATA index a600cb0..34ec5593 100644 --- a/ui/base/data_transfer_policy/DIR_METADATA +++ b/ui/base/data_transfer_policy/DIR_METADATA
@@ -1,12 +1,7 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "OS>Software>Enterprise>DLP" } -team_email: "chromeos-dlp@google.com" \ No newline at end of file +team_email: "chromeos-dlp@google.com" +buganizer_public: { + component_id: 1457113 +}
diff --git a/ui/base/dragdrop/DIR_METADATA b/ui/base/dragdrop/DIR_METADATA index 7d0a14e..060c29b7 100644 --- a/ui/base/dragdrop/DIR_METADATA +++ b/ui/base/dragdrop/DIR_METADATA
@@ -1,12 +1,7 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Blink>DataTransfer" } -team_email: "storage-dev@chromium.org" \ No newline at end of file +team_email: "storage-dev@chromium.org" +buganizer_public: { + component_id: 1456484 +}
diff --git a/ui/base/emoji/DIR_METADATA b/ui/base/emoji/DIR_METADATA index f343444..b95192f 100644 --- a/ui/base/emoji/DIR_METADATA +++ b/ui/base/emoji/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Internals>Input" } +buganizer_public: { + component_id: 1456650 +}
diff --git a/ui/base/glib/DIR_METADATA b/ui/base/glib/DIR_METADATA index d072fa6..45f7798a6 100644 --- a/ui/base/glib/DIR_METADATA +++ b/ui/base/glib/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Internals" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1456292 +}
diff --git a/ui/base/idle/DIR_METADATA b/ui/base/idle/DIR_METADATA index d072fa6..45f7798a6 100644 --- a/ui/base/idle/DIR_METADATA +++ b/ui/base/idle/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Internals" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1456292 +}
diff --git a/ui/base/ime/DIR_METADATA b/ui/base/ime/DIR_METADATA index e0756fd7..41559387 100644 --- a/ui/base/ime/DIR_METADATA +++ b/ui/base/ime/DIR_METADATA
@@ -1,13 +1,8 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { - # For non-Chrome/Chromium OS: +# For Chrome/Chromium OS, please see //ui/base/ime/ash/COMMON_METADATA. +# For non-Chrome/Chromium OS: +monorail: { component: "UI>Input>Text>IME" - # For Chrome/Chromium OS, please see //ui/base/ime/ash/COMMON_METADATA. +} +buganizer_public: { + component_id: 1456787 }
diff --git a/ui/base/ime/character_composer.cc b/ui/base/ime/character_composer.cc index 3734ca8..613d2fd 100644 --- a/ui/base/ime/character_composer.cc +++ b/ui/base/ime/character_composer.cc
@@ -61,9 +61,10 @@ namespace ui { -CharacterComposer::CharacterComposer() : composition_mode_(KEY_SEQUENCE_MODE) {} +CharacterComposer::CharacterComposer(PreeditStringMode mode) + : preedit_string_mode_(mode) {} -CharacterComposer::~CharacterComposer() {} +CharacterComposer::~CharacterComposer() = default; void CharacterComposer::Reset() { compose_buffer_.clear(); @@ -123,6 +124,11 @@ compose_buffer_.clear(); UTF32CharacterToUTF16(composed_character_utf32, &composed_character_); } + + if (preedit_string_mode_ == PreeditStringMode::kAlwaysEnabled) { + UpdatePreeditStringSequenceMode(); + } + return true; } // Key press is not a part of composition. @@ -149,11 +155,31 @@ } } compose_buffer_.clear(); + + if (preedit_string_mode_ == PreeditStringMode::kAlwaysEnabled) { + UpdatePreeditStringSequenceMode(); + } + return true; } return false; } +void CharacterComposer::UpdatePreeditStringSequenceMode() { + CHECK_EQ(preedit_string_mode_, PreeditStringMode::kAlwaysEnabled); + for (auto key : compose_buffer_) { + if (key.IsCharacter()) { + base::WriteUnicodeCharacter(key.ToCharacter(), &preedit_string_); + } else if (key.IsDeadKey()) { + base::WriteUnicodeCharacter(key.ToDeadKeyCombiningCharacter(), + &preedit_string_); + } else if (key.IsComposeKey() && (compose_buffer_.size() == 1)) { + base::WriteUnicodeCharacter(kPreeditStringComposeKeySymbol, + &preedit_string_); + } + } +} + bool CharacterComposer::FilterKeyPressHexMode(const KeyEvent& event) { DCHECK(composition_mode_ == HEX_MODE); const size_t kMaxHexSequenceLength = 8;
diff --git a/ui/base/ime/character_composer.h b/ui/base/ime/character_composer.h index d9d0b478..3d3b3ced 100644 --- a/ui/base/ime/character_composer.h +++ b/ui/base/ime/character_composer.h
@@ -25,7 +25,22 @@ public: using ComposeBuffer = std::vector<DomKey>; - CharacterComposer(); + // The U+00B7 "middle dot" character is also used by GTK to represent the + // compose key in preedit strings. + static constexpr char16_t kPreeditStringComposeKeySymbol = 0x00B7; + + // Decides in which modes the preedit string is enabled. If disabled for a + // mode, it is always empty in that mode. + enum class PreeditStringMode { + // Enable in both hex and sequence mode. + kAlwaysEnabled, + // Enable in hex mode, disable in sequence mode. + kHexModeOnly, + }; + + // Disable the preedit string in sequence mode by default. + explicit CharacterComposer( + PreeditStringMode mode = PreeditStringMode::kHexModeOnly); CharacterComposer(const CharacterComposer&) = delete; CharacterComposer& operator=(const CharacterComposer&) = delete; @@ -62,6 +77,9 @@ // Filters keypress in key sequence mode. bool FilterKeyPressSequenceMode(const ui::KeyEvent& event); + // Updates preedit string in key sequence mode. + void UpdatePreeditStringSequenceMode(); + // Filters keypress in hexadecimal mode. bool FilterKeyPressHexMode(const ui::KeyEvent& event); @@ -84,7 +102,9 @@ std::u16string preedit_string_; // Composition mode which this instance is in. - CompositionMode composition_mode_; + CompositionMode composition_mode_ = KEY_SEQUENCE_MODE; + + const PreeditStringMode preedit_string_mode_; }; // Abstract class for determining whether a ComposeBuffer forms a valid @@ -100,7 +120,7 @@ // The sequence matches a composition sequence. FULL_MATCH }; - ComposeChecker() {} + ComposeChecker() = default; ComposeChecker(const ComposeChecker&) = delete; ComposeChecker& operator=(const ComposeChecker&) = delete;
diff --git a/ui/base/ime/character_composer_unittest.cc b/ui/base/ime/character_composer_unittest.cc index a6dfd89..83fc0a3 100644 --- a/ui/base/ime/character_composer_unittest.cc +++ b/ui/base/ime/character_composer_unittest.cc
@@ -308,9 +308,10 @@ ExpectUnicodeKeyNotFiltered(VKEY_A, DomCode::US_A, EF_NONE, 'a'); } -TEST_F(CharacterComposerTest, KeySequenceCompositionPreedit) { +TEST_F(CharacterComposerTest, KeySequenceCompositionPreeditDisabled) { // LATIN SMALL LETTER A WITH ACUTE - // preedit_string() is always empty in key sequence composition mode. + // preedit_string() is by default always empty in key sequence composition + // mode. ExpectDeadKeyFiltered(kCombiningAcute); EXPECT_TRUE(character_composer_.preedit_string().empty()); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', @@ -318,7 +319,8 @@ EXPECT_TRUE(character_composer_.preedit_string().empty()); // LATIN SMALL LETTER A WITH ACUTE (via Compose key) - // preedit_string() is always empty in key sequence composition mode. + // preedit_string() is by default always empty in key sequence composition + // mode. ExpectComposeKeyFiltered(); EXPECT_TRUE(character_composer_.preedit_string().empty()); ExpectUnicodeKeyFiltered(VKEY_OEM_7, DomCode::QUOTE, 0, '\''); @@ -328,6 +330,36 @@ EXPECT_TRUE(character_composer_.preedit_string().empty()); } +TEST_F(CharacterComposerTest, KeySequenceCompositionPreeditEnabled) { + // Same test instructions as for KeySequenceCompositionPreeditDisabled, but + // adjusted expectations. + + // Reconstruct to set flag. + // TODO(max@igalia.com): get rid of placement new by making + // `character_composer_` a unique_ptr. + new (&character_composer_) + CharacterComposer(CharacterComposer::PreeditStringMode::kAlwaysEnabled); + + // LATIN SMALL LETTER A WITH ACUTE + ExpectDeadKeyFiltered(kCombiningAcute); + EXPECT_EQ(character_composer_.preedit_string(), + std::u16string(1, kCombiningAcute)); + ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', + std::u16string(1, 0x00E1)); + EXPECT_TRUE(character_composer_.preedit_string().empty()); + + // LATIN SMALL LETTER A WITH ACUTE (via Compose key) + ExpectComposeKeyFiltered(); + EXPECT_EQ( + character_composer_.preedit_string(), + std::u16string(1, CharacterComposer::kPreeditStringComposeKeySymbol)); + ExpectUnicodeKeyFiltered(VKEY_OEM_7, DomCode::QUOTE, 0, '\''); + EXPECT_EQ(character_composer_.preedit_string(), u"'"); + ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', + std::u16string(1, 0x00E1)); + EXPECT_TRUE(character_composer_.preedit_string().empty()); +} + // Verify the structure of the primary |TreeComposeChecker| table. TEST_F(CharacterComposerTest, MainTableIsCorrectlyOrdered) { // This file is included here intentionally, instead of the top of the file,
diff --git a/ui/base/l10n/DIR_METADATA b/ui/base/l10n/DIR_METADATA index 0d5c5e7c..6f943ed 100644 --- a/ui/base/l10n/DIR_METADATA +++ b/ui/base/l10n/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "UI>Internationalization" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1456398 +}
diff --git a/ui/base/pointer/DIR_METADATA b/ui/base/pointer/DIR_METADATA index f343444..b95192f 100644 --- a/ui/base/pointer/DIR_METADATA +++ b/ui/base/pointer/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Internals>Input" } +buganizer_public: { + component_id: 1456650 +}
diff --git a/ui/base/resource/DIR_METADATA b/ui/base/resource/DIR_METADATA index d072fa6..45f7798a6 100644 --- a/ui/base/resource/DIR_METADATA +++ b/ui/base/resource/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Internals" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1456292 +}
diff --git a/ui/base/test/DIR_METADATA b/ui/base/test/DIR_METADATA index d22dc2f4..adf3662 100644 --- a/ui/base/test/DIR_METADATA +++ b/ui/base/test/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Tests" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457350 +}
diff --git a/ui/base/text/DIR_METADATA b/ui/base/text/DIR_METADATA index b514feb..55c4d027 100644 --- a/ui/base/text/DIR_METADATA +++ b/ui/base/text/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "UI>Localization" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1456895 +}
diff --git a/ui/base/webui/DIR_METADATA b/ui/base/webui/DIR_METADATA index f0076025..613ca0c 100644 --- a/ui/base/webui/DIR_METADATA +++ b/ui/base/webui/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "UI>Browser>WebUI" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457323 +}
diff --git a/ui/chromeos/translations/ui_chromeos_strings_be.xtb b/ui/chromeos/translations/ui_chromeos_strings_be.xtb index 60d6aef3..0b4e50c 100644 --- a/ui/chromeos/translations/ui_chromeos_strings_be.xtb +++ b/ui/chromeos/translations/ui_chromeos_strings_be.xtb
@@ -95,7 +95,7 @@ <translation id="1742316578210444689">Іўрыт (транслітарацыя)</translation> <translation id="1747761757048858544">Нідэрландская (Нідэрланды)</translation> <translation id="174937106936716857">Агульная колькасць файлаў</translation> -<translation id="1755345808328621801">Гэты файл створаны для ПК з праграмным забеспячэннем Windows. Ён несумяшчальны з вашай прыладай Chrome OS. Пашукайце ў Chrome Web Store адпаведную праграму на замену.</translation> +<translation id="1755345808328621801">Гэты файл створаны для ПК з праграмным забеспячэннем Windows. Ён несумяшчальны з вашай прыладай Chrome OS. Пашукайце ў Вэб-краме Chrome адпаведную праграму на замену.</translation> <translation id="1757915090001272240">Шырокая лацініца</translation> <translation id="1761091787730831947">Абагуліць з <ph name="VM_NAME" /></translation> <translation id="1773212559869067373">Сертыфікат аўтэнтыфікацыі адхілены ў лакальнай сетцы</translation> @@ -243,7 +243,7 @@ <translation id="2949781154072577687">Фармаціруецца дыск "<ph name="DRIVE_NAME" />"...</translation> <translation id="2951236788251446349">Медуза</translation> <translation id="2958458230122209142">У вашым індывідуальным сховішчы мала месца. Застаецца <ph name="REMAINING_PERCENTAGE" />% з <ph name="TOTAL_SPACE" />.</translation> -<translation id="2977940621473452797">Гэты файл прызначаны для камп'ютара з праграмным забеспячэннем Macintosh. Ён несумяшчальны з вашай прыладай Chrome OS. Пашукайце ў Chrome Web Store адпаведную праграму на замену.</translation> +<translation id="2977940621473452797">Гэты файл прызначаны для камп'ютара з праграмным забеспячэннем Macintosh. Ён несумяшчальны з вашай прыладай Chrome OS. Пашукайце ў Вэб-краме Chrome адпаведную праграму на замену.</translation> <translation id="2984337792991268709">Сёння <ph name="TODAY_DAYTIME" /></translation> <translation id="299638574917407533">Французская (Канада)</translation> <translation id="3003189754374775221">Сетка <ph name="NETWORK_INDEX" /> з <ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="NETWORK_PROVIDER_NAME" />, магутнасць сігналу – <ph name="SIGNAL_STRENGTH" />%, падключыцеся да сеткі</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ky.xtb b/ui/chromeos/translations/ui_chromeos_strings_ky.xtb index 42eca55..4fbf75a 100644 --- a/ui/chromeos/translations/ui_chromeos_strings_ky.xtb +++ b/ui/chromeos/translations/ui_chromeos_strings_ky.xtb
@@ -95,7 +95,7 @@ <translation id="1742316578210444689">Ивритче (транслитерация)</translation> <translation id="1747761757048858544">Голландча (Нидерланддар)</translation> <translation id="174937106936716857">Жалпы файлдардын саны</translation> -<translation id="1755345808328621801">Бул файл Windows программасын колдонгон компьютер үчүн түзүлгөн. Ал ChromeOS негизинде иштеген түзмөгүңүзгө дал келбейт. Chrome Интернет дүкөнүнөн анын ордуна колдонула турган ылайыктуу колдонмо издеп көрүңүз.</translation> +<translation id="1755345808328621801">Бул файл Windows программасын колдонгон компьютер үчүн түзүлгөн. Ал ChromeOS негизинде иштеген түзмөгүңүзгө дал келбейт. Chrome Web Store'дон анын ордуна колдонула турган ылайыктуу колдонмо издеп көрүңүз.</translation> <translation id="1757915090001272240">Жазы латын тамгалары</translation> <translation id="1761091787730831947"><ph name="VM_NAME" /> аркылуу бөлүшүү</translation> <translation id="1773212559869067373">Аныктыгын текшерүү тастыктамасы жергиликтүү деңгээлде четке кагылды</translation> @@ -243,7 +243,7 @@ <translation id="2949781154072577687"><ph name="DRIVE_NAME" /> форматталууда...</translation> <translation id="2951236788251446349">Медуза</translation> <translation id="2958458230122209142">Жеке сактагычта орун аз. <ph name="TOTAL_SPACE" /> ичинен <ph name="REMAINING_PERCENTAGE" />% калды.</translation> -<translation id="2977940621473452797">Бул файл Macintosh программасын колдонгон компьютер үчүн түзүлгөн. Ал ChromeOS негизинде иштеген түзмөгүңүзгө дал келбейт. Chrome Интернет дүкөнүнөн анын ордуна колдонула турган ылайыктуу колдонмо издеп көрүңүз.</translation> +<translation id="2977940621473452797">Бул файл Macintosh программасын колдонгон компьютер үчүн түзүлгөн. Ал ChromeOS негизинде иштеген түзмөгүңүзгө дал келбейт. Chrome Web Store'дон анын ордуна колдонула турган ылайыктуу колдонмо издеп көрүңүз.</translation> <translation id="2984337792991268709">Бүгүн <ph name="TODAY_DAYTIME" /></translation> <translation id="299638574917407533">Французча (Канада)</translation> <translation id="3003189754374775221"><ph name="NETWORK_COUNT" /> ичинен <ph name="NETWORK_INDEX" />-тармак, <ph name="NETWORK_NAME" />, <ph name="NETWORK_PROVIDER_NAME" />, сигналдын күчү <ph name="SIGNAL_STRENGTH" />%, туташуу</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_mr.xtb b/ui/chromeos/translations/ui_chromeos_strings_mr.xtb index 12d924d..4f247cd 100644 --- a/ui/chromeos/translations/ui_chromeos_strings_mr.xtb +++ b/ui/chromeos/translations/ui_chromeos_strings_mr.xtb
@@ -165,7 +165,7 @@ <translation id="2303301624314357662">फाइल <ph name="FILE_NAME" /> उघडत आहे.</translation> <translation id="2304820083631266885">ग्रह</translation> <translation id="2305020378527873881"><ph name="VOLUME_NAME" /> बाहेर काढले गेले आहे.</translation> -<translation id="2307462900900812319">नेटवर्क कॉंफिगर करा</translation> +<translation id="2307462900900812319">नेटवर्क कॉन्फिगर करा</translation> <translation id="2312704192806647271">{COUNT,plural, =1{<ph name="BEGIN_LIST" /><ph name="END_LIST" /> हा आयडी असलेले एक्स्टेंशन लोकेट करू शकत नाही. तुमच्या अॅडमिनिस्ट्रेटरशी संपर्क साधा.}other{<ph name="BEGIN_LIST" /><ph name="END_LIST" /> हे आयडी असलेले एक्स्टेंशन लोकेट करू शकत नाही. तुमच्या अॅडमिनिस्ट्रेटरशी संपर्क साधा.}}</translation> <translation id="2325650632570794183">हा फाइल प्रकार सपोर्टेड नाही. कृपया या प्रकारची फाइल उघडू शकणारे अॅप शोधण्यासाठी Chrome वेब स्टोअरला भेट द्या.</translation> <translation id="2326539130272988168">बल्गेरियन</translation> @@ -890,7 +890,7 @@ <translation id="78104721049218340">किडमनी कीबोर्डसह थाई</translation> <translation id="7814857791038398352">Microsoft OneDrive</translation> <translation id="7827012282502221009"><ph name="NUMBER_OF_TB" /> TB</translation> -<translation id="7831491651892296503">नेटवर्क कॉंफिगर करताना एरर आली</translation> +<translation id="7831491651892296503">नेटवर्क कॉन्फिगर करताना एरर आली</translation> <translation id="7839804798877833423">या फाइल प्राप्त करताना अंदाजे <ph name="FILE_SIZE" /> मोबाइल डेटा वापरला जाईल.</translation> <translation id="7846076177841592234">निवड रद्द करा</translation> <translation id="7853966320808728790">फ्रेंच बेपो</translation> @@ -932,7 +932,7 @@ <translation id="8138705869659070104">डिव्हाइस सेटअपनंतर सक्रिय करा</translation> <translation id="813913629614996137">सुरू करत आहे…</translation> <translation id="8147028810663464959">वर्णाची रुंदी पूर्ण आहे</translation> -<translation id="8151638057146502721">कॉंफिगर करा</translation> +<translation id="8151638057146502721">कॉन्फिगर करा</translation> <translation id="8154666764013920974">{NUM_ERROR,plural, =1{१ एरर.}other{# एरर.}}</translation> <translation id="8154842056504218462">सर्व नोंदी निवडल्या आहेत.</translation> <translation id="8157684860301034423">ॲप माहिती पुन्हा मिळवता आली नाही.</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_pa.xtb b/ui/chromeos/translations/ui_chromeos_strings_pa.xtb index f1d66f8..a4b999b7 100644 --- a/ui/chromeos/translations/ui_chromeos_strings_pa.xtb +++ b/ui/chromeos/translations/ui_chromeos_strings_pa.xtb
@@ -95,7 +95,7 @@ <translation id="1742316578210444689">ਹਿਬਰੂ ਲਿਪੀਅੰਤਰਨ</translation> <translation id="1747761757048858544">ਡੱਚ (ਨੀਦਰਲੈਂਡ)</translation> <translation id="174937106936716857">ਫ਼ਾਈਲਾਂ ਦੀ ਕੁੱਲ ਗਿਣਤੀ</translation> -<translation id="1755345808328621801">ਇਹ ਫ਼ਾਈਲ Windows ਸਾਫ਼ਟਵੇਅਰ ਵਰਤਣ ਵਾਲੇ PC ਲਈ ਤਿਆਰ ਕੀਤੀ ਗਈ ਹੈ। ਇਹ ਤੁਹਾਡੇ ChromeOS ਨਾਲ ਚਲਣ ਵਾਲੇ ਡੀਵਾਈਸ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇਸ ਦੇ ਬਦਲਾਅ ਵਜੋਂ ਕਿਸੇ ਅਨੁਕੂਲ ਐਪ ਲਈ 'Chrome Web Store' ਖੋਜੋ।</translation> +<translation id="1755345808328621801">ਇਹ ਫ਼ਾਈਲ Windows ਸਾਫ਼ਟਵੇਅਰ ਵਰਤਣ ਵਾਲੇ PC ਲਈ ਤਿਆਰ ਕੀਤੀ ਗਈ ਹੈ। ਇਹ ਤੁਹਾਡੇ ChromeOS ਨਾਲ ਚਲਣ ਵਾਲੇ ਡੀਵਾਈਸ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇਸ ਦੇ ਬਦਲਾਅ ਵਜੋਂ ਕਿਸੇ ਅਨੁਕੂਲ ਐਪ ਲਈ 'Chrome ਵੈੱਬ ਸਟੋਰ' ਖੋਜੋ।</translation> <translation id="1757915090001272240">ਵਾਈਡ ਲਾਤੀਨੀ</translation> <translation id="1761091787730831947"><ph name="VM_NAME" /> ਨਾਲ ਸਾਂਝਾ ਕਰੋ</translation> <translation id="1773212559869067373">ਪ੍ਰਮਾਣਿਕਤਾ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਨੂੰ ਸਥਾਨਕ ਰੂਪ ਵਿਚ ਅਸਵੀਕਾਰ ਕੀਤਾ ਗਿਆ</translation> @@ -167,7 +167,7 @@ <translation id="2305020378527873881"><ph name="VOLUME_NAME" /> ਨੂੰ ਕੱਢ ਦਿੱਤਾ ਗਿਆ ਹੈ।</translation> <translation id="2307462900900812319">ਨੈੱਟਵਰਕ ਸੰਰੂਪਿਤ ਕਰੋ</translation> <translation id="2312704192806647271">{COUNT,plural, =1{ਆਈਡੀ ਵਾਲੀ ਐਕਸਟੈਂਸ਼ਨ <ph name="BEGIN_LIST" /><ph name="END_LIST" /> ਨੂੰ ਲੱਭਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ ਹੈ। ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।}one{ਆਈਡੀ ਵਾਲੀ ਐਕਸਟੈਂਸ਼ਨ <ph name="BEGIN_LIST" /><ph name="END_LIST" /> ਨੂੰ ਲੱਭਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ ਹੈ। ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।}other{ਆਈਡੀਆਂ ਵਾਲੀਆਂ ਐਕਸਟੈਂਸ਼ਨਾਂ <ph name="BEGIN_LIST" /><ph name="END_LIST" /> ਨੂੰ ਲੱਭਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ ਹੈ। ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।}}</translation> -<translation id="2325650632570794183">ਇਹ ਫ਼ਾਈਲ ਕਿਸਮ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਅਜਿਹੀ ਐਪ ਲੱਭਣ ਲਈ 'Chrome Web Store' 'ਤੇ ਜਾਓ ਜੋ ਇਸ ਕਿਸਮ ਦੀ ਫ਼ਾਈਲ ਖੋਲ੍ਹ ਸਕਦੀ ਹੈ।</translation> +<translation id="2325650632570794183">ਇਹ ਫ਼ਾਈਲ ਕਿਸਮ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਅਜਿਹੀ ਐਪ ਲੱਭਣ ਲਈ 'Chrome ਵੈੱਬ ਸਟੋਰ' 'ਤੇ ਜਾਓ ਜੋ ਇਸ ਕਿਸਮ ਦੀ ਫ਼ਾਈਲ ਖੋਲ੍ਹ ਸਕਦੀ ਹੈ।</translation> <translation id="2326539130272988168">ਬੁਲਗਾਰੀਆਈ</translation> <translation id="233822363739146957">ਤੁਹਾਡੀਆਂ ਸਾਰੀਆਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਸਿੰਕ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਜਗ੍ਹਾ ਨਹੀਂ ਹੈ</translation> <translation id="23721837607121582">ਮੋਬਾਈਲ ਪ੍ਰੋਫਾਈਲ ਡਾਊਨਲੋਡ ਕਰੋ, <ph name="NETWORK_COUNT" /> ਵਿੱਚੋਂ <ph name="NETWORK_INDEX" /> ਨੈੱਟਵਰਕ, <ph name="NETWORK_NAME" /></translation> @@ -243,7 +243,7 @@ <translation id="2949781154072577687"><ph name="DRIVE_NAME" /> ਨੂੰ ਫਾਰਮੈਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…</translation> <translation id="2951236788251446349">ਜੈਲੀਫ਼ਿਸ਼</translation> <translation id="2958458230122209142">ਸਟੋਰੇਜ ਘੱਟ ਹੈ। ਤੁਹਾਡੀ <ph name="TOTAL_SPACE" /> ਵਿਅਕਤੀਗਤ ਸਟੋਰੇਜ ਵਿੱਚ <ph name="REMAINING_PERCENTAGE" />% ਬਾਕੀ।</translation> -<translation id="2977940621473452797">ਇਹ ਫ਼ਾਈਲ Macintosh ਸਾਫ਼ਟਵੇਅਰ ਵਰਤਣ ਵਾਲੇ ਕੰਪਿਊਟਰ ਲਈ ਤਿਆਰ ਕੀਤੀ ਗਈ ਹੈ। ਇਹ ਤੁਹਾਡੇ ChromeOS ਨਾਲ ਚਲਣ ਵਾਲੇ ਡੀਵਾਈਸ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇਸ ਦੇ ਬਦਲਾਅ ਵਜੋਂ ਕਿਸੇ ਅਨੁਕੂਲ ਐਪ ਲਈ 'Chrome Web Store' ਖੋਜੋ।</translation> +<translation id="2977940621473452797">ਇਹ ਫ਼ਾਈਲ Macintosh ਸਾਫ਼ਟਵੇਅਰ ਵਰਤਣ ਵਾਲੇ ਕੰਪਿਊਟਰ ਲਈ ਤਿਆਰ ਕੀਤੀ ਗਈ ਹੈ। ਇਹ ਤੁਹਾਡੇ ChromeOS ਨਾਲ ਚਲਣ ਵਾਲੇ ਡੀਵਾਈਸ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇਸ ਦੇ ਬਦਲਾਅ ਵਜੋਂ ਕਿਸੇ ਅਨੁਕੂਲ ਐਪ ਲਈ 'Chrome ਵੈੱਬ ਸਟੋਰ' ਖੋਜੋ।</translation> <translation id="2984337792991268709">ਅੱਜ <ph name="TODAY_DAYTIME" /></translation> <translation id="299638574917407533">ਫਰਾਂਸੀਸੀ (ਕੈਨੇਡਾ)</translation> <translation id="3003189754374775221">ਨੈੱਟਵਰਕ <ph name="NETWORK_COUNT" /> ਵਿੱਚੋਂ <ph name="NETWORK_INDEX" />, <ph name="NETWORK_NAME" />, <ph name="NETWORK_PROVIDER_NAME" />, ਸਿਗਨਲ ਦੀ ਤੀਬਰਤਾ <ph name="SIGNAL_STRENGTH" />%, ਕਨੈਕਟ</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_vi.xtb b/ui/chromeos/translations/ui_chromeos_strings_vi.xtb index 1338397..888d4d9 100644 --- a/ui/chromeos/translations/ui_chromeos_strings_vi.xtb +++ b/ui/chromeos/translations/ui_chromeos_strings_vi.xtb
@@ -95,7 +95,7 @@ <translation id="1742316578210444689">Tiếng Do Thái (chuyển tự)</translation> <translation id="1747761757048858544">Tiếng Hà Lan (Hà Lan)</translation> <translation id="174937106936716857">Tổng số lượng tệp</translation> -<translation id="1755345808328621801">Tệp này dành cho máy tính sử dụng phần mềm Windows. Tệp này không tương thích với thiết bị chạy ChromeOS của bạn. Vui lòng tìm kiếm ứng dụng thay thế phù hợp trong Chrome Web Store.</translation> +<translation id="1755345808328621801">Tệp này dành cho máy tính sử dụng phần mềm Windows. Tệp này không tương thích với thiết bị chạy ChromeOS của bạn. Vui lòng tìm kiếm ứng dụng thay thế phù hợp trong Cửa hàng Chrome trực tuyến.</translation> <translation id="1757915090001272240">Wide Latin</translation> <translation id="1761091787730831947">Chia sẻ với <ph name="VM_NAME" /></translation> <translation id="1773212559869067373">Chứng chỉ xác thực bị từ chối cục bộ</translation> @@ -167,7 +167,7 @@ <translation id="2305020378527873881"><ph name="VOLUME_NAME" /> đã được đẩy ra.</translation> <translation id="2307462900900812319">Định cấu hình mạng</translation> <translation id="2312704192806647271">{COUNT,plural, =1{Không tìm thấy tiện ích có mã nhận dạng <ph name="BEGIN_LIST" /><ph name="END_LIST" />. Hãy liên hệ với quản trị viên của bạn.}other{Không tìm thấy các tiện ích có mã nhận dạng <ph name="BEGIN_LIST" /><ph name="END_LIST" />. Hãy liên hệ với quản trị viên của bạn.}}</translation> -<translation id="2325650632570794183">Loại tệp này không được hỗ trợ. Vui lòng truy cập Chrome Web Store để tìm ứng dụng có thể mở loại tệp này.</translation> +<translation id="2325650632570794183">Loại tệp này không được hỗ trợ. Vui lòng truy cập Cửa hàng Chrome trực tuyến để tìm ứng dụng có thể mở loại tệp này.</translation> <translation id="2326539130272988168">Tiếng Bungary</translation> <translation id="233822363739146957">Không gian lưu trữ không đủ để đồng bộ hoá tất cả các tệp của bạn</translation> <translation id="23721837607121582">Tải hồ sơ mạng di động xuống, Mạng <ph name="NETWORK_INDEX" />/<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" /></translation> @@ -243,7 +243,7 @@ <translation id="2949781154072577687">Đang định dạng <ph name="DRIVE_NAME" />...</translation> <translation id="2951236788251446349">Sứa</translation> <translation id="2958458230122209142">Sắp hết bộ nhớ, <ph name="TOTAL_SPACE" /> bộ nhớ cá nhân hiện còn <ph name="REMAINING_PERCENTAGE" />%.</translation> -<translation id="2977940621473452797">Tệp này dành cho máy tính sử dụng phần mềm Macintosh. Tệp này không tương thích với thiết bị chạy ChromeOS của bạn. Vui lòng tìm kiếm ứng dụng thay thế phù hợp trong Chrome Web Store.</translation> +<translation id="2977940621473452797">Tệp này dành cho máy tính sử dụng phần mềm Macintosh. Tệp này không tương thích với thiết bị chạy ChromeOS của bạn. Vui lòng tìm kiếm ứng dụng thay thế phù hợp trong Cửa hàng Chrome trực tuyến.</translation> <translation id="2984337792991268709">Hôm nay <ph name="TODAY_DAYTIME" /></translation> <translation id="299638574917407533">Tiếng Pháp (Canada)</translation> <translation id="3003189754374775221">Mạng <ph name="NETWORK_INDEX" />/<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="NETWORK_PROVIDER_NAME" />, Cường độ tín hiệu <ph name="SIGNAL_STRENGTH" />%, Kết nối</translation>
diff --git a/ui/events/DIR_METADATA b/ui/events/DIR_METADATA index 0c443e73..a2e8d1e40 100644 --- a/ui/events/DIR_METADATA +++ b/ui/events/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "UI>Input" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457729 +}
diff --git a/ui/events/android/DIR_METADATA b/ui/events/android/DIR_METADATA index 0dd9004..f5a8ef9f 100644 --- a/ui/events/android/DIR_METADATA +++ b/ui/events/android/DIR_METADATA
@@ -1,12 +1,7 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Blink>Input" } -team_email: "input-dev@chromium.org" \ No newline at end of file +team_email: "input-dev@chromium.org" +buganizer_public: { + component_id: 1456874 +}
diff --git a/ui/events/blink/DIR_METADATA b/ui/events/blink/DIR_METADATA index 0dd9004..f5a8ef9f 100644 --- a/ui/events/blink/DIR_METADATA +++ b/ui/events/blink/DIR_METADATA
@@ -1,12 +1,7 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Blink>Input" } -team_email: "input-dev@chromium.org" \ No newline at end of file +team_email: "input-dev@chromium.org" +buganizer_public: { + component_id: 1456874 +}
diff --git a/ui/events/gesture_detection/DIR_METADATA b/ui/events/gesture_detection/DIR_METADATA index 0dd9004..f5a8ef9f 100644 --- a/ui/events/gesture_detection/DIR_METADATA +++ b/ui/events/gesture_detection/DIR_METADATA
@@ -1,12 +1,7 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Blink>Input" } -team_email: "input-dev@chromium.org" \ No newline at end of file +team_email: "input-dev@chromium.org" +buganizer_public: { + component_id: 1456874 +}
diff --git a/ui/events/keycodes/DIR_METADATA b/ui/events/keycodes/DIR_METADATA index 19b048f..ea59e37 100644 --- a/ui/events/keycodes/DIR_METADATA +++ b/ui/events/keycodes/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "IO>Keyboard" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1456647 +}
diff --git a/ui/gfx/color_conversions.cc b/ui/gfx/color_conversions.cc index 6c52a56..07e6ef7 100644 --- a/ui/gfx/color_conversions.cc +++ b/ui/gfx/color_conversions.cc
@@ -23,6 +23,27 @@ constexpr float kD50_y = 1.0f; constexpr float kD50_z = 0.8251f; +// Evaluate the specified transfer function using point symmetry around the +// origin. This means that if the transfer function f is valid only for positive +// numbers, let g be the extended transfer function for all reals, defined as +// g(x) = sign(x) * f(abs(x)). +float skcmsTrFnEvalExt(const skcms_TransferFunction* fn, float x) { + if (x < 0) { + return -skcms_TransferFunction_eval(fn, -x); + } else { + return skcms_TransferFunction_eval(fn, x); + } +} + +// Same as the above but for the pow function. +float powExt(float x, float p) { + if (x < 0) { + return -powf(-x, p); + } else { + return powf(x, p); + } +} + const skcms_Matrix3x3* getXYDZ65toXYZD50matrix() { constexpr float kD65_x = 0.3127f; constexpr float kD65_y = 0.3290f; @@ -142,35 +163,32 @@ std::tuple<float, float, float> ApplyInverseTransferFnsRGB(float r, float g, float b) { - return std::make_tuple( - skcms_TransferFunction_eval(getSRGBInverseTransferFunction(), r), - skcms_TransferFunction_eval(getSRGBInverseTransferFunction(), g), - skcms_TransferFunction_eval(getSRGBInverseTransferFunction(), b)); + return std::make_tuple(skcmsTrFnEvalExt(getSRGBInverseTransferFunction(), r), + skcmsTrFnEvalExt(getSRGBInverseTransferFunction(), g), + skcmsTrFnEvalExt(getSRGBInverseTransferFunction(), b)); } std::tuple<float, float, float> ApplyTransferFnsRGB(float r, float g, float b) { - return std::make_tuple( - skcms_TransferFunction_eval(&SkNamedTransferFn::kSRGB, r), - skcms_TransferFunction_eval(&SkNamedTransferFn::kSRGB, g), - skcms_TransferFunction_eval(&SkNamedTransferFn::kSRGB, b)); + return std::make_tuple(skcmsTrFnEvalExt(&SkNamedTransferFn::kSRGB, r), + skcmsTrFnEvalExt(&SkNamedTransferFn::kSRGB, g), + skcmsTrFnEvalExt(&SkNamedTransferFn::kSRGB, b)); } std::tuple<float, float, float> ApplyTransferFnProPhoto(float r, float g, float b) { return std::make_tuple( - skcms_TransferFunction_eval(&SkNamedTransferFnExt::kProPhotoRGB, r), - skcms_TransferFunction_eval(&SkNamedTransferFnExt::kProPhotoRGB, g), - skcms_TransferFunction_eval(&SkNamedTransferFnExt::kProPhotoRGB, b)); + skcmsTrFnEvalExt(&SkNamedTransferFnExt::kProPhotoRGB, r), + skcmsTrFnEvalExt(&SkNamedTransferFnExt::kProPhotoRGB, g), + skcmsTrFnEvalExt(&SkNamedTransferFnExt::kProPhotoRGB, b)); } std::tuple<float, float, float> ApplyTransferFnAdobeRGB(float r, float g, float b) { - return std::make_tuple( - skcms_TransferFunction_eval(&SkNamedTransferFn::k2Dot2, r), - skcms_TransferFunction_eval(&SkNamedTransferFn::k2Dot2, g), - skcms_TransferFunction_eval(&SkNamedTransferFn::k2Dot2, b)); + return std::make_tuple(skcmsTrFnEvalExt(&SkNamedTransferFn::k2Dot2, r), + skcmsTrFnEvalExt(&SkNamedTransferFn::k2Dot2, g), + skcmsTrFnEvalExt(&SkNamedTransferFn::k2Dot2, b)); } skcms_TransferFunction* getProPhotoInverseTransferFunction() { @@ -184,9 +202,9 @@ float g, float b) { return std::make_tuple( - skcms_TransferFunction_eval(getProPhotoInverseTransferFunction(), r), - skcms_TransferFunction_eval(getProPhotoInverseTransferFunction(), g), - skcms_TransferFunction_eval(getProPhotoInverseTransferFunction(), b)); + skcmsTrFnEvalExt(getProPhotoInverseTransferFunction(), r), + skcmsTrFnEvalExt(getProPhotoInverseTransferFunction(), g), + skcmsTrFnEvalExt(getProPhotoInverseTransferFunction(), b)); } skcms_TransferFunction* getAdobeRGBInverseTransferFunction() { @@ -199,18 +217,17 @@ float g, float b) { return std::make_tuple( - skcms_TransferFunction_eval(getAdobeRGBInverseTransferFunction(), r), - skcms_TransferFunction_eval(getAdobeRGBInverseTransferFunction(), g), - skcms_TransferFunction_eval(getAdobeRGBInverseTransferFunction(), b)); + skcmsTrFnEvalExt(getAdobeRGBInverseTransferFunction(), r), + skcmsTrFnEvalExt(getAdobeRGBInverseTransferFunction(), g), + skcmsTrFnEvalExt(getAdobeRGBInverseTransferFunction(), b)); } std::tuple<float, float, float> ApplyTransferFnRec2020(float r, float g, float b) { - return std::make_tuple( - skcms_TransferFunction_eval(&SkNamedTransferFn::kRec2020, r), - skcms_TransferFunction_eval(&SkNamedTransferFn::kRec2020, g), - skcms_TransferFunction_eval(&SkNamedTransferFn::kRec2020, b)); + return std::make_tuple(skcmsTrFnEvalExt(&SkNamedTransferFn::kRec2020, r), + skcmsTrFnEvalExt(&SkNamedTransferFn::kRec2020, g), + skcmsTrFnEvalExt(&SkNamedTransferFn::kRec2020, b)); } skcms_TransferFunction* getRec2020nverseTransferFunction() { @@ -223,9 +240,9 @@ float g, float b) { return std::make_tuple( - skcms_TransferFunction_eval(getRec2020nverseTransferFunction(), r), - skcms_TransferFunction_eval(getRec2020nverseTransferFunction(), g), - skcms_TransferFunction_eval(getRec2020nverseTransferFunction(), b)); + skcmsTrFnEvalExt(getRec2020nverseTransferFunction(), r), + skcmsTrFnEvalExt(getRec2020nverseTransferFunction(), g), + skcmsTrFnEvalExt(getRec2020nverseTransferFunction(), b)); } } // namespace @@ -407,9 +424,9 @@ skcms_Vector3 lms_intermediate = skcms_Matrix3x3_apply(getXYZToLMSMatrix(), &xyz_input); - lms_intermediate.vals[0] = pow(lms_intermediate.vals[0], 1.0f / 3.0f); - lms_intermediate.vals[1] = pow(lms_intermediate.vals[1], 1.0f / 3.0f); - lms_intermediate.vals[2] = pow(lms_intermediate.vals[2], 1.0f / 3.0f); + lms_intermediate.vals[0] = powExt(lms_intermediate.vals[0], 1.0f / 3.0f); + lms_intermediate.vals[1] = powExt(lms_intermediate.vals[1], 1.0f / 3.0f); + lms_intermediate.vals[2] = powExt(lms_intermediate.vals[2], 1.0f / 3.0f); skcms_Vector3 lab_output = skcms_Matrix3x3_apply(getLMSToOklabMatrix(), &lms_intermediate);
diff --git a/ui/ozone/platform/wayland/host/wayland_data_offer.cc b/ui/ozone/platform/wayland/host/wayland_data_offer.cc index f19e1d3..dbcc4da 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_offer.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_offer.cc
@@ -27,10 +27,12 @@ } void WaylandDataOffer::Accept(uint32_t serial, const std::string& mime_type) { + mime_type_accepted_ = true; wl_data_offer_accept(data_offer_.get(), serial, mime_type.c_str()); } void WaylandDataOffer::Reject(uint32_t serial) { + mime_type_accepted_ = false; // Passing a null MIME type means "reject." wl_data_offer_accept(data_offer_.get(), serial, nullptr); } @@ -58,8 +60,9 @@ void WaylandDataOffer::FinishOffer() { if (wl::get_version_of_object(data_offer_.get()) >= WL_DATA_OFFER_FINISH_SINCE_VERSION) { - // As per the spec it is illegal to call finish if no action was received. - if (dnd_action_) { + // As per the spec it is illegal to call finish if no mimetype was accepted + // or no action was received. + if (mime_type_accepted_ && dnd_action_) { wl_data_offer_finish(data_offer_.get()); } }
diff --git a/ui/ozone/platform/wayland/host/wayland_data_offer.h b/ui/ozone/platform/wayland/host/wayland_data_offer.h index 5036b7e..d93f3e4 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_offer.h +++ b/ui/ozone/platform/wayland/host/wayland_data_offer.h
@@ -59,6 +59,8 @@ uint32_t source_actions_; // Action selected by the compositor uint32_t dnd_action_; + // Whether a MIME type was accepted. + bool mime_type_accepted_ = false; }; } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc index ffdaee3..7b50bc77 100644 --- a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc +++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
@@ -50,6 +50,15 @@ namespace ui { namespace { +// Only enable the preedit string for sequence mode (i.e. when using dead keys +// or the Compose key) on Linux ozone/wayland (see b/220370007). +constexpr CharacterComposer::PreeditStringMode kPreeditStringMode = +#if BUILDFLAG(IS_LINUX) + CharacterComposer::PreeditStringMode::kAlwaysEnabled; +#else + CharacterComposer::PreeditStringMode::kHexModeOnly; +#endif // BUILDFLAG(IS_LINUX) + absl::optional<size_t> OffsetFromUTF8Offset(const base::StringPiece& text, uint32_t offset) { if (offset > text.length()) @@ -245,7 +254,8 @@ : connection_(connection), key_delegate_(key_delegate), ime_delegate_(ime_delegate), - text_input_(nullptr) { + text_input_(nullptr), + character_composer_(kPreeditStringMode) { connection_->window_manager()->AddObserver(this); Init(); }
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc index d2f3bf86..450fc05 100644 --- a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -16,7 +16,9 @@ #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_flags.h" #include "ui/base/ime/text_input_type.h" +#include "ui/events/base_event_utils.h" #include "ui/events/event.h" +#include "ui/events/ozone/events_ozone.h" #include "ui/gfx/range/range.h" #include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/host/wayland_input_method_context.h" @@ -152,6 +154,7 @@ void OnCommit(const std::u16string& text) override { was_on_commit_called_ = true; + last_commit_text_ = text; } void OnConfirmCompositionText(bool keep_selection) override { last_on_confirm_composition_arg_ = keep_selection; @@ -189,6 +192,10 @@ bool was_on_commit_called() const { return was_on_commit_called_; } + absl::optional<std::u16string> last_commit_text() const { + return last_commit_text_; + } + const absl::optional<bool>& last_on_confirm_composition_arg() const { return last_on_confirm_composition_arg_; } @@ -228,6 +235,7 @@ private: bool was_on_commit_called_ = false; + absl::optional<std::u16string> last_commit_text_; absl::optional<bool> last_on_confirm_composition_arg_; bool was_on_preedit_changed_called_ = false; bool was_on_set_preedit_region_called_ = false; @@ -1747,6 +1755,91 @@ #endif } +namespace { + +std::unique_ptr<KeyEvent> CreateKeyEventForCharacterComposer( + KeyboardCode keyboard_code, + DomCode dom_code, + DomKey dom_key) { + auto event = + std::make_unique<KeyEvent>(ET_KEY_PRESSED, keyboard_code, dom_code, + EF_NONE, dom_key, EventTimeForNow()); + // We need to set this flag to make sure the event is sent to + // CharacterComposer. + ui::SetKeyboardImeFlags(event.get(), ui::kPropertyKeyboardImeIgnoredFlag); + return event; +} + +} // namespace + +TEST_P(WaylandInputMethodContextTest, CharacterComposerPreeditStringDeadKey) { + const char16_t kCombiningAcute = 0x0301; + + auto event = CreateKeyEventForCharacterComposer( + VKEY_UNKNOWN, DomCode::NONE, + DomKey::DeadKeyFromCombiningCharacter(kCombiningAcute)); + EXPECT_TRUE(input_method_context_->DispatchKeyEvent(*event)); + EXPECT_TRUE(input_method_context_delegate_->was_on_preedit_changed_called()); + + // Preedit string in sequence mode (i.e. using dead keys or the compose key) + // should only be enabled on Linux ozone/wayland. Everywhere else, the preedit + // string should always be empty. +#if BUILDFLAG(IS_LINUX) + std::u16string preedit_string(1, kCombiningAcute); +#else + std::u16string preedit_string = u""; +#endif // BUILDFLAG(IS_LINUX) + EXPECT_EQ( + input_method_context_->predicted_state_for_testing().surrounding_text, + preedit_string); + + event = CreateKeyEventForCharacterComposer(VKEY_A, DomCode::US_A, + DomKey::FromCharacter('a')); + EXPECT_TRUE(input_method_context_->DispatchKeyEvent(*event)); + EXPECT_TRUE(input_method_context_delegate_->was_on_preedit_changed_called()); + EXPECT_TRUE(input_method_context_delegate_->was_on_commit_called()); + // The composed text should be the same on all platforms. + EXPECT_EQ(input_method_context_delegate_->last_commit_text(), u"á"); +} + +TEST_P(WaylandInputMethodContextTest, + CharacterComposerPreeditStringComposeKey) { + auto event = CreateKeyEventForCharacterComposer( + VKEY_COMPOSE, DomCode::ALT_RIGHT, DomKey::COMPOSE); + EXPECT_TRUE(input_method_context_->DispatchKeyEvent(*event)); + EXPECT_TRUE(input_method_context_delegate_->was_on_preedit_changed_called()); + +#if BUILDFLAG(IS_LINUX) + std::u16string preedit_string( + 1, ui::CharacterComposer::kPreeditStringComposeKeySymbol); +#else + std::u16string preedit_string = u""; +#endif // BUILDFLAG(IS_LINUX) + EXPECT_EQ( + input_method_context_->predicted_state_for_testing().surrounding_text, + preedit_string); + + event = CreateKeyEventForCharacterComposer(VKEY_OEM_7, DomCode::QUOTE, + DomKey::FromCharacter('\'')); + EXPECT_TRUE(input_method_context_->DispatchKeyEvent(*event)); + EXPECT_TRUE(input_method_context_delegate_->was_on_preedit_changed_called()); + +#if BUILDFLAG(IS_LINUX) + preedit_string = u"'"; +#endif // BUILDFLAG(IS_LINUX) + EXPECT_EQ( + input_method_context_->predicted_state_for_testing().surrounding_text, + preedit_string); + + event = CreateKeyEventForCharacterComposer(VKEY_A, DomCode::US_A, + DomKey::FromCharacter('a')); + EXPECT_TRUE(input_method_context_->DispatchKeyEvent(*event)); + EXPECT_TRUE(input_method_context_delegate_->was_on_preedit_changed_called()); + EXPECT_TRUE(input_method_context_delegate_->was_on_commit_called()); + // The composed text should be the same on all platforms. + EXPECT_EQ(input_method_context_delegate_->last_commit_text(), u"á"); +} + class WaylandInputMethodContextNoKeyboardTest : public WaylandInputMethodContextTest { public:
diff --git a/ui/strings/translations/ui_strings_nl.xtb b/ui/strings/translations/ui_strings_nl.xtb index bde034c..8fd9859 100644 --- a/ui/strings/translations/ui_strings_nl.xtb +++ b/ui/strings/translations/ui_strings_nl.xtb
@@ -137,7 +137,7 @@ <translation id="5843690142429128814">Afbeelding.</translation> <translation id="5866104238061687188">{YEARS,plural, =1{over 1 j}other{over # j}}</translation> <translation id="588258955323874662">Volledig scherm</translation> -<translation id="5906667377645263094">{SECONDS,plural, =1{1 seconde resterend}other{# seconden reseterend}}</translation> +<translation id="5906667377645263094">{SECONDS,plural, =1{1 seconde resterend}other{# seconden resterend}}</translation> <translation id="5941711191222866238">Minimaliseren</translation> <translation id="5943826764092288734">{HOURS,plural, =1{1 uur}other{# uur}}</translation> <translation id="6007284015834422026">Extensie vastgezet</translation>
diff --git a/ui/views/DIR_METADATA b/ui/views/DIR_METADATA index d1a6630..a8619d2e 100644 --- a/ui/views/DIR_METADATA +++ b/ui/views/DIR_METADATA
@@ -1,3 +1,6 @@ monorail: { component: "Internals>Views" } +buganizer_public: { + component_id: 1456991 +}
diff --git a/ui/views/accessibility/DIR_METADATA b/ui/views/accessibility/DIR_METADATA index 173f7e6..069ff65 100644 --- a/ui/views/accessibility/DIR_METADATA +++ b/ui/views/accessibility/DIR_METADATA
@@ -2,3 +2,6 @@ monorail: { component: "UI>Accessibility" } +buganizer_public: { + component_id: 1457135 +}
diff --git a/ui/views/animation/ink_drop_highlight_unittest.cc b/ui/views/animation/ink_drop_highlight_unittest.cc index b976b06..0cff55b1 100644 --- a/ui/views/animation/ink_drop_highlight_unittest.cc +++ b/ui/views/animation/ink_drop_highlight_unittest.cc
@@ -33,7 +33,9 @@ protected: InkDropHighlight* ink_drop_highlight() { return ink_drop_highlight_.get(); } - InkDropHighlightTestApi* test_api() { return test_api_.get(); } + InkDropHighlightTestApi test_api() { + return InkDropHighlightTestApi(ink_drop_highlight_.get()); + } // Observer of the test target. TestInkDropHighlightObserver* observer() { return &observer_; } @@ -49,9 +51,6 @@ // The test target. std::unique_ptr<InkDropHighlight> ink_drop_highlight_; - // Allows privileged access to the the |ink_drop_highlight_|. - std::unique_ptr<InkDropHighlightTestApi> test_api_; - // Observer of the test target. TestInkDropHighlightObserver observer_; @@ -73,14 +72,11 @@ void InkDropHighlightTest::InitHighlight( std::unique_ptr<InkDropHighlight> new_highlight) { ink_drop_highlight_ = std::move(new_highlight); - test_api_ = - std::make_unique<InkDropHighlightTestApi>(ink_drop_highlight_.get()); - test_api()->SetDisableAnimationTimers(true); + test_api().SetDisableAnimationTimers(true); ink_drop_highlight()->set_observer(&observer_); } void InkDropHighlightTest::DestroyHighlight() { - test_api_.reset(); ink_drop_highlight_.reset(); } @@ -92,13 +88,13 @@ ink_drop_highlight()->FadeIn(base::Seconds(1)); EXPECT_TRUE(ink_drop_highlight()->IsFadingInOrVisible()); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); EXPECT_TRUE(ink_drop_highlight()->IsFadingInOrVisible()); ink_drop_highlight()->FadeOut(base::Seconds(1)); EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible()); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible()); } @@ -113,7 +109,7 @@ EXPECT_EQ(1, observer()->last_animation_started_ordinal()); EXPECT_FALSE(observer()->AnimationHasEnded()); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); EXPECT_TRUE(observer()->AnimationHasEnded()); EXPECT_EQ(2, observer()->last_animation_ended_ordinal()); @@ -127,7 +123,7 @@ EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn, observer()->last_animation_started_context()); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); EXPECT_TRUE(observer()->AnimationHasEnded()); EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn, observer()->last_animation_started_context()); @@ -136,14 +132,14 @@ EXPECT_EQ(InkDropHighlight::AnimationType::kFadeOut, observer()->last_animation_started_context()); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); EXPECT_EQ(InkDropHighlight::AnimationType::kFadeOut, observer()->last_animation_started_context()); } TEST_F(InkDropHighlightTest, VerifyObserversAreNotifiedOfSuccessfulAnimations) { ink_drop_highlight()->FadeIn(base::Seconds(1)); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); EXPECT_EQ(2, observer()->last_animation_ended_ordinal()); EXPECT_EQ(InkDropAnimationEndedReason::SUCCESS, @@ -171,10 +167,10 @@ ink_drop_highlight()->set_observer(nullptr); ink_drop_highlight()->FadeIn(base::Seconds(1)); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); ink_drop_highlight()->FadeOut(base::Milliseconds(0)); - test_api()->CompleteAnimations(); + test_api().CompleteAnimations(); EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible()); } @@ -214,7 +210,7 @@ << "Device Scale Factor: " << dsf << std::endl); ink_drop_highlight()->layer()->OnDeviceScaleFactorChanged(dsf); - gfx::Transform transform = test_api()->CalculateTransform(); + gfx::Transform transform = test_api().CalculateTransform(); gfx::PointF transformed_layer_origin = transform.MapPoint( gfx::PointF(ink_drop_highlight()->layer()->bounds().origin()));
diff --git a/ui/views/animation/test/ink_drop_highlight_test_api.cc b/ui/views/animation/test/ink_drop_highlight_test_api.cc index 69f8c05d..7c7c338 100644 --- a/ui/views/animation/test/ink_drop_highlight_test_api.cc +++ b/ui/views/animation/test/ink_drop_highlight_test_api.cc
@@ -15,18 +15,18 @@ InkDropHighlightTestApi::InkDropHighlightTestApi( InkDropHighlight* ink_drop_highlight) : ui::test::MultiLayerAnimatorTestController(this), - ink_drop_highlight_(ink_drop_highlight) {} + ink_drop_highlight_(*ink_drop_highlight) {} InkDropHighlightTestApi::~InkDropHighlightTestApi() = default; std::vector<ui::LayerAnimator*> InkDropHighlightTestApi::GetLayerAnimators() { std::vector<ui::LayerAnimator*> animators; - animators.push_back(ink_drop_highlight()->layer_->GetAnimator()); + animators.push_back(ink_drop_highlight_->layer_->GetAnimator()); return animators; } gfx::Transform InkDropHighlightTestApi::CalculateTransform() { - return ink_drop_highlight()->CalculateTransform(); + return ink_drop_highlight_->CalculateTransform(); } } // namespace views::test
diff --git a/ui/views/animation/test/ink_drop_highlight_test_api.h b/ui/views/animation/test/ink_drop_highlight_test_api.h index 18ea10c..3edddbf 100644 --- a/ui/views/animation/test/ink_drop_highlight_test_api.h +++ b/ui/views/animation/test/ink_drop_highlight_test_api.h
@@ -7,7 +7,7 @@ #include <vector> -#include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "ui/compositor/test/multi_layer_animator_test_controller.h" #include "ui/compositor/test/multi_layer_animator_test_controller_delegate.h" #include "ui/gfx/geometry/transform.h" @@ -40,17 +40,9 @@ gfx::Transform CalculateTransform(); - protected: - InkDropHighlight* ink_drop_highlight() { - return static_cast<const InkDropHighlightTestApi*>(this) - ->ink_drop_highlight(); - } - - InkDropHighlight* ink_drop_highlight() const { return ink_drop_highlight_; } - private: // The InkDropHighlight to provide internal access to. - raw_ptr<InkDropHighlight, DanglingUntriaged> ink_drop_highlight_; + const raw_ref<InkDropHighlight> ink_drop_highlight_; }; } // namespace test
diff --git a/ui/views/animation/test/ink_drop_host_test_api.cc b/ui/views/animation/test/ink_drop_host_test_api.cc index 0f5ecec..181c87d3 100644 --- a/ui/views/animation/test/ink_drop_host_test_api.cc +++ b/ui/views/animation/test/ink_drop_host_test_api.cc
@@ -11,7 +11,7 @@ namespace views::test { InkDropHostTestApi::InkDropHostTestApi(InkDropHost* ink_drop_host) - : ink_drop_host_(ink_drop_host) {} + : ink_drop_host_(*ink_drop_host) {} InkDropHostTestApi::~InkDropHostTestApi() = default;
diff --git a/ui/views/animation/test/ink_drop_host_test_api.h b/ui/views/animation/test/ink_drop_host_test_api.h index 0434b4b..9eba569e 100644 --- a/ui/views/animation/test/ink_drop_host_test_api.h +++ b/ui/views/animation/test/ink_drop_host_test_api.h
@@ -8,7 +8,7 @@ #include <memory> #include <vector> -#include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "ui/views/animation/ink_drop.h" #include "ui/views/animation/ink_drop_host.h" @@ -54,7 +54,7 @@ private: // The InkDropHost to provide internal access to. - raw_ptr<InkDropHost, DanglingUntriaged> ink_drop_host_; + const raw_ref<InkDropHost> ink_drop_host_; }; } // namespace views::test
diff --git a/ui/views/bubble/DIR_METADATA b/ui/views/bubble/DIR_METADATA index 960749c..9b130f7b 100644 --- a/ui/views/bubble/DIR_METADATA +++ b/ui/views/bubble/DIR_METADATA
@@ -1,3 +1,6 @@ monorail: { component: "UI>Browser>Bubbles" } +buganizer_public: { + component_id: 1457260 +}
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm index 1928af3f..e1913fc 100644 --- a/ui/views/cocoa/bridged_native_widget_unittest.mm +++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -487,6 +487,7 @@ // ui::CocoaTest::TearDown will wait until all NSWindows are destroyed, so // be sure to destroy the widget (which will destroy its NSWindow) // beforehand. + native_widget_mac_ = nullptr; widget_.reset(); ui::CocoaTest::TearDown(); } @@ -504,8 +505,7 @@ protected: std::unique_ptr<Widget> widget_; - raw_ptr<MockNativeWidgetMac, DanglingUntriaged> - native_widget_mac_; // Weak. Owned by |widget_|. + raw_ptr<MockNativeWidgetMac> native_widget_mac_; // Owned by `widget_`. // Use a frameless window, otherwise Widget will try to center the window // before the tests covering the Init() flow are ready to do that. @@ -975,6 +975,7 @@ // Prepares a new |window_| and |widget_| for a call to PerformInit(). void CreateNewWidgetToInit() { + native_widget_mac_ = nullptr; widget_ = std::make_unique<Widget>(); native_widget_mac_ = new MockNativeWidgetMac(widget_.get()); } @@ -1002,6 +1003,7 @@ native_widget_mac_ = native_widget.get(); EXPECT_FALSE(bridge()); EXPECT_FALSE(GetNSWindowHost()->GetInProcessNSWindow()); + native_widget_mac_ = nullptr; } // Tests the shadow type given in InitParams. @@ -1034,8 +1036,6 @@ CreateNewWidgetToInit(); PerformInit(); EXPECT_TRUE(BridgeWindowHasShadow()); // Preserves shadow. - - widget_.reset(); } // Ensure a nil NSTextInputContext is returned when the ui::TextInputClient is
diff --git a/ui/views/cocoa/drag_drop_client_mac_unittest.mm b/ui/views/cocoa/drag_drop_client_mac_unittest.mm index 6530bfb..64ceb2c 100644 --- a/ui/views/cocoa/drag_drop_client_mac_unittest.mm +++ b/ui/views/cocoa/drag_drop_client_mac_unittest.mm
@@ -169,17 +169,13 @@ class DragDropClientMacTest : public WidgetTest { public: - DragDropClientMacTest() - : widget_(new Widget), - bridge_(nullptr), - ns_window_host_(nullptr), - target_(nullptr) {} + DragDropClientMacTest() = default; DragDropClientMacTest(const DragDropClientMacTest&) = delete; DragDropClientMacTest& operator=(const DragDropClientMacTest&) = delete; DragDropClientMac* drag_drop_client() { - return ns_window_host_->drag_drop_client(); + return ns_window_host()->drag_drop_client(); } NSDragOperation DragUpdate(NSPasteboard* pasteboard) { @@ -205,35 +201,39 @@ void SetUp() override { WidgetTest::SetUp(); - widget_ = CreateTopLevelPlatformWidget(); + widget_ = CreateTopLevelPlatformWidget()->GetWeakPtr(); gfx::Rect bounds(0, 0, 100, 100); widget_->SetBounds(bounds); - - ns_window_host_ = NativeWidgetMacNSWindowHost::GetFromNativeWindow( - widget_->GetNativeWindow()); - bridge_ = ns_window_host_->GetInProcessNSWindowBridge(); widget_->Show(); - target_ = new DragDropView(); - widget_->non_client_view()->frame_view()->AddChildView(target_.get()); + target_ = widget_->non_client_view()->frame_view()->AddChildView( + std::make_unique<DragDropView>()); target_->SetBoundsRect(bounds); drag_drop_client()->source_operation_ = ui::DragDropTypes::DRAG_COPY; } void TearDown() override { + target_ = nullptr; if (widget_) widget_->CloseNow(); WidgetTest::TearDown(); } + remote_cocoa::NativeWidgetNSWindowBridge* bridge() { + return ns_window_host()->GetInProcessNSWindowBridge(); + } + + NativeWidgetMacNSWindowHost* ns_window_host() { + return NativeWidgetMacNSWindowHost::GetFromNativeWindow( + widget_->GetNativeWindow()); + } + protected: - raw_ptr<Widget, DanglingUntriaged> widget_ = nullptr; - raw_ptr<remote_cocoa::NativeWidgetNSWindowBridge, DanglingUntriaged> bridge_ = - nullptr; - raw_ptr<NativeWidgetMacNSWindowHost, DanglingUntriaged> ns_window_host_ = - nullptr; - raw_ptr<DragDropView, DanglingUntriaged> target_ = nullptr; + base::WeakPtr<Widget> widget_; + raw_ptr<DragDropView> target_ = nullptr; + + private: MockDraggingInfo* __strong dragging_info_; }; @@ -260,8 +260,8 @@ // Although this is not an interactive UI test, acquiring capture should be OK // since the runloop will exit before the system has any opportunity to // capture anything. - bridge_->AcquireCapture(); - EXPECT_TRUE(ns_window_host_->IsMouseCaptureActive()); + bridge()->AcquireCapture(); + EXPECT_TRUE(ns_window_host()->IsMouseCaptureActive()); // Create the drop data std::unique_ptr<OSExchangeData> data(std::make_unique<OSExchangeData>()); @@ -287,7 +287,7 @@ ui::mojom::DragEventSource::kMouse); // The capture should be released. - EXPECT_FALSE(ns_window_host_->IsMouseCaptureActive()); + EXPECT_FALSE(ns_window_host()->IsMouseCaptureActive()); } // Tests if the drag and drop target rejects the dropped data with the @@ -327,6 +327,7 @@ // View object that will close Widget on drop. class DragDropCloseView : public DragDropView { + METADATA_HEADER(DragDropCloseView, DragDropView) public: DragDropCloseView() = default; @@ -350,6 +351,9 @@ } }; +BEGIN_METADATA(DragDropCloseView) +END_METADATA + // Tests that closing Widget on drop does not crash. TEST_F(DragDropClientMacTest, CloseWidgetOnDrop) { OSExchangeData data; @@ -357,16 +361,16 @@ data.SetString(text); SetData(data); - target_ = new DragDropCloseView(); - widget_->non_client_view()->frame_view()->AddChildView(target_.get()); - target_->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); - target_->set_formats(ui::OSExchangeData::STRING | ui::OSExchangeData::URL); + DragDropCloseView* target = + widget_->non_client_view()->frame_view()->AddChildView( + std::make_unique<DragDropCloseView>()); + target->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); + target->set_formats(ui::OSExchangeData::STRING | ui::OSExchangeData::URL); + // Dropping will destroy target_. + target_ = nullptr; EXPECT_EQ(DragUpdate(nil), NSDragOperationCopy); EXPECT_EQ(Drop(), NSDragOperationMove); - - // Drop callback will have deleted the widget. - widget_ = nullptr; } } // namespace views::test
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm index a03cc0d..f3af42a7 100644 --- a/ui/views/widget/native_widget_mac_unittest.mm +++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -94,10 +94,13 @@ // NativeWidgetNSWindowBridge friend to access private members. class BridgedNativeWidgetTestApi { public: - explicit BridgedNativeWidgetTestApi(NSWindow* window) { - bridge_ = NativeWidgetMacNSWindowHost::GetFromNativeWindow(window) - ->GetInProcessNSWindowBridge(); - } + explicit BridgedNativeWidgetTestApi(NSWindow* window) + : bridge_(*NativeWidgetMacNSWindowHost::GetFromNativeWindow(window) + ->GetInProcessNSWindowBridge()) {} + + explicit BridgedNativeWidgetTestApi(Widget* widget) + : BridgedNativeWidgetTestApi( + widget->GetNativeWindow().GetNativeNSWindow()) {} BridgedNativeWidgetTestApi(const BridgedNativeWidgetTestApi&) = delete; BridgedNativeWidgetTestApi& operator=(const BridgedNativeWidgetTestApi&) = @@ -122,7 +125,7 @@ } private: - raw_ptr<remote_cocoa::NativeWidgetNSWindowBridge, DanglingUntriaged> bridge_; + const raw_ref<remote_cocoa::NativeWidgetNSWindowBridge> bridge_; }; // Custom native_widget to create a NativeWidgetMacTestWindow. @@ -266,12 +269,16 @@ BEGIN_METADATA(SimpleBubbleView) END_METADATA -class CustomTooltipView : public View { +class CustomTooltipView : public View, public ViewObserver { METADATA_HEADER(CustomTooltipView, View) public: CustomTooltipView(const std::u16string& tooltip, View* tooltip_handler) - : tooltip_(tooltip), tooltip_handler_(tooltip_handler) {} + : tooltip_(tooltip) { + if (tooltip_handler) { + tooltip_handler_observation_.Observe(tooltip_handler); + } + } CustomTooltipView(const CustomTooltipView&) = delete; CustomTooltipView& operator=(const CustomTooltipView&) = delete; @@ -282,12 +289,20 @@ } View* GetTooltipHandlerForPoint(const gfx::Point& point) override { - return tooltip_handler_ ? tooltip_handler_.get() : this; + return tooltip_handler_observation_.IsObserving() + ? tooltip_handler_observation_.GetSource() + : this; + } + + // ViewObserver:: + void OnViewIsDeleting(View* observed_view) override { + tooltip_handler_observation_.Reset(); } private: std::u16string tooltip_; - raw_ptr<View, DanglingUntriaged> tooltip_handler_; // Weak + base::ScopedObservation<View, ViewObserver> tooltip_handler_observation_{ + this}; }; BEGIN_METADATA(CustomTooltipView) @@ -1272,14 +1287,14 @@ EXPECT_FALSE(modal_dialog_widget->IsVisible()); ScopedSwizzleWaiter show_waiter([ConstrainedWindowAnimationShow class]); - BridgedNativeWidgetTestApi test_api( - modal_dialog_widget->GetNativeWindow().GetNativeNSWindow()); - EXPECT_FALSE(test_api.show_animation()); + EXPECT_FALSE( + BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation()); modal_dialog_widget->Show(); // Visible immediately (although it animates from transparent). EXPECT_TRUE(modal_dialog_widget->IsVisible()); - NSAnimation* animation = test_api.show_animation(); + NSAnimation* animation = + BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation(); EXPECT_TRUE(animation); EXPECT_TRUE([animation isAnimating]); @@ -1288,7 +1303,8 @@ EXPECT_TRUE(modal_dialog_widget->IsVisible()); EXPECT_TRUE(show_waiter.method_called()); EXPECT_FALSE([animation isAnimating]); - EXPECT_FALSE(test_api.show_animation()); + EXPECT_FALSE( + BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation()); return modal_dialog_widget; } @@ -1369,15 +1385,12 @@ params.workspace = kDummyWindowRestorationData; widget->Init(std::move(params)); - BridgedNativeWidgetTestApi test_api( - widget->GetNativeWindow().GetNativeNSWindow()); - - EXPECT_TRUE(test_api.HasWindowRestorationData()); + EXPECT_TRUE(BridgedNativeWidgetTestApi(widget).HasWindowRestorationData()); // Show() ultimately invokes SetVisibilityState(). widget->Show(); - EXPECT_FALSE(test_api.HasWindowRestorationData()); + EXPECT_FALSE(BridgedNativeWidgetTestApi(widget).HasWindowRestorationData()); widget->CloseNow(); } @@ -1393,15 +1406,12 @@ params.workspace = kDummyWindowRestorationData; widget->Init(std::move(params)); - BridgedNativeWidgetTestApi test_api( - widget->GetNativeWindow().GetNativeNSWindow()); - - EXPECT_TRUE(test_api.HasWindowRestorationData()); + EXPECT_TRUE(BridgedNativeWidgetTestApi(widget).HasWindowRestorationData()); // Show() ultimately invokes SetVisibilityState(). widget->Show(); - EXPECT_FALSE(test_api.HasWindowRestorationData()); + EXPECT_FALSE(BridgedNativeWidgetTestApi(widget).HasWindowRestorationData()); widget->CloseNow(); } @@ -1417,13 +1427,13 @@ modal_dialog_widget->SetBounds(gfx::Rect(50, 50, 200, 150)); EXPECT_FALSE(modal_dialog_widget->IsVisible()); - BridgedNativeWidgetTestApi test_api( - modal_dialog_widget->GetNativeWindow().GetNativeNSWindow()); - EXPECT_FALSE(test_api.show_animation()); + EXPECT_FALSE( + BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation()); modal_dialog_widget->Show(); EXPECT_TRUE(modal_dialog_widget->IsVisible()); - NSAnimation* animation = test_api.show_animation(); + NSAnimation* animation = + BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation(); EXPECT_TRUE(animation); EXPECT_TRUE([animation isAnimating]); @@ -1431,31 +1441,34 @@ // and clear references from NativeWidgetNSWindowBridge. modal_dialog_widget->Hide(); EXPECT_FALSE([animation isAnimating]); - EXPECT_FALSE(test_api.show_animation()); + EXPECT_FALSE( + BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation()); animation = nil; // Disable animations and show again. modal_dialog_widget->SetVisibilityAnimationTransition(Widget::ANIMATE_NONE); modal_dialog_widget->Show(); - EXPECT_FALSE(test_api.show_animation()); // No animation this time. + EXPECT_FALSE(BridgedNativeWidgetTestApi(modal_dialog_widget) + .show_animation()); // No animation this time. modal_dialog_widget->Hide(); // Test after re-enabling. modal_dialog_widget->SetVisibilityAnimationTransition(Widget::ANIMATE_BOTH); modal_dialog_widget->Show(); - EXPECT_TRUE(test_api.show_animation()); - animation = test_api.show_animation(); + EXPECT_TRUE(BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation()); + animation = BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation(); // Test whether disabling native animations also disables custom modal ones. modal_dialog_widget->SetVisibilityChangedAnimationsEnabled(false); modal_dialog_widget->Show(); - EXPECT_FALSE(test_api.show_animation()); // No animation this time. + EXPECT_FALSE(BridgedNativeWidgetTestApi(modal_dialog_widget) + .show_animation()); // No animation this time. modal_dialog_widget->Hide(); // Renable. modal_dialog_widget->SetVisibilityChangedAnimationsEnabled(true); modal_dialog_widget->Show(); - EXPECT_TRUE(test_api.show_animation()); - animation = test_api.show_animation(); + EXPECT_TRUE(BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation()); + animation = BridgedNativeWidgetTestApi(modal_dialog_widget).show_animation(); // Closing should also cancel the animation. EXPECT_TRUE([animation isAnimating]); @@ -1909,35 +1922,34 @@ init_params.opacity = Widget::InitParams::WindowOpacity::kTranslucent; widget = CreateWidgetWithTestWindow(std::move(init_params), &window); - BridgedNativeWidgetTestApi test_api(window); // First paint on a translucent window needs to invalidate the shadow. Once. EXPECT_EQ(0, [window invalidateShadowCount]); - test_api.SimulateFrameSwap(rect.size()); + BridgedNativeWidgetTestApi(window).SimulateFrameSwap(rect.size()); EXPECT_EQ(1, [window invalidateShadowCount]); - test_api.SimulateFrameSwap(rect.size()); + BridgedNativeWidgetTestApi(window).SimulateFrameSwap(rect.size()); EXPECT_EQ(1, [window invalidateShadowCount]); // Resizing the window also needs to trigger a shadow invalidation. [window setContentSize:NSMakeSize(123, 456)]; // A "late" frame swap at the old size should do nothing. - test_api.SimulateFrameSwap(rect.size()); + BridgedNativeWidgetTestApi(window).SimulateFrameSwap(rect.size()); EXPECT_EQ(1, [window invalidateShadowCount]); - test_api.SimulateFrameSwap(gfx::Size(123, 456)); + BridgedNativeWidgetTestApi(window).SimulateFrameSwap(gfx::Size(123, 456)); EXPECT_EQ(2, [window invalidateShadowCount]); - test_api.SimulateFrameSwap(gfx::Size(123, 456)); + BridgedNativeWidgetTestApi(window).SimulateFrameSwap(gfx::Size(123, 456)); EXPECT_EQ(2, [window invalidateShadowCount]); // Hiding the window does not require shadow invalidation. widget->Hide(); - test_api.SimulateFrameSwap(gfx::Size(123, 456)); + BridgedNativeWidgetTestApi(window).SimulateFrameSwap(gfx::Size(123, 456)); EXPECT_EQ(2, [window invalidateShadowCount]); // Showing a translucent window after hiding it, should trigger shadow // invalidation. widget->Show(); - test_api.SimulateFrameSwap(gfx::Size(123, 456)); + BridgedNativeWidgetTestApi(window).SimulateFrameSwap(gfx::Size(123, 456)); EXPECT_EQ(3, [window invalidateShadowCount]); widget->CloseNow(); @@ -2065,10 +2077,7 @@ // Test class for Full Keyboard Access related tests. class NativeWidgetMacFullKeyboardAccessTest : public NativeWidgetMacTest { public: - NativeWidgetMacFullKeyboardAccessTest() - : widget_(nullptr), - bridge_(nullptr), - fake_full_keyboard_access_(nullptr) {} + NativeWidgetMacFullKeyboardAccessTest() = default; protected: // testing::Test: @@ -2076,25 +2085,25 @@ NativeWidgetMacTest::SetUp(); widget_ = CreateTopLevelPlatformWidget(); - bridge_ = NativeWidgetMacNSWindowHost::GetFromNativeWindow( - widget_->GetNativeWindow()) - ->GetInProcessNSWindowBridge(); - fake_full_keyboard_access_ = - ui::test::ScopedFakeFullKeyboardAccess::GetInstance(); - DCHECK(fake_full_keyboard_access_); widget_->Show(); } void TearDown() override { - widget_->CloseNow(); + widget_.ExtractAsDangling()->CloseNow(); NativeWidgetMacTest::TearDown(); } - raw_ptr<Widget, DanglingUntriaged> widget_ = nullptr; - raw_ptr<remote_cocoa::NativeWidgetNSWindowBridge, DanglingUntriaged> bridge_ = - nullptr; - raw_ptr<ui::test::ScopedFakeFullKeyboardAccess, DanglingUntriaged> - fake_full_keyboard_access_ = nullptr; + remote_cocoa::NativeWidgetNSWindowBridge* bridge() { + return NativeWidgetMacNSWindowHost::GetFromNativeWindow( + widget_->GetNativeWindow()) + ->GetInProcessNSWindowBridge(); + } + + static ui::test::ScopedFakeFullKeyboardAccess* fake_full_keyboard_access() { + return ui::test::ScopedFakeFullKeyboardAccess::GetInstance(); + } + + raw_ptr<Widget> widget_ = nullptr; }; // Ensure that calling SetSize doesn't change the origin. @@ -2181,11 +2190,11 @@ // sets the keyboard accessibility mode on the associated focus manager. TEST_F(NativeWidgetMacFullKeyboardAccessTest, FullKeyboardToggle) { EXPECT_TRUE(widget_->GetFocusManager()->keyboard_accessible()); - fake_full_keyboard_access_->set_full_keyboard_access_state(false); - [bridge_->ns_view() updateFullKeyboardAccess]; + fake_full_keyboard_access()->set_full_keyboard_access_state(false); + [bridge()->ns_view() updateFullKeyboardAccess]; EXPECT_FALSE(widget_->GetFocusManager()->keyboard_accessible()); - fake_full_keyboard_access_->set_full_keyboard_access_state(true); - [bridge_->ns_view() updateFullKeyboardAccess]; + fake_full_keyboard_access()->set_full_keyboard_access_state(true); + [bridge()->ns_view() updateFullKeyboardAccess]; EXPECT_TRUE(widget_->GetFocusManager()->keyboard_accessible()); } @@ -2194,7 +2203,7 @@ TEST_F(NativeWidgetMacFullKeyboardAccessTest, Initialization) { EXPECT_TRUE(widget_->GetFocusManager()->keyboard_accessible()); - fake_full_keyboard_access_->set_full_keyboard_access_state(false); + fake_full_keyboard_access()->set_full_keyboard_access_state(false); Widget* widget2 = CreateTopLevelPlatformWidget(); EXPECT_FALSE(widget2->GetFocusManager()->keyboard_accessible()); widget2->CloseNow(); @@ -2206,8 +2215,8 @@ EXPECT_TRUE(widget_->GetFocusManager()->keyboard_accessible()); widget_->Hide(); - fake_full_keyboard_access_->set_full_keyboard_access_state(false); - // [bridge_->ns_view() updateFullKeyboardAccess] is not explicitly called + fake_full_keyboard_access()->set_full_keyboard_access_state(false); + // [bridge()->ns_view() updateFullKeyboardAccess] is not explicitly called // since we may not receive full keyboard access toggle notifications when our // application is inactive. @@ -2215,7 +2224,7 @@ EXPECT_FALSE(widget_->GetFocusManager()->keyboard_accessible()); widget_->Hide(); - fake_full_keyboard_access_->set_full_keyboard_access_state(true); + fake_full_keyboard_access()->set_full_keyboard_access_state(true); widget_->Show(); EXPECT_TRUE(widget_->GetFocusManager()->keyboard_accessible()); @@ -2251,7 +2260,7 @@ explicit NativeHostHolder(NativeViewHost* host) : host_(host), view_([[NSView alloc] init]) {} - const raw_ptr<NativeViewHost, DanglingUntriaged> host_; + const raw_ptr<NativeViewHost> host_; NSView* __strong view_; }; @@ -2280,8 +2289,9 @@ } void TearDown() override { - widget_->CloseNow(); hosts_.clear(); + native_host_parent_ = nullptr; + widget_.ExtractAsDangling()->CloseNow(); WidgetTest::TearDown(); } @@ -2291,8 +2301,8 @@ NSArray<NSView*>* GetStartingSubviews() { return starting_subviews_; } - raw_ptr<Widget, DanglingUntriaged> widget_ = nullptr; - raw_ptr<View, DanglingUntriaged> native_host_parent_ = nullptr; + raw_ptr<Widget> widget_ = nullptr; + raw_ptr<View> native_host_parent_ = nullptr; std::vector<std::unique_ptr<NativeHostHolder>> hosts_; NSArray<NSView*>* __strong starting_subviews_; };
diff --git a/ui/web_dialogs/DIR_METADATA b/ui/web_dialogs/DIR_METADATA index 643d2bac..744e51f 100644 --- a/ui/web_dialogs/DIR_METADATA +++ b/ui/web_dialogs/DIR_METADATA
@@ -1,3 +1,6 @@ monorail: { component: "Internals>Core" } +buganizer_public: { + component_id: 1456128 +}
diff --git a/ui/webui/DIR_METADATA b/ui/webui/DIR_METADATA index f0076025..613ca0c 100644 --- a/ui/webui/DIR_METADATA +++ b/ui/webui/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "UI>Browser>WebUI" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457323 +}
diff --git a/ui/webui/resources/cr_components/color_change_listener/COMMON_METADATA b/ui/webui/resources/cr_components/color_change_listener/COMMON_METADATA index 6b904ae5..3122b32 100644 --- a/ui/webui/resources/cr_components/color_change_listener/COMMON_METADATA +++ b/ui/webui/resources/cr_components/color_change_listener/COMMON_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Themes" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457357 +}
diff --git a/ui/webui/resources/cr_components/customize_color_scheme_mode/COMMON_METADATA b/ui/webui/resources/cr_components/customize_color_scheme_mode/COMMON_METADATA index 6b904ae5..3122b32 100644 --- a/ui/webui/resources/cr_components/customize_color_scheme_mode/COMMON_METADATA +++ b/ui/webui/resources/cr_components/customize_color_scheme_mode/COMMON_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Themes" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457357 +}
diff --git a/ui/webui/resources/cr_components/customize_themes/COMMON_METADATA b/ui/webui/resources/cr_components/customize_themes/COMMON_METADATA index 6b904ae5..3122b32 100644 --- a/ui/webui/resources/cr_components/customize_themes/COMMON_METADATA +++ b/ui/webui/resources/cr_components/customize_themes/COMMON_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Themes" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457357 +}
diff --git a/ui/webui/resources/cr_components/help_bubble/COMMON_METADATA b/ui/webui/resources/cr_components/help_bubble/COMMON_METADATA index 973c3b1f..d9a6646 100644 --- a/ui/webui/resources/cr_components/help_bubble/COMMON_METADATA +++ b/ui/webui/resources/cr_components/help_bubble/COMMON_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>UserEducation" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457609 +}
diff --git a/ui/webui/resources/cr_components/theme_color_picker/COMMON_METADATA b/ui/webui/resources/cr_components/theme_color_picker/COMMON_METADATA index 6b904ae5..3122b32 100644 --- a/ui/webui/resources/cr_components/theme_color_picker/COMMON_METADATA +++ b/ui/webui/resources/cr_components/theme_color_picker/COMMON_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Themes" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457357 +}
diff --git a/ui/webui/resources/js/browser_command/DIR_METADATA b/ui/webui/resources/js/browser_command/DIR_METADATA index eb6250a8..5093cd5 100644 --- a/ui/webui/resources/js/browser_command/DIR_METADATA +++ b/ui/webui/resources/js/browser_command/DIR_METADATA
@@ -1,3 +1,6 @@ monorail: { component: "UI>Browser>NewTabPage" } +buganizer_public: { + component_id: 1457163 +}
diff --git a/ui/webui/resources/roboto/DIR_METADATA b/ui/webui/resources/roboto/DIR_METADATA index eb55f181..e773b40 100644 --- a/ui/webui/resources/roboto/DIR_METADATA +++ b/ui/webui/resources/roboto/DIR_METADATA
@@ -1,11 +1,6 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "UI>Browser" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1457469 +}
diff --git a/v8 b/v8 index f243ba1..19ff14d 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit f243ba1bf4f7673ff645e31af0370f22e968d19d +Subproject commit 19ff14d2f82c8ff9c1d66265486ec2be7bcbe3c6