diff --git a/DEPS b/DEPS index 2bf04fe9..8045b4a 100644 --- a/DEPS +++ b/DEPS
@@ -299,19 +299,19 @@ # 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': 'f42bb59753feff1eb831991ad29075150bbec626', + 'skia_revision': '0834eea9de33f68c8c8129d3be21e539dde490e7', # 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': '6cd9d55b3be68f3ba3ad48c83f878a156bc0430a', + 'v8_revision': '594d6e12d62cabde031c20471a654b927b46d952', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '275745ff8b294d025f3dac0eb431998442f600b8', + 'angle_revision': '4b375fe5f51f3503dd4a88a5a13596db3dbf78e3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'f70c1194c1730893f7848cff07ca4ec196269709', + 'swiftshader_revision': 'a8133cbb3c8969e3c1e6b3cea2c02ec8312ef9ca', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -415,7 +415,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'b3eb2e09c68723b23dda602602cf3ef5f48a196d', + 'dawn_revision': '0ab79c2accfe342465aeda872b3aabd1d140d8c9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1508,7 +1508,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '180ea8ed2b2e73fb52d4201a021d0acd2801c05b', + 'cb55e66137f2601c1670d7fbd8f98d4c252d12e2', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1667,7 +1667,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'dp2RQWmveEINZyA9NNi-6HB9ilkVW2dfJ7m4g3YvzJgC', + 'version': 'YTyVPkY5O2nkIxZIlN-Z4vbTlcfp8XK1K8EaaHMIQA4C', }, ], 'condition': 'checkout_android and non_git_source', @@ -1970,7 +1970,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd36e7e10909f4da15efe9683d0d531ad21b0b430', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '465965353f053ebc8f1a7219dd70e923f384c08d', 'condition': 'checkout_chromeos', }, @@ -2867,7 +2867,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@fa392b2f49641c1cf3921d147f2974a75c177800', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@a0de53f5f078733c45d9cf84500e92b908c62d15', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@93231001597dad1149a5d035af30eda50b9e6b6c', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@c9aad99f9276817f18f72a4696239237c83cb775', @@ -3065,7 +3065,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'EROgaUyPSfW6EM5-2L2cObIwGLB0vGUGoLzy7blZpscC', + 'version': 'MwXRw0tS1vXAmnnXQmq29ESpYREwok_BfemqhCTz6YEC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4707,7 +4707,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '6d082702c7c77c8dc97cdf1a572a852b53e569df', + '76f095ce054370cefa6ea76ff83685a554e45873', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java index 670f964..241fe1c6 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
@@ -23,17 +23,24 @@ import org.chromium.android_webview.AwContents.VisualStateCallback; import org.chromium.android_webview.test.util.GraphicsTestUtils; import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.RequiresRestart; import org.chromium.base.test.util.UrlUtils; +import org.chromium.content_public.browser.WebContentsObserver; +import org.chromium.content_public.browser.test.util.JavaScriptUtils; import org.chromium.content_public.common.ContentUrlConstants; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** AwContents rendering / pixel tests. */ @RunWith(Parameterized.class) @UseParametersRunnerFactory(AwJUnit4ClassRunnerWithParameters.Factory.class) +@Batch(Batch.PER_CLASS) public class AwContentsRenderTest extends AwParameterizedTest { @Rule public AwActivityTestRule mActivityTestRule; @@ -207,4 +214,91 @@ return Color.GREEN == bitmap.getPixel(250, 250); }); } + + private static class TitleUpdatedHelper extends CallbackHelper { + private String mTitle; + + public String getTitle() { + return mTitle; + } + + public void setTitle(String title) { + mTitle = title; + notifyCalled(); + } + } + + private static final String CALL_RAF = "window.requestAnimationFrame(window.onAnimationFrame);"; + + @Test + @SmallTest + @Feature({"AndroidWebView"}) + @RequiresRestart("Tests pause feature which will prevent rendering") + public void testPausePreventsRAF() throws Throwable { + final String html = + "<html><head><style>body {background-color:#227788}</style></head>" + + "<body>" + + "<script>" + + " var raf_count = 0;" + + " window.onAnimationFrame = function(timestamp) {" + + " document.title=++raf_count;" + + " };" + + "</script>" + + " Hello world!</body></html>"; + AwActivityTestRule.enableJavaScriptOnUiThread(mAwContents); + // Loading the html via a data URI requires us to encode '#' symbols as '%23'. + mActivityTestRule.loadUrlSync( + mAwContents, + mContentsClient.getOnPageFinishedHelper(), + "data:text/html," + html.replace("#", "%23")); + + final TitleUpdatedHelper onTitleUpdatedHelper = new TitleUpdatedHelper(); + final WebContentsObserver web_contents_observer = + ThreadUtils.runOnUiThreadBlocking( + () -> + new WebContentsObserver(mAwContents.getWebContents()) { + @Override + public void titleWasSet(String title) { + onTitleUpdatedHelper.setTitle(title); + } + }); + + int callCount = onTitleUpdatedHelper.getCallCount(); + JavaScriptUtils.executeJavaScriptAndWaitForResult(mAwContents.getWebContents(), CALL_RAF); + onTitleUpdatedHelper.waitForCallback(callCount); + Assert.assertEquals("1", onTitleUpdatedHelper.getTitle()); + callCount = onTitleUpdatedHelper.getCallCount(); + + ThreadUtils.runOnUiThreadBlocking( + () -> { + mAwContents.onPause(); + Assert.assertFalse(mAwContents.isPageVisible()); + }); + + // VisualStateCallback#onComplete won't be called when WebView is + // invisible. So there is no reliable way to tell if View#setVisibility + // has taken effect. Instead we will continue to run rAF until either frame production stops + // or the polling times out in 1.5s. This timeout will emit a test failure. + AwActivityTestRule.pollInstrumentationThread( + () -> { + int callCount2 = onTitleUpdatedHelper.getCallCount(); + // Even though we are hidden, the JS should successfully run to request the rAF. + // However frame production should be disabled, so the actual frame should not + // run, nor update the title. + JavaScriptUtils.executeJavaScriptAndWaitForResult( + mAwContents.getWebContents(), CALL_RAF); + + try { + onTitleUpdatedHelper.waitForCallback( + callCount2, 1, 500, TimeUnit.MILLISECONDS); + // If we produced a frame fail this run of the polling. Polling will re-run + // until success or timeout. + return false; + } catch (TimeoutException e) { + // Timeout is expected. + return true; + } + }); + ThreadUtils.runOnUiThreadBlocking(() -> web_contents_observer.observe(null)); + } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java index cf56843..5d83d96 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
@@ -195,7 +195,8 @@ Rect workArea = displayAndroid.getBounds(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R - && UiAndroidFeatureMap.isEnabled(UiAndroidFeatures.USING_CORRECT_WORK_AREA)) { + && UiAndroidFeatureMap.isEnabled( + UiAndroidFeatures.ANDROID_USE_CORRECT_DISPLAY_WORK_AREA)) { workArea.inset(displayAndroid.getInsets()); }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index a5ad191..b2fb087 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -4135,8 +4135,6 @@ "shelf/swipe_home_to_overview_controller_unittest.cc", "shelf/test/hotseat_state_watcher.cc", "shelf/test/hotseat_state_watcher.h", - "shelf/test/widget_animation_smoothness_inspector.cc", - "shelf/test/widget_animation_smoothness_inspector.h", "shell_unittest.cc", "style/ash_color_mixer_unittest.cc", "style/ash_color_provider_unittest.cc",
diff --git a/ash/accelerators/ash_accelerator_configuration_unittest.cc b/ash/accelerators/ash_accelerator_configuration_unittest.cc index f941ca5..4eafa0d4 100644 --- a/ash/accelerators/ash_accelerator_configuration_unittest.cc +++ b/ash/accelerators/ash_accelerator_configuration_unittest.cc
@@ -18,6 +18,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "base/containers/contains.h" +#include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/types/optional_ref.h"
diff --git a/ash/ambient/backdrop/ambient_backend_controller_impl.cc b/ash/ambient/backdrop/ambient_backend_controller_impl.cc index 16b09c3..48d8135 100644 --- a/ash/ambient/backdrop/ambient_backend_controller_impl.cc +++ b/ash/ambient/backdrop/ambient_backend_controller_impl.cc
@@ -28,6 +28,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "base/uuid.h" #include "chromeos/assistant/internal/ambient/backdrop_client_config.h"
diff --git a/ash/ambient/ui/photo_view_unittest.cc b/ash/ambient/ui/photo_view_unittest.cc index c946a3d..20ac0006 100644 --- a/ash/ambient/ui/photo_view_unittest.cc +++ b/ash/ambient/ui/photo_view_unittest.cc
@@ -12,6 +12,7 @@ #include "ash/assistant/ui/assistant_view_ids.h" #include "ash/public/cpp/ambient/proto/photo_cache_entry.pb.h" #include "ash/webui/personalization_app/mojom/personalization_app.mojom-shared.h" +#include "base/strings/string_number_conversions.h" #include "ui/display/manager/display_manager.h" #include "ui/display/test/display_manager_test_api.h" #include "ui/gfx/geometry/rect.h"
diff --git a/ash/app_list/app_list_presenter_unittest.cc b/ash/app_list/app_list_presenter_unittest.cc index 3317794..36aed79 100644 --- a/ash/app_list/app_list_presenter_unittest.cc +++ b/ash/app_list/app_list_presenter_unittest.cc
@@ -80,6 +80,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h"
diff --git a/ash/app_list/test/app_list_test_helper.cc b/ash/app_list/test/app_list_test_helper.cc index fb950c65..0b2ae2e4 100644 --- a/ash/app_list/test/app_list_test_helper.cc +++ b/ash/app_list/test/app_list_test_helper.cc
@@ -32,6 +32,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_util.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/animation/tween.h" #include "ui/views/widget/root_view.h"
diff --git a/ash/app_list/views/app_list_item_view_pixeltest.cc b/ash/app_list/views/app_list_item_view_pixeltest.cc index 79ac686..1b4f383 100644 --- a/ash/app_list/views/app_list_item_view_pixeltest.cc +++ b/ash/app_list/views/app_list_item_view_pixeltest.cc
@@ -27,6 +27,7 @@ #include "ash/test/pixel/ash_pixel_test_init_params.h" #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" #include "base/functional/bind.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h"
diff --git a/ash/app_list/views/app_list_search_view_unittest.cc b/ash/app_list/views/app_list_search_view_unittest.cc index 1b8817eb..3f5e4ca3 100644 --- a/ash/app_list/views/app_list_search_view_unittest.cc +++ b/ash/app_list/views/app_list_search_view_unittest.cc
@@ -34,6 +34,7 @@ #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h"
diff --git a/ash/app_list/views/app_list_view_pixeltest.cc b/ash/app_list/views/app_list_view_pixeltest.cc index e860bc6..446e24e 100644 --- a/ash/app_list/views/app_list_view_pixeltest.cc +++ b/ash/app_list/views/app_list_view_pixeltest.cc
@@ -24,6 +24,7 @@ #include "ash/test/view_drawn_waiter.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "components/feature_engagement/public/feature_constants.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/app_list/views/search_box_view_unittest.cc b/ash/app_list/views/search_box_view_unittest.cc index 273f998..a5725f3 100644 --- a/ash/app_list/views/search_box_view_unittest.cc +++ b/ash/app_list/views/search_box_view_unittest.cc
@@ -51,6 +51,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h"
diff --git a/ash/app_list/views/search_result_view_unittest.cc b/ash/app_list/views/search_result_view_unittest.cc index bdd340e..dcc65e0 100644 --- a/ash/app_list/views/search_result_view_unittest.cc +++ b/ash/app_list/views/search_result_view_unittest.cc
@@ -3,11 +3,13 @@ // found in the LICENSE file. #include "ash/app_list/views/search_result_view.h" + #include <memory> #include "ash/app_list/model/search/test_search_result.h" #include "ash/public/cpp/app_list/app_list_types.h" #include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/views/controls/label.h" #include "ui/views/layout/flex_layout_view.h"
diff --git a/ash/constants/notifier_catalogs.h b/ash/constants/notifier_catalogs.h index fa140a5..f20130c 100644 --- a/ash/constants/notifier_catalogs.h +++ b/ash/constants/notifier_catalogs.h
@@ -215,7 +215,8 @@ kBocaSpotlightStarted = 196, kFaceGazeActive = 197, kUsbPeripheralDeviceOrEndpointLimit = 198, - kMaxValue = kUsbPeripheralDeviceOrEndpointLimit + kOnTaskResourceNotSupported = 199, + kMaxValue = kOnTaskResourceNotSupported }; // A living catalog that registers system nudges.
diff --git a/ash/glanceables/glanceables_unittest.cc b/ash/glanceables/glanceables_unittest.cc index d5a45b38..8cc7384f 100644 --- a/ash/glanceables/glanceables_unittest.cc +++ b/ash/glanceables/glanceables_unittest.cc
@@ -22,6 +22,7 @@ #include "ash/test/ash_test_base.h" #include "base/functional/bind.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/time/time.h"
diff --git a/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc b/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc index a1add228..3565edf0 100644 --- a/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc +++ b/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc
@@ -21,6 +21,7 @@ #include "ash/test/ash_test_base.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/test/gtest_tags.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h"
diff --git a/ash/login/ui/login_pin_input_view_unittest.cc b/ash/login/ui/login_pin_input_view_unittest.cc index 17bc88b6..0cd6d72 100644 --- a/ash/login/ui/login_pin_input_view_unittest.cc +++ b/ash/login/ui/login_pin_input_view_unittest.cc
@@ -13,6 +13,7 @@ #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_enums.mojom-shared.h" #include "ui/accessibility/ax_node_data.h"
diff --git a/ash/public/cpp/desk_template.cc b/ash/public/cpp/desk_template.cc index ca6aa39..e06e709 100644 --- a/ash/public/cpp/desk_template.cc +++ b/ash/public/cpp/desk_template.cc
@@ -7,6 +7,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/window_properties.h" #include "base/i18n/time_formatting.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chromeos/ui/base/app_types.h"
diff --git a/ash/public/cpp/wallpaper/wallpaper_info.cc b/ash/public/cpp/wallpaper/wallpaper_info.cc index 5b3ce4d..528b47b 100644 --- a/ash/public/cpp/wallpaper/wallpaper_info.cc +++ b/ash/public/cpp/wallpaper/wallpaper_info.cc
@@ -11,6 +11,7 @@ #include "ash/public/cpp/wallpaper/online_wallpaper_params.h" #include "ash/public/cpp/wallpaper/wallpaper_types.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/types/cxx23_to_underlying.h" namespace ash {
diff --git a/ash/quick_insert/quick_insert_copy_media.cc b/ash/quick_insert/quick_insert_copy_media.cc index 240a568c..33329a8 100644 --- a/ash/quick_insert/quick_insert_copy_media.cc +++ b/ash/quick_insert/quick_insert_copy_media.cc
@@ -20,6 +20,7 @@ #include "base/functional/overloaded.h" #include "base/strings/escape.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/quick_insert/search/quick_insert_date_search.cc b/ash/quick_insert/search/quick_insert_date_search.cc index de223a1..d5ead9c 100644 --- a/ash/quick_insert/search/quick_insert_date_search.cc +++ b/ash/quick_insert/search/quick_insert_date_search.cc
@@ -21,6 +21,7 @@ #include "base/containers/to_vector.h" #include "base/i18n/case_conversion.h" #include "base/i18n/time_formatting.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h"
diff --git a/ash/quick_pair/common/fast_pair/fast_pair_decoder_unittest.cc b/ash/quick_pair/common/fast_pair/fast_pair_decoder_unittest.cc index 01429bdc..e922206 100644 --- a/ash/quick_pair/common/fast_pair/fast_pair_decoder_unittest.cc +++ b/ash/quick_pair/common/fast_pair/fast_pair_decoder_unittest.cc
@@ -12,6 +12,7 @@ #include "ash/constants/ash_features.h" #include "ash/quick_pair/common/fast_pair/fast_pair_service_data_creator.h" +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/shelf/hotseat_widget_unittest.cc b/ash/shelf/hotseat_widget_unittest.cc index 6107891..afbad442 100644 --- a/ash/shelf/hotseat_widget_unittest.cc +++ b/ash/shelf/hotseat_widget_unittest.cc
@@ -34,7 +34,6 @@ #include "ash/shelf/shelf_view_test_api.h" #include "ash/shelf/test/hotseat_state_watcher.h" #include "ash/shelf/test/shelf_layout_manager_test_base.h" -#include "ash/shelf/test/widget_animation_smoothness_inspector.h" #include "ash/shell.h" #include "ash/system/ime_menu/ime_menu_tray.h" #include "ash/system/overview/overview_button_tray.h" @@ -2761,65 +2760,6 @@ } } -// TODO(manucornet): Enable this test once the new API for layer animation -// sequence observers is available. -TEST_P(HotseatWidgetTest, DISABLED_OverviewToHomeAnimationAndBackIsSmooth) { - // Go into tablet mode and make sure animations are over. - HotseatWidget* hotseat = GetPrimaryShelf()->hotseat_widget(); - { - views::WidgetAnimationWaiter waiter(hotseat); - TabletModeControllerTestApi().EnterTabletMode(); - waiter.WaitForAnimation(); - } - - ui::ScopedAnimationDurationScaleMode regular_animations( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - - // Go into overview and back to know what to expect in terms of bounds. - const gfx::Rect shown_hotseat_bounds = hotseat->GetWindowBoundsInScreen(); - { - views::WidgetAnimationWaiter waiter(hotseat); - StartOverview(); - waiter.WaitForAnimation(); - } - - const gfx::Rect extended_hotseat_bounds = hotseat->GetWindowBoundsInScreen(); - { - views::WidgetAnimationWaiter waiter(hotseat); - EndOverview(); - waiter.WaitForAnimation(); - } - - // The extended hotseat should be higher (lower value of Y) than the - // shown hotseat. - EXPECT_GT(shown_hotseat_bounds.y(), extended_hotseat_bounds.y()); - - // We should start with the hotseat in its shown position again. - EXPECT_EQ(shown_hotseat_bounds, hotseat->GetWindowBoundsInScreen()); - - { - WidgetAnimationSmoothnessInspector inspector(hotseat); - views::WidgetAnimationWaiter waiter(hotseat); - StartOverview(); - waiter.WaitForAnimation(); - EXPECT_TRUE(inspector.CheckAnimation(4)); - } - - // The hotseat should now be extended. - EXPECT_EQ(extended_hotseat_bounds, hotseat->GetWindowBoundsInScreen()); - - { - WidgetAnimationSmoothnessInspector inspector(hotseat); - views::WidgetAnimationWaiter waiter(hotseat); - EndOverview(); - waiter.WaitForAnimation(); - EXPECT_TRUE(inspector.CheckAnimation(4)); - } - - // And we should now be back where we started. - EXPECT_EQ(shown_hotseat_bounds, hotseat->GetWindowBoundsInScreen()); -} - class HotseatWidgetRTLTest : public ShelfLayoutManagerTestBase, public testing::WithParamInterface<bool> { public:
diff --git a/ash/shelf/launcher_nudge_controller_unittest.cc b/ash/shelf/launcher_nudge_controller_unittest.cc index 12a9644b..5d4f021 100644 --- a/ash/shelf/launcher_nudge_controller_unittest.cc +++ b/ash/shelf/launcher_nudge_controller_unittest.cc
@@ -21,6 +21,7 @@ #include "base/command_line.h" #include "base/json/values_util.h" #include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "ui/compositor/layer.h"
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 161b6450..2938d32 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -81,6 +81,7 @@ #include "base/i18n/rtl.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/icu_test_util.h" #include "base/test/metrics/histogram_tester.h"
diff --git a/ash/shelf/shelf_view_test_api.cc b/ash/shelf/shelf_view_test_api.cc index 101c519c..ab6bd6a1 100644 --- a/ash/shelf/shelf_view_test_api.cc +++ b/ash/shelf/shelf_view_test_api.cc
@@ -14,6 +14,7 @@ #include "ash/shelf/shelf_widget.h" #include "base/functional/callback.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "ui/views/animation/bounds_animator.h" #include "ui/views/controls/menu/menu_runner.h"
diff --git a/ash/shelf/test/shelf_test_base.cc b/ash/shelf/test/shelf_test_base.cc index 0c1d602..f95dba7 100644 --- a/ash/shelf/test/shelf_test_base.cc +++ b/ash/shelf/test/shelf_test_base.cc
@@ -10,6 +10,7 @@ #include "ash/shelf/shelf_view_test_api.h" #include "ash/shelf/shelf_widget.h" #include "ash/test/ash_test_util.h" +#include "base/strings/string_number_conversions.h" #include "ui/gfx/image/image_unittest_util.h" namespace ash {
diff --git a/ash/shelf/test/widget_animation_smoothness_inspector.cc b/ash/shelf/test/widget_animation_smoothness_inspector.cc deleted file mode 100644 index 9b80f0f..0000000 --- a/ash/shelf/test/widget_animation_smoothness_inspector.cc +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/shelf/test/widget_animation_smoothness_inspector.h" - -#include "base/strings/stringprintf.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/compositor/layer_animator.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -const char kErrorFormat[] = - "Animation changes the widget's %s but stutters at value %d between steps " - "%lu and %lu (on a total of %lu steps)"; - -WidgetAnimationSmoothnessInspector::WidgetAnimationSmoothnessInspector( - views::Widget* widget) - : widget_(widget) { - widget->GetLayer()->GetAnimator()->AddObserver(this); -} - -WidgetAnimationSmoothnessInspector::~WidgetAnimationSmoothnessInspector() { - widget_->GetLayer()->GetAnimator()->RemoveObserver(this); -} - -bool WidgetAnimationSmoothnessInspector::CheckAnimation( - unsigned int min_steps) const { - DCHECK(min_steps > 2) << "An animation with 2 steps or less isn't " - << "really an animation"; - - if (bound_history_.size() < min_steps) - return false; - const unsigned long total_step_count = bound_history_.size(); - const unsigned long interval_between_steps_to_check = - total_step_count / (min_steps - 1); - const gfx::Rect initial_bounds = bound_history_.front(); - const gfx::Rect final_bounds = bound_history_.back(); - const bool x_changed = initial_bounds.x() != final_bounds.x(); - const bool y_changed = initial_bounds.y() != final_bounds.y(); - const bool w_changed = initial_bounds.width() != final_bounds.width(); - const bool h_changed = initial_bounds.height() != final_bounds.height(); - - // An animation that changes nothing can't be considered smooth. - if (!x_changed && !y_changed && !w_changed && !h_changed) - return false; - - int last_x = initial_bounds.x(); - int last_y = initial_bounds.y(); - int last_w = initial_bounds.width(); - int last_h = initial_bounds.height(); - - auto print_error = [=](const char* dimension, int value, - unsigned long step) -> void { - // Step numbers are 1-based in user-visible messages. - DLOG(ERROR) << base::StringPrintf( - kErrorFormat, dimension, value, - 1 + step - interval_between_steps_to_check, 1 + step, total_step_count); - }; - - for (unsigned long i = interval_between_steps_to_check; i < total_step_count; - i += interval_between_steps_to_check) { - // Check the actual last step on the last loop iteration. - if ((total_step_count - i) < interval_between_steps_to_check) - i = total_step_count - 1; - - const gfx::Rect bounds = bound_history_[i]; - if (x_changed && bounds.x() == last_x) { - print_error("x", last_x, i); - return false; - } - if (y_changed && bounds.y() == last_y) { - print_error("y", last_y, i); - return false; - } - if (w_changed && bounds.width() == last_y) { - print_error("width", last_w, i); - return false; - } - if (h_changed && bounds.height() == last_h) { - print_error("height", last_h, i); - return false; - } - last_x = bounds.x(); - last_y = bounds.y(); - last_w = bounds.width(); - last_h = bounds.height(); - } - return true; -} - -void WidgetAnimationSmoothnessInspector::OnLayerAnimationEnded( - ui::LayerAnimationSequence* sequence) { - bound_history_.push_back(widget_->GetClientAreaBoundsInScreen()); -} - -void WidgetAnimationSmoothnessInspector::OnLayerAnimationAborted( - ui::LayerAnimationSequence* sequence) {} - -void WidgetAnimationSmoothnessInspector::OnLayerAnimationScheduled( - ui::LayerAnimationSequence* sequence) { - bound_history_.push_back(widget_->GetClientAreaBoundsInScreen()); -} - -void WidgetAnimationSmoothnessInspector::OnLayerAnimationProgressed( - const ui::LayerAnimationSequence* sequence) { - bound_history_.push_back(widget_->GetClientAreaBoundsInScreen()); -} - -} // namespace ash
diff --git a/ash/shelf/test/widget_animation_smoothness_inspector.h b/ash/shelf/test/widget_animation_smoothness_inspector.h deleted file mode 100644 index 2f08c0d..0000000 --- a/ash/shelf/test/widget_animation_smoothness_inspector.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SHELF_TEST_WIDGET_ANIMATION_SMOOTHNESS_INSPECTOR_H_ -#define ASH_SHELF_TEST_WIDGET_ANIMATION_SMOOTHNESS_INSPECTOR_H_ - -#include "base/memory/raw_ptr.h" -#include "ui/compositor/layer_animation_observer.h" - -namespace views { -class Widget; -} - -namespace ash { - -// TOOD(manucornet): This class will perform its intended purpose only after -// the new API for layer aimation sequence observers lands. -class WidgetAnimationSmoothnessInspector : ui::LayerAnimationObserver { - public: - explicit WidgetAnimationSmoothnessInspector(views::Widget* widget); - ~WidgetAnimationSmoothnessInspector() override; - - // Returns whether the animation had at least |min_steps| steps (including - // the initial and final steps), going smoothly from the initial state - // to the final state. - bool CheckAnimation(unsigned int min_steps) const; - - // ui::LayerAnimationObserver: - void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; - void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; - void OnLayerAnimationScheduled(ui::LayerAnimationSequence* sequence) override; - - // TOOD(manucornet): Make this an override once the new API for layer - // aimation sequence observers is in. - void OnLayerAnimationProgressed(const ui::LayerAnimationSequence* sequence); - - private: - // Unowned - raw_ptr<views::Widget> widget_; - - std::vector<gfx::Rect> bound_history_; -}; - -} // namespace ash - -#endif // ASH_SHELF_TEST_WIDGET_ANIMATION_SMOOTHNESS_INSPECTOR_H_
diff --git a/ash/system/accessibility/autoclick_menu_bubble_controller.cc b/ash/system/accessibility/autoclick_menu_bubble_controller.cc index 6c083be..d0e193d 100644 --- a/ash/system/accessibility/autoclick_menu_bubble_controller.cc +++ b/ash/system/accessibility/autoclick_menu_bubble_controller.cc
@@ -22,6 +22,7 @@ #include "ash/wm/workspace_controller.h" #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" +#include "base/strings/string_number_conversions.h" #include "ui/aura/window_tree_host.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h"
diff --git a/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc b/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc index 3dcb45d..f0c9dda 100644 --- a/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc +++ b/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc
@@ -11,6 +11,7 @@ #include "ash/system/focus_mode/focus_mode_tasks_provider.h" #include "ash/test/ash_test_base.h" #include "base/i18n/rtl.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/compositor/layer.h"
diff --git a/ash/system/holding_space/holding_space_drag_util.cc b/ash/system/holding_space/holding_space_drag_util.cc index cf8e9f5..f590eae 100644 --- a/ash/system/holding_space/holding_space_drag_util.cc +++ b/ash/system/holding_space/holding_space_drag_util.cc
@@ -19,6 +19,7 @@ #include "base/containers/adapters.h" #include "base/i18n/rtl.h" #include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h"
diff --git a/ash/system/holding_space/holding_space_item_views_section_unittest.cc b/ash/system/holding_space/holding_space_item_views_section_unittest.cc index 5b70cc0..6ac0df1 100644 --- a/ash/system/holding_space/holding_space_item_views_section_unittest.cc +++ b/ash/system/holding_space/holding_space_item_views_section_unittest.cc
@@ -21,6 +21,7 @@ #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "ui/views/widget/unique_widget_ptr.h" #include "ui/views/widget/widget.h"
diff --git a/ash/system/holding_space/holding_space_tray_unittest.cc b/ash/system/holding_space/holding_space_tray_unittest.cc index 3aee04e7..d3d18aa 100644 --- a/ash/system/holding_space/holding_space_tray_unittest.cc +++ b/ash/system/holding_space/holding_space_tray_unittest.cc
@@ -53,6 +53,7 @@ #include "base/files/file_path.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/run_until.h"
diff --git a/ash/system/input_device_settings/input_device_settings_metadata_manager.cc b/ash/system/input_device_settings/input_device_settings_metadata_manager.cc index 8429a363..3583b9c8 100644 --- a/ash/system/input_device_settings/input_device_settings_metadata_manager.cc +++ b/ash/system/input_device_settings/input_device_settings_metadata_manager.cc
@@ -7,6 +7,7 @@ #include "ash/system/input_device_settings/input_device_settings_metadata.h" #include "ash/system/input_device_settings/input_device_settings_pref_names.h" #include "base/containers/contains.h" +#include "base/strings/string_number_conversions.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/scoped_user_pref_update.h"
diff --git a/ash/system/notification_center/ash_message_popup_collection_unittest.cc b/ash/system/notification_center/ash_message_popup_collection_unittest.cc index 19ef792..b420d76 100644 --- a/ash/system/notification_center/ash_message_popup_collection_unittest.cc +++ b/ash/system/notification_center/ash_message_popup_collection_unittest.cc
@@ -38,6 +38,7 @@ #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" #include "base/command_line.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h"
diff --git a/ash/system/notification_center/views/ash_notification_view_unittest.cc b/ash/system/notification_center/views/ash_notification_view_unittest.cc index 2b47ce8..d8df143b 100644 --- a/ash/system/notification_center/views/ash_notification_view_unittest.cc +++ b/ash/system/notification_center/views/ash_notification_view_unittest.cc
@@ -35,6 +35,7 @@ #include "ash/test/ash_test_base.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h"
diff --git a/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.h b/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.h index 14d5e0d..de0bf77 100644 --- a/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.h +++ b/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.h
@@ -68,6 +68,7 @@ void OnInvalidUSB4CableWarning() override {} void OnInvalidTBTCableWarning() override {} void OnSpeedLimitingCableWarning() override {} + void OnUsbDeviceOrEndpointLimit() override {} private: friend class PciePeripheralNotificationControllerTest;
diff --git a/ash/system/phonehub/camera_roll_view_unittest.cc b/ash/system/phonehub/camera_roll_view_unittest.cc index 4eb0b6e..5cb4a874 100644 --- a/ash/system/phonehub/camera_roll_view_unittest.cc +++ b/ash/system/phonehub/camera_roll_view_unittest.cc
@@ -7,6 +7,7 @@ #include "ash/system/phonehub/camera_roll_thumbnail.h" #include "ash/system/phonehub/phone_hub_metrics.h" #include "ash/test/ash_test_base.h" +#include "base/strings/string_number_conversions.h" #include "chromeos/ash/components/phonehub/camera_roll_item.h" #include "chromeos/ash/components/phonehub/fake_camera_roll_manager.h" #include "chromeos/ash/components/phonehub/fake_user_action_recorder.h"
diff --git a/ash/system/phonehub/phone_hub_tray.cc b/ash/system/phonehub/phone_hub_tray.cc index f7bb4eaa..873becd 100644 --- a/ash/system/phonehub/phone_hub_tray.cc +++ b/ash/system/phonehub/phone_hub_tray.cc
@@ -41,6 +41,7 @@ #include "base/functional/callback_helpers.h" #include "base/notreached.h" #include "base/power_monitor/power_monitor.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/time/default_clock.h"
diff --git a/ash/system/power/peripheral_battery_notifier.cc b/ash/system/power/peripheral_battery_notifier.cc index 8d53265..1c44739 100644 --- a/ash/system/power/peripheral_battery_notifier.cc +++ b/ash/system/power/peripheral_battery_notifier.cc
@@ -19,6 +19,7 @@ #include "base/functional/bind.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "components/device_event_log/device_event_log.h"
diff --git a/ash/system/power/power_event_observer.cc b/ash/system/power/power_event_observer.cc index ccd4348..8694320 100644 --- a/ash/system/power/power_event_observer.cc +++ b/ash/system/power/power_event_observer.cc
@@ -23,6 +23,7 @@ #include "base/functional/bind.h" #include "base/location.h" #include "base/scoped_multi_source_observation.h" +#include "base/strings/string_number_conversions.h" #include "base/task/single_thread_task_runner.h" #include "chromeos/ash/components/feature_usage/feature_usage_metrics.h" #include "ui/aura/window.h"
diff --git a/ash/system/time/calendar_event_list_item_view.cc b/ash/system/time/calendar_event_list_item_view.cc index 03821596..dff8d3fc 100644 --- a/ash/system/time/calendar_event_list_item_view.cc +++ b/ash/system/time/calendar_event_list_item_view.cc
@@ -20,6 +20,7 @@ #include "ash/system/time/event_date_formatter_util.h" #include "base/containers/fixed_flat_map.h" #include "base/functional/bind.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "google_apis/calendar/calendar_api_response_types.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/system/time/date_helper.cc b/ash/system/time/date_helper.cc index a8babc80..c31e882 100644 --- a/ash/system/time/date_helper.cc +++ b/ash/system/time/date_helper.cc
@@ -12,6 +12,7 @@ #include "base/containers/contains.h" #include "base/i18n/unicodestring.h" #include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "third_party/icu/source/common/unicode/dtintrv.h" #include "third_party/icu/source/i18n/unicode/dtitvfmt.h"
diff --git a/ash/system/tray/tray_event_filter_unittest.cc b/ash/system/tray/tray_event_filter_unittest.cc index 47cc824..d60c092 100644 --- a/ash/system/tray/tray_event_filter_unittest.cc +++ b/ash/system/tray/tray_event_filter_unittest.cc
@@ -27,6 +27,7 @@ #include "ash/system/unified/unified_system_tray_controller.h" #include "ash/test/ash_test_base.h" #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/window.h"
diff --git a/ash/system/unified/notification_icons_controller_unittest.cc b/ash/system/unified/notification_icons_controller_unittest.cc index 006128b..e125b51 100644 --- a/ash/system/unified/notification_icons_controller_unittest.cc +++ b/ash/system/unified/notification_icons_controller_unittest.cc
@@ -17,6 +17,7 @@ #include "ash/system/tray/tray_item_view.h" #include "ash/system/unified/notification_counter_view.h" #include "ash/test/ash_test_base.h" +#include "base/strings/string_number_conversions.h" #include "ui/base/l10n/l10n_util.h" #include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/notification.h"
diff --git a/ash/system/unified/unified_system_tray_unittest.cc b/ash/system/unified/unified_system_tray_unittest.cc index 387cbf0..d3b0196 100644 --- a/ash/system/unified/unified_system_tray_unittest.cc +++ b/ash/system/unified/unified_system_tray_unittest.cc
@@ -48,6 +48,7 @@ #include "ash/test_shell_delegate.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/command_line.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h"
diff --git a/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc b/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc index 983450e..768d5b8 100644 --- a/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc +++ b/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc
@@ -16,6 +16,7 @@ #include "ash/strings/grit/ash_strings.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" +#include "components/vector_icons/vector_icons.h" #include "third_party/cros_system_api/dbus/typecd/dbus-constants.h" #include "ui/base/l10n/l10n_util.h" #include "ui/message_center/message_center.h" @@ -37,6 +38,8 @@ "cros_usb_peripheral_invalid_tbt_cable_notification_id"; const char kUsbPeripheralSpeedLimitingCableNotificationId[] = "cros_usb_peripheral_speed_limiting_cable_notification_id"; +const char kUsbPeripheralDeviceOrEndpointLimitNotificationId[] = + "cros_usb_peripheral_device_or_endpoint_limit_notification_id"; const char kNotificationDisplayLandingPageUrl[] = "https://support.google.com/chromebook?p=cable_notification"; const char kNotificationDeviceLandingPageUrl[] = @@ -271,4 +274,35 @@ message_center_->AddNotification(std::move(notification)); } +// Notify the user that they have reached a USB device or endpoint limit. +void UsbPeripheralNotificationController::OnUsbDeviceOrEndpointLimit() { + if (!ShouldDisplayNotification()) { + return; + } + + message_center::RichNotificationData optional; + optional.pinned = false; + std::unique_ptr<message_center::Notification> notification = + CreateSystemNotificationPtr( + message_center::NOTIFICATION_TYPE_SIMPLE, + kUsbPeripheralDeviceOrEndpointLimitNotificationId, + l10n_util::GetStringUTF16( + IDS_ASH_USB_NOTIFICATION_LIMIT_REACHED_TITLE), + l10n_util::GetStringUTF16( + IDS_ASH_USB_NOTIFICATION_LIMIT_REACHED_BODY), + /*display_source=*/std::u16string(), GURL(), + message_center::NotifierId( + message_center::NotifierType::SYSTEM_COMPONENT, + kNotifierUsbPeripheral, + NotificationCatalogName::kUsbPeripheralDeviceOrEndpointLimit), + optional, + base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( + message_center::HandleNotificationClickDelegate:: + ButtonClickCallback(base::DoNothing())), + vector_icons::kUsbIcon, + message_center::SystemNotificationWarningLevel::WARNING); + + message_center_->AddNotification(std::move(notification)); +} + } // namespace ash
diff --git a/ash/system/usb_peripheral/usb_peripheral_notification_controller.h b/ash/system/usb_peripheral/usb_peripheral_notification_controller.h index 400647d..c950773e 100644 --- a/ash/system/usb_peripheral/usb_peripheral_notification_controller.h +++ b/ash/system/usb_peripheral/usb_peripheral_notification_controller.h
@@ -39,6 +39,7 @@ void OnInvalidUSB4CableWarning() override; void OnInvalidTBTCableWarning() override; void OnSpeedLimitingCableWarning() override; + void OnUsbDeviceOrEndpointLimit() override; // Stubs from PCIE Notification controller void OnLimitedPerformancePeripheralReceived() override {}
diff --git a/ash/system/usb_peripheral/usb_peripheral_notification_controller_unittest.cc b/ash/system/usb_peripheral/usb_peripheral_notification_controller_unittest.cc index d32dbfe8..065d274e 100644 --- a/ash/system/usb_peripheral/usb_peripheral_notification_controller_unittest.cc +++ b/ash/system/usb_peripheral/usb_peripheral_notification_controller_unittest.cc
@@ -25,7 +25,8 @@ "cros_usb_peripheral_invalid_tbt_cable_notification_id"; const char kUsbPeripheralSpeedLimitingCableNotificationId[] = "cros_usb_peripheral_speed_limiting_cable_notification_id"; - +const char kUsbPeripheralDeviceOrEndpointLimitNotificationId[] = + "cros_usb_peripheral_device_or_endpoint_limit_notification_id"; } // namespace class UsbPeripheralNotificationControllerTest : public AshTestBase { @@ -122,6 +123,22 @@ } TEST_F(UsbPeripheralNotificationControllerTest, + UsbDeviceOrEndpointLimitNotification) { + EXPECT_EQ(MessageCenter::Get()->NotificationCount(), 0u); + controller()->OnUsbDeviceOrEndpointLimit(); + EXPECT_EQ(MessageCenter::Get()->NotificationCount(), 1u); + + message_center::Notification* notification = + MessageCenter::Get()->FindVisibleNotificationById( + kUsbPeripheralDeviceOrEndpointLimitNotificationId); + ASSERT_TRUE(notification); + + EXPECT_EQ(notification->buttons().size(), 0u); + controller()->OnUsbDeviceOrEndpointLimit(); + EXPECT_EQ(MessageCenter::Get()->NotificationCount(), 1u); +} + +TEST_F(UsbPeripheralNotificationControllerTest, SpeedLimitingCableNotificationWithClick) { EXPECT_EQ(MessageCenter::Get()->NotificationCount(), 0u); controller()->OnSpeedLimitingCableWarning();
diff --git a/ash/test/pixel/ash_pixel_differ.cc b/ash/test/pixel/ash_pixel_differ.cc index 3b51ba4..4ea6887 100644 --- a/ash/test/pixel/ash_pixel_differ.cc +++ b/ash/test/pixel/ash_pixel_differ.cc
@@ -9,6 +9,7 @@ #include "ash/root_window_controller.h" #include "ash/shell.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" namespace ash {
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index b90dde3..78997b11 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -68,6 +68,7 @@ #include "base/memory/raw_ptr.h" #include "base/metrics/metrics_hashes.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/task/current_thread.h" #include "base/task/task_observer.h"
diff --git a/ash/wallpaper/wallpaper_utils/sea_pen_metadata_utils_unittest.cc b/ash/wallpaper/wallpaper_utils/sea_pen_metadata_utils_unittest.cc index 83bcca3..55ad891 100644 --- a/ash/wallpaper/wallpaper_utils/sea_pen_metadata_utils_unittest.cc +++ b/ash/wallpaper/wallpaper_utils/sea_pen_metadata_utils_unittest.cc
@@ -12,6 +12,7 @@ #include "base/i18n/rtl.h" #include "base/json/json_writer.h" #include "base/json/values_util.h" +#include "base/strings/string_number_conversions.h" #include "base/test/icu_test_util.h" #include "base/test/task_environment.h" #include "base/test/test_future.h"
diff --git a/ash/webui/diagnostics_ui/backend/input/input_data_provider.cc b/ash/webui/diagnostics_ui/backend/input/input_data_provider.cc index 0ac3a72..10f0886 100644 --- a/ash/webui/diagnostics_ui/backend/input/input_data_provider.cc +++ b/ash/webui/diagnostics_ui/backend/input/input_data_provider.cc
@@ -28,6 +28,7 @@ #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_util.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "chromeos/dbus/power/power_manager_client.h" #include "ui/aura/client/aura_constants.h" #include "ui/display/screen.h"
diff --git a/ash/webui/recorder_app_ui/recorder_app_ui.cc b/ash/webui/recorder_app_ui/recorder_app_ui.cc index 7ac0cf0f..a40aa34 100644 --- a/ash/webui/recorder_app_ui/recorder_app_ui.cc +++ b/ash/webui/recorder_app_ui/recorder_app_ui.cc
@@ -25,6 +25,7 @@ #include "ash/webui/recorder_app_ui/resources/grit/recorder_app_resources_map.h" #include "ash/webui/recorder_app_ui/url_constants.h" #include "base/feature_list.h" +#include "base/strings/string_number_conversions.h" #include "chromeos/ash/components/audio/cras_audio_handler.h" #include "chromeos/ash/components/mojo_service_manager/connection.h" #include "chromeos/constants/devicetype.h"
diff --git a/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc b/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc index 0846f40..33198f7 100644 --- a/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc +++ b/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc
@@ -36,6 +36,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/user_metrics.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/task/sequenced_task_runner.h" #include "components/prefs/pref_member.h" #include "mojo/public/cpp/bindings/clone_traits.h"
diff --git a/ash/wm/coral/coral_controller.cc b/ash/wm/coral/coral_controller.cc index a85a7fe..982639f 100644 --- a/ash/wm/coral/coral_controller.cc +++ b/ash/wm/coral/coral_controller.cc
@@ -25,6 +25,7 @@ #include "ash/wm/snap_group/snap_group.h" #include "ash/wm/snap_group/snap_group_controller.h" #include "base/command_line.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/ash/components/mojo_service_manager/connection.h" #include "chromeos/ash/services/coral/public/mojom/coral_service.mojom.h"
diff --git a/ash/wm/coral/coral_controller_unittest.cc b/ash/wm/coral/coral_controller_unittest.cc index 9fa23c82..1914d0a 100644 --- a/ash/wm/coral/coral_controller_unittest.cc +++ b/ash/wm/coral/coral_controller_unittest.cc
@@ -35,6 +35,7 @@ #include "ash/wm/snap_group/snap_group_controller.h" #include "ash/wm/snap_group/snap_group_test_util.h" #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" +#include "base/strings/string_number_conversions.h" #include "base/test/run_until.h" #include "base/test/scoped_feature_list.h" #include "components/app_constants/constants.h"
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index f55369b..374a33b8 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -60,6 +60,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h"
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc index 5064f14..103318e 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -38,6 +38,7 @@ #include "ash/wm/work_area_insets.h" #include "base/command_line.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h"
diff --git a/ash/wm/test/wm_pixel_diff_test.cc b/ash/wm/test/wm_pixel_diff_test.cc index b53629c6..12c4ea0a 100644 --- a/ash/wm/test/wm_pixel_diff_test.cc +++ b/ash/wm/test/wm_pixel_diff_test.cc
@@ -25,6 +25,7 @@ #include "ash/wm/window_restore/informed_restore_controller.h" #include "ash/wm/window_state.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "chromeos/constants/chromeos_features.h" #include "components/app_constants/constants.h" #include "third_party/skia/include/core/SkColor.h"
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc index ec3a3bb..8145174 100644 --- a/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -63,6 +63,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "chromeos/ash/components/audio/sounds.h" #include "ui/aura/client/aura_constants.h"
diff --git a/base/message_loop/message_pump_io_ios.cc b/base/message_loop/message_pump_io_ios.cc index 0f7aae4..526c67a 100644 --- a/base/message_loop/message_pump_io_ios.cc +++ b/base/message_loop/message_pump_io_ios.cc
@@ -100,10 +100,13 @@ CFFileDescriptorEnableCallBacks(scoped_fdref.get(), callback_types); - // TODO(wtc): what should the 'order' argument be? + // `order` is set to the same value as MessagePumpCFRunLoopBase's + // `work_source_`'s order. It should not be lower than the latter to avoid + // starving that run loop (which can happen in + // IOWatcherFdTest.ReadPersistent, for example). apple::ScopedCFTypeRef<CFRunLoopSourceRef> scoped_fd_source( CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, - scoped_fdref.get(), 0)); + scoped_fdref.get(), /*order=*/1)); if (!scoped_fd_source) { NOTREACHED() << "CFFileDescriptorCreateRunLoopSource failed"; }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/CarryOn.java b/base/test/android/javatests/src/org/chromium/base/test/transit/CarryOn.java index d1bbe061..6f38736 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/CarryOn.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/CarryOn.java
@@ -20,7 +20,7 @@ private final String mName; private static int sLastCarryOnId = 2000; - protected CarryOn() { + public CarryOn() { mId = ++sLastCarryOnId; String className = getClass().getSimpleName(); mName =
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionalState.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionalState.java index 2dd1fdf..de90454 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionalState.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionalState.java
@@ -231,7 +231,7 @@ } /** Declare as an element a View that matches |viewMatcher|. */ - protected <ViewT extends View> ViewElement<ViewT> declareView(ViewSpec<ViewT> viewSpec) { + public <ViewT extends View> ViewElement<ViewT> declareView(ViewSpec<ViewT> viewSpec) { return mElements.declareView(viewSpec); } @@ -253,7 +253,7 @@ } /** Declare as an element a View that matches |viewSpec| with extra Options. */ - protected <ViewT extends View> ViewElement<ViewT> declareView( + public <ViewT extends View> ViewElement<ViewT> declareView( ViewSpec<ViewT> viewSpec, ViewElement.Options options) { return mElements.declareView(viewSpec, options); } @@ -264,12 +264,12 @@ } /** Declare as a Condition that a View is not displayed. */ - protected void declareNoView(ViewSpec<?> viewSpec) { + public void declareNoView(ViewSpec<?> viewSpec) { mElements.declareNoView(viewSpec); } /** Declare as a Condition that a View is not displayed. */ - protected void declareNoView(Matcher<View> viewMatcher) { + public void declareNoView(Matcher<View> viewMatcher) { mElements.declareNoView(viewMatcher); } @@ -283,7 +283,7 @@ * <p>Further, no promises are made that the Condition is false after exiting the State. Use a * scoped {@link LogicalElement} in this case. */ - protected final void declareEnterCondition(Condition condition) { + public final void declareEnterCondition(Condition condition) { mElements.declareEnterCondition(condition); } @@ -297,7 +297,7 @@ * <p>Further, no promises are made that the Condition is false after exiting the State. Use a * scoped {@link LogicalElement} in this case. */ - protected <ProductT, T extends ConditionWithResult<ProductT>> + public <ProductT, T extends ConditionWithResult<ProductT>> Element<ProductT> declareEnterConditionAsElement(T condition) { return mElements.declareEnterConditionAsElement(condition); } @@ -309,7 +309,7 @@ * <p>No promises are made that the Condition is false as long as the ConditionalState is * ACTIVE. For these cases, use a scoped {@link LogicalElement}. */ - protected final void declareExitCondition(Condition condition) { + public final void declareExitCondition(Condition condition) { mElements.declareExitCondition(condition); } @@ -319,13 +319,13 @@ * <p>When the {@link Element}'s enter Condition becomes fulfilled, |delayedDeclarations| will * be run to declare new Elements. */ - protected void declareElementFactory( + public void declareElementFactory( Element<?> element, Callback<Elements.Builder> delayedDeclarations) { mElements.declareElementFactory(element, delayedDeclarations); } /** Declare a custom Element. */ - protected <T extends Element<?>> T declareElement(T element) { + public <T extends Element<?>> T declareElement(T element) { return mElements.declareElement(element); } }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/Facility.java b/base/test/android/javatests/src/org/chromium/base/test/transit/Facility.java index fb0e0396..95f1a74 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/Facility.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/Facility.java
@@ -6,6 +6,7 @@ import org.chromium.base.test.transit.Transition.Trigger; import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * Facility is a {@link ConditionalState} scoped to a single host {@link Station} instance. @@ -27,7 +28,7 @@ * @param <HostStationT> the type of host {@link Station} this is scoped to. */ @NullMarked -public abstract class Facility<HostStationT extends Station<?>> extends ConditionalState { +public class Facility<HostStationT extends Station<?>> extends ConditionalState { private static int sLastFacilityId = 1000; private final int mId = ++sLastFacilityId; @@ -36,6 +37,30 @@ @SuppressWarnings("NullAway") protected HostStationT mHostStation; + protected final @Nullable String mCustomName; + + /** + * Constructor for named subclasses. + * + * <p>Named subclasses should let name default to the simple class name, e.g. "<S4|F1002: + * SubclassNameFacility>". + */ + protected Facility() { + super(); + mCustomName = null; + } + + /** + * Create an empty Facility. Elements can be declared after creation. + * + * @param name Direct instantiations should provide a name which will be displayed as + * "<S4|F1002: ProvidedName>", + */ + public Facility(String name) { + super(); + mCustomName = name; + } + void setHostStation(Station station) { assert mHostStation == null : "Facility " + this + " already added to a station. Tried to add it to " + station; @@ -48,7 +73,7 @@ "<S%s|F%s: %s>", mHostStation == null ? "-unset" : mHostStation.getId(), mId, - getClass().getSimpleName()); + mCustomName != null ? mCustomName : getClass().getSimpleName()); } @Override
diff --git a/build/linux/sysroot_scripts/generated_package_lists/bullseye.amd64 b/build/linux/sysroot_scripts/generated_package_lists/bullseye.amd64 index 10c7c4a..c2f16b4 100644 --- a/build/linux/sysroot_scripts/generated_package_lists/bullseye.amd64 +++ b/build/linux/sysroot_scripts/generated_package_lists/bullseye.amd64
@@ -136,7 +136,6 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.66.8-1+deb11u4_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.31-13+deb11u5_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dbg_2.31-13+deb11u5_amd64.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u11_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u5_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.31-13+deb11u5_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.2.1+dfsg-1+deb11u1_amd64.deb @@ -589,6 +588,7 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.36.1-8+deb11u2_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/util-linux_2.36.1-8+deb11u2_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.36.1-8+deb11u2_amd64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind/valgrind_3.16.1-1_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.3.224.0-1~bpo11+1_amd64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.3.224.0-1~bpo11+1_amd64.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/bullseye.arm64 b/build/linux/sysroot_scripts/generated_package_lists/bullseye.arm64 index dc91af3..b086db9 100644 --- a/build/linux/sysroot_scripts/generated_package_lists/bullseye.arm64 +++ b/build/linux/sysroot_scripts/generated_package_lists/bullseye.arm64
@@ -135,7 +135,6 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.66.8-1+deb11u4_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.31-13+deb11u5_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dbg_2.31-13+deb11u5_arm64.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u11_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u5_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.31-13+deb11u5_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.2.1+dfsg-1+deb11u1_arm64.deb @@ -588,6 +587,7 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.36.1-8+deb11u2_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/util-linux_2.36.1-8+deb11u2_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.36.1-8+deb11u2_arm64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind/valgrind_3.16.1-1_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.3.224.0-1~bpo11+1_arm64.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.3.224.0-1~bpo11+1_arm64.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/bullseye.armhf b/build/linux/sysroot_scripts/generated_package_lists/bullseye.armhf index 5a46939..dda073e 100644 --- a/build/linux/sysroot_scripts/generated_package_lists/bullseye.armhf +++ b/build/linux/sysroot_scripts/generated_package_lists/bullseye.armhf
@@ -132,7 +132,6 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.66.8-1+deb11u4_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.31-13+deb11u5_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dbg_2.31-13+deb11u5_armhf.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u11_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u5_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.31-13+deb11u5_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.2.1+dfsg-1+deb11u1_armhf.deb @@ -583,6 +582,7 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.36.1-8+deb11u2_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/util-linux_2.36.1-8+deb11u2_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.36.1-8+deb11u2_armhf.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind/valgrind_3.16.1-1_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.3.224.0-1~bpo11+1_armhf.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.3.224.0-1~bpo11+1_armhf.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/bullseye.i386 b/build/linux/sysroot_scripts/generated_package_lists/bullseye.i386 index 5cc58e8b..c5216ab4 100644 --- a/build/linux/sysroot_scripts/generated_package_lists/bullseye.i386 +++ b/build/linux/sysroot_scripts/generated_package_lists/bullseye.i386
@@ -134,7 +134,6 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.66.8-1+deb11u4_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.31-13+deb11u5_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dbg_2.31-13+deb11u5_i386.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u11_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u5_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.31-13+deb11u5_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.2.1+dfsg-1+deb11u1_i386.deb @@ -586,6 +585,7 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.36.1-8+deb11u2_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/util-linux_2.36.1-8+deb11u2_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.36.1-8+deb11u2_i386.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind/valgrind_3.16.1-1_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.3.224.0-1~bpo11+1_i386.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.3.224.0-1~bpo11+1_i386.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/bullseye.mips64el b/build/linux/sysroot_scripts/generated_package_lists/bullseye.mips64el index 4213b1f2..a9b496b 100644 --- a/build/linux/sysroot_scripts/generated_package_lists/bullseye.mips64el +++ b/build/linux/sysroot_scripts/generated_package_lists/bullseye.mips64el
@@ -130,7 +130,6 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.66.8-1+deb11u4_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.31-13+deb11u5_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dbg_2.31-13+deb11u5_mips64el.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u11_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u5_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.31-13+deb11u5_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.2.1+dfsg-1+deb11u1_mips64el.deb @@ -580,6 +579,7 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.36.1-8+deb11u2_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/util-linux_2.36.1-8+deb11u2_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.36.1-8+deb11u2_mips64el.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind/valgrind_3.16.1-1_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.3.224.0-1~bpo11+1_mips64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.3.224.0-1~bpo11+1_mips64el.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/bullseye.mipsel b/build/linux/sysroot_scripts/generated_package_lists/bullseye.mipsel index bf657db..cbad0e9 100644 --- a/build/linux/sysroot_scripts/generated_package_lists/bullseye.mipsel +++ b/build/linux/sysroot_scripts/generated_package_lists/bullseye.mipsel
@@ -129,8 +129,6 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev-bin_2.66.8-1+deb11u4_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.66.8-1+deb11u4_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.31-13+deb11u5_mipsel.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dbg_2.31-13+deb11u5_mipsel.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u11_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u5_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.31-13+deb11u5_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.2.1+dfsg-1+deb11u1_mipsel.deb @@ -580,7 +578,7 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.36.1-8+deb11u2_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/util-linux_2.36.1-8+deb11u2_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.36.1-8+deb11u2_mipsel.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind/valgrind_3.16.1-1_mipsel.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.3.224.0-1~bpo11+1_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.3.224.0-1~bpo11+1_mipsel.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wavpack/libwavpack1_5.4.0-1_mipsel.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/bullseye.ppc64el b/build/linux/sysroot_scripts/generated_package_lists/bullseye.ppc64el index d0e9aa9..d709953 100644 --- a/build/linux/sysroot_scripts/generated_package_lists/bullseye.ppc64el +++ b/build/linux/sysroot_scripts/generated_package_lists/bullseye.ppc64el
@@ -136,7 +136,6 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.66.8-1+deb11u4_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.31-13+deb11u5_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dbg_2.31-13+deb11u5_ppc64el.deb -https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u11_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.31-13+deb11u5_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.31-13+deb11u5_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.2.1+dfsg-1+deb11u1_ppc64el.deb @@ -586,6 +585,7 @@ https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.36.1-8+deb11u2_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/util-linux_2.36.1-8+deb11u2_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.36.1-8+deb11u2_ppc64el.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind/valgrind_3.16.1-1_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.3.224.0-1~bpo11+1_ppc64el.deb https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.3.224.0-1~bpo11+1_ppc64el.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/trixie.riscv64 b/build/linux/sysroot_scripts/generated_package_lists/trixie.riscv64 new file mode 100644 index 0000000..1273786f --- /dev/null +++ b/build/linux/sysroot_scripts/generated_package_lists/trixie.riscv64
@@ -0,0 +1,628 @@ +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/abseil/libabsl-dev_20230802.1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/abseil/libabsl20230802_20230802.1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/acl/libacl1_2.3.2-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/adduser/adduser_3.137_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/adwaita-icon-theme/adwaita-icon-theme_47.0-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/alsa-lib/libasound2-data_1.2.13-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/alsa-lib/libasound2-dev_1.2.13-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/alsa-lib/libasound2t64_1.2.13-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/aom/libaom3_3.11.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/apparmor/libapparmor1_3.1.7-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/architecture-properties/native-architecture_0.2.5_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/at-spi2-common_2.55.0.1-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/gir1.2-atk-1.0_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/gir1.2-atspi-2.0_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/libatk-bridge2.0-0t64_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/libatk-bridge2.0-dev_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/libatk1.0-0t64_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/libatk1.0-dev_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/libatspi2.0-0t64_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/at-spi2-core/libatspi2.0-dev_2.55.0.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/attr/libattr1_2.5.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/audit/libaudit-common_4.0.2-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/audit/libaudit1_4.0.2-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/avahi/libavahi-client3_0.8-16_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/avahi/libavahi-common-data_0.8-16_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/a/avahi/libavahi-common3_0.8-16_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/base-files/base-files_13.6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/base-passwd/base-passwd_3.6.6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/binutils-common_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/binutils-riscv64-linux-gnu_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/binutils_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/libbinutils_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/libctf-nobfd0_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/libctf0_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/libgprofng0_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/binutils/libsframe1_2.43.90.20250127-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/bluez/libbluetooth-dev_5.79-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/bluez/libbluetooth3_5.79-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/brotli/libbrotli-dev_1.1.0-2+b6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/brotli/libbrotli1_1.1.0-2+b6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/bzip2/bzip2_1.0.8-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/b/bzip2/libbz2-dev_1.0.8-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cairo/libcairo-gobject2_1.18.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cairo/libcairo-script-interpreter2_1.18.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cairo/libcairo2-dev_1.18.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cairo/libcairo2_1.18.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cdebconf/libdebconfclient0_0.277_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/chromaprint/libchromaprint1_1.5.1-7_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cjson/libcjson1_1.7.18-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/codec2/libcodec2-1.2_1.2.0-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/colord/gir1.2-colord-1.0_1.4.7-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/colord/libcolord-dev_1.4.7-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/colord/libcolord2_1.4.7-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cups/libcups2-dev_2.4.10-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cups/libcups2t64_2.4.10-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cups/libcupsimage2-dev_2.4.10-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cups/libcupsimage2t64_2.4.10-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/curl/libcurl3t64-gnutls_8.11.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/curl/libcurl4-gnutls-dev_8.11.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cyrus-sasl2/libsasl2-2_2.1.28+dfsg1-8+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/c/cyrus-sasl2/libsasl2-modules-db_2.1.28+dfsg1-8+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dav1d/libdav1d7_1.5.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/db5.3/libdb5.3t64_5.3.28+dfsg2-9_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/dbus-bin_1.16.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/dbus-daemon_1.16.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/dbus-session-bus-common_1.16.0-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/dbus-system-bus-common_1.16.0-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/dbus-user-session_1.16.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/dbus_1.16.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/libdbus-1-3_1.16.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dbus/libdbus-1-dev_1.16.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dconf/dconf-gsettings-backend_0.40.0-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dconf/dconf-service_0.40.0-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dconf/libdconf1_0.40.0-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/debconf/debconf_1.5.89_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/double-conversion/libdouble-conversion3_3.3.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dpkg/dpkg-dev_1.22.11_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dpkg/dpkg_1.22.11_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/dpkg/libdpkg-perl_1.22.11_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/d/duktape/libduktape207_2.7.0-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/e/e2fsprogs/comerr-dev_2.1-1.47.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/e/e2fsprogs/libcom-err2_1.47.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/e/elfutils/libelf-dev_0.192-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/e/elfutils/libelf1t64_0.192-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/e/expat/libexpat1-dev_2.6.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/e/expat/libexpat1_2.6.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libavcodec-dev_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libavcodec61_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libavformat-dev_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libavformat61_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libavutil-dev_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libavutil59_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libswresample-dev_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/ffmpeg/libswresample5_7.1-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/flac/libflac-dev_1.4.3+ds-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/flac/libflac12t64_1.4.3+ds-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fontconfig/fontconfig-config_2.15.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fontconfig/fontconfig_2.15.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fontconfig/libfontconfig-dev_2.15.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fontconfig/libfontconfig1-dev_2.15.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fontconfig/libfontconfig1_2.15.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fonts-dejavu/fonts-dejavu-core_2.37-8_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fonts-dejavu/fonts-dejavu-mono_2.37-8_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/freetype/libfreetype-dev_2.13.3+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/freetype/libfreetype6_2.13.3+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fribidi/libfribidi-dev_1.0.16-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/f/fribidi/libfribidi0_1.0.16-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/game-music-emu/libgme0_0.6.3-7+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-12/gcc-12-base_12.4.0-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-12/libgcc-12-dev_12.4.0-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-12/libstdc++-12-dev_12.4.0-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-12_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-14/libasan8_14.2.0-12_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-14/libatomic1_14.2.0-12_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-12_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-14/libgomp1_14.2.0-12_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gcc-14/libstdc++6_14.2.0-12_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gdbm/libgdbm-compat4t64_1.24-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gdbm/libgdbm6t64_1.24-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gdk-pixbuf/gir1.2-gdkpixbuf-2.0_2.42.12+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gdk-pixbuf/libgdk-pixbuf-2.0-0_2.42.12+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gdk-pixbuf/libgdk-pixbuf-2.0-dev_2.42.12+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gdk-pixbuf/libgdk-pixbuf2.0-bin_2.42.12+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gdk-pixbuf/libgdk-pixbuf2.0-common_2.42.12+dfsg-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/giflib/libgif7_5.2.2-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/gir1.2-glib-2.0-dev_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/gir1.2-glib-2.0_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/girepository-tools_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libgio-2.0-dev-bin_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libgio-2.0-dev_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libgirepository-2.0-0_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-0t64_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-bin_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-data_2.82.4-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev-bin_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glib2.0/libglib2.0-dev_2.82.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc-dev-bin_2.40-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6-dev_2.40-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/glibc/libc6_2.40-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp-dev_6.3.0+dfsg-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmp10_6.3.0+dfsg-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gmp/libgmpxx4ldbl_6.3.0+dfsg-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gnutls28/libgnutls-dane0t64_3.8.8-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gnutls28/libgnutls-openssl27t64_3.8.8-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gnutls28/libgnutls28-dev_3.8.8-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gnutls28/libgnutls30t64_3.8.8-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gobject-introspection/gir1.2-freedesktop-dev_1.82.0-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gobject-introspection/gir1.2-freedesktop_1.82.0-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/graphene/gir1.2-graphene-1.0_1.10.8-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/graphene/libgraphene-1.0-0_1.10.8-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/graphene/libgraphene-1.0-dev_1.10.8-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/graphite2/libgraphite2-3_1.3.14-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/graphite2/libgraphite2-dev_1.3.14-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk+3.0/gir1.2-gtk-3.0_3.24.43-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk+3.0/libgtk-3-0t64_3.24.43-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk+3.0/libgtk-3-common_3.24.43-5_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk+3.0/libgtk-3-dev_3.24.43-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk4/gir1.2-gtk-4.0_4.16.12+ds-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk4/gtk-update-icon-cache_4.16.12+ds-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk4/libgtk-4-1_4.16.12+ds-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk4/libgtk-4-common_4.16.12+ds-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/g/gtk4/libgtk-4-dev_4.16.12+ds-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/harfbuzz/gir1.2-harfbuzz-0.0_10.2.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/harfbuzz/libharfbuzz-cairo0_10.2.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/harfbuzz/libharfbuzz-dev_10.2.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/harfbuzz/libharfbuzz-gobject0_10.2.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/harfbuzz/libharfbuzz-icu0_10.2.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/harfbuzz/libharfbuzz-subset0_10.2.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/harfbuzz/libharfbuzz0b_10.2.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/hicolor-icon-theme/hicolor-icon-theme_0.18-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/h/highway/libhwy1t64_1.2.0-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/i/icu/icu-devtools_72.1-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/i/icu/libicu-dev_72.1-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/i/icu/libicu72_72.1-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/i/imath/libimath-3-1-29t64_3.1.12-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/i/init-system-helpers/init-system-helpers_1.68_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/j/jansson/libjansson4_2.14-2+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/j/jbigkit/libjbig-dev_2.1-6.1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/j/jbigkit/libjbig0_2.1-6.1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/j/jpeg-xl/libjxl0.10_0.10.4-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/keyutils/libkeyutils1_1.6.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/krb5-multidev_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libgssapi-krb5-2_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libgssrpc4t64_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libk5crypto3_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libkadm5clnt-mit12_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libkadm5srv-mit12_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libkdb5-10t64_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libkrb5-3_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libkrb5-dev_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/k/krb5/libkrb5support0_1.21.3-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lame/libmp3lame0_3.100-6+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lcms2/liblcms2-2_2.16-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lcms2/liblcms2-dev_2.16-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lerc/liblerc-dev_4.0.0+ds-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lerc/liblerc4_4.0.0+ds-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/linux/linux-libc-dev_6.12.10-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/llvm-toolchain-19/libllvm19_19.1.6-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lm-sensors/libsensors-config_3.6.0-10_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lm-sensors/libsensors5_3.6.0-10+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lsb/lsb-base_11.6_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/l/lzo2/liblzo2-2_2.10-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/liba/libasyncns/libasyncns0_0.8-6+b5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libb/libb2/libb2-1_0.98.1-1.1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libb/libbluray/libbluray2_1.3.4-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libb/libbsd/libbsd0_0.12.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libc/libcap-ng/libcap-ng0_0.8.5-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libc/libcap2/libcap-dev_2.66-5+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libc/libcap2/libcap2_2.66-5+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libc/libcloudproviders/gir1.2-cloudproviders-0.3.0_0.3.6-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libc/libcloudproviders/libcloudproviders-dev_0.3.6-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libc/libcloudproviders/libcloudproviders0_0.3.6-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdatrie/libdatrie-dev_0.2.13-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdatrie/libdatrie1_0.2.13-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdbusmenu/gir1.2-dbusmenu-glib-0.4_18.10.20180917~bzr492+repack1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdbusmenu/libdbusmenu-glib-dev_18.10.20180917~bzr492+repack1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdbusmenu/libdbusmenu-glib4_18.10.20180917~bzr492+repack1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdeflate/libdeflate-dev_1.23-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdeflate/libdeflate0_1.23-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdrm/libdrm-amdgpu1_2.4.123-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdrm/libdrm-common_2.4.123-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdrm/libdrm-dev_2.4.123-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdrm/libdrm-nouveau2_2.4.123-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdrm/libdrm-radeon1_2.4.123-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdrm/libdrm2_2.4.123-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdvdnav/libdvdnav4_6.1.1-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libd/libdvdread/libdvdread8t64_6.1.3-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libe/libedit/libedit2_3.1-20250104-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libe/libepoxy/libepoxy-dev_1.5.10-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libe/libepoxy/libepoxy0_1.5.10-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libe/libevdev/libevdev-dev_1.13.3+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libe/libevdev/libevdev2_1.13.3+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libe/libevent/libevent-2.1-7t64_2.1.12-stable-10+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libf/libffi/libffi-dev_3.4.6-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libf/libffi/libffi8_3.4.6-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgcrypt20/libgcrypt20-dev_1.11.0-7_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgcrypt20/libgcrypt20_1.11.0-7_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglu/libglu1-mesa-dev_9.0.2-1.1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglu/libglu1-mesa_9.0.2-1.1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libegl-dev_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libegl1_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libgl-dev_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libgl1_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libgles-dev_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libgles1_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libgles2_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libglvnd-core-dev_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libglvnd-dev_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libglvnd0_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libglx-dev_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libglx0_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libopengl-dev_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libglvnd/libopengl0_1.7.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgpg-error/libgpg-error-dev_1.51-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgpg-error/libgpg-error0_1.51-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgsm/libgsm1_1.0.22-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgudev/gir1.2-gudev-1.0_238-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgudev/libgudev-1.0-0_238-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libg/libgudev/libgudev-1.0-dev_238-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libi/libice/libice-dev_1.1.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libi/libice/libice6_1.1.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libi/libidn2/libidn2-0_2.3.7-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libi/libidn2/libidn2-dev_2.3.7-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libi/libinput/libinput-bin_1.26.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libi/libinput/libinput-dev_1.26.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libi/libinput/libinput10_1.26.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libj/libjpeg-turbo/libjpeg-dev_2.1.5-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libj/libjpeg-turbo/libjpeg62-turbo-dev_2.1.5-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.1.5-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libj/libjsoncpp/libjsoncpp-dev_1.9.6-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libj/libjsoncpp/libjsoncpp26_1.9.6-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libm/libmd/libmd0_1.1.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libo/libogg/libogg-dev_1.3.5-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libo/libogg/libogg0_1.3.5-3+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libo/libopenmpt/libopenmpt0t64_0.7.13-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libpciaccess/libpciaccess-dev_0.17-3+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libpciaccess/libpciaccess0_0.17-3+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libpgm/libpgm-5.3-0t64_5.3.128~dfsg-2.1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libpng1.6/libpng-dev_1.6.44-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libpng1.6/libpng16-16t64_1.6.44-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libproxy/libproxy1v5_0.5.9-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libpsl/libpsl-dev_0.21.2-1.1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libp/libpsl/libpsl5t64_0.21.2-1.1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libr/librabbitmq/librabbitmq4_0.15.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libr/librist/librist4_0.2.11+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libr/librsvg/librsvg2-2_2.59.1+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libseccomp/libseccomp2_2.5.5-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libselinux/libselinux1-dev_3.7-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libselinux/libselinux1_3.7-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsemanage/libsemanage-common_3.7-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsemanage/libsemanage2_3.7-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsepol/libsepol-dev_3.7-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsepol/libsepol2_3.7-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libset-scalar-perl/libset-scalar-perl_1.29-3_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsm/libsm-dev_1.2.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsm/libsm6_1.2.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsndfile/libsndfile1_1.2.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsodium/libsodium23_1.0.18-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libsoxr/libsoxr0_0.1.3-4+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libssh/libssh-4_0.11.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libssh2/libssh2-1-dev_1.11.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libs/libssh2/libssh2-1t64_1.11.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libt/libtasn1-6/libtasn1-6-dev_4.19.0-3+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libt/libtasn1-6/libtasn1-6_4.19.0-3+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libt/libthai/libthai-data_0.1.29-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libt/libthai/libthai-dev_0.1.29-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libt/libthai/libthai0_0.1.29-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libt/libtheora/libtheoradec1_1.2.0~alpha1+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libt/libtheora/libtheoraenc1_1.2.0~alpha1+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libu/libudfread/libudfread0_1.1.2-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libu/libunistring/libunistring5_1.3-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libu/libutempter/libutempter-dev_1.2.1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libu/libutempter/libutempter0_1.2.1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libva/libva-dev_2.22.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libva/libva-drm2_2.22.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libva/libva-glx2_2.22.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libva/libva-wayland2_2.22.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libva/libva-x11-2_2.22.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libva/libva2_2.22.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libvdpau/libvdpau1_1.5-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libvorbis/libvorbis0a_1.3.7-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libvorbis/libvorbisenc2_1.3.7-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libvorbis/libvorbisfile3_1.3.7-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libvpx/libvpx-dev_1.15.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libv/libvpx/libvpx9_1.15.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwacom/libwacom-common_2.13.0-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwacom/libwacom-dev_2.13.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwacom/libwacom9_2.13.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwebp/libsharpyuv-dev_1.5.0-0.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwebp/libsharpyuv0_1.5.0-0.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwebp/libwebp-dev_1.5.0-0.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwebp/libwebp7_1.5.0-0.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwebp/libwebpdecoder3_1.5.0-0.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwebp/libwebpdemux2_1.5.0-0.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libw/libwebp/libwebpmux3_1.5.0-0.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libx11/libx11-6_1.8.10-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libx11/libx11-data_1.8.10-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libx11/libx11-dev_1.8.10-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libx11/libx11-xcb-dev_1.8.10-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libx11/libx11-xcb1_1.8.10-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxau/libxau-dev_1.0.11-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxau/libxau6_1.0.11-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-dri2-0-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-dri2-0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-dri3-0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-dri3-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-glx0-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-glx0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-present-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-present0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-randr0-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-randr0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-render0-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-render0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-shape0-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-shape0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-shm0-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-shm0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-sync-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-sync1_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-xfixes0-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-xfixes0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-xinerama0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-xinput0_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb-xkb1_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb1-dev_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcb/libxcb1_1.17.0-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcomposite/libxcomposite-dev_0.4.6-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcomposite/libxcomposite1_0.4.6-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcrypt/libcrypt-dev_4.4.38-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcursor/libxcursor-dev_1.2.3-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxcursor/libxcursor1_1.2.3-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxdamage/libxdamage-dev_1.1.6-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxdamage/libxdamage1_1.1.6-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxdmcp/libxdmcp-dev_1.1.5-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxdmcp/libxdmcp6_1.1.5-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxext/libxext-dev_1.3.4-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxext/libxext6_1.3.4-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxfixes/libxfixes-dev_6.0.0-2+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxfixes/libxfixes3_6.0.0-2+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxi/libxi-dev_1.8.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxi/libxi6_1.8.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxinerama/libxinerama-dev_1.1.4-3+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxinerama/libxinerama1_1.1.4-3+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxkbcommon/libxkbcommon-dev_1.7.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxkbcommon/libxkbcommon-x11-0_1.7.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxkbcommon/libxkbcommon0_1.7.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxml2/libxml2-dev_2.12.7+dfsg+really2.9.14-0.2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxml2/libxml2_2.12.7+dfsg+really2.9.14-0.2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxrandr/libxrandr-dev_1.5.4-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxrandr/libxrandr2_1.5.4-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxrender/libxrender-dev_0.9.10-1.1+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxrender/libxrender1_0.9.10-1.1+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxshmfence/libxshmfence-dev_1.3-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxshmfence/libxshmfence1_1.3-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxslt/libxslt1-dev_1.1.35-1.1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxslt/libxslt1.1_1.1.35-1.1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxss/libxss-dev_1.2.3-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxss/libxss1_1.2.3-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxt/libxt-dev_1.2.1-1.2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxt/libxt6t64_1.2.1-1.2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxtst/libxtst-dev_1.2.5-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxtst/libxtst6_1.2.5-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxxf86vm/libxxf86vm-dev_1.1.4-1+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libx/libxxf86vm/libxxf86vm1_1.1.4-1+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libz/libzstd/libzstd-dev_1.5.6+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/libz/libzstd/libzstd1_1.5.6+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/make-dfsg/make_4.4.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mbedtls/libmbedcrypto16_3.6.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/md4c/libmd4c0_0.5.2-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/media-types/media-types_10.1.0_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/libegl-mesa0_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/libegl1-mesa-dev_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/libgbm-dev_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/libgbm1_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/libgl1-mesa-dri_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/libglapi-mesa_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/libglx-mesa0_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/mesa-common-dev_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mesa/mesa-libgallium_24.2.8-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mpg123/libmpg123-0t64_1.32.10-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mtdev/libmtdev-dev_1.1.6-1.2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/m/mtdev/libmtdev1t64_1.1.6-1.2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ncurses/libncurses-dev_6.5-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ncurses/libncurses6_6.5-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ncurses/libncursesw6_6.5-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ncurses/libtinfo6_6.5-2+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/netbase/netbase_6.4_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nettle/libhogweed6t64_3.10-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nettle/libnettle8t64_3.10-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nettle/nettle-dev_3.10-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nghttp2/libnghttp2-14_1.64.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nghttp2/libnghttp2-dev_1.64.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nghttp3/libnghttp3-9_1.6.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nghttp3/libnghttp3-dev_1.6.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ngtcp2/libngtcp2-16_1.9.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ngtcp2/libngtcp2-crypto-gnutls-dev_1.9.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ngtcp2/libngtcp2-crypto-gnutls8_1.9.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/ngtcp2/libngtcp2-dev_1.9.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/norm/libnorm1t64_1.5.9+dfsg-3.1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nspr/libnspr4-dev_4.36-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nspr/libnspr4_4.36-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nss/libnss3-dev_3.107-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/n/nss/libnss3_3.107-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/ocl-icd/ocl-icd-libopencl1_2.3.2-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/openexr/libopenexr-3-1-30_3.1.5-5.1+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/openjpeg2/libopenjp2-7_2.5.0-2+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/openldap/libldap-dev_2.6.9+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/openldap/libldap2_2.6.9+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/openssl/libssl-dev_3.4.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/openssl/libssl3t64_3.4.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/openssl/openssl-provider-legacy_3.4.0-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/opus/libopus-dev_1.5.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/o/opus/libopus0_1.5.2-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/p11-kit/libp11-kit-dev_0.25.5-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/p11-kit/libp11-kit0_0.25.5-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pam/libpam-modules_1.5.3-7+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pam/libpam-runtime_1.5.3-7_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pam/libpam0g-dev_1.5.3-7+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pam/libpam0g_1.5.3-7+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pango1.0/gir1.2-pango-1.0_1.56.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pango1.0/libpango-1.0-0_1.56.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pango1.0/libpango1.0-dev_1.56.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pango1.0/libpangocairo-1.0-0_1.56.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pango1.0/libpangoft2-1.0-0_1.56.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pango1.0/libpangoxft-1.0-0_1.56.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pango1.0/pango1.0-tools_1.56.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/patch/patch_2.7.6-7+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pci.ids/pci.ids_0.0~2025.01.13-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pciutils/libpci-dev_3.13.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pciutils/libpci3_3.13.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pcre2/libpcre2-16-0_10.44-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pcre2/libpcre2-32-0_10.44-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pcre2/libpcre2-8-0_10.44-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pcre2/libpcre2-dev_10.44-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pcre2/libpcre2-posix3_10.44-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/perl/libperl5.40_5.40.0-8_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/perl/perl-base_5.40.0-8_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/perl/perl-modules-5.40_5.40.0-8_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/perl/perl_5.40.0-8_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pipewire/libpipewire-0.3-0t64_1.2.7-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pipewire/libpipewire-0.3-dev_1.2.7-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pipewire/libspa-0.2-dev_1.2.7-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pipewire/libspa-0.2-modules_1.2.7-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pixman/libpixman-1-0_0.44.0-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pixman/libpixman-1-dev_0.44.0-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pkgconf/libpkgconf3_1.8.1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pkgconf/pkgconf-bin_1.8.1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pkgconf/pkgconf_1.8.1-4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/procps/libproc2-0_4.0.4-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/procps/procps_4.0.4-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pulseaudio/libpulse-dev_17.0+dfsg1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pulseaudio/libpulse-mainloop-glib0_17.0+dfsg1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/pulseaudio/libpulse0_17.0+dfsg1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/python-packaging/python3-packaging_24.2-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/python3-defaults/libpython3-stdlib_3.13.1-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/python3-defaults/python3_3.13.1-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/python3.13/libpython3.13-minimal_3.13.1-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/python3.13/libpython3.13-stdlib_3.13.1-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/python3.13/python3.13-minimal_3.13.1-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/p/python3.13/python3.13_3.13.1-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6concurrent6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6core6t64_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6dbus6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6gui6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6network6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6opengl6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6openglwidgets6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6printsupport6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6sql6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6test6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6widgets6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/libqt6xml6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/qmake6-bin_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/qmake6_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/qt6-base-dev-tools_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/qt6-base-dev_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qt6-base/qt6-qpa-plugins_6.7.2+dfsg-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5concurrent5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5core5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5dbus5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5gui5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5network5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5printsupport5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5sql5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5test5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5widgets5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/libqt5xml5t64_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/qt5-qmake-bin_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/qt5-qmake_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/qtbase5-dev-tools_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtbase-opensource-src/qtbase5-dev_5.15.15+dfsg-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/q/qtchooser/qtchooser_66-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/re2/libre2-11_20240501-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/re2/libre2-dev_20240501-3+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/readline/libreadline8t64_8.2-6_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/readline/readline-common_8.2-6_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/rpcsvc-proto/rpcsvc-proto_1.4.3-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/rtmpdump/librtmp-dev_2.4+20151223.gitfa8646d.1-2+b5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/rtmpdump/librtmp1_2.4+20151223.gitfa8646d.1-2+b5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/r/rust-rav1e/librav1e0.7_0.7.1-9_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/sed/sed_4.9-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/sgml-base/sgml-base_1.31_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/shadow/login.defs_4.16.0-7_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/shadow/passwd_4.16.0-7_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/shared-mime-info/shared-mime-info_2.4-5+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/shine/libshine3_3.1.1-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/snappy/libsnappy-dev_1.2.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/snappy/libsnappy1v5_1.2.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/speech-dispatcher/libspeechd-dev_0.11.5-5.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/speech-dispatcher/libspeechd2_0.11.5-5.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/speex/libspeex1_1.2.1-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/sqlite3/libsqlite3-0_3.46.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/srt/libsrt1.5-gnutls_1.5.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/svt-av1/libsvtav1enc2_2.3.0+dfsg-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/sysprof/libsysprof-capture-4-dev_47.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/systemd/libpam-systemd_257.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/systemd/libsystemd-dev_257.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/systemd/libsystemd0_257.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/systemd/libudev-dev_257.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/systemd/libudev1_257.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/systemd/systemd-sysv_257.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/systemd/systemd_257.2-3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/s/sysvinit/sysvinit-utils_3.13-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/t/tar/tar_1.35+dfsg-3.1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/t/tiff/libtiff-dev_4.5.1+git230720-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/t/tiff/libtiff6_4.5.1+git230720-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/t/tiff/libtiffxx6_4.5.1+git230720-5_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/t/tslib/libts0t64_1.22-1.1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/t/twolame/libtwolame0_0.4.0-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/t/tzdata/tzdata_2024b-6_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/unbound/libunbound8_1.22.0-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/libblkid-dev_2.40.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/libblkid1_2.40.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/libmount-dev_2.40.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/libmount1_2.40.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/libuuid1_2.40.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/mount_2.40.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/u/util-linux/uuid-dev_2.40.4-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/valgrind-if-available/valgrind-if-available_3.18.1-1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan-dev_1.4.304.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/v/vulkan-loader/libvulkan1_1.4.304.0-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland-protocols/wayland-protocols_1.39-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland/libwayland-bin_1.23.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland/libwayland-client0_1.23.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland/libwayland-cursor0_1.23.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland/libwayland-dev_1.23.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland/libwayland-egl-backend-dev_1.23.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland/libwayland-egl1_1.23.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/wayland/libwayland-server0_1.23.0-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/w/webrtc-audio-processing/libwebrtc-audio-processing1_0.3-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/x264/libx264-164_0.164.3108+git31e19f9-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/x265/libx265-215_4.1-2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util-cursor/libxcb-cursor0_0.1.4-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util-image/libxcb-image0-dev_0.4.0-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util-image/libxcb-image0_0.4.0-2+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util-keysyms/libxcb-keysyms1_0.4.0-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util-renderutil/libxcb-render-util0-dev_0.3.9-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util-renderutil/libxcb-render-util0_0.3.9-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util-wm/libxcb-icccm4_0.4.2-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util/libxcb-util-dev_0.4.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xcb-util/libxcb-util1_0.4.1-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xft/libxft-dev_2.3.6-1+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xft/libxft2_2.3.6-1+b4_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xkeyboard-config/xkb-data_2.42-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xml-core/xml-core_0.19_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xorg-sgml-doctools/xorg-sgml-doctools_1.11-1.1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xorg/x11-common_7.7+24_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xorgproto/x11proto-core-dev_2024.1-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xorgproto/x11proto-dev_2024.1-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xorgproto/x11proto-render-dev_2024.1-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xorgproto/x11proto-scrnsaver-dev_2024.1-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xorgproto/x11proto-xf86vidmode-dev_2024.1-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xtrans/xtrans-dev_1.4.0-1_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xvidcore/libxvidcore4_1.3.7-1+b2_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xz-utils/liblzma-dev_5.6.3-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xz-utils/liblzma5_5.6.3-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/x/xz-utils/xz-utils_5.6.3-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/z3/libz3-4_4.13.3-1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/zeromq3/libzmq5_4.3.5-1+b3_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/zlib/libminizip-dev_1.3.dfsg+really1.3.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/zlib/libminizip1t64_1.3.dfsg+really1.3.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/zlib/zlib1g-dev_1.3.dfsg+really1.3.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_riscv64.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/zvbi/libzvbi-common_0.2.43-2_all.deb +https://snapshot.debian.org/archive/debian/20250129T203412Z/pool/main/z/zvbi/libzvbi0t64_0.2.43-2_riscv64.deb
diff --git a/build/linux/sysroot_scripts/reversion_glibc.py b/build/linux/sysroot_scripts/reversion_glibc.py index 0630dfb..e7bfa3e 100644 --- a/build/linux/sysroot_scripts/reversion_glibc.py +++ b/build/linux/sysroot_scripts/reversion_glibc.py
@@ -11,6 +11,9 @@ # //chrome/installer/linux/debian/dist_package_versions.json and # //chrome/installer/linux/rpm/dist_package_provides.json MAX_ALLOWED_GLIBC_VERSION = [2, 26] +MAX_ALLOWED_GLIBC_VERSION_ARCH = { + "riscv64": [2, 33], +} VERSION_PATTERN = re.compile("GLIBC_([0-9\.]+)") SECTION_PATTERN = re.compile(r"^ *\[ *[0-9]+\] +(\S+) +\S+ + ([0-9a-f]+) .*$") @@ -25,7 +28,9 @@ } -def reversion_glibc(bin_file: str) -> None: +def reversion_glibc(bin_file: str, arch: str) -> None: + max_allowed_glibc_version = MAX_ALLOWED_GLIBC_VERSION_ARCH.get( + arch, MAX_ALLOWED_GLIBC_VERSION) # The two dictionaries below map from symbol name to # (symbol version, symbol index). # @@ -77,7 +82,7 @@ continue version = [int(part) for part in match.group(1).split(".")] - if version < MAX_ALLOWED_GLIBC_VERSION: + if version < max_allowed_glibc_version: old_supported_version = supported_version.get( base_name, ([-1], -1)) supported_version[base_name] = max((version, index), @@ -101,7 +106,7 @@ bin_data = bytearray(open(bin_file, "rb").read()) for name, (version, index) in default_version.items(): # No need to rewrite the default if it's already an allowed version. - if version <= MAX_ALLOWED_GLIBC_VERSION: + if version <= max_allowed_glibc_version: continue if name in SYMBOL_ALLOWLIST:
diff --git a/build/linux/sysroot_scripts/sysroot_creator.py b/build/linux/sysroot_scripts/sysroot_creator.py index f67c275..128063c8 100755 --- a/build/linux/sysroot_scripts/sysroot_creator.py +++ b/build/linux/sysroot_scripts/sysroot_creator.py
@@ -21,7 +21,22 @@ import reversion_glibc DISTRO = "debian" -RELEASE = "bullseye" +RELEASES = { + "amd64": "bullseye", + "i386": "bullseye", + "armhf": "bullseye", + "arm64": "bullseye", + "mipsel": "bullseye", + "mips64el": "bullseye", + "ppc64el": "bullseye", + "riscv64": "trixie", +} + +GCC_VERSIONS = { + "bullseye": 10, + "trixie": 12, +} + # This number is appended to the sysroot key to cause full rebuilds. It # should be incremented when removing packages or patching existing packages. @@ -31,7 +46,6 @@ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) CHROME_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..", "..")) -BUILD_DIR = os.path.join(CHROME_DIR, "out", "sysroot-build", RELEASE) # gpg keyring file generated using generate_keyring.sh KEYRING_FILE = os.path.join(SCRIPT_DIR, "keyring.gpg") @@ -49,6 +63,17 @@ ("bullseye-updates", ["main", "contrib", "non-free"]), ("bullseye-backports", ["main", "contrib", "non-free"]), ] +APT_SOURCES_LIST_RISCV = [("trixie", ["main", "contrib"])] +APT_SOURCES_LISTS = { + "amd64": APT_SOURCES_LIST, + "i386": APT_SOURCES_LIST, + "armhf": APT_SOURCES_LIST, + "arm64": APT_SOURCES_LIST, + "mipsel": APT_SOURCES_LIST, + "mips64el": APT_SOURCES_LIST, + "ppc64el": APT_SOURCES_LIST, + "riscv64": APT_SOURCES_LIST_RISCV, +} TRIPLES = { "amd64": "x86_64-linux-gnu", @@ -58,6 +83,12 @@ "mipsel": "mipsel-linux-gnu", "mips64el": "mips64el-linux-gnuabi64", "ppc64el": "powerpc64le-linux-gnu", + "riscv64": "riscv64-linux-gnu", +} + +LIB_DIRS = { + "bullseye": "lib", + "trixie": "usr/lib", } REQUIRED_TOOLS = [ @@ -137,7 +168,7 @@ "mesa-common-dev", "qt6-base-dev", "qtbase5-dev", - "valgrind", + "valgrind-if-available", ] @@ -229,15 +260,15 @@ raise Exception(f"Failed to download file after {retries} attempts") -def sanity_check() -> None: +def sanity_check(build_dir: str) -> None: """ Performs sanity checks to ensure the environment is correctly set up. """ banner("Sanity Checks") # Determine the Chrome build directory - os.makedirs(BUILD_DIR, exist_ok=True) - print(f"Using build directory: {BUILD_DIR}") + os.makedirs(build_dir, exist_ok=True) + print(f"Using build directory: {build_dir}") # Check for required tools missing = [tool for tool in REQUIRED_TOOLS if not shutil.which(tool)] @@ -251,9 +282,9 @@ os.makedirs(install_root) -def create_tarball(install_root: str, arch: str) -> None: - tarball_path = os.path.join(BUILD_DIR, - f"{DISTRO}_{RELEASE}_{arch}_sysroot.tar.xz") +def create_tarball(install_root: str, arch: str, build_dir: str) -> None: + tarball_path = os.path.join( + build_dir, f"{DISTRO}_{RELEASES[arch]}_{arch}_sysroot.tar.xz") banner("Creating tarball " + tarball_path) command = [ "tar", @@ -273,16 +304,16 @@ subprocess.run(command, check=True) -def generate_package_list_dist_repo(arch: str, dist: str, - repo_name: str) -> list[dict[str, str]]: +def generate_package_list_dist_repo(arch: str, dist: str, repo_name: str, + build_dir: str) -> list[dict[str, str]]: repo_basedir = f"{ARCHIVE_URL}/dists/{dist}" - package_list = f"{BUILD_DIR}/Packages.{dist}_{repo_name}_{arch}" + package_list = f"{build_dir}/Packages.{dist}_{repo_name}_{arch}" package_list = f"{package_list}.{PACKAGES_EXT}" package_file_arch = f"{repo_name}/binary-{arch}/Packages.{PACKAGES_EXT}" package_list_arch = f"{repo_basedir}/{package_file_arch}" download_or_copy_non_unique_filename(package_list_arch, package_list) - verify_package_listing(package_file_arch, package_list, dist) + verify_package_listing(package_file_arch, package_list, dist, build_dir) with lzma.open(package_list, "rt") as src: return [ @@ -293,21 +324,26 @@ ] -def generate_package_list(arch: str) -> dict[str, str]: +def generate_package_list(arch: str, build_dir: str) -> dict[str, str]: # Workaround for some misconfigured package dependencies. BROKEN_DEPS = { "libgcc1", "qt6-base-abi", + "libc-dev", # pulls in a newer libc6-dev } package_meta = {} - for dist, repos in APT_SOURCES_LIST: + sources = APT_SOURCES_LISTS[arch] + for dist, repos in sources: for repo_name in repos: - for meta in generate_package_list_dist_repo(arch, dist, repo_name): + for meta in generate_package_list_dist_repo( + arch, dist, repo_name, build_dir): package_meta[meta["Package"]] = meta if "Provides" not in meta: continue for provides in meta["Provides"].split(", "): + # Strip version requirements + provides = provides.split()[0] if provides in package_meta: continue package_meta[provides] = meta @@ -327,9 +363,10 @@ # Read the input file and create a dictionary mapping package names to URLs # and checksums. missing = set(DEBIAN_PACKAGES) + # Add corresponding libstdc++-dev package (needed for trixie) + missing.add(f"libstdc++-{GCC_VERSIONS[RELEASES[arch]]}-dev") package_dict: dict[str, str] = {} - for meta in package_meta.values(): - package = meta["Package"] + for package in package_meta: if package in missing: missing.remove(package) add_package_dependencies(package) @@ -338,7 +375,7 @@ # Write the URLs and checksums of the requested packages to the output file output_file = os.path.join(SCRIPT_DIR, "generated_package_lists", - f"{RELEASE}.{arch}") + f"{RELEASES[arch]}.{arch}") with open(output_file, "w") as f: f.write("\n".join(sorted(package_dict)) + "\n") return package_dict @@ -370,6 +407,10 @@ features_h = os.path.join(install_root, "usr", "include", "features.h") replace_in_file(features_h, r"(#define\s+__GLIBC_MINOR__)", r"\1 26 //") + # C23 STRTOL requires glibc >= 2.38 + replace_in_file(features_h, r"(#\s?define\s+__GLIBC_USE_C23_STRTOL)", + r"\1 0 //") + # fcntl64() was introduced in glibc 2.28. Make sure to use fcntl() instead. fcntl_h = os.path.join(install_root, "usr", "include", "fcntl.h") replace_in_file( @@ -385,7 +426,7 @@ "include", TRIPLES[arch], "c++", - "10", + str(GCC_VERSIONS[RELEASES[arch]]), "bits", "c++config.h", ) @@ -411,7 +452,7 @@ # Avoid requiring unsupported glibc versions. for lib in ["libc.so.6", "libm.so.6", "libcrypt.so.1"]: lib_path = os.path.join(install_root, "lib", TRIPLES[arch], lib) - reversion_glibc.reversion_glibc(lib_path) + reversion_glibc.reversion_glibc(lib_path, arch) # GTK4 is provided by bookworm (12), but pango is provided by bullseye # (11). Fix the GTK4 pkgconfig file to relax the pango version @@ -424,6 +465,16 @@ os.remove(os.path.join(install_root, "usr/bin/X11")) +def create_extra_symlinks(install_root: str, arch: str): + if RELEASES[arch] != "bullseye": + # Recent debian releases no longer symlink lib{dl,pthread,rt}.so + for lib in ["libdl.so.2", "librt.so.1", "libpthread.so.0"]: + os.symlink( + lib, + os.path.join(install_root, "lib", TRIPLES[arch], + lib.rpartition(".")[0])) + + def replace_in_file(file_path: str, search_pattern: str, replace_pattern: str) -> None: with open(file_path, "r") as file: @@ -549,15 +600,17 @@ """ # Preserve these files. gcc_triple = "i686-linux-gnu" if arch == "i386" else TRIPLES[arch] + gcc_version = GCC_VERSIONS[RELEASES[arch]] ALLOWLIST = { "usr/bin/cups-config", - f"usr/lib/gcc/{gcc_triple}/10/libgcc.a", + f"usr/lib/gcc/{gcc_triple}/{gcc_version}/libgcc.a", f"usr/lib/{TRIPLES[arch]}/libc_nonshared.a", f"usr/lib/{TRIPLES[arch]}/libffi_pic.a", } for file in ALLOWLIST: - assert os.path.exists(os.path.join(install_root, file)) + assert os.path.exists(os.path.join(install_root, + file)), f"{file} does not exist" # Remove all executables and static libraries, and any symlinks that # were pointing to them. @@ -590,9 +643,11 @@ few files used by other Chromium-related projects. """ PRESERVED_FILES = ( - 'libc-2.31.so', - 'libm-2.31.so', - 'ld-2.31.so', + # Old debian(bullseye) has ld-2.31.so, + # while in trixie, it is ld-linux-$ARCH.so.2 + r'(libc\.so\.\d)|(libc-\d.\d\d\.so)', + r'(libm\.so\.\d)|(libm-\d.\d\d\.so)', + r'(ld-linux.*\.so\.\d)|(ld-\d.\d\d\.so)', ) PRESERVED_SECTIONS = { @@ -608,13 +663,17 @@ } preserved_files_count = 0 - lib_arch_path = os.path.join(install_root, "lib", TRIPLES[arch]) + lib_dir = LIB_DIRS[RELEASES[arch]] + lib_arch_path = os.path.join(install_root, lib_dir, TRIPLES[arch]) for root, _, files in os.walk(install_root): for file in files: file_path = os.path.join(root, file) - if file_path.startswith(lib_arch_path) and file in PRESERVED_FILES: - preserved_files_count += 1 - continue + if file_path.startswith(lib_arch_path): + for preserved in PRESERVED_FILES: + if re.match(preserved, + file) and not os.path.islink(file_path): + preserved_files_count += 1 + continue if (os.access(file, os.X_OK) or file.endswith((".a", ".o")) or os.path.islink(file_path)): @@ -651,7 +710,9 @@ ] + [file_path]) subprocess.run(objcopy_cmd, check=True, stderr=subprocess.PIPE) if preserved_files_count != len(PRESERVED_FILES): - raise Exception("Expected file to preserve missing") + raise Exception( + f"Expected file(s) to preserve missing, preserved " + + f"{preserved_files_count}, expected {len(PRESERVED_FILES)}") def record_metadata(install_root: str) -> dict[str, tuple[float, float]]: @@ -700,23 +761,24 @@ os.utime(file_path, restore_time, follow_symlinks=False) -def build_sysroot(arch: str) -> None: - install_root = os.path.join(BUILD_DIR, f"{RELEASE}_{arch}_staging") +def build_sysroot(arch: str, build_dir: str) -> None: + install_root = os.path.join(build_dir, f"{RELEASES[arch]}_{arch}_staging") clear_install_dir(install_root) - packages = generate_package_list(arch) - install_into_sysroot(BUILD_DIR, install_root, packages) + packages = generate_package_list(arch, build_dir) + install_into_sysroot(build_dir, install_root, packages) old_metadata = record_metadata(install_root) hacks_and_patches(install_root, SCRIPT_DIR, arch) + create_extra_symlinks(install_root, arch) cleanup_jail_symlinks(install_root) removing_unnecessary_files(install_root, arch) strip_sections(install_root, arch) restore_metadata(install_root, old_metadata) - create_tarball(install_root, arch) + create_tarball(install_root, arch, build_dir) -def upload_sysroot(arch: str) -> str: - tarball_path = os.path.join(BUILD_DIR, - f"{DISTRO}_{RELEASE}_{arch}_sysroot.tar.xz") +def upload_sysroot(arch: str, build_dir: str) -> str: + tarball_path = os.path.join( + build_dir, f"{DISTRO}_{RELEASES[arch]}_{arch}_sysroot.tar.xz") command = [ "upload_to_google_storage_first_class.py", "--bucket", @@ -726,8 +788,8 @@ return subprocess.check_output(command).decode("utf-8") -def verify_package_listing(file_path: str, output_file: str, - dist: str) -> None: +def verify_package_listing(file_path: str, output_file: str, dist: str, + build_dir: str) -> None: """ Verifies the downloaded Packages.xz file against its checksum and GPG keys. """ @@ -736,8 +798,8 @@ release_list = f"{repo_basedir}/{RELEASE_FILE}" release_list_gpg = f"{repo_basedir}/{RELEASE_FILE_GPG}" - release_file = os.path.join(BUILD_DIR, f"{dist}-{RELEASE_FILE}") - release_file_gpg = os.path.join(BUILD_DIR, f"{dist}-{RELEASE_FILE_GPG}") + release_file = os.path.join(build_dir, f"{dist}-{RELEASE_FILE}") + release_file_gpg = os.path.join(build_dir, f"{dist}-{RELEASE_FILE_GPG}") if not os.path.exists(KEYRING_FILE): raise Exception(f"KEYRING_FILE not found: {KEYRING_FILE}") @@ -775,13 +837,15 @@ parser.add_argument("command", choices=["build", "upload"]) parser.add_argument("architecture", choices=list(TRIPLES)) args = parser.parse_args() + build_dir = os.path.join(CHROME_DIR, "out", "sysroot-build", + RELEASES[args.architecture]) - sanity_check() + sanity_check(build_dir) if args.command == "build": - build_sysroot(args.architecture) + build_sysroot(args.architecture, build_dir) elif args.command == "upload": - upload_sysroot(args.architecture) + upload_sysroot(args.architecture, build_dir) if __name__ == "__main__":
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java index 5b49b66..c7938f4 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java
@@ -11,6 +11,7 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import org.chromium.base.metrics.RecordUserAction; import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.R; import org.chromium.chrome.browser.tab.TabArchiveSettings; @@ -174,6 +175,12 @@ mTabArchiveSettings.setAutoDeleteEnabled(!disableAutoDeleteFeature); mTabArchiveSettings.setAutoDeleteDecisionMade(true); + if (disableAutoDeleteFeature) { + RecordUserAction.record("Tabs.ArchivedTabAutoDeletePromo.No"); + } else { + RecordUserAction.record("Tabs.ArchivedTabAutoDeletePromo.Yes"); + } + cleanupSheetResourcesOnly(); }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java index 7a9d07f..471db77e 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java
@@ -225,7 +225,7 @@ tabSwitcherStation = pageStation.openRegularTabSwitcher(); - mRenderTestRule.render(cta.findViewById(R.id.pane_frame), "3_native_tabs"); + mRenderTestRule.render(cta.findViewById(R.id.pane_frame), "3_native_tabs_v2"); RegularNewTabPageStation previousPage = tabSwitcherStation.leaveHubToPreviousTabViaBack(
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java index ffaa29bf..f6c1ee1 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java
@@ -70,6 +70,7 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.feed.sections.SectionHeaderListProperties; @@ -435,9 +436,14 @@ onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed())); } + // The three-dot button in the feed's header is removed by the `NewTabPageCustomization` + // feature. Disabling this feature flag ensures the current test continues to validate the + // three-dot button's functionality. + // TODO(crbug.com/376238770): Removes this test once the feature flag turns on by default. @Test @MediumTest @Feature({"NewTabPage", "FeedNewTabPage"}) + @DisableFeatures("NewTabPageCustomization") @ParameterAnnotations.UseMethodParameter(SigninPromoParams.class) public void testArticleSectionHeaderWithMenu(boolean disableSigninPromoCard) throws Exception { openNewTabPage();
diff --git a/chrome/android/java/res/layout/contextual_search_related_searches_view.xml b/chrome/android/java/res/layout/contextual_search_related_searches_view.xml index ff38d4f..690f590 100644 --- a/chrome/android/java/res/layout/contextual_search_related_searches_view.xml +++ b/chrome/android/java/res/layout/contextual_search_related_searches_view.xml
@@ -16,7 +16,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@macro/overlay_panel_bar_background_color" - android:layout_marginBottom="@dimen/toolbar_progress_bar_height" android:layout_gravity="top"> <!-- ChipView elements and their container are dynamically added here. --> </org.chromium.chrome.browser.compositor.bottombar.contextualsearch.NoSystemGestureFrameLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java index d5590ce..aeaa0b1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.RelatedSearchesSectionHost; import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma; import org.chromium.chrome.browser.contextualsearch.RelatedSearchesUma; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.components.browser_ui.widget.chips.ChipProperties; import org.chromium.components.browser_ui.widget.chips.ChipsCoordinator; import org.chromium.ui.base.LocalizationUtils; @@ -555,6 +556,29 @@ if (newState == RecyclerView.SCROLL_STATE_IDLE) invalidate(false); } }); + setBottomMargin(); + } + + /** + * Sets the bottom margin of the control view. + */ + private void setBottomMargin() { + View controlView = getControlView(); + if (controlView == null) return; + + ViewGroup.MarginLayoutParams params = + (ViewGroup.MarginLayoutParams) controlView.getLayoutParams(); + if (ChromeFeatureList.sAndroidProgressBarVisualUpdate.isEnabled()) { + params.bottomMargin = + mContext.getResources() + .getDimensionPixelSize( + R.dimen.toolbar_progress_bar_increased_height); + } else { + params.bottomMargin = + mContext.getResources() + .getDimensionPixelSize(R.dimen.toolbar_progress_bar_height); + } + controlView.setLayoutParams(params); } /** @@ -599,6 +623,8 @@ ViewGroup parent = (ViewGroup) coordinatorView.getParent(); if (parent != null) parent.removeView(coordinatorView); relatedSearchesViewGroup.addView(coordinatorView); + // Ensure the bottom margin is correctly set after view updates. + setBottomMargin(); invalidate(false); // Log carousel visible item position
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index cc95f7a..1c0bd28 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -1203,6 +1203,14 @@ if (IntentUtils.safeHasExtra(intent, EXTRA_OPEN_IN_BROWSER_STATE)) { featureUsage.log(CustomTabsFeature.EXTRA_OPEN_IN_BROWSER_STATE); } + if (IntentUtils.safeHasExtra( + intent, TrustedWebActivityIntentBuilder.EXTRA_LAUNCH_HANDLER_CLIENT_MODE)) { + featureUsage.log(CustomTabsFeature.EXTRA_LAUNCH_HANDLER); + } + if (IntentUtils.safeHasExtra( + intent, TrustedWebActivityIntentBuilder.EXTRA_FILE_HANDLING_DATA)) { + featureUsage.log(CustomTabsFeature.EXTRA_FILE_HANDLERS); + } } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java index 2f228f8..c573772 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java
@@ -22,6 +22,7 @@ // NOTE: This must be kept in sync with the definition |CustomTabsFeatureUsed| // in tools/metrics/histograms/enums.xml. + // LINT.IfChange(CustomTabsFeature) @IntDef({ CustomTabsFeature.CTF_SESSIONS, CustomTabsFeature.EXTRA_ACTION_BUTTON_BUNDLE, @@ -86,6 +87,8 @@ CustomTabsFeature.EXTRA_HTTPS_REDIRECT_HOST, CustomTabsFeature.EXTRA_HTTPS_REDIRECT_PATH, CustomTabsFeature.EXTRA_OPEN_IN_BROWSER_STATE, + CustomTabsFeature.EXTRA_LAUNCH_HANDLER, + CustomTabsFeature.EXTRA_FILE_HANDLERS, CustomTabsFeature.COUNT }) @Retention(RetentionPolicy.SOURCE) @@ -155,11 +158,15 @@ int EXTRA_HTTPS_REDIRECT_HOST = 61; int EXTRA_HTTPS_REDIRECT_PATH = 62; int EXTRA_OPEN_IN_BROWSER_STATE = 63; + int EXTRA_LAUNCH_HANDLER = 64; + int EXTRA_FILE_HANDLERS = 65; /** Total count of entries. */ - int COUNT = 64; + int COUNT = 66; } + // LINT.ThenChange(/tools/metrics/histograms/metadata/custom_tabs/enums.xml:CustomTabsFeatureUsed) + /** Tracks whether we have written each enum or not. */ private final BitSet mUsed = new BitSet(CustomTabsFeature.COUNT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java index cef136f..7fcb596d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java
@@ -6,12 +6,14 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.omnibox.ChromeAutocompleteSchemeClassifier; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.omnibox.AutocompleteSchemeClassifier; import org.chromium.components.permissions.BluetoothChooserAndroidDelegate; /** The implementation of {@link BluetoothChooserAndroidDelegate} for Chrome. */ +@NullMarked public class ChromeBluetoothChooserAndroidDelegate implements BluetoothChooserAndroidDelegate { private final Profile mProfile;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothScanningPromptAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothScanningPromptAndroidDelegate.java index 8ef85d9..96052be0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothScanningPromptAndroidDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothScanningPromptAndroidDelegate.java
@@ -6,12 +6,14 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.omnibox.ChromeAutocompleteSchemeClassifier; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.omnibox.AutocompleteSchemeClassifier; import org.chromium.components.permissions.BluetoothScanningPromptAndroidDelegate; /** The implementation of {@link BluetoothScanningPromptAndroidDelegate} for Chrome. */ +@NullMarked public class ChromeBluetoothScanningPromptAndroidDelegate implements BluetoothScanningPromptAndroidDelegate {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/SerialChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/SerialChooserDialog.java index e9ae16a..6617d85 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/SerialChooserDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/SerialChooserDialog.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.device_dialog; +import static org.chromium.build.NullUtil.assertNonNull; + import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.content.BroadcastReceiver; @@ -23,6 +25,9 @@ import org.jni_zero.NativeMethods; import org.chromium.base.ContextUtils; +import org.chromium.build.annotations.Initializer; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.ChromeAutocompleteSchemeClassifier; import org.chromium.chrome.browser.profiles.Profile; @@ -44,6 +49,7 @@ * A dialog for showing available serial devices. This dialog is shown when a website requests to * connect to a serial device (e.g. through a serial.requestPort Javascript call). */ +@NullMarked public class SerialChooserDialog implements ItemChooserDialog.ItemSelectedCallback, PermissionCallback { @@ -66,7 +72,7 @@ private final Profile mProfile; /** Help text to show when the Bluetooth adapter is off. */ - private SpannableString mAdapterOffStatus; + private @Nullable SpannableString mAdapterOffStatus; // Used to keep track of when the Mode Changed Receiver is registered. boolean mIsLocationModeChangedReceiverRegistered; @@ -113,8 +119,7 @@ SerialChooserDialog( WindowAndroid windowAndroid, long nativeSerialChooserDialogPtr, Profile profile) { mWindowAndroid = windowAndroid; - mContext = mWindowAndroid.getContext().get(); - assert mContext != null; + mContext = assertNonNull(mWindowAndroid.getContext().get()); mNativeSerialChooserDialogPtr = nativeSerialChooserDialogPtr; mProfile = profile; } @@ -128,6 +133,7 @@ * the serial port. For valid values see SecurityStateModel::SecurityLevel. */ @VisibleForTesting + @Initializer void show(Activity activity, String origin, int securityLevel) { // Emphasize the origin. SpannableString originSpannableString = new SpannableString(origin); @@ -308,7 +314,8 @@ } else { String unableToTurnOnAdapter = mContext.getString(R.string.bluetooth_unable_to_turn_on_adapter); - mItemChooserDialog.setErrorState(unableToTurnOnAdapter, mAdapterOffStatus); + mItemChooserDialog.setErrorState( + unableToTurnOnAdapter, assertNonNull(mAdapterOffStatus)); } break; } @@ -337,7 +344,7 @@ @CalledByNative @VisibleForTesting - static SerialChooserDialog create( + static @Nullable SerialChooserDialog create( WindowAndroid windowAndroid, @JniType("std::u16string") String origin, int securityLevel,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialog.java index 1b9e574..e8b5653 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialog.java
@@ -14,6 +14,9 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.Initializer; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.ChromeAutocompleteSchemeClassifier; import org.chromium.chrome.browser.profiles.Profile; @@ -30,6 +33,7 @@ * A dialog for showing available USB devices. This dialog is shown when a website requests to * connect to a USB device (e.g. through a usb.requestDevice Javascript call). */ +@NullMarked public class UsbChooserDialog implements ItemChooserDialog.ItemSelectedCallback { /** The dialog to show to let the user pick a device. */ ItemChooserDialog mItemChooserDialog; @@ -56,6 +60,7 @@ * the USB device. For valid values see SecurityStateModel::SecurityLevel. */ @VisibleForTesting + @Initializer void show(Activity activity, String origin, int securityLevel) { // Emphasize the origin. SpannableString originSpannableString = new SpannableString(origin); @@ -133,7 +138,7 @@ @CalledByNative @VisibleForTesting - static UsbChooserDialog create( + static @Nullable UsbChooserDialog create( WindowAndroid windowAndroid, @JniType("std::u16string") String origin, int securityLevel,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java index 145f89d..8c603b5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.feed.SnapScrollHelper; +import org.chromium.chrome.browser.flags.ChromeFeatureList; /** This class handles snap scroll for the search box on a {@link NewTabPage}. */ public class SnapScrollHelperImpl implements SnapScrollHelper { @@ -43,9 +44,14 @@ mUpdateSearchBoxOnScrollRunnable = mNewTabPageLayout::updateSearchBoxOnScroll; Resources res = newTabPageLayout.getResources(); - mToolbarHeight = - res.getDimensionPixelSize(R.dimen.toolbar_height_no_shadow) - + res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_height); + if (ChromeFeatureList.sAndroidProgressBarVisualUpdate.isEnabled()) { + mToolbarHeight = res.getDimensionPixelSize(R.dimen.toolbar_height_no_shadow) + + res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_increased_height); + } else { + mToolbarHeight = + res.getDimensionPixelSize(R.dimen.toolbar_height_no_shadow) + + res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_height); + } mSearchBoxTransitionStartOffset = res.getDimensionPixelSize(R.dimen.ntp_search_box_transition_start_offset); mSearchBoxTransitionEndOffset =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 1bb7dca..f929200 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1039,6 +1039,13 @@ mToolbarLongPressMenuHandler.getOnLongClickListener(); ViewStub progressBarStub = mActivity.findViewById(R.id.progress_bar_stub); + if (ChromeFeatureList.sAndroidProgressBarVisualUpdate.isEnabled()) { + ViewGroup.LayoutParams progressBarParams = progressBarStub.getLayoutParams(); + progressBarParams.height = mActivity.getResources().getDimensionPixelSize( + R.dimen.toolbar_progress_bar_increased_height); + progressBarStub.setLayoutParams(progressBarParams); + } + mProgressBarContainer = progressBarStub.inflate(); ToolbarProgressBar progressBar = mProgressBarContainer.findViewById(R.id.toolbar_progress_bar);
diff --git a/chrome/android/javatests/BUILD.gn b/chrome/android/javatests/BUILD.gn index cb95919..7823e113 100644 --- a/chrome/android/javatests/BUILD.gn +++ b/chrome/android/javatests/BUILD.gn
@@ -529,6 +529,7 @@ "src/org/chromium/chrome/browser/app/bookmarks/ReadingListTest.java", "src/org/chromium/chrome/browser/app/edge_to_edge/EdgeToEdgeInstrumentationTest.java", "src/org/chromium/chrome/browser/app/edge_to_edge/EdgeToEdgePTTest.java", + "src/org/chromium/chrome/browser/app/edge_to_edge/EdgeToEdgeStartupTest.java", "src/org/chromium/chrome/browser/app/flags/ChromeCachedFlagsTest.java", "src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetricsTest.java", "src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuPTTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuPTTest.java index 8054b06..7b9ee2e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuPTTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuPTTest.java
@@ -112,7 +112,7 @@ RegularNewTabPageStation newTabPage = blankPage.openRegularTabAppMenu().openNewTab(); RegularNewTabPageAppMenuFacility menu = newTabPage.openAppMenu(); - mRenderTestRule.render(menu.menuListElement.get(), "regular_ntp_app_menu"); + mRenderTestRule.render(menu.menuListElement.get(), "regular_ntp_app_menu_v3"); menu.verifyPresentItems(); assertFinalDestination(newTabPage, menu); @@ -151,7 +151,7 @@ WebPageStation blankPage = mCtaTestRule.startOnBlankPage(); RegularWebPageAppMenuFacility menu = blankPage.openRegularTabAppMenu(); - mRenderTestRule.render(menu.menuListElement.get(), "regular_webpage_app_menu"); + mRenderTestRule.render(menu.menuListElement.get(), "regular_webpage_app_menu_v2"); menu.verifyPresentItems(); assertFinalDestination(blankPage, menu);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/edge_to_edge/EdgeToEdgeStartupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/edge_to_edge/EdgeToEdgeStartupTest.java new file mode 100644 index 0000000..3a9b687 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/edge_to_edge/EdgeToEdgeStartupTest.java
@@ -0,0 +1,78 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.app.edge_to_edge; + +import static org.junit.Assert.assertNull; + +import android.os.Build.VERSION_CODES; + +import androidx.test.filters.LargeTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DoNotBatch; +import org.chromium.base.test.util.Features.EnableFeatures; +import org.chromium.base.test.util.MinAndroidSdkLevel; +import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController; +import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeUtils; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.transit.ChromeTransitTestRules; +import org.chromium.chrome.test.transit.FreshCtaTransitTestRule; +import org.chromium.chrome.test.transit.edge_to_edge.EdgeToEdgeBottomChinFacility; +import org.chromium.ui.base.DeviceFormFactor; +import org.chromium.ui.test.util.DeviceRestriction; + +/** Test looking to test startup behavior for edge to edge. */ +@RunWith(ChromeJUnit4ClassRunner.class) +@DoNotBatch(reason = "This test interacts with startup and native initialization") +@CommandLineFlags.Add({ + ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + ChromeSwitches.DISABLE_MINIMUM_SHOW_DURATION +}) +@EnableFeatures({ + ChromeFeatureList.EDGE_TO_EDGE_BOTTOM_CHIN, + ChromeFeatureList.EDGE_TO_EDGE_MONITOR_CONFIGURATIONS +}) +// Bots <= VERSION_CODES.S use 3-bottom nav bar. See crbug.com/352402600 +@MinAndroidSdkLevel(VERSION_CODES.S_V2) +@Restriction({DeviceFormFactor.PHONE, DeviceRestriction.RESTRICTION_TYPE_NON_AUTO}) +public class EdgeToEdgeStartupTest { + + @Rule + public FreshCtaTransitTestRule mActivityTestRule = + ChromeTransitTestRules.freshChromeTabbedActivityRule(); + + @Before + public void setup() { + EdgeToEdgeUtils.setObservedTappableNavigationBarForTesting(false); + } + + @Test + @LargeTest + public void testStartOnNewPage() { + mActivityTestRule + .startOnBlankPage() + .enterFacilitySync(new EdgeToEdgeBottomChinFacility<>(false), null); + + // Hop off, and assume invalid insets came in. + EdgeToEdgeUtils.setObservedTappableNavigationBarForTesting(true); + + mActivityTestRule.recreateActivity(); + mActivityTestRule.waitForActivityNativeInitializationComplete(); + + EdgeToEdgeController controller = + mActivityTestRule.getActivity().getEdgeToEdgeControllerSupplierForTesting().get(); + assertNull( + "Edge to edge should no longer recreate after seeing tappable insets.", + controller); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 9d94b59..e3542e2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -265,7 +265,7 @@ waitForView((ViewGroup) mNtp.getView(), allOf(withId(R.id.header_title), isDisplayed())); View view = mNtp.getCoordinatorForTesting().getHeaderViewForTesting(); // Check header is expanded. - mRenderTestRule.render(view, "expandable_header_expanded"); + mRenderTestRule.render(view, "expandable_header_expanded_v2"); // Toggle header on the current tab. onView(withId(R.id.feed_stream_recycler_view)) @@ -273,7 +273,7 @@ waitForView((ViewGroup) mNtp.getView(), allOf(withId(R.id.header_title), isDisplayed())); onView(withId(R.id.header_title)).perform(click()); // Check header is collapsed. - mRenderTestRule.render(view, "expandable_header_collapsed_v2"); + mRenderTestRule.render(view, "expandable_header_collapsed_v3"); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java index e37782d..e7f1ec0d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -789,6 +789,8 @@ * Verifies that when the feature flag is enabled, the PREF_HOME_MODULES_CONFIG is removed from * the settings page. */ + // TODO(crbug.com/376238770): Remove @EnableFeatures once the feature flag is turned on by + // default. @Test @SmallTest @EnableFeatures(ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION) @@ -800,11 +802,13 @@ } /** - * Verifies that when the feature flag is disabled by default, the PREF_HOME_MODULES_CONFIG is - * removed from the settings page, only if hasModuleShownInSettings returns false. + * Verifies that when the feature flag is turned off, the PREF_HOME_MODULES_CONFIG is removed + * from the settings page, only if hasModuleShownInSettings returns false. */ + // TODO(crbug.com/376238770): Removes this test when the feature flag is turned on by default. @Test @SmallTest + @DisableFeatures("NewTabPageCustomization") public void testHomeModulesConfigSettingsWithCustomizableModuleWhileFeatureTurnOff() { when(mHomeModulesConfigManager.hasModuleShownInSettings()).thenReturn(true); HomeModulesConfigManager.setInstanceForTesting(mHomeModulesConfigManager);
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 e7dce32..751c1fa 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
@@ -135,9 +135,13 @@ import java.util.List; /** Unit tests for {@link TabbedAppMenuPropertiesDelegate}. */ +// TODO(crbug.com/376238770): Removes ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION from +// @DisableFeatures() and adds "Customize New Tab Page" to all expectedItems list once the feature +// flag is turned on by default. @RunWith(BaseRobolectricTestRunner.class) @DisableFeatures({ ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_PAGE_SUMMARY, + ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION, DomDistillerFeatures.READER_MODE_IMPROVEMENTS }) public class TabbedAppMenuPropertiesDelegateUnitTest {
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index 82f18d52..8dc9481 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -1027,18 +1027,6 @@ <message name="IDS_ENTERPRISE_SIGNIN_EXPLANATION_WITH_PROFILE_CREATION" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. Additionally notifies the user that they can create a new profile instead. This message is followed by a 'Learn more' link."> You are signing in with a managed account and giving its administrator control over your Chromium profile. Your Chromium data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to <ph name="USER_NAME">$1<ex>pat@example.com</ex></ph>. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. You can optionally create a new profile to keep your existing Chromium data separate. <ph name="LEARN_MORE">$2<ex>Learn more</ex></ph> </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE" desc="The title of the dialog to confirm adding a new work profile with the signed-in enterprise account"> - Add Work Profile to this browser - </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. This message is followed by a 'Learn more' link."> - You are adding a work profile to this browser and giving your administrator control over just the work profile. - </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE" desc="Notice that work profiles are separated from any personal profile"> - This work profile is completely separate from your personal profile. - </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. This message is followed by a 'Learn more' link."> - Any Chromium data that is generated during the use of this profile (such as the creation of bookmarks, history, passwords, and other settings) can be removed by the work profile administrator. <ph name="LEARN_MORE">$1<ex>Learn more</ex></ph> - </message> <message name="IDS_ENTERPRISE_VALUE_PROPOSITION_PROFILE_REQUIRED_BY_ORG_KNOWN_DOMAIN_TITLE" desc="Title of the screen in the profile creation flow where the user is asked whether they want to confirm signing in to Chromium with their enterprise account when it is mandatory to sign in to Chromium with the enterprise account."> Your organization, <ph name="MANAGER">$1<ex>manager.com</ex></ph>, requires you to sign into Chromium </message>
diff --git a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION.png.sha1 b/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION.png.sha1 deleted file mode 100644 index 9290a470..0000000 --- a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -71c8aeff18ba65c4d376e9a462e1c4d4674f1702 \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION.png.sha1 b/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION.png.sha1 deleted file mode 100644 index 9290a470..0000000 --- a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -71c8aeff18ba65c4d376e9a462e1c4d4674f1702 \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE.png.sha1 b/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE.png.sha1 deleted file mode 100644 index 9290a470..0000000 --- a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -71c8aeff18ba65c4d376e9a462e1c4d4674f1702 \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE.png.sha1 b/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE.png.sha1 deleted file mode 100644 index 9290a470..0000000 --- a/chrome/app/chromium_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -71c8aeff18ba65c4d376e9a462e1c4d4674f1702 \ No newline at end of file
diff --git a/chrome/app/extensions_strings.grdp b/chrome/app/extensions_strings.grdp index 7da108b9..6393496 100644 --- a/chrome/app/extensions_strings.grdp +++ b/chrome/app/extensions_strings.grdp
@@ -724,6 +724,9 @@ <message name="IDS_EXTENSIONS_ZERO_STATE_CHIPS_IPH_DESCRIPTION" desc="An one line description for the extensions zero state in-product-help promo."> Extensions are add-ons for Chrome that can help you do more </message> + <message name="IDS_EXTENSIONS_ZERO_STATE_PLAIN_LINK_IPH_DESCRIPTION" desc="An one line description for the extensions zero state in-product-help promo."> + Extensions are add-ons to Chrome that can help you + </message> <message name="IDS_EXTENSIONS_ZERO_STATE_IPH_SHOPPING_CATEGORY_LABEL" desc="Label for the button that opens the Chrome Web Store shopping category page."> Find coupons </message> @@ -739,5 +742,20 @@ <message name="IDS_EXTENSIONS_ZERO_STATE_IPH_DISMISS_BUTTON_TITLE" desc="Title attribute for the button that dismisses the extensions zero state in-product-help promo."> Close </message> + <message name="IDS_EXTENSIONS_ZERO_STATE_IPH_SHOPPING_CATEGORY_LINK" desc="Link text for the button that opens the Chrome Web Store shopping category page."> + Find coupons + </message> + <message name="IDS_EXTENSIONS_ZERO_STATE_IPH_WRITING_HELP_COLLECTION_LINK" desc="Link text for the button that opens the Chrome Web Store writing help collection page."> + Write better + </message> + <message name="IDS_EXTENSIONS_ZERO_STATE_IPH_PRODUCTIVITY_CATEGORY_LINK" desc="Link text for the button that opens the Chrome Web Store producitivty category page."> + Boost productivity + </message> + <message name="IDS_EXTENSIONS_ZERO_STATE_IPH_AI_PRODUCTIVITY_COLLECTION_LINK" desc="Link text for the button that opens the Chrome Web Store ai productivity collection page."> + Enhance with AI + </message> + <message name="IDS_EXTENSIONS_ZERO_STATE_IPH_DISMISS_BUTTON_TEXT" desc="Text on the button that dismisses the extensions zero state promo IPH."> + Got it + </message> </if> </grit-part>
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_AI_PRODUCTIVITY_COLLECTION_LINK.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_AI_PRODUCTIVITY_COLLECTION_LINK.png.sha1 new file mode 100644 index 0000000..75707ed --- /dev/null +++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_AI_PRODUCTIVITY_COLLECTION_LINK.png.sha1
@@ -0,0 +1 @@ +40d12b168db603b73f53d4f8aed7f81d23be27e1 \ No newline at end of file
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_DISMISS_BUTTON_TEXT.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_DISMISS_BUTTON_TEXT.png.sha1 new file mode 100644 index 0000000..425f6e1 --- /dev/null +++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_DISMISS_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@ +c80ec57b4b3e8149891aee2cc6a235b945e7a33d \ No newline at end of file
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_PRODUCTIVITY_CATEGORY_LINK.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_PRODUCTIVITY_CATEGORY_LINK.png.sha1 new file mode 100644 index 0000000..3e86f8a0 --- /dev/null +++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_PRODUCTIVITY_CATEGORY_LINK.png.sha1
@@ -0,0 +1 @@ +4a7c9c772fcb9a332b5d007b36f0a0d78bf6823a \ No newline at end of file
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_SHOPPING_CATEGORY_LINK.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_SHOPPING_CATEGORY_LINK.png.sha1 new file mode 100644 index 0000000..3625c09 --- /dev/null +++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_SHOPPING_CATEGORY_LINK.png.sha1
@@ -0,0 +1 @@ +32ecb301dca6a5578be43b7908425babf39cea13 \ No newline at end of file
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_WRITING_HELP_COLLECTION_LINK.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_WRITING_HELP_COLLECTION_LINK.png.sha1 new file mode 100644 index 0000000..86a9d9f --- /dev/null +++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_IPH_WRITING_HELP_COLLECTION_LINK.png.sha1
@@ -0,0 +1 @@ +16acd7a30fb82cca03eaa7a46f88f59567fef2b3 \ No newline at end of file
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_PLAIN_LINK_IPH_DESCRIPTION.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_PLAIN_LINK_IPH_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..c76e57c --- /dev/null +++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_ZERO_STATE_PLAIN_LINK_IPH_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +8c34c72e6001e011bbe41b5b025f5345e2dc8e5a \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index 9fda1292..8f88ed9a 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -1003,18 +1003,6 @@ <message name="IDS_ENTERPRISE_SIGNIN_EXPLANATION_WITH_PROFILE_CREATION" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. Additionally notifies the user that they can create a new profile instead. This message is followed by a 'Learn more' link."> You are signing in with a managed account and giving its administrator control over your Google Chrome profile. Your Chrome data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to <ph name="USER_NAME">$1<ex>pat@example.com</ex></ph>. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. You can optionally create a new profile to keep your existing Chrome data separate. <ph name="LEARN_MORE">$2<ex>Learn more</ex></ph> </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE" desc="The title of the dialog to confirm adding a new work profile with the signed-in enterprise account"> - Add Work Profile to this browser - </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. This message is followed by a 'Learn more' link."> - You are adding a work profile to this browser and giving your administrator control over just the work profile. - </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE" desc="Notice that work profiles are separated from any personal profile"> - This work profile is completely separate from your personal profile. - </message> - <message name="IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. This message is followed by a 'Learn more' link."> - Any Chrome data that is generated during the use of this profile (such as the creation of bookmarks, history, passwords, and other settings) can be removed by the work profile administrator. <ph name="LEARN_MORE">$1<ex>Learn more</ex></ph> - </message> <message name="IDS_ENTERPRISE_VALUE_PROPOSITION_PROFILE_REQUIRED_BY_ORG_KNOWN_DOMAIN_TITLE" desc="Title of the screen in the profile creation flow where the user is asked whether they want to confirm signing in to Chrome with their enterprise account when it is mandatory to sign in to Chrome with the enterprise account."> Your organization, <ph name="MANAGER">$1<ex>manager.com</ex></ph>, requires you to sign into Chrome </message>
diff --git a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION.png.sha1 deleted file mode 100644 index e6c3cea..0000000 --- a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_CREATION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -cfca689b4efef6973e4a4a1948d6e79f3fc0e1ad \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION.png.sha1 deleted file mode 100644 index e6c3cea..0000000 --- a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_EXPLANATION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -cfca689b4efef6973e4a4a1948d6e79f3fc0e1ad \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE.png.sha1 deleted file mode 100644 index e6c3cea..0000000 --- a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_ISOLATION_NOTICE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -cfca689b4efef6973e4a4a1948d6e79f3fc0e1ad \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE.png.sha1 deleted file mode 100644 index e6c3cea..0000000 --- a/chrome/app/google_chrome_strings_grd/IDS_ENTERPRISE_SIGNIN_WORK_PROFILE_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -cfca689b4efef6973e4a4a1948d6e79f3fc0e1ad \ No newline at end of file
diff --git a/chrome/app/profiles_strings.grdp b/chrome/app/profiles_strings.grdp index 2fc86ff..f9776da 100644 --- a/chrome/app/profiles_strings.grdp +++ b/chrome/app/profiles_strings.grdp
@@ -44,7 +44,7 @@ <message name="IDS_AVATAR_BUTTON_SIGNIN_PAUSED" desc="Short label for the avatar button when the profile is in a Signin Paused state." meaning="The account is signed in on Chrome but signed out on the Web."> Verify it's you </message> - <message name="IDS_AVATAR_BUTTON_WORK" desc="Short label for the avatar button when the profile is a work profile." meaning="Using a work profile"> + <message name="IDS_AVATAR_BUTTON_WORK" desc="Short label for the avatar button when the profile is a managed profile in an enterprise environment, such as a business, government organization, or other workplace." meaning="Using a managed profile, as for a workplace"> Work </message> <message name="IDS_AVATAR_BUTTON_SCHOOL" desc="Short label for the avatar button when the profile is a school profile." meaning="Using a school profile">
diff --git a/chrome/app/profiles_strings_grdp/IDS_AVATAR_BUTTON_WORK.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_AVATAR_BUTTON_WORK.png.sha1 index 99a340fe..c486094 100644 --- a/chrome/app/profiles_strings_grdp/IDS_AVATAR_BUTTON_WORK.png.sha1 +++ b/chrome/app/profiles_strings_grdp/IDS_AVATAR_BUTTON_WORK.png.sha1
@@ -1 +1 @@ -879f8eeb610fdfd057045af96e64237af5f6526f \ No newline at end of file +2a2a6520595d86b02afe01d725bd297e5a1f6c93 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f6710eb..450d54a 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -5266,6 +5266,7 @@ "//chrome/browser/ash/boca", "//chrome/browser/ash/boca/babelorca", "//chrome/browser/ash/boca/on_task", + "//chrome/browser/ash/boca/spotlight", "//chrome/browser/ash/boot_times_recorder", "//chrome/browser/ash/borealis", "//chrome/browser/ash/bruschetta", @@ -5805,6 +5806,7 @@ "//chrome/browser/ash/boca", "//chrome/browser/ash/boca/babelorca", "//chrome/browser/ash/boca/on_task", + "//chrome/browser/ash/boca/spotlight", "//chrome/browser/ash/borealis", "//chrome/browser/ash/bruschetta", "//chrome/browser/ash/calendar",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 745c2f5f..61f2402 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -6683,6 +6683,14 @@ FEATURE_VALUE_TYPE(omnibox_feature_configs::ContextualSearch:: kContextualSearchOpenLensActionUsesThumbnail)}, + {"contextual-suggestions-ablate-others-when-present", + flag_descriptions::kContextualSuggestionsAblateOthersWhenPresentName, + flag_descriptions:: + kContextualSuggestionsAblateOthersWhenPresentDescription, + kOsDesktop, + FEATURE_VALUE_TYPE(omnibox_feature_configs::ContextualSearch:: + kContextualSuggestionsAblateOthersWhenPresent)}, + {"omnibox-contextual-search-on-focus-suggestions", flag_descriptions::kOmniboxContextualSearchOnFocusSuggestionsName, flag_descriptions::kOmniboxContextualSearchOnFocusSuggestionsDescription, @@ -12517,6 +12525,13 @@ FEATURE_VALUE_TYPE(password_manager::features::kFillRecoveryPassword)}, #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) + {"android-use-correct-display-work-area", + flag_descriptions::kAndroidUseCorrectDisplayWorkAreaName, + flag_descriptions::kAndroidUseCorrectDisplayWorkAreaDescription, + kOsAndroid, FEATURE_VALUE_TYPE(ui::kAndroidUseCorrectDisplayWorkArea)}, +#endif // BUILDFLAG(IS_ANDROID) + #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || \ BUILDFLAG(IS_CHROMEOS) {"enable-site-search-allow-user-override-policy",
diff --git a/chrome/browser/ai/ai_language_model_unittest.cc b/chrome/browser/ai/ai_language_model_unittest.cc index 64593f6..af4c2dad 100644 --- a/chrome/browser/ai/ai_language_model_unittest.cc +++ b/chrome/browser/ai/ai_language_model_unittest.cc
@@ -304,6 +304,10 @@ .WillByDefault(Return(on_device_model::Capabilities( {on_device_model::CapabilityFlags::kImageInput, on_device_model::CapabilityFlags::kAudioInput}))); + ON_CALL(*mock_optimization_guide_keyed_service_, + GetOnDeviceModelEligibility(_)) + .WillByDefault(Return( + optimization_guide::OnDeviceModelEligibilityReason::kSuccess)); } mojo::Remote<blink::mojom::AILanguageModel> CreateSession( @@ -697,7 +701,7 @@ future.SetValue(error); }); - auto expected_input = blink::mojom::AILanguageModelExpectedInput::New(); + auto expected_input = blink::mojom::AILanguageModelExpected::New(); expected_input->languages.emplace(); expected_input->languages->push_back(blink::mojom::AILanguageCode::New("ja")); @@ -710,7 +714,7 @@ blink::mojom::AIManagerCreateClientError::kUnsupportedLanguage); } -TEST_F(AILanguageModelTest, UnsupportedCapability) { +TEST_F(AILanguageModelTest, UnsupportedInputCapability) { ON_CALL(*mock_optimization_guide_keyed_service_, GetOnDeviceCapabilities()) .WillByDefault(Return(on_device_model::Capabilities())); @@ -720,7 +724,7 @@ future.SetValue(error); }); - auto expected_input = blink::mojom::AILanguageModelExpectedInput::New(); + auto expected_input = blink::mojom::AILanguageModelExpected::New(); expected_input->type = blink::mojom::AILanguageModelPromptType::kImage; auto options = blink::mojom::AILanguageModelCreateOptions::New(); @@ -732,8 +736,30 @@ blink::mojom::AIManagerCreateClientError::kUnableToCreateSession); } +TEST_F(AILanguageModelTest, UnsupportedOutputCapability) { + ON_CALL(*mock_optimization_guide_keyed_service_, GetOnDeviceCapabilities()) + .WillByDefault(Return(on_device_model::Capabilities())); + + base::test::TestFuture<blink::mojom::AIManagerCreateClientError> future; + AITestUtils::MockCreateLanguageModelClient language_model_client; + EXPECT_CALL(language_model_client, OnError(_)).WillOnce([&](auto error) { + future.SetValue(error); + }); + + auto expected_output = blink::mojom::AILanguageModelExpected::New(); + expected_output->type = blink::mojom::AILanguageModelPromptType::kImage; + + auto options = blink::mojom::AILanguageModelCreateOptions::New(); + options->expected_outputs.emplace(); + options->expected_outputs->push_back(std::move(expected_output)); + GetAIManagerRemote()->CreateLanguageModel( + language_model_client.BindNewPipeAndPassRemote(), std::move(options)); + EXPECT_EQ(future.Take(), + blink::mojom::AIManagerCreateClientError::kUnableToCreateSession); +} + TEST_F(AILanguageModelTest, MultimodalInputImageNotSpecified) { - auto audio_input = blink::mojom::AILanguageModelExpectedInput::New(); + auto audio_input = blink::mojom::AILanguageModelExpected::New(); audio_input->type = blink::mojom::AILanguageModelPromptType::kAudio; auto options = blink::mojom::AILanguageModelCreateOptions::New(); options->expected_inputs.emplace(); @@ -769,7 +795,7 @@ } TEST_F(AILanguageModelTest, MultimodalInputAudioNotSpecified) { - auto image_input = blink::mojom::AILanguageModelExpectedInput::New(); + auto image_input = blink::mojom::AILanguageModelExpected::New(); image_input->type = blink::mojom::AILanguageModelPromptType::kImage; auto options = blink::mojom::AILanguageModelCreateOptions::New(); options->expected_inputs.emplace(); @@ -805,9 +831,9 @@ } TEST_F(AILanguageModelTest, MultimodalInput) { - auto audio_input = blink::mojom::AILanguageModelExpectedInput::New(); + auto audio_input = blink::mojom::AILanguageModelExpected::New(); audio_input->type = blink::mojom::AILanguageModelPromptType::kAudio; - auto image_input = blink::mojom::AILanguageModelExpectedInput::New(); + auto image_input = blink::mojom::AILanguageModelExpected::New(); image_input->type = blink::mojom::AILanguageModelPromptType::kImage; auto options = blink::mojom::AILanguageModelCreateOptions::New(); @@ -1039,10 +1065,6 @@ #define MAYBE_CanCreate_WaitsForEligibility CanCreate_WaitsForEligibility #endif TEST_F(AILanguageModelTest, MAYBE_CanCreate_WaitsForEligibility) { - EXPECT_CALL(*mock_optimization_guide_keyed_service_, - GetOnDeviceModelEligibility(_)) - .WillRepeatedly( - Return(optimization_guide::OnDeviceModelEligibilityReason::kSuccess)); base::test::TestFuture<base::OnceCallback<void( optimization_guide::OnDeviceModelEligibilityReason)>> eligibility_future; @@ -1065,18 +1087,17 @@ blink::mojom::ModelAvailabilityCheckResult::kAvailable); } -TEST_F(AILanguageModelTest, CanCreate_IsLanguagesSupported) { - EXPECT_CALL(*mock_optimization_guide_keyed_service_, - GetOnDeviceModelEligibility(_)) - .WillRepeatedly( - Return(optimization_guide::OnDeviceModelEligibilityReason::kSuccess)); - +TEST_F(AILanguageModelTest, CanCreate_SupportedLanguages) { base::MockCallback<AIManager::CanCreateLanguageModelCallback> callback; auto options = blink::mojom::AILanguageModelCreateOptions::New(); - options->expected_inputs = - std::vector<blink::mojom::AILanguageModelExpectedInputPtr>(); + options->expected_inputs.emplace(); options->expected_inputs->push_back( - blink::mojom::AILanguageModelExpectedInput::New( + blink::mojom::AILanguageModelExpected::New( + blink::mojom::AILanguageModelPromptType::kText, + AITestUtils::ToMojoLanguageCodes({"en"}))); + options->expected_outputs.emplace(); + options->expected_outputs->push_back( + blink::mojom::AILanguageModelExpected::New( blink::mojom::AILanguageModelPromptType::kText, AITestUtils::ToMojoLanguageCodes({"en"}))); EXPECT_CALL(callback, @@ -1085,20 +1106,28 @@ callback.Get()); } -TEST_F(AILanguageModelTest, CanCreate_UnIsLanguagesSupported) { - EXPECT_CALL(*mock_optimization_guide_keyed_service_, - GetOnDeviceModelEligibility(_)) - .WillRepeatedly( - Return(optimization_guide::OnDeviceModelEligibilityReason::kSuccess)); - +TEST_F(AILanguageModelTest, CanCreate_UnsupportedInputLanguages) { base::MockCallback<AIManager::CanCreateLanguageModelCallback> callback; EXPECT_CALL(callback, Run(blink::mojom::ModelAvailabilityCheckResult:: kUnavailableUnsupportedLanguage)); auto options = blink::mojom::AILanguageModelCreateOptions::New(); - options->expected_inputs = - std::vector<blink::mojom::AILanguageModelExpectedInputPtr>(); + options->expected_inputs.emplace(); options->expected_inputs->push_back( - blink::mojom::AILanguageModelExpectedInput::New( + blink::mojom::AILanguageModelExpected::New( + blink::mojom::AILanguageModelPromptType::kText, + AITestUtils::ToMojoLanguageCodes({"ja"}))); + GetAIManagerInterface()->CanCreateLanguageModel(std::move(options), + callback.Get()); +} + +TEST_F(AILanguageModelTest, CanCreate_UnsupportedOutputLanguages) { + base::MockCallback<AIManager::CanCreateLanguageModelCallback> callback; + EXPECT_CALL(callback, Run(blink::mojom::ModelAvailabilityCheckResult:: + kUnavailableUnsupportedLanguage)); + auto options = blink::mojom::AILanguageModelCreateOptions::New(); + options->expected_outputs.emplace(); + options->expected_outputs->push_back( + blink::mojom::AILanguageModelExpected::New( blink::mojom::AILanguageModelPromptType::kText, AITestUtils::ToMojoLanguageCodes({"ja"}))); GetAIManagerInterface()->CanCreateLanguageModel(std::move(options),
diff --git a/chrome/browser/ai/ai_manager.cc b/chrome/browser/ai/ai_manager.cc index ebfcafa..c46613afe 100644 --- a/chrome/browser/ai/ai_manager.cc +++ b/chrome/browser/ai/ai_manager.cc
@@ -156,6 +156,23 @@ language::ExtractBaseLanguage(language->code) == "en"; }; +// Returns whether optional LanguageModel expected_inputs or expected_outputs +// vectors contain only supported languages. Returns true for absent languages. +bool AreExpectedLanguagesSupported( + const std::optional<std::vector<blink::mojom::AILanguageModelExpectedPtr>>& + expected_vector) { + if (!expected_vector) { + return true; + } + for (const auto& expected_entry : expected_vector.value()) { + if (expected_entry->languages.has_value() && + !AIManager::IsLanguagesSupported(expected_entry->languages.value())) { + return false; + } + } + return true; +} + template <typename ContextBoundObjectType, typename ContextBoundObjectReceiverInterface, typename ClientRemoteInterface, @@ -275,21 +292,24 @@ mojo::Remote<ClientRemoteInterface> client_remote_; }; -// Get the capabilities specified from the expected input types. +// Get the capabilities specified from the expected input or output types. on_device_model::Capabilities GetExpectedCapabilities( - std::vector<blink::mojom::AILanguageModelExpectedInputPtr>& inputs) { + const std::optional<std::vector<blink::mojom::AILanguageModelExpectedPtr>>& + expected_vector) { on_device_model::Capabilities capabilities; - for (const auto& input : inputs) { - switch (input->type) { - case blink::mojom::AILanguageModelPromptType::kText: - // Text capabilities are included by default. - break; - case blink::mojom::AILanguageModelPromptType::kImage: - capabilities.Put(on_device_model::CapabilityFlags::kImageInput); - break; - case blink::mojom::AILanguageModelPromptType::kAudio: - capabilities.Put(on_device_model::CapabilityFlags::kAudioInput); - break; + if (expected_vector) { + for (const auto& expected_entry : expected_vector.value()) { + switch (expected_entry->type) { + case blink::mojom::AILanguageModelPromptType::kText: + // Text capabilities are included by default. + break; + case blink::mojom::AILanguageModelPromptType::kImage: + capabilities.Put(on_device_model::CapabilityFlags::kImageInput); + break; + case blink::mojom::AILanguageModelPromptType::kAudio: + capabilities.Put(on_device_model::CapabilityFlags::kAudioInput); + break; + } } } return capabilities; @@ -362,28 +382,28 @@ kUnavailableEnterprisePolicyDisabled); return; } - on_device_model::Capabilities capabilities; - if (options && options->expected_inputs.has_value()) { - capabilities = GetExpectedCapabilities(options->expected_inputs.value()); - if (!capabilities.empty() && - !base::FeatureList::IsEnabled( - blink::features::kAIPromptAPIMultimodalInput)) { + + on_device_model::Capabilities input_capabilities; + if (options) { + input_capabilities = GetExpectedCapabilities(options->expected_inputs); + if (!GetExpectedCapabilities(options->expected_outputs).empty() || + (!input_capabilities.empty() && + !base::FeatureList::IsEnabled( + blink::features::kAIPromptAPIMultimodalInput))) { std::move(callback).Run(blink::mojom::ModelAvailabilityCheckResult:: kUnavailableModelAdaptationNotAvailable); return; } - for (const auto& expected_input : options->expected_inputs.value()) { - if (expected_input->languages.has_value() && - !IsLanguagesSupported(expected_input->languages.value())) { - std::move(callback).Run(blink::mojom::ModelAvailabilityCheckResult:: - kUnavailableUnsupportedLanguage); - return; - } + if (!AreExpectedLanguagesSupported(options->expected_inputs) || + !AreExpectedLanguagesSupported(options->expected_outputs)) { + std::move(callback).Run(blink::mojom::ModelAvailabilityCheckResult:: + kUnavailableUnsupportedLanguage); + return; } } CanCreateSession(optimization_guide::ModelBasedCapabilityKey::kPromptApi, - capabilities, std::move(callback)); + input_capabilities, std::move(callback)); } void AIManager::CreateLanguageModel( @@ -391,17 +411,13 @@ client, blink::mojom::AILanguageModelCreateOptionsPtr options) { CHECK(options); - if (options->expected_inputs.has_value()) { - for (const auto& expected_input : options->expected_inputs.value()) { - if (expected_input->languages.has_value() && - !IsLanguagesSupported(expected_input->languages.value())) { - mojo::Remote<blink::mojom::AIManagerCreateLanguageModelClient>( - std::move(client)) - ->OnError( - blink::mojom::AIManagerCreateClientError::kUnsupportedLanguage); - return; - } - } + if (!AreExpectedLanguagesSupported(options->expected_inputs) || + !AreExpectedLanguagesSupported(options->expected_outputs)) { + mojo::Remote<blink::mojom::AIManagerCreateLanguageModelClient>( + std::move(client)) + ->OnError( + blink::mojom::AIManagerCreateClientError::kUnsupportedLanguage); + return; } if (!model_broker_client_) { @@ -449,23 +465,24 @@ language_model_params->default_sampling_params->temperature; } - if (options->expected_inputs) { - params->capabilities = GetExpectedCapabilities(*options->expected_inputs); - - if (!params->capabilities.empty()) { - auto* service = OptimizationGuideKeyedServiceFactory::GetForProfile( - Profile::FromBrowserContext(browser_context_)); - if (!base::FeatureList::IsEnabled( - blink::features::kAIPromptAPIMultimodalInput) || - !service->GetOnDeviceCapabilities().HasAll(params->capabilities)) { - mojo::Remote<blink::mojom::AIManagerCreateLanguageModelClient>( - std::move(client)) - ->OnError(blink::mojom::AIManagerCreateClientError:: - kUnableToCreateSession); - return; - } + params->capabilities = GetExpectedCapabilities(options->expected_inputs); + on_device_model::Capabilities output_capabilities = + GetExpectedCapabilities(options->expected_outputs); + if (!params->capabilities.empty() || !output_capabilities.empty()) { + auto* service = OptimizationGuideKeyedServiceFactory::GetForProfile( + Profile::FromBrowserContext(browser_context_)); + if (!output_capabilities.empty() || + !base::FeatureList::IsEnabled( + blink::features::kAIPromptAPIMultimodalInput) || + !service->GetOnDeviceCapabilities().HasAll(params->capabilities)) { + mojo::Remote<blink::mojom::AIManagerCreateLanguageModelClient>( + std::move(client)) + ->OnError( + blink::mojom::AIManagerCreateClientError::kUnableToCreateSession); + return; } } + mojo::PendingRemote<on_device_model::mojom::Session> session; model_client->solution().CreateSession( session.InitWithNewPipeAndPassReceiver(), params.Clone());
diff --git a/chrome/browser/ai/ai_manager_unittest.cc b/chrome/browser/ai/ai_manager_unittest.cc index c1f8f2f..2baf440 100644 --- a/chrome/browser/ai/ai_manager_unittest.cc +++ b/chrome/browser/ai/ai_manager_unittest.cc
@@ -157,7 +157,8 @@ /*sampling_params=*/nullptr, /*initial_prompts=*/ std::vector<blink::mojom::AILanguageModelPromptPtr>(), - /*expected_inputs=*/std::nullopt)); + /*expected_inputs=*/std::nullopt, + /*expected_outputs=*/std::nullopt)); run_loop.Run(); ASSERT_EQ(1u, GetAIManagerContextBoundObjectSetSize());
diff --git a/chrome/browser/android/contextualsearch/native_contextual_search_context.h b/chrome/browser/android/contextualsearch/native_contextual_search_context.h index 598dc7a..6c8312c 100644 --- a/chrome/browser/android/contextualsearch/native_contextual_search_context.h +++ b/chrome/browser/android/contextualsearch/native_contextual_search_context.h
@@ -7,7 +7,6 @@ #include "base/android/jni_android.h" #include "components/contextual_search/core/browser/contextual_search_context.h" -#include "url/gurl.h" // A ContextualSearchContext subclass that is modifiable via JNI. This is the // native implementation of the Java ContextualSearchContext; Instance lifetimes
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android.h b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h index 6fa5cb41..eecf301 100644 --- a/chrome/browser/android/customtabs/tab_interaction_recorder_android.h +++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h
@@ -14,7 +14,6 @@ #include "content/public/browser/document_user_data.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" -#include "url/gurl.h" namespace customtabs {
diff --git a/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc b/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc index 156f3dd..aea2208 100644 --- a/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc +++ b/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc
@@ -21,6 +21,7 @@ #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/task/thread_pool.h" #include "base/test/bind.h" #include "chrome/browser/accessibility/service/accessibility_service_router_factory.h"
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc index 3e53d938..223cd2a9 100644 --- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -35,6 +35,7 @@ #include "base/command_line.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h"
diff --git a/chrome/browser/ash/app_list/app_list_controller_delegate.h b/chrome/browser/ash/app_list/app_list_controller_delegate.h index 009c0cd..c55c1345 100644 --- a/chrome/browser/ash/app_list/app_list_controller_delegate.h +++ b/chrome/browser/ash/app_list/app_list_controller_delegate.h
@@ -20,6 +20,7 @@ class Window; } // namespace aura +class GURL; class Profile; // Interface to allow the view delegate to call out to whatever is controlling
diff --git a/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.cc b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.cc index 267108a..a52ce800 100644 --- a/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.cc +++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.cc
@@ -12,6 +12,7 @@ #include "base/json/json_reader.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
diff --git a/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h b/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h index 5fc7606..1b83301 100644 --- a/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h +++ b/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h
@@ -8,6 +8,7 @@ #include <string> #include "chrome/browser/ash/app_list/app_list_controller_delegate.h" +#include "url/gurl.h" namespace test {
diff --git a/chrome/browser/ash/app_restore/arc_window_utils.cc b/chrome/browser/ash/app_restore/arc_window_utils.cc index b8e5d0c..0353bf1 100644 --- a/chrome/browser/ash/app_restore/arc_window_utils.cc +++ b/chrome/browser/ash/app_restore/arc_window_utils.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ash/app_restore/arc_window_utils.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/ash/app_restore/full_restore_prefs.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc index aea3fea6b..0e820216a 100644 --- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc +++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -27,6 +27,7 @@ #include "base/logging.h" #include "base/memory/singleton.h" #include "base/posix/eintr_wrapper.h" +#include "base/strings/string_number_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "base/time/time.h"
diff --git a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc index d9fa87b..67b2e8f 100644 --- a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc +++ b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc
@@ -24,6 +24,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_factory.h" #include "chrome/browser/ash/arc/session/arc_service_launcher.h"
diff --git a/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl_unittest.cc b/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl_unittest.cc index e518558..ae818a1f 100644 --- a/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl_unittest.cc +++ b/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl_unittest.cc
@@ -11,6 +11,7 @@ #include "base/containers/flat_map.h" #include "base/functional/bind.h" #include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
diff --git a/chrome/browser/ash/attestation/platform_verification_flow.h b/chrome/browser/ash/attestation/platform_verification_flow.h index 6b56b31..801f43b2 100644 --- a/chrome/browser/ash/attestation/platform_verification_flow.h +++ b/chrome/browser/ash/attestation/platform_verification_flow.h
@@ -17,7 +17,6 @@ #include "chromeos/ash/components/dbus/attestation/interface.pb.h" #include "chromeos/ash/components/dbus/constants/attestation_constants.h" #include "components/account_id/account_id.h" -#include "url/gurl.h" class AccountId;
diff --git a/chrome/browser/ash/boca/BUILD.gn b/chrome/browser/ash/boca/BUILD.gn index b095ce6..b4335dd6 100644 --- a/chrome/browser/ash/boca/BUILD.gn +++ b/chrome/browser/ash/boca/BUILD.gn
@@ -34,6 +34,7 @@ "//chromeos/ash/components/boca", "//chromeos/ash/components/boca:invalidations", "//chromeos/ash/components/boca:spotlight", + "//chromeos/ash/components/boca:spotlight_lib", "//chromeos/ash/components/boca/babelorca", "//chromeos/ash/components/boca/babelorca:soda_installer", "//chromeos/ash/components/boca/on_task",
diff --git a/chrome/browser/ash/boca/DEPS b/chrome/browser/ash/boca/DEPS index bbbf67e..468eb128 100644 --- a/chrome/browser/ash/boca/DEPS +++ b/chrome/browser/ash/boca/DEPS
@@ -46,6 +46,7 @@ "+chrome/browser/ash/accessibility/live_caption/system_live_caption_service.h", # Files needed by spotlight/ "+chrome/browser/ash/policy/remote_commands/crd/public", + "+chrome/browser/device_identity", ] specific_include_rules = {
diff --git a/chrome/browser/ash/boca/boca_manager.cc b/chrome/browser/ash/boca/boca_manager.cc index 389ac81..e03a44e 100644 --- a/chrome/browser/ash/boca/boca_manager.cc +++ b/chrome/browser/ash/boca/boca_manager.cc
@@ -5,9 +5,11 @@ #include "chrome/browser/ash/boca/boca_manager.h" #include <memory> +#include <optional> #include <utility> #include "ash/constants/ash_features.h" +#include "base/check_deref.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.h" @@ -15,6 +17,8 @@ #include "chrome/browser/ash/boca/on_task/on_task_extensions_manager_impl.h" #include "chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl.h" #include "chrome/browser/ash/boca/spotlight/spotlight_crd_manager_impl.h" +#include "chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.h" +#include "chrome/browser/device_identity/device_oauth2_token_service_factory.h" #include "chrome/browser/gcm/gcm_profile_service_factory.h" #include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -28,6 +32,7 @@ #include "chromeos/ash/components/boca/invalidations/invalidation_service_impl.h" #include "chromeos/ash/components/boca/on_task/on_task_session_manager.h" #include "chromeos/ash/components/boca/session_api/session_client_impl.h" +#include "chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.h" #include "chromeos/ash/components/boca/spotlight/spotlight_crd_manager.h" #include "chromeos/ash/components/boca/spotlight/spotlight_session_manager.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" @@ -102,6 +107,10 @@ return babel_orca_manager; } +DeviceOAuth2TokenService& GetOAuthServiceForSpotlight() { + return CHECK_DEREF(DeviceOAuth2TokenServiceFactory::Get()); +} + } // namespace BocaManager::BocaManager( @@ -119,6 +128,8 @@ babel_orca_manager_(std::move(babel_orca_manager)), boca_metrics_manager_(std::move(boca_metrics_manager)), spotlight_session_manager_(std::move(spotlight_session_manager)) { + spotlight_token_fetcher_ = + std::make_unique<boca::FakeSpotlightOAuthTokenFetcher>(std::nullopt, ""); AddObservers(nullptr); } @@ -156,6 +167,11 @@ spotlight_session_manager_ = std::make_unique<boca::SpotlightSessionManager>( std::make_unique<boca::SpotlightCrdManagerImpl>(profile->GetPrefs())); + if (ash::features::IsBocaSpotlightRobotRequesterEnabled() && !is_consumer) { + spotlight_token_fetcher_ = + std::make_unique<boca::SpotlightOAuthTokenFetcherImpl>( + GetOAuthServiceForSpotlight()); + } gcm::GCMDriver* gcm_driver = gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver(); @@ -193,6 +209,11 @@ } boca_session_manager_->AddObserver(boca_metrics_manager_.get()); boca_session_manager_->AddObserver(spotlight_session_manager_.get()); + if (ash::features::IsBocaSpotlightRobotRequesterEnabled() && + ash::boca_util::IsProducer(user)) { + boca_session_manager_->set_spotlight_token_fetcher( + spotlight_token_fetcher_.get()); + } } } // namespace ash
diff --git a/chrome/browser/ash/boca/boca_manager.h b/chrome/browser/ash/boca/boca_manager.h index a0066e7..71aacf8 100644 --- a/chrome/browser/ash/boca/boca_manager.h +++ b/chrome/browser/ash/boca/boca_manager.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_ASH_BOCA_BOCA_MANAGER_H_ #define CHROME_BROWSER_ASH_BOCA_BOCA_MANAGER_H_ +#include <memory> + #include "chrome/browser/ash/boca/boca_app_client_impl.h" #include "chromeos/ash/components/boca/babelorca/babel_orca_manager.h" #include "chromeos/ash/components/boca/babelorca/soda_installer.h" @@ -13,6 +15,7 @@ #include "chromeos/ash/components/boca/invalidations/invalidation_service_impl.h" #include "chromeos/ash/components/boca/on_task/on_task_session_manager.h" #include "chromeos/ash/components/boca/session_api/session_client_impl.h" +#include "chromeos/ash/components/boca/spotlight/spotlight_oauth_token_fetcher.h" #include "chromeos/ash/components/boca/spotlight/spotlight_session_manager.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_service.h" @@ -68,6 +71,7 @@ void AddObservers(const user_manager::User* user); std::unique_ptr<babelorca::SodaInstaller> soda_installer_; + std::unique_ptr<boca::SpotlightOAuthTokenFetcher> spotlight_token_fetcher_; std::unique_ptr<boca::OnTaskSessionManager> on_task_session_manager_; std::unique_ptr<boca::SessionClientImpl> session_client_impl_; std::unique_ptr<boca::BocaSessionManager> boca_session_manager_;
diff --git a/chrome/browser/ash/boca/boca_manager_unittest.cc b/chrome/browser/ash/boca/boca_manager_unittest.cc index b57a0479..50e6f21 100644 --- a/chrome/browser/ash/boca/boca_manager_unittest.cc +++ b/chrome/browser/ash/boca/boca_manager_unittest.cc
@@ -101,6 +101,7 @@ class BocaManagerTest : public testing::Test { protected: BocaManagerTest() = default; + void SetUp() override { // This is called in the FCMHandler. ON_CALL(mock_instance_id_driver_, @@ -149,10 +150,13 @@ class BocaManagerProducerTest : public BocaManagerTest { protected: BocaManagerProducerTest() = default; + void SetUp() override { BocaManagerTest::SetUp(); - scoped_feature_list_.InitWithFeatures({ash::features::kBoca}, - /*disabled_features=*/{}); + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{ash::features::kBoca}, + /*disabled_features=*/{ash::features::kBocaSpotlightRobotRequester}); + boca_manager_ = std::make_unique<BocaManager>( std::make_unique<boca::OnTaskSessionManager>( /*system_web_app_manager=*/nullptr, /*extensions_manager=*/nullptr), @@ -167,6 +171,7 @@ /*spotlight_notification_handler=*/nullptr, /*spotlight_crd_manager=*/nullptr, /*spotlight_service=*/nullptr)); } + std::unique_ptr<BocaManager> boca_manager_; TestingPrefServiceSimple pref_service_; }; @@ -198,14 +203,59 @@ boca_manager_->GetSpotlightSessionManagerForTesting())); } +TEST_F(BocaManagerProducerTest, + VerifySpotlightTokenFetcherWasNotAddedForProducer) { + ASSERT_FALSE( + boca_manager_->GetBocaSessionManager()->HasSpotlightTokenFetcher()); +} + +class BocaManagerProducerTestSpotlightRobotRequesterEnabled + : public BocaManagerTest { + protected: + BocaManagerProducerTestSpotlightRobotRequesterEnabled() = default; + + void SetUp() override { + BocaManagerTest::SetUp(); + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{ash::features::kBoca, + ash::features::kBocaSpotlightRobotRequester}, + /*disabled_features=*/{}); + + boca_manager_ = std::make_unique<BocaManager>( + std::make_unique<boca::OnTaskSessionManager>( + /*system_web_app_manager=*/nullptr, /*extensions_manager=*/nullptr), + std::move(session_client_impl_), std::move(boca_session_manager_), + std::move(invalidation_service_impl_), + std::make_unique<boca::BabelOrcaManager>( + &pref_service_, identity_test_env_.identity_manager(), + url_loader_factory_.GetSafeWeakWrapper(), + GetBabelOrcaControllerFactory()), + std::make_unique<boca::BocaMetricsManager>(/*is_producer=*/true), + std::make_unique<boca::SpotlightSessionManager>( + /*spotlight_notification_handler=*/nullptr, + /*spotlight_crd_manager=*/nullptr, /*spotlight_service=*/nullptr)); + } + + std::unique_ptr<BocaManager> boca_manager_; + TestingPrefServiceSimple pref_service_; +}; + +TEST_F(BocaManagerProducerTestSpotlightRobotRequesterEnabled, + VerifySpotlightTokenFetcherWasAddedForProducer) { + ASSERT_TRUE( + boca_manager_->GetBocaSessionManager()->HasSpotlightTokenFetcher()); +} + class BocaManagerConsumerTest : public BocaManagerTest { protected: BocaManagerConsumerTest() = default; + void SetUp() override { BocaManagerTest::SetUp(); scoped_feature_list_.InitWithFeatures( /* enabled_features=*/{ash::features::kBoca, - ash::features::kBocaConsumer}, + ash::features::kBocaConsumer, + ash::features::kBocaSpotlightRobotRequester}, /* disabled_features=*/{}); boca_manager_ = std::make_unique<BocaManager>( @@ -222,6 +272,7 @@ /*spotlight_notification_handler=*/nullptr, /*spotlight_crd_manager=*/nullptr, /*spotlight_service=*/nullptr)); } + std::unique_ptr<BocaManager> boca_manager_; TestingPrefServiceSimple pref_service_; }; @@ -247,6 +298,12 @@ boca_manager_->GetSpotlightSessionManagerForTesting())); } +TEST_F(BocaManagerConsumerTest, + VerifySpotlightTokenFetcherWasNotAddedForProducer) { + ASSERT_FALSE( + boca_manager_->GetBocaSessionManager()->HasSpotlightTokenFetcher()); +} + TEST_F(BocaManagerConsumerTest, VerifyDependenciesTearDownProperly) { boca_manager_->Shutdown(); ASSERT_EQ(nullptr, invalidation_service_impl_);
diff --git a/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker.cc b/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker.cc index 42740b6..df840b5 100644 --- a/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker.cc +++ b/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker.cc
@@ -39,6 +39,7 @@ #include "components/sessions/content/session_tab_helper.h" #include "content/public/browser/browser_thread.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/public/cpp/notifier_id.h" // static Browser* LockedSessionWindowTracker::GetBrowserWithTab( @@ -165,6 +166,19 @@ // no Boca SWA instance being tracked. Skip close for now. return; } + ash::boca::OnTaskNotificationsManager::NotificationCreateParams + notification_create_params( + ash::boca::kOnTaskResourceNotSupportedInLockedModeNotificationId, + /*title=*/l10n_util::GetStringUTF16(IDS_ON_TASK_NOTIFICATION_TITLE), + /*message_id=*/ + IDS_ON_TASK_CANNOT_OPEN_UNSUPPORTED_RESOURCES_IN_LOCKED_MODE_MESSAGE, + /*notifier_id=*/ + message_center::NotifierId( + message_center::NotifierType::SYSTEM_COMPONENT, + ash::boca::kOnTaskNotifierId, + ash::NotificationCatalogName::kOnTaskResourceNotSupported)); + notifications_manager_->CreateNotification( + std::move(notification_create_params)); browser->window()->Close(); }
diff --git a/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc b/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc index abc53fe..4f65805 100644 --- a/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc +++ b/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc
@@ -33,7 +33,9 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "chromeos/ash/components/boca/boca_window_observer.h" +#include "chromeos/ash/components/boca/on_task/notification_constants.h" #include "chromeos/ash/components/boca/on_task/on_task_blocklist.h" +#include "chromeos/ash/components/boca/on_task/util/mock_clock.h" #include "chromeos/ash/components/boca/proto/bundle.pb.h" #include "chromeos/ash/components/boca/proto/roster.pb.h" #include "chromeos/strings/grit/chromeos_strings.h" @@ -90,6 +92,31 @@ MOCK_METHOD(void, OnWindowTrackerCleanedup, (), (override)); }; +// Fake delegate implementation for the `OnTaskNotificationsManager` to minimize +// dependency on Ash UI. +class FakeOnTaskNotificationsManagerDelegate + : public ash::boca::OnTaskNotificationsManager::Delegate { + public: + FakeOnTaskNotificationsManagerDelegate() = default; + FakeOnTaskNotificationsManagerDelegate( + const FakeOnTaskNotificationsManagerDelegate&) = delete; + FakeOnTaskNotificationsManagerDelegate& operator=( + const FakeOnTaskNotificationsManagerDelegate&) = delete; + ~FakeOnTaskNotificationsManagerDelegate() override = default; + + void ShowNotification( + std::unique_ptr<message_center::Notification> notification) override { + notifications_shown_.insert(notification->id()); + } + + bool WasNotificationShown(const std::string& id) { + return notifications_shown_.contains(id); + } + + private: + std::set<std::string> notifications_shown_; +}; + class OnTaskLockedSessionWindowTrackerBrowserTestBase : public InProcessBrowserTest { protected: @@ -108,12 +135,23 @@ ash::SystemWebAppManager::Get(profile())->InstallSystemAppsForTesting(); system_web_app_manager_ = std::make_unique<OnTaskSystemWebAppManagerImpl>(profile()); + + // Set up notifications manager with the fake delegate for testing purposes. + auto fake_notifications_delegate = + std::make_unique<FakeOnTaskNotificationsManagerDelegate>(); + fake_notifications_delegate_ptr_ = fake_notifications_delegate.get(); + LockedSessionWindowTrackerFactory::GetForBrowserContext(profile()) + ->SetNotificationManagerForTesting( + ash::boca::OnTaskNotificationsManager::CreateForTest( + std::move(fake_notifications_delegate))); + host_resolver()->AddRule("*", "127.0.0.1"); InProcessBrowserTest::SetUpOnMainThread(); } void TearDownOnMainThread() override { system_web_app_manager_.reset(); + fake_notifications_delegate_ptr_ = nullptr; InProcessBrowserTest::TearDownOnMainThread(); } @@ -143,9 +181,19 @@ return system_web_app_manager_.get(); } + void VerifyResourceNotSupportedNotificationShown() { + ash::boca::MockClock::Get().Advance( + ash::boca::kOnTaskNotificationCountdownInterval); + content::RunAllTasksUntilIdle(); + EXPECT_TRUE(fake_notifications_delegate_ptr_->WasNotificationShown( + ash::boca::kOnTaskResourceNotSupportedInLockedModeNotificationId)); + } + private: base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<OnTaskSystemWebAppManagerImpl> system_web_app_manager_; + raw_ptr<FakeOnTaskNotificationsManagerDelegate> + fake_notifications_delegate_ptr_; }; class OnTaskLockedSessionWindowTrackerBrowserTest @@ -821,6 +869,7 @@ content::RunAllTasksUntilIdle(); EXPECT_EQ(BrowserList::GetInstance()->size(), original_browser_count); EXPECT_FALSE(browser_weak_ptr); + VerifyResourceNotSupportedNotificationShown(); } IN_PROC_BROWSER_TEST_F(OnTaskLockedSessionWindowTrackerBrowserTest,
diff --git a/chrome/browser/ash/boca/spotlight/BUILD.gn b/chrome/browser/ash/boca/spotlight/BUILD.gn index dd0701d..ce26d9a4 100644 --- a/chrome/browser/ash/boca/spotlight/BUILD.gn +++ b/chrome/browser/ash/boca/spotlight/BUILD.gn
@@ -10,8 +10,12 @@ sources = [ "spotlight_crd_manager_impl.cc", "spotlight_crd_manager_impl.h", + "spotlight_oauth_token_fetcher_impl.cc", + "spotlight_oauth_token_fetcher_impl.h", ] + public_deps = [ "//chrome/browser:browser_public_dependencies" ] + deps = [ "//ash", "//ash/constants", @@ -19,6 +23,7 @@ "//chrome/browser/ash/policy/remote_commands/crd/public", "//chrome/browser/ash/policy/remote_commands/crd/public:interface", "//chromeos/ash/components/boca:spotlight", + "//chromeos/ash/components/boca:spotlight_lib", ] } @@ -35,6 +40,7 @@ "//ash/constants", "//base", "//base/test:test_support", + "//chrome/browser", "//chrome/browser/ash/policy/remote_commands/crd/public:interface", "//chrome/browser/ui/ash/system_web_apps", "//chrome/test:test_support",
diff --git a/chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.cc b/chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.cc new file mode 100644 index 0000000..cf5f8046 --- /dev/null +++ b/chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.cc
@@ -0,0 +1,67 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.h" + +#include <memory> +#include <optional> +#include <string> +#include <utility> + +#include "chrome/browser/device_identity/device_oauth2_token_service.h" +#include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/oauth2_access_token_manager.h" + +namespace ash::boca { + +namespace { + +constexpr char kCloudDevicesOAuth2Scope[] = + "https://www.googleapis.com/auth/clouddevices"; +constexpr char kChromotingRemoteSupportOAuth2Scope[] = + "https://www.googleapis.com/auth/chromoting.remote.support"; +constexpr char kTachyonOAuth2Scope[] = + "https://www.googleapis.com/auth/tachyon"; + +} // namespace + +SpotlightOAuthTokenFetcherImpl::SpotlightOAuthTokenFetcherImpl( + DeviceOAuth2TokenService& oauth_service) + : OAuth2AccessTokenManager::Consumer("boca_spotlight"), + oauth_service_(oauth_service) {} + +SpotlightOAuthTokenFetcherImpl::~SpotlightOAuthTokenFetcherImpl() = default; + +void SpotlightOAuthTokenFetcherImpl::Start(OAuthTokenCallback done_callback) { + VLOG(1) << "[Boca] Fetching OAuth access token"; + + done_callback_ = std::move(done_callback); + + OAuth2AccessTokenManager::ScopeSet scopes{ + GaiaConstants::kGoogleUserInfoEmail, kCloudDevicesOAuth2Scope, + kChromotingRemoteSupportOAuth2Scope, kTachyonOAuth2Scope}; + oauth_request_ = oauth_service_->StartAccessTokenRequest(scopes, this); +} + +std::string SpotlightOAuthTokenFetcherImpl::GetDeviceRobotEmail() { + return oauth_service_->GetRobotAccountId().ToString(); +} + +void SpotlightOAuthTokenFetcherImpl::OnGetTokenSuccess( + const OAuth2AccessTokenManager::Request* request, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) { + VLOG(1) << "[Boca] Received OAuth access token"; + oauth_request_.reset(); + std::move(done_callback_).Run(token_response.access_token); +} + +void SpotlightOAuthTokenFetcherImpl::OnGetTokenFailure( + const OAuth2AccessTokenManager::Request* request, + const GoogleServiceAuthError& error) { + LOG(WARNING) << "[Boca] Failed to get OAuth access token: " + << error.ToString(); + oauth_request_.reset(); + std::move(done_callback_).Run(std::nullopt); +} +} // namespace ash::boca
diff --git a/chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.h b/chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.h new file mode 100644 index 0000000..730333a --- /dev/null +++ b/chrome/browser/ash/boca/spotlight/spotlight_oauth_token_fetcher_impl.h
@@ -0,0 +1,46 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_BOCA_SPOTLIGHT_SPOTLIGHT_OAUTH_TOKEN_FETCHER_IMPL_H_ +#define CHROME_BROWSER_ASH_BOCA_SPOTLIGHT_SPOTLIGHT_OAUTH_TOKEN_FETCHER_IMPL_H_ + +#include "base/functional/callback.h" +#include "base/memory/raw_ref.h" +#include "chromeos/ash/components/boca/spotlight/spotlight_oauth_token_fetcher.h" +#include "google_apis/gaia/oauth2_access_token_manager.h" + +class DeviceOAuth2TokenService; + +namespace ash::boca { + +class SpotlightOAuthTokenFetcherImpl + : public SpotlightOAuthTokenFetcher, + public OAuth2AccessTokenManager::Consumer { + public: + explicit SpotlightOAuthTokenFetcherImpl( + DeviceOAuth2TokenService& oauth_service); + ~SpotlightOAuthTokenFetcherImpl() override; + + void Start(OAuthTokenCallback done_callback) override; + + std::string GetDeviceRobotEmail() override; + + private: + // `OAuth2AccessTokenManager::Consumer` implementation. + void OnGetTokenSuccess( + const OAuth2AccessTokenManager::Request* request, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) override; + + void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request, + const GoogleServiceAuthError& error) override; + + const raw_ref<DeviceOAuth2TokenService> oauth_service_; + OAuthTokenCallback done_callback_; + // Handle for the OAuth access token request. + std::unique_ptr<OAuth2AccessTokenManager::Request> oauth_request_; +}; + +} // namespace ash::boca + +#endif // CHROME_BROWSER_ASH_BOCA_SPOTLIGHT_SPOTLIGHT_OAUTH_TOKEN_FETCHER_IMPL_H_
diff --git a/chrome/browser/ash/borealis/borealis_app_uninstaller.cc b/chrome/browser/ash/borealis/borealis_app_uninstaller.cc index 5072349..ebcefe5 100644 --- a/chrome/browser/ash/borealis/borealis_app_uninstaller.cc +++ b/chrome/browser/ash/borealis/borealis_app_uninstaller.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ash/borealis/borealis_app_uninstaller.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/ash/borealis/borealis_app_launcher.h" #include "chrome/browser/ash/borealis/borealis_installer.h" #include "chrome/browser/ash/borealis/borealis_service.h"
diff --git a/chrome/browser/ash/borealis/borealis_survey_handler.cc b/chrome/browser/ash/borealis/borealis_survey_handler.cc index aacce62..b67341c 100644 --- a/chrome/browser/ash/borealis/borealis_survey_handler.cc +++ b/chrome/browser/ash/borealis/borealis_survey_handler.cc
@@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/system/sys_info.h" #include "base/task/task_traits.h"
diff --git a/chrome/browser/ash/borealis/borealis_util.cc b/chrome/browser/ash/borealis/borealis_util.cc index cea57512..82b29f4 100644 --- a/chrome/browser/ash/borealis/borealis_util.cc +++ b/chrome/browser/ash/borealis/borealis_util.cc
@@ -9,6 +9,7 @@ #include "base/base64.h" #include "base/no_destructor.h" #include "base/process/launch.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h"
diff --git a/chrome/browser/ash/bruschetta/bruschetta_download.cc b/chrome/browser/ash/bruschetta/bruschetta_download.cc index 8ee1a37..37e050f 100644 --- a/chrome/browser/ash/bruschetta/bruschetta_download.cc +++ b/chrome/browser/ash/bruschetta/bruschetta_download.cc
@@ -11,6 +11,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "chrome/browser/ash/bruschetta/bruschetta_network_context.h"
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry_unittest.cc b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry_unittest.cc index 8bba626..3a4e20e 100644 --- a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry_unittest.cc +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry_unittest.cc
@@ -13,6 +13,7 @@ #include "app_controls_metrics_utils.h" #include "ash/constants/ash_pref_names.h" #include "base/containers/contains.h" +#include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_forward.h"
diff --git a/chrome/browser/ash/crosapi/vpn_service_ash.cc b/chrome/browser/ash/crosapi/vpn_service_ash.cc index b66b5025..b411c64 100644 --- a/chrome/browser/ash/crosapi/vpn_service_ash.cc +++ b/chrome/browser/ash/crosapi/vpn_service_ash.cc
@@ -11,6 +11,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/types/cxx23_to_underlying.h" #include "base/uuid.h" #include "base/values.h"
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc index c19eb22..3dd3e56a 100644 --- a/chrome/browser/ash/crostini/crostini_manager.cc +++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -24,6 +24,7 @@ #include "base/metrics/histogram_functions.h" #include "base/notimplemented.h" #include "base/notreached.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/system/sys_info.h"
diff --git a/chrome/browser/ash/events/event_rewriter_unittest.cc b/chrome/browser/ash/events/event_rewriter_unittest.cc index 3c04405b..75422b54 100644 --- a/chrome/browser/ash/events/event_rewriter_unittest.cc +++ b/chrome/browser/ash/events/event_rewriter_unittest.cc
@@ -28,6 +28,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h"
diff --git a/chrome/browser/ash/extensions/default_keyboard_extension_browser_test.h b/chrome/browser/ash/extensions/default_keyboard_extension_browser_test.h index 9a41fb9..94843f8 100644 --- a/chrome/browser/ash/extensions/default_keyboard_extension_browser_test.h +++ b/chrome/browser/ash/extensions/default_keyboard_extension_browser_test.h
@@ -8,7 +8,6 @@ #include "base/files/file_path.h" #include "chrome/test/base/in_process_browser_test.h" #include "extensions/common/extension_id.h" -#include "url/gurl.h" namespace base { class CommandLine;
diff --git a/chrome/browser/ash/extensions/file_manager/system_notification_manager.cc b/chrome/browser/ash/extensions/file_manager/system_notification_manager.cc index ca98e4a4..ae18fb8 100644 --- a/chrome/browser/ash/extensions/file_manager/system_notification_manager.cc +++ b/chrome/browser/ash/extensions/file_manager/system_notification_manager.cc
@@ -19,6 +19,7 @@ #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/types/cxx23_to_underlying.h" #include "chrome/browser/ash/drive/file_system_util.h"
diff --git a/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc index a1596b41..6909eb0 100644 --- a/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc +++ b/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc
@@ -4,6 +4,7 @@ #include "base/memory/raw_ptr.h" #include "base/path_service.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/to_string.h" #include "base/test/bind.h" #include "base/test/gmock_callback_support.h"
diff --git a/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc b/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc index 65a899c..af09425 100644 --- a/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc +++ b/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc
@@ -10,6 +10,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/i18n/time_formatting.h" #include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" #include "base/test/gmock_callback_support.h" #include "base/test/mock_callback.h" #include "base/test/test_future.h"
diff --git a/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.cc b/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.cc index 51a58dfa..f15d4ae7 100644 --- a/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.cc +++ b/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.cc
@@ -7,13 +7,10 @@ namespace ash::floating_workspace_metrics_util { -void RecordFloatingWorkspaceV1InitializedHistogram() { - base::UmaHistogramBoolean(kFloatingWorkspaceV1Initialized, true); -} - -void RecordFloatingWorkspaceV1RestoredSessionType( - RestoredBrowserSessionType type) { - base::UmaHistogramEnumeration(kFloatingWorkspaceV1RestoredSessionType, type); +void RecordFloatingWorkspaceStartupUiClosureReason( + StartupUiClosureReason reason) { + base::UmaHistogramEnumeration(kFloatingWorkspaceStartupUiClosureReason, + reason); } void RecordFloatingWorkspaceV2TemplateLaunchFailureType( @@ -22,14 +19,6 @@ type); } -// TODO(b/274501763): rename for better clarity since this does not just record -// for timeout reasons. -void RecordFloatingWorkspaceV2TemplateLaunchTimeout( - LaunchTemplateTimeoutType type) { - base::UmaHistogramEnumeration(kFloatingWorkspaceV2TemplateLaunchTimedOut, - type); -} - void RecordFloatingWorkspaceV2TemplateLoadTime(base::TimeDelta duration) { constexpr size_t bucket_count = 50; constexpr base::TimeDelta min_bucket = base::Seconds(0);
diff --git a/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.h b/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.h index aa9fe6f..73e0696 100644 --- a/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.h +++ b/chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.h
@@ -10,26 +10,24 @@ namespace ash::floating_workspace_metrics_util { -enum class RestoredBrowserSessionType { - // Unknown browser session. - kUnknown = 0, - // Local session restored. - kLocal, - // Remote Session restored. - kRemote, - kMaxValue = kRemote, +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// LINT.IfChange(StartupUiClosureReason) +enum class StartupUiClosureReason { + // User manually pressed the button to close the UI without waiting for + // sessions to restore. + kManual = 0, + // UI closed automatically once the session was restored. + kAutomatic, + kMaxValue = kAutomatic, }; +// LINT.ThenChange(//tools/metrics/histograms/metadata/ash/enums.xml:FloatingWorkspaceStartupUiClosureReason) -enum class LaunchTemplateTimeoutType { - // Unknown timeout reason. - kUnknown = 0, - // Passed wait period timeout. - kPassedWaitPeriod, - // No floating workspace template. - kNoFloatingWorkspaceTemplate, - kMaxValue = kNoFloatingWorkspaceTemplate, -}; - +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// LINT.IfChange(LaunchTemplateFailureType) enum class LaunchTemplateFailureType { // Unknown error. kUnknownError = 0, @@ -39,11 +37,10 @@ kDesksCountCheckFailedError, kMaxValue = kDesksCountCheckFailedError, }; +// LINT.ThenChange(//tools/metrics/histograms/metadata/ash/enums.xml:FloatingWorkspaceV2LaunchTemplateFailureType) -inline constexpr char kFloatingWorkspaceV1Initialized[] = - "Ash.FloatingWorkspace.FloatingWorkspaceV1Initialized"; -inline constexpr char kFloatingWorkspaceV1RestoredSessionType[] = - "Ash.FloatingWorkspace.FloatingWorkspaceV1RestoredSessionType"; +inline constexpr char kFloatingWorkspaceStartupUiClosureReason[] = + "Ash.FloatingWorkspace.StartupUiClosureReason"; inline constexpr char kFloatingWorkspaceV2TemplateLaunchFailureStatus[] = "Ash.FloatingWorkspace.TemplateLaunchFailureStatus"; @@ -60,13 +57,11 @@ inline constexpr char kFloatingWorkspaceV2TemplateNotFound[] = "Ash.FloatingWorkspace.TemplateNotFound"; -void RecordFloatingWorkspaceV1InitializedHistogram(); -void RecordFloatingWorkspaceV1RestoredSessionType( - RestoredBrowserSessionType type); +void RecordFloatingWorkspaceStartupUiClosureReason( + StartupUiClosureReason reason); + void RecordFloatingWorkspaceV2TemplateLaunchFailureType( LaunchTemplateFailureType type); -void RecordFloatingWorkspaceV2TemplateLaunchTimeout( - LaunchTemplateTimeoutType type); void RecordFloatingWorkspaceV2TemplateLoadTime(base::TimeDelta duration); void RecordFloatingWorkspaceV2TemplateSize(size_t file_size); void RecordFloatingWorkspaceV2TemplateUploadStatusHistogram(
diff --git a/chrome/browser/ash/floating_workspace/floating_workspace_service.cc b/chrome/browser/ash/floating_workspace/floating_workspace_service.cc index c428bcb..46722e3 100644 --- a/chrome/browser/ash/floating_workspace/floating_workspace_service.cc +++ b/chrome/browser/ash/floating_workspace/floating_workspace_service.cc
@@ -180,8 +180,6 @@ if (version_ == floating_workspace_util::FloatingWorkspaceVersion:: kFloatingWorkspaceV1Enabled) { - floating_workspace_metrics_util:: - RecordFloatingWorkspaceV1InitializedHistogram(); InitForV1(); return; } @@ -507,16 +505,12 @@ } SessionRestore::RestoreForeignSessionWindows( profile_, session_windows.begin(), session_windows.end()); - floating_workspace_metrics_util::RecordFloatingWorkspaceV1RestoredSessionType( - floating_workspace_metrics_util::RestoredBrowserSessionType::kRemote); } void FloatingWorkspaceService::RestoreLocalSessionWindows() { // Restore local session based on user settings in // chrome://settings/onStartup. UserSessionManager::GetInstance()->LaunchBrowser(profile_); - floating_workspace_metrics_util::RecordFloatingWorkspaceV1RestoredSessionType( - floating_workspace_metrics_util::RestoredBrowserSessionType::kLocal); } sync_sessions::OpenTabsUIDelegate*
diff --git a/chrome/browser/ash/floating_workspace/floating_workspace_service_unittest.cc b/chrome/browser/ash/floating_workspace/floating_workspace_service_unittest.cc index c919ba6e..ef19ab0 100644 --- a/chrome/browser/ash/floating_workspace/floating_workspace_service_unittest.cc +++ b/chrome/browser/ash/floating_workspace/floating_workspace_service_unittest.cc
@@ -17,6 +17,7 @@ #include "base/check_deref.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h"
diff --git a/chrome/browser/ash/growth/campaigns_manager_session.cc b/chrome/browser/ash/growth/campaigns_manager_session.cc index 3f16bcc44..843222f6 100644 --- a/chrome/browser/ash/growth/campaigns_manager_session.cc +++ b/chrome/browser/ash/growth/campaigns_manager_session.cc
@@ -16,6 +16,7 @@ #include "base/check.h" #include "base/check_is_test.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "chrome/browser/apps/app_service/app_service_proxy_ash.h"
diff --git a/chrome/browser/ash/hats/hats_dialog.cc b/chrome/browser/ash/hats/hats_dialog.cc index 78aba478..050d7b1 100644 --- a/chrome/browser/ash/hats/hats_dialog.cc +++ b/chrome/browser/ash/hats/hats_dialog.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "base/strings/escape.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/task/thread_pool.h" #include "chrome/browser/ash/hats/hats_config.h"
diff --git a/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc b/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc index 25b7458..383c2d1 100644 --- a/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc +++ b/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc
@@ -6,6 +6,7 @@ #include "ash/constants/ash_pref_names.h" #include "base/feature_list.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/task_environment.h" #include "chrome/browser/ash/input_method/assistive_window_controller_delegate.h"
diff --git a/chrome/browser/ash/input_method/editor_text_query_provider.cc b/chrome/browser/ash/input_method/editor_text_query_provider.cc index 5493927..a5d8dcb 100644 --- a/chrome/browser/ash/input_method/editor_text_query_provider.cc +++ b/chrome/browser/ash/input_method/editor_text_query_provider.cc
@@ -10,6 +10,7 @@ #include "base/metrics/field_trial_params.h" #include "base/notreached.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chrome/browser/ash/input_method/editor_helpers.h" #include "chrome/browser/ash/input_method/editor_metrics_recorder.h"
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc index 376c3cf..2e0fcd6 100644 --- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc +++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -19,6 +19,7 @@ #include "base/metrics/user_metrics.h" #include "base/numerics/safe_conversions.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_offset_string_conversions.h" #include "base/strings/utf_string_conversion_utils.h"
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc index b393fe73..88fe8a1 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc
@@ -13,6 +13,7 @@ #include "base/json/json_reader.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h"
diff --git a/chrome/browser/ash/login/screens/display_size_screen.cc b/chrome/browser/ash/login/screens/display_size_screen.cc index d1931d27..853a6bf2 100644 --- a/chrome/browser/ash/login/screens/display_size_screen.cc +++ b/chrome/browser/ash/login/screens/display_size_screen.cc
@@ -9,6 +9,7 @@ #include "ash/shell.h" #include "base/metrics/histogram_functions.h" #include "base/numerics/ranges.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/ash/login/login_pref_names.h" #include "chrome/browser/ash/login/users/chrome_user_manager_util.h" #include "chrome/browser/ash/login/wizard_context.h"
diff --git a/chrome/browser/ash/net/dns_over_https/templates_uri_resolver_impl.cc b/chrome/browser/ash/net/dns_over_https/templates_uri_resolver_impl.cc index dfcf2b0..79a3ed9 100644 --- a/chrome/browser/ash/net/dns_over_https/templates_uri_resolver_impl.cc +++ b/chrome/browser/ash/net/dns_over_https/templates_uri_resolver_impl.cc
@@ -10,6 +10,7 @@ #include "ash/constants/ash_features.h" #include "base/check_is_test.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "chrome/browser/ash/policy/core/device_attributes.h" #include "chrome/browser/ash/policy/core/device_attributes_fake.h"
diff --git a/chrome/browser/ash/policy/dlp/dialogs/files_policy_dialog_browsertest.cc b/chrome/browser/ash/policy/dlp/dialogs/files_policy_dialog_browsertest.cc index e1b09e7..968c08f 100644 --- a/chrome/browser/ash/policy/dlp/dialogs/files_policy_dialog_browsertest.cc +++ b/chrome/browser/ash/policy/dlp/dialogs/files_policy_dialog_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/functional/callback_helpers.h" #include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h"
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h index c3dc348..6e75d9c2 100644 --- a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h +++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h
@@ -29,7 +29,6 @@ #include "ui/aura/window_observer.h" #include "ui/wm/public/activation_change_observer.h" #include "ui/wm/public/activation_client.h" -#include "url/gurl.h" namespace aura { class Window;
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc index 2747c82f..7fdf5c6 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc
@@ -14,6 +14,7 @@ #include "base/check.h" #include "base/memory/scoped_refptr.h" +#include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/test_future.h" #include "base/test/test_mock_time_task_runner.h"
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc b/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc index 8e5e1798..b3dc6668 100644 --- a/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc +++ b/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc
@@ -20,6 +20,7 @@ #include "base/metrics/histogram_functions.h" #include "base/notreached.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "base/types/expected.h" #include "base/uuid.h"
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_reboot_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_reboot_job.cc index 3c60c11..9215ed2 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_reboot_job.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_reboot_job.cc
@@ -12,6 +12,7 @@ #include "base/json/json_reader.h" #include "base/location.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/system/sys_info.h" #include "base/task/single_thread_task_runner.h" #include "base/time/default_clock.h"
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_unittest.cc index 52d03ab..b91765a 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_unittest.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/constants/ash_pref_names.h" #include "ash/constants/ash_switches.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/test/scoped_command_line.h" #include "base/test/test_future.h"
diff --git a/chrome/browser/ash/policy/skyvault/signin_notification_helper.cc b/chrome/browser/ash/policy/skyvault/signin_notification_helper.cc index 982749c..513ca38 100644 --- a/chrome/browser/ash/policy/skyvault/signin_notification_helper.cc +++ b/chrome/browser/ash/policy/skyvault/signin_notification_helper.cc
@@ -9,6 +9,7 @@ #include "ash/public/cpp/notification_utils.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service_factory.h"
diff --git a/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc b/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc index 14ee9a23..8c8d77ef 100644 --- a/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc +++ b/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ash/policy/skyvault/signin_notification_helper.h" +#include "base/strings/string_number_conversions.h" #include "base/test/mock_callback.h" #include "chrome/browser/ash/policy/skyvault/odfs_skyvault_uploader.h" #include "chrome/browser/notifications/notification_display_service_tester.h"
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc index 9f09d551..1150d775 100644 --- a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc +++ b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
@@ -36,6 +36,7 @@ #include "base/notreached.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h"
diff --git a/chrome/browser/ash/policy/uploading/system_log_uploader.h b/chrome/browser/ash/policy/uploading/system_log_uploader.h index 2514097..631604d6 100644 --- a/chrome/browser/ash/policy/uploading/system_log_uploader.h +++ b/chrome/browser/ash/policy/uploading/system_log_uploader.h
@@ -22,6 +22,8 @@ #include "chromeos/ash/components/settings/cros_settings.h" #include "components/policy/core/common/remote_commands/remote_command_job.h" +class GURL; + namespace base { class SequencedTaskRunner; }
diff --git a/chrome/browser/ash/policy/uploading/upload_job.h b/chrome/browser/ash/policy/uploading/upload_job.h index b21e28f..2b7c8f3e 100644 --- a/chrome/browser/ash/policy/uploading/upload_job.h +++ b/chrome/browser/ash/policy/uploading/upload_job.h
@@ -9,8 +9,6 @@ #include <memory> #include <string> -#include "url/gurl.h" - namespace policy { class DataSegment;
diff --git a/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc b/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc index 71feadb..ff446f5d 100644 --- a/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc +++ b/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc
@@ -12,6 +12,7 @@ #include "ash/constants/ash_features.h" #include "base/cancelable_callback.h" #include "base/functional/bind.h" +#include "base/strings/string_number_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h"
diff --git a/chrome/browser/ash/printing/print_servers_manager_unittest.cc b/chrome/browser/ash/printing/print_servers_manager_unittest.cc index 349c562..be27abc 100644 --- a/chrome/browser/ash/printing/print_servers_manager_unittest.cc +++ b/chrome/browser/ash/printing/print_servers_manager_unittest.cc
@@ -12,6 +12,7 @@ #include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/test/task_environment.h" #include "chrome/browser/ash/printing/enterprise/print_servers_provider.h"
diff --git a/chrome/browser/ash/printing/usb_printer_util.cc b/chrome/browser/ash/printing/usb_printer_util.cc index 8b21fa5d..dea8d23 100644 --- a/chrome/browser/ash/printing/usb_printer_util.cc +++ b/chrome/browser/ash/printing/usb_printer_util.cc
@@ -20,6 +20,7 @@ #include "base/numerics/byte_conversions.h" #include "base/numerics/safe_conversions.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ash/printing/zeroconf_printer_detector.cc b/chrome/browser/ash/printing/zeroconf_printer_detector.cc index e79ade5a..282308094 100644 --- a/chrome/browser/ash/printing/zeroconf_printer_detector.cc +++ b/chrome/browser/ash/printing/zeroconf_printer_detector.cc
@@ -17,6 +17,7 @@ #include "base/containers/contains.h" #include "base/containers/fixed_flat_set.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h"
diff --git a/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc b/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc index 56281c5..81a43a5 100644 --- a/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc +++ b/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc
@@ -12,6 +12,7 @@ #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/ash/scalable_iph/customizable_test_env_browser_test_base.h" #include "chrome/browser/ash/scalable_iph/mock_scalable_iph_delegate.h" #include "chrome/browser/ash/scalable_iph/scalable_iph_delegate_impl.h"
diff --git a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc index 69445fce..3cb06a1 100644 --- a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc +++ b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
@@ -25,6 +25,7 @@ #include "base/functional/bind.h" #include "base/scoped_observation.h" #include "base/strings/pattern.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/apps/app_service/app_registry_cache_waiter.h" #include "chrome/browser/ash/app_list/app_list_client_impl.h" #include "chrome/browser/ash/app_list/app_list_model_updater.h"
diff --git a/chrome/browser/ash/smb_client/smb_service_unittest.cc b/chrome/browser/ash/smb_client/smb_service_unittest.cc index e15b2ca4..913b18b 100644 --- a/chrome/browser/ash/smb_client/smb_service_unittest.cc +++ b/chrome/browser/ash/smb_client/smb_service_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ash/smb_client/smb_service.h" #include "base/json/json_reader.h" +#include "base/strings/string_number_conversions.h" #include "base/test/gmock_callback_support.h" #include "chrome/browser/ash/smb_client/smb_service_test_base.h" #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ash/system_web_apps/apps/media_app/media_web_app_info.cc b/chrome/browser/ash/system_web_apps/apps/media_app/media_web_app_info.cc index 9cc38d74..930d39a9 100644 --- a/chrome/browser/ash/system_web_apps/apps/media_app/media_web_app_info.cc +++ b/chrome/browser/ash/system_web_apps/apps/media_app/media_web_app_info.cc
@@ -13,6 +13,7 @@ #include "ash/webui/media_app_ui/url_constants.h" #include "base/containers/span.h" #include "base/files/file_path.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/apps/app_service/app_launch_params.h"
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc index b2f8df7..2ead8b7 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc
@@ -15,6 +15,7 @@ #include "ash/wallpaper/sea_pen_wallpaper_manager.h" #include "ash/wallpaper/wallpaper_utils/sea_pen_metadata_utils.h" #include "ash/webui/common/mojom/sea_pen.mojom.h" +#include "base/strings/string_number_conversions.h" #include "base/task/sequenced_task_runner.h" #include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.h" #include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_utils.h"
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider.cc index 68ba11bc..abbddeda 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider.cc
@@ -11,6 +11,7 @@ #include "ash/wallpaper/wallpaper_controller_impl.h" #include "base/check.h" #include "base/metrics/histogram_functions.h" +#include "base/strings/string_number_conversions.h" WallpaperMetricsProvider::WallpaperMetricsProvider() = default; WallpaperMetricsProvider::~WallpaperMetricsProvider() = default;
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider_unittest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider_unittest.cc index cb1fa3c..22ae5e7 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider_unittest.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/wallpaper_metrics_provider_unittest.cc
@@ -17,6 +17,7 @@ #include "ash/webui/common/mojom/sea_pen.mojom.h" #include "base/hash/hash.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/test_future.h"
diff --git a/chrome/browser/ash/usb/cros_usb_detector.cc b/chrome/browser/ash/usb/cros_usb_detector.cc index 3ad4d0a..5596d93ee8 100644 --- a/chrome/browser/ash/usb/cros_usb_detector.cc +++ b/chrome/browser/ash/usb/cros_usb_detector.cc
@@ -19,6 +19,7 @@ #include "base/files/file_util.h" #include "base/functional/callback_helpers.h" #include "base/numerics/safe_conversions.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h"
diff --git a/chrome/browser/ash/wallpaper_handlers/google_photos_wallpaper_handlers.cc b/chrome/browser/ash/wallpaper_handlers/google_photos_wallpaper_handlers.cc index 3b5293b..bf2ec14 100644 --- a/chrome/browser/ash/wallpaper_handlers/google_photos_wallpaper_handlers.cc +++ b/chrome/browser/ash/wallpaper_handlers/google_photos_wallpaper_handlers.cc
@@ -14,6 +14,7 @@ #include "base/functional/bind.h" #include "base/i18n/time_formatting.h" #include "base/memory/weak_ptr.h" +#include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "base/values.h" #include "chrome/browser/ash/wallpaper_handlers/wallpaper_prefs.h"
diff --git a/chrome/browser/ash/wallpaper_handlers/mock_google_photos_wallpaper_handlers.cc b/chrome/browser/ash/wallpaper_handlers/mock_google_photos_wallpaper_handlers.cc index 326939b..87a3bbb 100644 --- a/chrome/browser/ash/wallpaper_handlers/mock_google_photos_wallpaper_handlers.cc +++ b/chrome/browser/ash/wallpaper_handlers/mock_google_photos_wallpaper_handlers.cc
@@ -11,6 +11,7 @@ #include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" #include "base/functional/bind.h" #include "base/functional/callback.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" namespace wallpaper_handlers {
diff --git a/chrome/browser/autofill/manual_filling_view_interface.h b/chrome/browser/autofill/manual_filling_view_interface.h index ee66610..853de1b 100644 --- a/chrome/browser/autofill/manual_filling_view_interface.h +++ b/chrome/browser/autofill/manual_filling_view_interface.h
@@ -11,7 +11,6 @@ #include "base/types/strong_alias.h" #include "build/build_config.h" #include "chrome/browser/keyboard_accessory/android/accessory_sheet_enums.h" -#include "url/gurl.h" class ManualFillingController;
diff --git a/chrome/browser/badging/badge_manager_delegate.h b/chrome/browser/badging/badge_manager_delegate.h index 101cca7..09fd273 100644 --- a/chrome/browser/badging/badge_manager_delegate.h +++ b/chrome/browser/badging/badge_manager_delegate.h
@@ -8,7 +8,6 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/badging/badge_manager.h" #include "components/webapps/common/web_app_id.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/browser_switcher/ieem_sitelist_parser.h b/chrome/browser/browser_switcher/ieem_sitelist_parser.h index 417d8cb..cb5403a 100644 --- a/chrome/browser/browser_switcher/ieem_sitelist_parser.h +++ b/chrome/browser/browser_switcher/ieem_sitelist_parser.h
@@ -11,7 +11,6 @@ #include "base/functional/callback.h" #include "chrome/browser/browser_switcher/browser_switcher_prefs.h" -#include "url/gurl.h" namespace browser_switcher {
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc index a4d1499..4523897 100644 --- a/chrome/browser/chrome_browser_main_win.cc +++ b/chrome/browser/chrome_browser_main_win.cc
@@ -18,11 +18,13 @@ #include <stdint.h> #include <algorithm> +#include <optional> #include <string_view> #include <utility> #include <vector> #include "base/base_switches.h" +#include "base/check.h" #include "base/command_line.h" #include "base/dcheck_is_on.h" #include "base/enterprise_util.h" @@ -469,6 +471,87 @@ } } +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) +// Switch used to install platform_experience_helper +const char kPlatformExperienceHelperForceInstallSwitch[] = "force-install"; +// Directory under which platform_experience_helper is installed +const wchar_t kPlatformExperienceHelperDir[] = L"PlatformExperienceHelper"; +// Name of the platform_experience_helper executable +const wchar_t kPlatformExperienceHelperExe[] = + L"platform_experience_helper.exe"; + +// This function might block. +// Returns true if the platform_experience_helper is installed. +// Returns true if it can't determine whether it's installed or not. +bool PlatformExperienceHelperMightBeInstalled() { + // Currently only implemented for user-level installs. + CHECK(!install_static::IsSystemInstall()); + + base::FilePath user_data_dir; + if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { + return true; + } + + base::FilePath peh_exe_path = + user_data_dir.Append(kPlatformExperienceHelperDir) + .Append(kPlatformExperienceHelperExe); + return base::PathExists(peh_exe_path); +} + +// This function might block. Returns nullopt if it can't find an existing path. +std::optional<base::FilePath> GetPlatformExperienceHelperInstallerPath() { + base::FilePath chrome_dir; + if (!base::PathService::Get(base::DIR_EXE, &chrome_dir)) { + return std::nullopt; + } + + const wchar_t kOsUpdateHandlerExe[] = L"os_update_handler.exe"; + base::FilePath exe_path = chrome_dir.AppendASCII(chrome::kChromeVersion) + .Append(kOsUpdateHandlerExe); + if (base::PathExists(exe_path)) { + return exe_path; + } + // In dev builds, the launcher will be in the executable directory. + exe_path = chrome_dir.Append(kOsUpdateHandlerExe); + if (base::PathExists(exe_path)) { + return exe_path; + } + return std::nullopt; +} + +// This function might block. +void MaybeInstallPlatformExperienceHelper() { + // TODO(crbug.com/393626337): remove this check once we implement PEH + // installation for system-level installs. + if (install_static::IsSystemInstall()) { + return; + } + + if (PlatformExperienceHelperMightBeInstalled()) { + return; + } + + std::optional<base::FilePath> peh_installer_path = + GetPlatformExperienceHelperInstallerPath(); + if (!peh_installer_path.has_value()) { + return; + } + base::CommandLine install_cmd(peh_installer_path.value()); + install_cmd.AppendSwitch(kPlatformExperienceHelperForceInstallSwitch); + InstallUtil::AppendModeAndChannelSwitches(&install_cmd); + + base::LaunchOptions launch_options; + launch_options.feedback_cursor_off = true; + launch_options.force_breakaway_from_job_ = true; + ::SetLastError(ERROR_SUCCESS); + base::Process process = base::LaunchProcess(install_cmd, launch_options); + if (!process.IsValid()) { + PLOG(ERROR) << "Failed to launch \"" << install_cmd.GetCommandLineString() + << "\""; + } +} +#endif // GOOGLE_CHROME_BRANDING + // This error message is not localized because we failed to load the // localization data files. const char kMissingLocaleDataTitle[] = "Missing File Error"; @@ -740,6 +823,12 @@ g_browser_process->local_state()->SetBoolean( prefs::kOsUpdateHandlerEnabled, base::FeatureList::IsEnabled(features::kRegisterOsUpdateHandlerWin)); + if (base::FeatureList::IsEnabled( + features::kInstallPlatformExperienceHelperWin)) { + base::ThreadPool::PostTask( + FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, + base::BindOnce(&MaybeInstallPlatformExperienceHelper)); + } #endif // GOOGLE_CHROME_BRANDING // Record the parent process at a low priority.
diff --git a/chrome/browser/chromeos/arc/open_with_menu.h b/chrome/browser/chromeos/arc/open_with_menu.h index b2f8f47..d17b9d0 100644 --- a/chrome/browser/chromeos/arc/open_with_menu.h +++ b/chrome/browser/chromeos/arc/open_with_menu.h
@@ -14,7 +14,6 @@ #include "chromeos/ash/experiences/arc/intent_helper/link_handler_model.h" #include "components/renderer_context_menu/render_view_context_menu_observer.h" #include "ui/menus/simple_menu_model.h" -#include "url/gurl.h" class RenderViewContextMenuProxy;
diff --git a/chrome/browser/compose/mock_chrome_compose_client.h b/chrome/browser/compose/mock_chrome_compose_client.h index 5f8af6e..d1c8ce4f 100644 --- a/chrome/browser/compose/mock_chrome_compose_client.h +++ b/chrome/browser/compose/mock_chrome_compose_client.h
@@ -8,7 +8,6 @@ #include "chrome/browser/compose/chrome_compose_client.h" #include "components/autofill/core/browser/foundations/autofill_client.h" #include "testing/gmock/include/gmock/gmock.h" -#include "url/gurl.h" class MockChromeComposeClient : public ChromeComposeClient { public:
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc index 70135d3..8b18487 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
@@ -53,6 +53,7 @@ #include "components/enterprise/connectors/core/common.h" #include "components/enterprise/connectors/core/features.h" #include "components/enterprise/connectors/core/reporting_utils.h" +#include "components/guest_view/browser/guest_view_base.h" #include "components/policy/core/common/chrome_schema.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h" @@ -68,13 +69,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_types.h" -#if BUILDFLAG(ENABLE_GLIC) -#include "chrome/browser/glic/glic_keyed_service.h" -#include "chrome/browser/glic/glic_profile_manager.h" -#include "chrome/browser/glic/host/guest_util.h" -#include "components/guest_view/browser/guest_view_base.h" -#endif - #if BUILDFLAG(ENTERPRISE_LOCAL_CONTENT_ANALYSIS) #include "chrome/browser/enterprise/connectors/analysis/content_analysis_sdk_manager.h" // nogncheck #endif @@ -441,35 +435,15 @@ show_fail_closed_ui ? FinalContentAnalysisResult::FAIL_CLOSED : FinalContentAnalysisResult::SUCCESS; -#if BUILDFLAG(ENABLE_GLIC) && BUILDFLAG(IS_WIN) + // This dialog is owned by the constrained_window code. content::WebContents* top_web_contents = guest_view::GuestViewBase::GetTopLevelWebContents( web_contents->GetResponsibleWebContents()); - if (glic::IsGlicWebUI(top_web_contents)) { - DVLOG(1) << __func__ - << ": Skipping web modal on glic surface. Showing glic timed " - "modal instead."; - if (glic::GlicProfileManager::GetInstance()) { - if (glic::GlicKeyedService* glic_keyed_service = - glic::GlicProfileManager::GetInstance()->GetLastActiveGlic()) { - std::u16string label = l10n_util::GetPluralStringFUTF16( - IDS_DEEP_SCANNING_DIALOG_UPLOAD_WARNING_MESSAGE, 1); - base::UmaHistogramEnumeration("Glic.Modal.DeepScanAccessPoint", - access_point); - glic_keyed_service->window_controller().ShowGlicModal(label); - } - } - delegate->Cancel(/*warning=*/false); - return; - } -#endif - - // This dialog is owned by the constrained_window code. delegate_ptr->dialog_ = new ContentAnalysisDialogController( std::move(delegate), delegate_ptr->data_.settings.cloud_or_local_settings .is_cloud_analysis(), - web_contents, access_point, files_count, result); + top_web_contents, access_point, files_count, result); return; }
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.cc index 0ffaf2a9..f4e9c71 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.cc
@@ -14,11 +14,9 @@ #include "chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h" #include "chrome/browser/enterprise/connectors/analysis/content_analysis_features.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h" -#include "chrome/common/buildflags.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "components/constrained_window/constrained_window_views.h" -#include "components/guest_view/browser/guest_view_base.h" #include "components/strings/grit/components_strings.h" #include "components/vector_icons/vector_icons.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" @@ -56,13 +54,6 @@ #include "base/win/windows_h_disallowed.h" -#if BUILDFLAG(ENABLE_GLIC) -#include "base/metrics/histogram_functions.h" -#include "chrome/browser/glic/host/guest_util.h" -#include "chrome/browser/glic/widget/glic_widget.h" -#include "components/guest_view/browser/guest_view_base.h" -#endif - namespace enterprise_connectors { namespace { @@ -112,25 +103,6 @@ void OnViewThemeChanged(views::View* view) override { view->SchedulePaint(); } }; -gfx::Rect GetDialogBounds(content::WebContents* contents, - const gfx::Rect& current_widget_bounds) { - gfx::Rect rect = contents->GetContainerBounds(); - - // This will show the dialog right above the top of the contents. - rect.set_y(rect.y() - 40); -#if BUILDFLAG(ENABLE_GLIC) - if (glic::IsGlicWebUI(contents)) { - // This will show the dialog right below the "header" part of Glic. - rect.set_y(rect.y() + 80); - } -#endif // BUILDFLAG(ENABLE_GLIC) - - rect.set_x(rect.x() + (rect.width() / 2) - - (current_widget_bounds.width() / 2)); - - return rect; -} - ContentAnalysisDialogController::TestObserver* observer_for_testing = nullptr; } // namespace @@ -310,22 +282,6 @@ return; } -// Glic port enabled for Mac only at the moment until fixed on Windows. -// TODO(416748209): Follow up with full port of ContentAnalysisDialog to use -// non web modals on both Mac and Windows for all sources. -#if BUILDFLAG(ENABLE_GLIC) && BUILDFLAG(IS_MAC) - if (glic::IsGlicWebUI(top_level_contents_.get())) { - // make sure only one dialog is displayed at a time. If a dialog exists we - // just update the view. - if (contents_view_) { - return; - } - ShowNonTabDialogNow(); - base::UmaHistogramEnumeration("Glic.Modal.DeepScan", access_point_); - return; - } -#endif - auto* manager = web_modal::WebContentsModalDialogManager::FromWebContents(web_contents()); if (!manager) { @@ -352,23 +308,6 @@ } } -void ContentAnalysisDialogController::ShowNonTabDialogNow() { - content::WebContents* top_web_contents = - guest_view::GuestViewBase::GetTopLevelWebContents(web_contents()); - raw_ptr<views::Widget> dialog_widget = - views::DialogDelegate::CreateDialogWidget( - weak_ptr_factory_.GetWeakPtr().get(), gfx::NativeWindow(), - top_web_contents->GetNativeView()); - - dialog_widget->SetBounds(GetDialogBounds( - top_web_contents, dialog_widget->GetWindowBoundsInScreen())); - - dialog_widget->Show(); - if (observer_for_testing) { - observer_for_testing->ViewsFirstShown(this, first_shown_timestamp_); - } -} - std::u16string ContentAnalysisDialogController::GetWindowTitle() const { return std::u16string(); }
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.h b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.h index 1e9d344ba..6677ce3 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.h +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_controller.h
@@ -216,7 +216,6 @@ // Callback function of delayed timer to make the dialog visible. void ShowDialogNow(); - void ShowNonTabDialogNow(); void UpdateStateFromFinalResult(FinalContentAnalysisResult final_result);
diff --git a/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.h b/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.h index e66cddd..f442c51 100644 --- a/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.h +++ b/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.h
@@ -14,7 +14,6 @@ #include "components/safe_browsing/core/common/proto/realtimeapi.pb.h" #include "content/public/browser/navigation_handle_user_data.h" #include "content/public/browser/web_contents_observer.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/enterprise/remote_commands/user_remote_commands_service_browsertest.cc b/chrome/browser/enterprise/remote_commands/user_remote_commands_service_browsertest.cc index 785e052..c6b1a9d 100644 --- a/chrome/browser/enterprise/remote_commands/user_remote_commands_service_browsertest.cc +++ b/chrome/browser/enterprise/remote_commands/user_remote_commands_service_browsertest.cc
@@ -179,6 +179,8 @@ auto fake_policy_data = std::make_unique<em::PolicyData>(); fake_policy_data->set_device_id( policy_manager->core()->client()->client_id()); + fake_policy_data->set_cec_enabled(true); + fake_policy_data->set_command_invalidation_topic("fake-topic"); store->set_policy_data_for_testing(std::move(fake_policy_data)); store->set_policy_signature_public_key_for_testing( test_server_->policy_storage()
diff --git a/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc b/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc index e0d533b..764fc12 100644 --- a/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc +++ b/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc
@@ -397,6 +397,19 @@ return false; } + // When moving a group between windows, Saved Tab Groups must pause + // listening since the group is in an invalid state. Since Extensions + // implements it's own bulk move action, pausing must be performed here. + tab_groups::TabGroupSyncService* tab_group_sync_service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile( + target_browser->profile()); + std::unique_ptr<tab_groups::ScopedLocalObservationPauser> + tab_groups_sync_movement_observation; + if (tab_group_sync_service) { + tab_groups_sync_movement_observation = + tab_group_sync_service->CreateScopedLocalObserverPauser(); + } + TabStripModel* source_tab_strip = source_browser->tab_strip_model(); std::unique_ptr<DetachedTabCollection> detached_group = source_tab_strip->DetachTabGroupForInsertion(group);
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index c1d925a..7d296ff 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -40,10 +40,13 @@ #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/error_console/error_console.h" #include "chrome/browser/extensions/error_console/error_console_test_observer.h" +#include "chrome/browser/extensions/extension_action_runner.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_browser_test_util.h" #include "chrome/browser/extensions/extension_tab_util.h" +#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/extension_with_management_policy_apitest.h" +#include "chrome/browser/extensions/permissions/active_tab_permission_granter.h" #include "chrome/browser/extensions/permissions/scripting_permissions_modifier.h" #include "chrome/browser/net/profile_network_context_service.h" #include "chrome/browser/net/profile_network_context_service_factory.h" @@ -97,6 +100,7 @@ #include "extensions/browser/process_manager.h" #include "extensions/browser/service_worker/service_worker_task_queue.h" #include "extensions/browser/service_worker/service_worker_test_utils.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/extension_builder.h" #include "extensions/common/extension_features.h" #include "extensions/common/features/feature.h" @@ -143,9 +147,6 @@ #endif #if !BUILDFLAG(IS_ANDROID) -#include "chrome/browser/extensions/extension_action_runner.h" -#include "chrome/browser/extensions/extension_util.h" -#include "chrome/browser/extensions/permissions/active_tab_permission_granter.h" #include "chrome/browser/extensions/test_extension_action_dispatcher_observer.h" #include "chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader.h" #include "chrome/browser/new_tab_page/one_google_bar/one_google_bar_service.h" @@ -165,6 +166,8 @@ #include "chrome/browser/ash/profiles/profile_helper.h" #endif // BUILDFLAG(IS_CHROMEOS) +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + using content::WebContents; namespace extensions { @@ -272,11 +275,11 @@ " xhr.send();\n" "});\n"; -#if !BUILDFLAG(IS_ANDROID) // Header values set by the server and by the extension. const char kHeaderValueFromExtension[] = "ValueFromExtension"; const char kHeaderValueFromServer[] = "ValueFromServer"; +#if !BUILDFLAG(IS_ANDROID) constexpr char kCORSUrl[] = "http://cors.test/cors"; constexpr char kCORSProxyUser[] = "testuser"; constexpr char kCORSProxyPass[] = "testpass"; @@ -452,14 +455,6 @@ test_dirs_.push_back(std::move(dir)); } - void NavigateToURL(const GURL& url) { -#if BUILDFLAG(IS_ANDROID) - ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), url)); -#else - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); -#endif - } - void OpenUrlInNewTab(const GURL& url) { #if BUILDFLAG(IS_ANDROID) android_ui_test_utils::OpenUrlInNewTab(profile(), web_contents(), url); @@ -563,7 +558,7 @@ { ExtensionTestMessageListener listener1("iframe1 ready"); ExtensionTestMessageListener listener2("iframe2 ready"); - NavigateToURL(extension->GetResourceURL("parent.html")); + ASSERT_TRUE(NavigateToURL(extension->GetResourceURL("parent.html"))); ASSERT_TRUE(listener1.WaitUntilSatisfied()); ASSERT_TRUE(listener2.WaitUntilSatisfied()); } @@ -749,13 +744,11 @@ BackgroundResourceFetchTestCase::kBackgroundResourceFetchDisabled)), ExtensionWebRequestApiTestWithContextType::PrintToStringParamName()); -#if BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiTestWithContextTypeMV3, WebRequestApi) { ASSERT_TRUE(StartEmbeddedTestServer()); ASSERT_TRUE(RunExtensionTest("webrequest/test_api")) << message_; } -#endif INSTANTIATE_TEST_SUITE_P( PersistentBackground, @@ -783,34 +776,34 @@ BackgroundResourceFetchTestCase::kBackgroundResourceFetchDisabled)), ExtensionWebRequestApiTestWithContextType::PrintToStringParamName()); +INSTANTIATE_TEST_SUITE_P( + PersistentBackground, + ExtensionWebRequestApiTestWithContextTypeForHstsTopLevelNavigationOnly, + ::testing::Values( + std::make_pair( + ContextType::kPersistentBackground, + BackgroundResourceFetchTestCase::kBackgroundResourceFetchEnabled), + std::make_pair( + ContextType::kPersistentBackground, + BackgroundResourceFetchTestCase::kBackgroundResourceFetchDisabled)), + ExtensionWebRequestApiTestWithContextType::PrintToStringParamName()); + +// These tests use webRequestBlocking and/or declarativeWebRequest. +// See crbug.com/332512510. +INSTANTIATE_TEST_SUITE_P( + ServiceWorker, + ExtensionWebRequestApiTestWithContextTypeForHstsTopLevelNavigationOnly, + ::testing::Values( + std::make_pair( + ContextType::kServiceWorkerMV2, + BackgroundResourceFetchTestCase::kBackgroundResourceFetchEnabled), + std::make_pair( + ContextType::kServiceWorkerMV2, + BackgroundResourceFetchTestCase::kBackgroundResourceFetchDisabled)), + ExtensionWebRequestApiTestWithContextType::PrintToStringParamName()); + // TODO(crbug.com/371324825): Enable more tests for Android build. #if !BUILDFLAG(IS_ANDROID) -INSTANTIATE_TEST_SUITE_P( - PersistentBackground, - ExtensionWebRequestApiTestWithContextTypeForHstsTopLevelNavigationOnly, - ::testing::Values( - std::make_pair( - ContextType::kPersistentBackground, - BackgroundResourceFetchTestCase::kBackgroundResourceFetchEnabled), - std::make_pair( - ContextType::kPersistentBackground, - BackgroundResourceFetchTestCase::kBackgroundResourceFetchDisabled)), - ExtensionWebRequestApiTestWithContextType::PrintToStringParamName()); - -// These tests use webRequestBlocking and/or declarativeWebRequest. -// See crbug.com/332512510. -INSTANTIATE_TEST_SUITE_P( - ServiceWorker, - ExtensionWebRequestApiTestWithContextTypeForHstsTopLevelNavigationOnly, - ::testing::Values( - std::make_pair( - ContextType::kServiceWorkerMV2, - BackgroundResourceFetchTestCase::kBackgroundResourceFetchEnabled), - std::make_pair( - ContextType::kServiceWorkerMV2, - BackgroundResourceFetchTestCase::kBackgroundResourceFetchDisabled)), - ExtensionWebRequestApiTestWithContextType::PrintToStringParamName()); - class DevToolsFrontendInWebRequestApiTest : public ExtensionApiTest { public: DevToolsFrontendInWebRequestApiTest() { @@ -901,6 +894,7 @@ std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_; std::unique_ptr<NavigateTabMessageHandler> navigation_handler_; }; +#endif // !BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiTestWithContextType, WebRequestApi) { @@ -908,6 +902,7 @@ ASSERT_TRUE(RunExtensionTest("webrequest/test_api")) << message_; } +#if !BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiTestWithContextType, WebRequestSimple) { ASSERT_TRUE(StartEmbeddedTestServer()); @@ -1915,6 +1910,7 @@ // extension should have access to the request. EXPECT_EQ("Intercepted requests: ?contentscript", listener_result.message()); } +#endif // !BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, HostedAppRequest) { ASSERT_TRUE(StartEmbeddedTestServer()); @@ -1940,12 +1936,13 @@ ASSERT_TRUE( LoadExtension(test_data_dir_.AppendASCII("webrequest_hosted_app"))); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), hosted_app_url)); + ASSERT_TRUE(NavigateToURL(hosted_app_url)); EXPECT_TRUE(listener1.WaitUntilSatisfied()); EXPECT_TRUE(listener2.WaitUntilSatisfied()); } +#if !BUILDFLAG(IS_ANDROID) // Tests that WebRequest works with runtime host permissions. IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiTestWithContextType, WebRequestWithWithheldPermissions) { @@ -2210,11 +2207,10 @@ EXPECT_EQ(0, get_clients_google_request_count()); EXPECT_EQ(0, get_yahoo_request_count()); - content::WebContents* web_contents = GetActiveWebContents(); - ASSERT_TRUE(web_contents); + auto* web_contents = GetActiveWebContents(); GURL main_frame_url = embedded_test_server()->GetURL("www.example.com", "/simple.html"); - EXPECT_TRUE(content::NavigateToURL(web_contents, main_frame_url)); + EXPECT_TRUE(NavigateToURL(main_frame_url)); content::WaitForLoadStop(web_contents); EXPECT_EQ(0, get_clients_google_request_count()); @@ -2302,9 +2298,7 @@ ->FlushProxyConfigMonitorForTesting(); // Navigate to a page. The URL doesn't matter. - content::WebContents* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, GURL("http://does.not.resolve.test/title2.html"))); + ASSERT_TRUE(NavigateToURL(GURL("http://does.not.resolve.test/title2.html"))); // The extension should not have seen the PAC request. EXPECT_EQ(0, GetCountFromBackgroundScript(extension, profile(), @@ -2316,12 +2310,12 @@ // The PAC request should have succeeded, as should the subsequent URL // request. - EXPECT_EQ( - content::PAGE_TYPE_NORMAL, - web_contents->GetController().GetLastCommittedEntry()->GetPageType()); + EXPECT_EQ(content::PAGE_TYPE_NORMAL, GetActiveWebContents() + ->GetController() + .GetLastCommittedEntry() + ->GetPageType()); } -#if !BUILDFLAG(IS_ANDROID) // Checks that the Dice response header is protected for Gaia URLs, but not // other URLs. IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiTestWithContextType, @@ -2390,14 +2384,12 @@ std::string control_header_value_; }; - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - TestWebContentsObserver test_webcontents_observer(web_contents); + TestWebContentsObserver test_webcontents_observer(GetActiveWebContents()); // Navigate to the Gaia URL intercepted by the extension. GURL url = embedded_test_server()->GetURL("gaia.com", "/extensions/dice.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + ASSERT_TRUE(NavigateToURL(url)); // Check that the Dice header was not changed by the extension. EXPECT_TRUE(test_webcontents_observer.did_finish_navigation_called()); @@ -2417,7 +2409,7 @@ // Navigate to a non-Gaia URL intercepted by the extension. test_webcontents_observer.Clear(); url = embedded_test_server()->GetURL("example.com", "/extensions/dice.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + ASSERT_TRUE(NavigateToURL(url)); // Check that the Dice header was changed by the extension. EXPECT_TRUE(test_webcontents_observer.did_finish_navigation_called()); @@ -2435,6 +2427,7 @@ "self.controlResponseHeaderCount")); } +#if !BUILDFLAG(IS_ANDROID) // Test that the webRequest events are dispatched for the WebSocket handshake // requests. // TODO(crbug.com/40715657): Test is flaky on multiple platforms. @@ -2601,19 +2594,20 @@ // First, check normal requests (e.g., navigations) to verify the extension // is working correctly. - content::WebContents* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL(web_contents, google_url)); + auto* web_contents = GetActiveWebContents(); + ASSERT_TRUE(NavigateToURL(google_url)); EXPECT_EQ(google_url, web_contents->GetLastCommittedURL()); // google.com should succeed. EXPECT_EQ(kGoogleBodyContent, - content::EvalJs(web_contents, "document.body.textContent.trim();")); + content::EvalJs(GetActiveWebContents(), + "document.body.textContent.trim();")); GURL example_url = embedded_test_server()->GetURL("example.com", "/extensions/body2.html"); // Navigation to example.com should fail. - ASSERT_FALSE(content::NavigateToURL(web_contents, example_url)); + ASSERT_FALSE(NavigateToURL(example_url)); { content::NavigationEntry* nav_entry = web_contents->GetController().GetLastCommittedEntry(); @@ -2730,10 +2724,8 @@ ":" + testcase.expected_initiator); ExtensionTestMessageListener initiator_listener; initiator_listener.set_extension_id(extension->id()); - ASSERT_TRUE(content::NavigateToURL( - web_contents, - embedded_test_server()->GetURL(testcase.navigate_before_start, - "/extensions/body1.html"))); + ASSERT_TRUE(NavigateToURL(embedded_test_server()->GetURL( + testcase.navigate_before_start, "/extensions/body1.html"))); content::WaitForLoadStop(web_contents); PerformXhrInFrame(web_contents->GetPrimaryMainFrame(), testcase.xhr_domain, port, "extensions/api_test/webrequest/xhr/data.json"); @@ -2866,8 +2858,7 @@ // Opens a chrome-untrusted:// page. auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, GURL("chrome-untrusted://test/title1.html"))); + ASSERT_TRUE(NavigateToURL(GURL("chrome-untrusted://test/title1.html"))); content::WaitForLoadStop(web_contents); auto* rfh = web_contents->GetPrimaryMainFrame(); @@ -2922,8 +2913,7 @@ // Opens a chrome-untrusted:// page. auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, GURL("chrome-untrusted://test/title1.html"))); + ASSERT_TRUE(NavigateToURL(GURL("chrome-untrusted://test/title1.html"))); content::WaitForLoadStop(web_contents); auto* rfh = web_contents->GetPrimaryMainFrame(); @@ -2960,8 +2950,7 @@ // Opens a chrome-untrusted:// page. auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, GURL("chrome-untrusted://test/title1.html"))); + ASSERT_TRUE(NavigateToURL(GURL("chrome-untrusted://test/title1.html"))); content::WaitForLoadStop(web_contents); auto* rfh = web_contents->GetPrimaryMainFrame(); @@ -2998,8 +2987,7 @@ // Opens a chrome-untrusted:// page. auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, GURL("chrome-untrusted://test/title1.html"))); + ASSERT_TRUE(NavigateToURL(GURL("chrome-untrusted://test/title1.html"))); content::WaitForLoadStop(web_contents); auto* rfh = web_contents->GetPrimaryMainFrame(); @@ -3330,9 +3318,8 @@ request_counter_name)); // Wait until all remote Javascript files have been blocked / pulled down. - auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL(web_contents, extension_test_url)); - content::WaitForLoadStop(web_contents); + ASSERT_TRUE(NavigateToURL(extension_test_url)); + content::WaitForLoadStop(GetActiveWebContents()); // Domain that hosts javascript file referenced by example_com. const std::string example2_com = "example2.com"; @@ -3359,9 +3346,8 @@ } // Wait until all remote Javascript files have been pulled down. - web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL(web_contents, extension_test_url)); - content::WaitForLoadStop(web_contents); + ASSERT_TRUE(NavigateToURL(extension_test_url)); + content::WaitForLoadStop(GetActiveWebContents()); // The server saw a request for the remote Javascript file. EXPECT_TRUE(BrowsedTo(example2_com)); @@ -3394,11 +3380,9 @@ const std::string test_path = "/defaultresponse?protected_url"; // Navigate to the protected domain and wait until page fully loads. - auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, + ASSERT_TRUE(NavigateToURL( embedded_test_server()->GetURL(protected_domain, test_path))); - content::WaitForLoadStop(web_contents); + content::WaitForLoadStop(GetActiveWebContents()); // The server saw a request for the protected site. EXPECT_TRUE(BrowsedTo(protected_domain)); @@ -3411,11 +3395,9 @@ // Now we'll test browsing to a non-protected website where we expect the // extension to see the request. - web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, + ASSERT_TRUE(NavigateToURL( embedded_test_server()->GetURL(unprotected_domain, test_path))); - content::WaitForLoadStop(web_contents); + content::WaitForLoadStop(GetActiveWebContents()); // The server saw a request for the non-protected site. EXPECT_TRUE(BrowsedTo(unprotected_domain)); @@ -3454,11 +3436,9 @@ content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); -#if !BUILDFLAG(IS_ANDROID) ExtensionActionRunner* runner = ExtensionActionRunner::GetForWebContents(web_contents); ASSERT_TRUE(runner); -#endif // !BUILDFLAG(IS_ANDROID) int port = embedded_test_server()->port(); const std::string kXhrPath = "simple.html"; @@ -3469,7 +3449,6 @@ kXhrPath); EXPECT_EQ(0, GetWebRequestCountFromBackgroundScript(extension, profile())); -#if !BUILDFLAG(IS_ANDROID) // Grant activeTab permission, and perform another XHR. The extension should // still be blocked due to ExtensionSettings policy on example.com. // Only records ACCESS_WITHHELD, not ACCESS_DENIED, this is why it matches @@ -3480,8 +3459,6 @@ base::RunLoop().RunUntilIdle(); EXPECT_TRUE(content::WaitForLoadStop(web_contents)); EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension->id())); -#endif // !BUILDFLAG(IS_ANDROID) - int xhr_count = GetWebRequestCountFromBackgroundScript(extension, profile()); // ... which means that we should have a non-zero xhr count if the policy // didn't block the events. @@ -3697,8 +3674,7 @@ // Navigate to a basic page so XHR requests work. auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL(web_contents, - embedded_test_server()->GetURL("/echo"))); + ASSERT_TRUE(NavigateToURL(embedded_test_server()->GetURL("/echo"))); content::WaitForLoadStop(web_contents); // Make a XHR request which redirects. The final response should not include @@ -3772,11 +3748,9 @@ EXPECT_TRUE(listener.WaitUntilSatisfied()); base::HistogramTester tester; - auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, + ASSERT_TRUE(NavigateToURL( embedded_test_server()->GetURL("/set-cookie?key1=val1&key2=val2"))); - content::WaitForLoadStop(web_contents); + content::WaitForLoadStop(GetActiveWebContents()); // Changed histograms should record kUserAgent request header along with // kSetCookie and kContentLength response headers. @@ -3863,10 +3837,9 @@ EXPECT_TRUE(listener.WaitUntilSatisfied()); base::HistogramTester tester; - auto* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL( - web_contents, embedded_test_server()->GetURL("/set-cookie?Foo=Bar"))); - content::WaitForLoadStop(web_contents); + ASSERT_TRUE( + NavigateToURL(embedded_test_server()->GetURL("/set-cookie?Foo=Bar"))); + content::WaitForLoadStop(GetActiveWebContents()); // Histograms for removed headers should record kUserAgent and kSetCookie. tester.ExpectUniqueSample("Extensions.WebRequest.RequestHeaderRemoved", @@ -4452,6 +4425,7 @@ ASSERT_TRUE(result); EXPECT_EQ(base::StringPrintf("[\"%s\"]", origin_incognito.c_str()), *result); } +#endif // !BUILDFLAG(IS_ANDROID) // A request handler that sets the Access-Control-Allow-Origin header. std::unique_ptr<net::test_server::HttpResponse> HandleXHRRequest( @@ -4475,28 +4449,27 @@ TestExtensionDir test_dir; test_dir.WriteManifest(R"({ - "name": "Web Request HSTS Test", - "manifest_version": 2, - "version": "0.1", - "background": { "scripts": ["background.js"], "persistent": true }, - "permissions": ["<all_urls>", "webRequest", "webRequestBlocking"] - })"); + "name": "Web Request HSTS Test", + "manifest_version": 2, + "version": "0.1", + "background": { "scripts": ["background.js"], "persistent": true }, + "permissions": ["<all_urls>", "webRequest", "webRequestBlocking"] + })"); test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), R"( - chrome.webRequest.onBeforeRedirect.addListener(function(details) { - self.headerCount = details.responseHeaders.length; - }, {urls: ['<all_urls>']}, - ['responseHeaders', 'extraHeaders']); + chrome.webRequest.onBeforeRedirect.addListener(function(details) { + self.headerCount = details.responseHeaders.length; + }, {urls: ['<all_urls>']}, + ['responseHeaders', 'extraHeaders']); - chrome.test.sendMessage('ready'); - )"); + chrome.test.sendMessage('ready'); + )"); ExtensionTestMessageListener listener("ready"); const Extension* extension = LoadExtension(test_dir.UnpackedPath()); ASSERT_TRUE(extension); EXPECT_TRUE(listener.WaitUntilSatisfied()); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), - https_test_server.GetURL("/echo"))); + ASSERT_TRUE(NavigateToURL(https_test_server.GetURL("/echo"))); content::StoragePartition* partition = profile()->GetDefaultStoragePartition(); @@ -4506,10 +4479,7 @@ base::Time::Now() + base::Days(100), true, run_loop.QuitClosure()); run_loop.Run(); - PerformXhrInFrame(browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetPrimaryMainFrame(), + PerformXhrInFrame(GetActiveWebContents()->GetPrimaryMainFrame(), https_test_server.host_port_pair().host(), https_test_server.port(), "echo"); EXPECT_GT( @@ -4517,6 +4487,7 @@ 0); } +#if !BUILDFLAG(IS_ANDROID) // Ensure that when an extension blocks a main-frame request, the resultant // error page attributes this to an extension. IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, @@ -6649,10 +6620,9 @@ ASSERT_TRUE(extension); // Load the page with the extension listeners. - content::WebContents* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL(web_contents, - extension->GetResourceURL("page.html"))); - content::RenderFrameHost* page_host = web_contents->GetPrimaryMainFrame(); + ASSERT_TRUE(NavigateToURL(extension->GetResourceURL("page.html"))); + content::RenderFrameHost* page_host = + GetActiveWebContents()->GetPrimaryMainFrame(); ASSERT_TRUE(page_host); // At this point, 3 listeners should be registered. @@ -6686,16 +6656,14 @@ EXPECT_EQ(0, get_third_count()); // Navigate to second.example. The second listener should fire. - ASSERT_TRUE(content::NavigateToURL( - GetActiveWebContents(), + ASSERT_TRUE(NavigateToURL( embedded_test_server()->GetURL("second.example", "/title1.html"))); EXPECT_EQ(1, get_first_count()); EXPECT_EQ(1, get_second_count()); EXPECT_EQ(0, get_third_count()); // Navigate to third.example. The third listener should fire. - ASSERT_TRUE(content::NavigateToURL( - GetActiveWebContents(), + ASSERT_TRUE(NavigateToURL( embedded_test_server()->GetURL("third.example", "/title1.html"))); EXPECT_EQ(1, get_first_count()); EXPECT_EQ(1, get_second_count()); @@ -6841,8 +6809,7 @@ profile(), "webRequest.onBeforeRequest")); // Navigate to a URL. The request should be seen by the extension. - EXPECT_TRUE(content::NavigateToURL( - GetActiveWebContents(), + EXPECT_TRUE(NavigateToURL( embedded_test_server()->GetURL("example.com", "/simple.html"))); auto get_request_count = [this, extension]() { @@ -6876,8 +6843,7 @@ // scenario, there's no guarantee this happens by the time navigation // completes. ExtensionTestMessageListener listener("event received"); - EXPECT_TRUE(content::NavigateToURL( - GetActiveWebContents(), + EXPECT_TRUE(NavigateToURL( embedded_test_server()->GetURL("example.com", "/simple.html"))); EXPECT_TRUE(listener.WaitUntilSatisfied()); } @@ -7008,8 +6974,7 @@ profile(), "webRequest.onBeforeRequest")); // Navigate to a page and verify that only the second listener fires. - EXPECT_TRUE(content::NavigateToURL( - GetActiveWebContents(), + EXPECT_TRUE(NavigateToURL( embedded_test_server()->GetURL("example.com", "/simple.html"))); EXPECT_EQ(0, GetCountFromBackgroundScript(extension, profile(), @@ -7068,10 +7033,9 @@ ASSERT_TRUE(extension); // Load the page with the extension listeners. - content::WebContents* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL(web_contents, - extension->GetResourceURL("page.html"))); - content::RenderFrameHost* page_host = web_contents->GetPrimaryMainFrame(); + ASSERT_TRUE(NavigateToURL(extension->GetResourceURL("page.html"))); + content::RenderFrameHost* page_host = + GetActiveWebContents()->GetPrimaryMainFrame(); ASSERT_TRUE(page_host); // At this point, 2 listeners should be registered. @@ -7166,10 +7130,9 @@ ASSERT_TRUE(extension); // Load the page with the extension listeners. - content::WebContents* web_contents = GetActiveWebContents(); - ASSERT_TRUE(content::NavigateToURL(web_contents, - extension->GetResourceURL("page.html"))); - content::RenderFrameHost* page_host = web_contents->GetPrimaryMainFrame(); + ASSERT_TRUE(NavigateToURL(extension->GetResourceURL("page.html"))); + content::RenderFrameHost* page_host = + GetActiveWebContents()->GetPrimaryMainFrame(); ASSERT_TRUE(page_host); // At this point, 2 listeners should be registered.
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc index 97f9aaf..ad264a8 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -26,10 +26,8 @@ #include "base/version.h" #include "base/version_info/version_info.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/api/webstore_private/extension_install_status.h" -#include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_allowlist.h" #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/install_approval.h" @@ -47,6 +45,7 @@ #include "components/crx_file/id_util.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h" #include "components/safe_browsing/core/browser/safe_browsing_metrics_collector.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -332,8 +331,7 @@ return gfx::ImageSkia::CreateFrom1xBitmap(icon); } - return is_app ? extensions::util::GetDefaultAppIcon() - : extensions::util::GetDefaultExtensionIcon(); + return is_app ? util::GetDefaultAppIcon() : util::GetDefaultExtensionIcon(); } // These values are persisted to logs. Entries should not be renumbered and @@ -445,9 +443,8 @@ InstallTracker* tracker = InstallTracker::Get(browser_context()); DCHECK(tracker); bool is_installed = - extensions::ExtensionRegistry::Get(browser_context()) - ->GetExtensionById(details().id, - extensions::ExtensionRegistry::EVERYTHING) != + ExtensionRegistry::Get(browser_context()) + ->GetExtensionById(details().id, ExtensionRegistry::EVERYTHING) != nullptr; if (is_installed || tracker->GetActiveInstall(details().id)) { return RespondNow( @@ -945,7 +942,7 @@ Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); std::string message_from_admin = - extensions::ExtensionManagementFactory::GetForBrowserContext(profile) + ExtensionManagementFactory::GetForBrowserContext(profile) ->BlockedInstallMessage(extension->id()); if (!message_from_admin.empty()) { blocked_by_policy_error_message_ = @@ -955,8 +952,8 @@ gfx::ImageSkia image = GetIconImage(icon, extension->is_app()); - if (extensions::ScopedTestDialogAutoConfirm::GetAutoConfirmValue() != - extensions::ScopedTestDialogAutoConfirm::NONE) { + if (ScopedTestDialogAutoConfirm::GetAutoConfirmValue() != + ScopedTestDialogAutoConfirm::NONE) { base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, std::move(done_callback)); return;
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h index 1b179259..e15af07 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
@@ -13,7 +13,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/values.h" -#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h" #include "chrome/browser/extensions/active_install_data.h" #include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/webstore_install_helper.h"
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 97868e0..6a376cf3 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -717,7 +717,10 @@ if (!Exists(extension_misc::kEspeakSpeechSynthesisExtensionId)) { AddComponentFromDir( - base::FilePath(extension_misc::kEspeakSpeechSynthesisExtensionPath), + base::FilePath( + ::features::IsAccessibilityManifestV3EnabledForEspeakNGTts() + ? extension_misc::kEspeakManifestV3SpeechSynthesisExtensionPath + : extension_misc::kEspeakSpeechSynthesisExtensionPath), extension_misc::kEspeakSpeechSynthesisExtensionId, base::BindRepeating( &ComponentLoader::FinishLoadSpeechSynthesisExtension,
diff --git a/chrome/browser/extensions/extension_uninstall_dialog.h b/chrome/browser/extensions/extension_uninstall_dialog.h index 0be79ba6..6202707 100644 --- a/chrome/browser/extensions/extension_uninstall_dialog.h +++ b/chrome/browser/extensions/extension_uninstall_dialog.h
@@ -22,7 +22,6 @@ #include "ui/base/interaction/element_identifier.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/native_widget_types.h" -#include "url/gurl.h" namespace views { class NativeWindowTracker;
diff --git a/chrome/browser/extensions/webstore_install_with_prompt.h b/chrome/browser/extensions/webstore_install_with_prompt.h index 317203b7..f00010f 100644 --- a/chrome/browser/extensions/webstore_install_with_prompt.h +++ b/chrome/browser/extensions/webstore_install_with_prompt.h
@@ -10,7 +10,6 @@ #include "chrome/browser/extensions/webstore_standalone_installer.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/native_window_tracker.h" -#include "url/gurl.h" namespace content { class WebContents;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 24ca56d..72884f0 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -340,6 +340,14 @@ "expiry_milestone": 142 }, { + "name": "android-use-correct-display-work-area", + "owners": [ + "renkens@google.com", + "cros-web-apps-team@google.com" + ], + "expiry_milestone": 145 + }, + { "name": "android-web-app-launch-handler", "owners": [ "sselyvon@google.com", "tkachenkoo@google.com", "cros-web-apps-team@google.com" ], "expiry_milestone": 145 @@ -1766,6 +1774,11 @@ "expiry_milestone": 160 }, { + "name": "contextual-suggestions-ablate-others-when-present", + "owners": [ "orinj@chromium.org", "khalidpeer@chromium.org", "chrome-desktop-search@google.com"], + "expiry_milestone": 150 + }, + { "name": "copy-image-filename-to-clipboard", "owners": [ "dmblack@google.com" ], "expiry_milestone": 136 @@ -10143,7 +10156,7 @@ "yuhengh@chromium.org", "tluk@chromium.org" ], - "expiry_milestone": 116 + "expiry_milestone": 140 }, { "name" : "webui-tab-strip-context-menu-after-tap",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index e6b6fad..72fd5bb 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2992,6 +2992,11 @@ "Enables web content thumbnail image to override the Lens icon " "for the omnibox entry point action match."; +const char kContextualSuggestionsAblateOthersWhenPresentName[] = + "Contextual suggestions ablate others when present"; +const char kContextualSuggestionsAblateOthersWhenPresentDescription[] = + "Makes contextual search suggestions exclusive in zero suggest."; + const char kOmniboxContextualSearchOnFocusSuggestionsName[] = "Omnibox contextual search on focus suggestions"; const char kOmniboxContextualSearchOnFocusSuggestionsDescription[] = @@ -6074,6 +6079,14 @@ "Display new minimal ui for PWAs on devices that support " "desktop windowing."; +const char kAndroidUseCorrectDisplayWorkAreaName[] = + "Enable accounting system UI for computing the display work area"; +const char kAndroidUseCorrectDisplayWorkAreaDescription[] = + "Enable accounting system's bars and display cutouts for the correct " + "computation of the display work area. The Web API Screen properties " + "availLeft / availTop / availHeight / availWidth accurately reflect the " + "accessible content display area."; + const char kAndroidWindowManagementWebApiName[] = "Window Management Web API"; const char kAndroidWindowManagementWebApiDescription[] = "Enable Window Management Web API. Websites can obtain information about "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 109e1f42..7a04d27c 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1720,6 +1720,9 @@ extern const char kContextualSearchOpenLensActionUsesThumbnailName[]; extern const char kContextualSearchOpenLensActionUsesThumbnailDescription[]; +extern const char kContextualSuggestionsAblateOthersWhenPresentName[]; +extern const char kContextualSuggestionsAblateOthersWhenPresentDescription[]; + extern const char kOmniboxContextualSearchOnFocusSuggestionsName[]; extern const char kOmniboxContextualSearchOnFocusSuggestionsDescription[]; @@ -3567,6 +3570,9 @@ extern const char kAndroidMinimalUiLargeScreenName[]; extern const char kAndroidMinimalUiLargeScreenDescription[]; +extern const char kAndroidUseCorrectDisplayWorkAreaName[]; +extern const char kAndroidUseCorrectDisplayWorkAreaDescription[]; + extern const char kAndroidWindowManagementWebApiName[]; extern const char kAndroidWindowManagementWebApiDescription[];
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 fa24ea24..f6199a6 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
@@ -821,7 +821,7 @@ public static final CachedFlag sNewTabPageAndroidTriggerForPrerender2 = newCachedFlag(NEW_TAB_PAGE_ANDROID_TRIGGER_FOR_PRERENDER2, true); public static final CachedFlag sNewTabPageCustomization = - newCachedFlag(NEW_TAB_PAGE_CUSTOMIZATION, false); + newCachedFlag(NEW_TAB_PAGE_CUSTOMIZATION, false, true); public static final CachedFlag sNewTabPageCustomizationToolbarButton = newCachedFlag(NEW_TAB_PAGE_CUSTOMIZATION_TOOLBAR_BUTTON, false); public static final CachedFlag sNotificationTrampoline =
diff --git a/chrome/browser/glic/BUILD.gn b/chrome/browser/glic/BUILD.gn index 48393094..51a70054 100644 --- a/chrome/browser/glic/BUILD.gn +++ b/chrome/browser/glic/BUILD.gn
@@ -43,8 +43,6 @@ "host/glic_web_client_access.h", "host/guest_util.h", "host/host.h", - "widget/glic_modal_manager.h", - "widget/glic_modal_view.h", "widget/glic_view.h", "widget/glic_window_controller.h", "widget/local_hotkey_manager.h", @@ -122,8 +120,6 @@ "widget/application_hotkey_delegate.h", "widget/browser_conditions.cc", "widget/browser_conditions.h", - "widget/glic_modal_manager.cc", - "widget/glic_modal_view.cc", "widget/glic_view.cc", "widget/glic_widget.cc", "widget/glic_widget.h",
diff --git a/chrome/browser/glic/glic_keyed_service.cc b/chrome/browser/glic/glic_keyed_service.cc index 1e0b4c3..e995442 100644 --- a/chrome/browser/glic/glic_keyed_service.cc +++ b/chrome/browser/glic/glic_keyed_service.cc
@@ -413,6 +413,10 @@ } void GlicKeyedService::TryPreload() { + if (base::FeatureList::IsEnabled(features::kGlicDisableWarming) && + !base::FeatureList::IsEnabled(features::kGlicWarming)) { + return; + } GlicProfileManager* glic_profile_manager = GlicProfileManager::GetInstance(); CHECK(glic_profile_manager); base::TimeDelta delay = GetWarmingDelay(); @@ -436,6 +440,10 @@ } void GlicKeyedService::TryPreloadFre() { + if (base::FeatureList::IsEnabled(features::kGlicDisableWarming) && + !base::FeatureList::IsEnabled(features::kGlicFreWarming)) { + return; + } GlicProfileManager* glic_profile_manager = GlicProfileManager::GetInstance(); CHECK(glic_profile_manager);
diff --git a/chrome/browser/glic/test_support/mock_glic_window_controller.h b/chrome/browser/glic/test_support/mock_glic_window_controller.h index fd85f854..065f8bc5 100644 --- a/chrome/browser/glic/test_support/mock_glic_window_controller.h +++ b/chrome/browser/glic/test_support/mock_glic_window_controller.h
@@ -75,7 +75,6 @@ MOCK_METHOD(GlicWindowAnimator*, window_animator, (), (override)); MOCK_METHOD(Profile*, profile, (), (override)); MOCK_METHOD(bool, IsDragging, (), (override)); - MOCK_METHOD(void, ShowGlicModal, (std::u16string), (override)); MOCK_METHOD(gfx::Rect, GetInitialBounds, (Browser*), (override)); MOCK_METHOD(void, ShowDetachedForTesting, (), (override)); MOCK_METHOD(void, SetPreviousPositionForTesting, (gfx::Point), (override));
diff --git a/chrome/browser/glic/widget/glic_modal_manager.cc b/chrome/browser/glic/widget/glic_modal_manager.cc deleted file mode 100644 index fe6acfd..0000000 --- a/chrome/browser/glic/widget/glic_modal_manager.cc +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/glic/widget/glic_modal_manager.h" - -#include "chrome/browser/glic/widget/glic_modal_view.h" - -namespace { - -constexpr int kHorizontalPadding = 16; -constexpr int kVerticalPadding = 16; -constexpr int kDistanceFromBottom = 16; - -} // namespace - -namespace glic { - -GlicModalManager::GlicModalManager() = default; - -GlicModalManager::~GlicModalManager() = default; - -void GlicModalManager::ShowModal(std::u16string label, - views::Widget* glic_widget) { - if (!glic_widget || modal_widget_) { - return; - } - modal_widget_ = std::make_unique<views::Widget>(); - - auto modal_view = std::make_unique<GlicModalView>( - glic_widget->GetColorProvider(), label, - base::BindRepeating(&GlicModalManager::CloseModal, base::Unretained(this), - views::Widget::ClosedReason::kCancelButtonClicked)); - - auto params = views::Widget::InitParams( - views::Widget::InitParams::Ownership::CLIENT_OWNS_WIDGET, - views::Widget::InitParams::Type::TYPE_POPUP); - params.parent = glic_widget->GetNativeView(); - modal_widget_->Init(std::move(params)); - modal_widget_->MakeCloseSynchronous( - base::BindOnce(&GlicModalManager::CloseModal, base::Unretained(this))); - modal_widget_->SetBounds(GetModalBounds(glic_widget, modal_view.get())); - modal_widget_->SetContentsView(std::move(modal_view)); - modal_widget_->Show(); - - // Automatically hide the dialog after 5 seconds. - scoped_refptr<base::SequencedTaskRunner> ui_task_runner = - base::SequencedTaskRunner::GetCurrentDefault(); - ui_task_runner->PostDelayedTask( - FROM_HERE, - base::BindOnce(&GlicModalManager::CloseModal, base::Unretained(this), - views::Widget::ClosedReason::kUnspecified), - base::Seconds(5)); -} - -void GlicModalManager::CloseModal(views::Widget::ClosedReason reason) { - modal_widget_.reset(); -} - -gfx::Rect GlicModalManager::GetModalBounds(views::Widget* glic_widget, - GlicModalView* modal_view) { - gfx::Rect parent_bounds = glic_widget->GetWindowBoundsInScreen(); - - views::SizeBounds available_size( - parent_bounds.size() - - gfx::Size(kHorizontalPadding * 2, kVerticalPadding * 2)); - gfx::Size preferred_size = modal_view->GetPreferredSize(available_size); - - // Center modal over parent horizontally and position it kDistanceFromBottom - // from the bottom of the parent. - gfx::Point center_point = parent_bounds.CenterPoint(); - int x = center_point.x() - preferred_size.width() / 2; - int y = - parent_bounds.bottom() - kDistanceFromBottom - preferred_size.height(); - return gfx::Rect(x, y, preferred_size.width(), preferred_size.height()); -} - -} // namespace glic
diff --git a/chrome/browser/glic/widget/glic_modal_manager.h b/chrome/browser/glic/widget/glic_modal_manager.h deleted file mode 100644 index 9c5d9d3..0000000 --- a/chrome/browser/glic/widget/glic_modal_manager.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_GLIC_WIDGET_GLIC_MODAL_MANAGER_H_ -#define CHROME_BROWSER_GLIC_WIDGET_GLIC_MODAL_MANAGER_H_ - -#include <memory> - -#include "ui/views/widget/widget.h" - -namespace glic { - -class GlicModalView; - -class GlicModalManager { - public: - GlicModalManager(); - ~GlicModalManager(); - GlicModalManager(const GlicModalManager&) = delete; - GlicModalManager& operator=(const GlicModalManager&) = delete; - - void ShowModal(std::u16string label, views::Widget* glic_widget); - - private: - void CloseModal(views::Widget::ClosedReason reason); - gfx::Rect GetModalBounds(views::Widget* glic_widget, - GlicModalView* modal_view); - - std::unique_ptr<views::Widget> modal_widget_; -}; - -} // namespace glic - -#endif // CHROME_BROWSER_GLIC_WIDGET_GLIC_MODAL_MANAGER_H_
diff --git a/chrome/browser/glic/widget/glic_modal_view.cc b/chrome/browser/glic/widget/glic_modal_view.cc deleted file mode 100644 index ba37c9d..0000000 --- a/chrome/browser/glic/widget/glic_modal_view.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/glic/widget/glic_modal_view.h" - -#include <memory> -#include <utility> - -#include "chrome/browser/ui/color/chrome_color_id.h" -#include "chrome/grit/generated_resources.h" -#include "components/vector_icons/vector_icons.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/geometry/insets.h" -#include "ui/views/background.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/button/image_button_factory.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/view_class_properties.h" - -namespace { - -constexpr int kCornerRadius = 4; -constexpr int kHorizontalPadding = 12; -constexpr int kVerticalPadding = 10; -constexpr int kSpacingBetweenItems = 8; -constexpr int kIconSize = 16; - -} // namespace - -namespace glic { -GlicModalView::GlicModalView(const ui::ColorProvider* color_provider, - const std::u16string& label_text, - base::RepeatingClosure close_callback) - : close_callback_(std::move(close_callback)) { - SetOrientation(views::BoxLayout::Orientation::kHorizontal); - SetInsideBorderInsets(gfx::Insets::VH(kVerticalPadding, kHorizontalPadding)); - SetBetweenChildSpacing(kSpacingBetweenItems); - SetCrossAxisAlignment(views::BoxLayout::CrossAxisAlignment::kCenter); - SetBackground(views::CreateRoundedRectBackground( - color_provider->GetColor(kColorGlicModalBackground), kCornerRadius, 0)); - label_ = AddChildView(std::make_unique<views::Label>(label_text)); - label_->SetMultiLine(true); - label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - label_->SetEnabledColor(color_provider->GetColor(kColorGlicModalForeground)); - label_->SetBackgroundColor( - color_provider->GetColor(kColorGlicModalBackground)); - label_->SetProperty(views::kMarginsKey, gfx::Insets::VH(kVerticalPadding, 0)); - SetFlexForView(label_, 1); - SetBetweenChildSpacing(kSpacingBetweenItems); - auto close_button = std::make_unique<views::ImageButton>(close_callback_); - views::SetImageFromVectorIconWithColor( - close_button.get(), vector_icons::kCloseIcon, kIconSize, - color_provider->GetColor(kColorGlicModalForeground), - color_provider->GetColor(kColorGlicModalForeground)); - close_button->SetTooltipText( - l10n_util::GetStringUTF16(IDS_TOAST_CLOSE_TOOLTIP)); - close_button_ = AddChildView(std::move(close_button)); -} - -GlicModalView::~GlicModalView() = default; - -} // namespace glic
diff --git a/chrome/browser/glic/widget/glic_modal_view.h b/chrome/browser/glic/widget/glic_modal_view.h deleted file mode 100644 index dfd34417..0000000 --- a/chrome/browser/glic/widget/glic_modal_view.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_GLIC_WIDGET_GLIC_MODAL_VIEW_H_ -#define CHROME_BROWSER_GLIC_WIDGET_GLIC_MODAL_VIEW_H_ - -#include <string> - -#include "base/functional/callback.h" -#include "base/memory/raw_ptr.h" -#include "ui/views/layout/box_layout_view.h" -#include "ui/views/layout/layout_types.h" - -namespace views { -class Label; -class ImageButton; -} // namespace views - -namespace glic { -// Creates a notification view with rounded corners, displaying a message and a -// close button. Intended to be used when it is needed to show modals over the -// glic widget. -class GlicModalView : public views::BoxLayoutView { - public: - explicit GlicModalView( - const ui::ColorProvider* color_provider, - const std::u16string& label_text, - base::RepeatingClosure close_callback = base::RepeatingClosure()); - - GlicModalView(const GlicModalView&) = delete; - GlicModalView& operator=(const GlicModalView&) = delete; - - ~GlicModalView() override; - - private: - raw_ptr<views::Label> label_ = nullptr; - raw_ptr<views::ImageButton> close_button_ = nullptr; - base::RepeatingClosure close_callback_; -}; - -} // namespace glic - -#endif // CHROME_BROWSER_GLIC_WIDGET_GLIC_MODAL_VIEW_H_
diff --git a/chrome/browser/glic/widget/glic_window_controller.h b/chrome/browser/glic/widget/glic_window_controller.h index 8ed5b2d..3233e2d 100644 --- a/chrome/browser/glic/widget/glic_window_controller.h +++ b/chrome/browser/glic/widget/glic_window_controller.h
@@ -19,7 +19,6 @@ #include "chrome/browser/glic/host/glic.mojom.h" #include "chrome/browser/glic/host/glic_web_client_access.h" #include "chrome/browser/glic/host/host.h" -#include "chrome/browser/glic/widget/glic_modal_manager.h" #include "chrome/browser/glic/widget/local_hotkey_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_window/public/browser_window_interface.h" @@ -224,8 +223,6 @@ virtual bool IsDragging() = 0; - virtual void ShowGlicModal(std::u16string label) = 0; - virtual gfx::Rect GetInitialBounds(Browser* browser) = 0; virtual void ShowDetachedForTesting() = 0;
diff --git a/chrome/browser/glic/widget/glic_window_controller_impl.cc b/chrome/browser/glic/widget/glic_window_controller_impl.cc index cd56142..c22212a 100644 --- a/chrome/browser/glic/widget/glic_window_controller_impl.cc +++ b/chrome/browser/glic/widget/glic_window_controller_impl.cc
@@ -24,8 +24,6 @@ #include "chrome/browser/glic/host/webui_contents_container.h" #include "chrome/browser/glic/resources/grit/glic_browser_resources.h" #include "chrome/browser/glic/widget/browser_conditions.h" -#include "chrome/browser/glic/widget/glic_modal_manager.h" -#include "chrome/browser/glic/widget/glic_modal_view.h" #include "chrome/browser/glic/widget/glic_view.h" #include "chrome/browser/glic/widget/glic_widget.h" #include "chrome/browser/glic/widget/glic_window_animator.h" @@ -292,7 +290,6 @@ fre_controller_( std::make_unique<GlicFreController>(profile, identity_manager)), window_finder_(std::make_unique<WindowFinder>()), - glic_modal_manager_(std::make_unique<GlicModalManager>()), glic_service_(glic_service), enabling_(enabling) { previous_position_ = GetPreviousPositionFromPrefs(profile_->GetPrefs()); @@ -631,10 +628,6 @@ glic_service_->metrics()->OnGlicWindowShown(); } -void GlicWindowControllerImpl::ShowGlicModal(std::u16string label) { - glic_modal_manager_->ShowModal(std::move(label), glic_widget_.get()); -} - void GlicWindowControllerImpl::SetupGlicWidget(Browser* browser) { auto initial_bounds = GetInitialBounds(browser); glic_window_hotkey_manager_ = MakeGlicWindowHotkeyManager(GetWeakPtr());
diff --git a/chrome/browser/glic/widget/glic_window_controller_impl.h b/chrome/browser/glic/widget/glic_window_controller_impl.h index 5f809a94..131c3ad2 100644 --- a/chrome/browser/glic/widget/glic_window_controller_impl.h +++ b/chrome/browser/glic/widget/glic_window_controller_impl.h
@@ -20,7 +20,6 @@ #include "chrome/browser/glic/host/glic_web_client_access.h" #include "chrome/browser/glic/host/host.h" #include "chrome/browser/glic/widget/application_hotkey_delegate.h" -#include "chrome/browser/glic/widget/glic_modal_manager.h" #include "chrome/browser/glic/widget/glic_window_controller.h" #include "chrome/browser/glic/widget/glic_window_hotkey_delegate.h" #include "chrome/browser/glic/widget/local_hotkey_manager.h" @@ -45,7 +44,6 @@ class GlicEnabling; class ScopedGlicButtonIndicator; class GlicButton; -class GlicModalManager; // This class owns and manages the glic window. This class has the same lifetime // as the GlicKeyedService, so it exists if and only if the profile exists. @@ -124,7 +122,6 @@ GlicWindowAnimator* window_animator() override; Profile* profile() override; bool IsDragging() override; - void ShowGlicModal(std::u16string label) override; gfx::Rect GetInitialBounds(Browser* browser) override; void ShowDetachedForTesting() override; void SetPreviousPositionForTesting(gfx::Point position) override; @@ -341,8 +338,6 @@ std::unique_ptr<WindowFinder> window_finder_; - std::unique_ptr<GlicModalManager> glic_modal_manager_; - std::unique_ptr<LocalHotkeyManager> application_hotkey_manager_; std::unique_ptr<LocalHotkeyManager> glic_window_hotkey_manager_;
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubUtils.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubUtils.java index e6b9f78d..2ab2cfb5 100644 --- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubUtils.java +++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubUtils.java
@@ -11,6 +11,7 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.theme.ThemeModuleUtils; +import org.chromium.ui.util.XrUtils; /** Feature related utilities for Hub. */ @NullMarked @@ -38,6 +39,9 @@ /** Whether enable the grid tab switcher UI update. */ public static boolean isGtsUpdateEnabled() { + // TODO(crbug.com/419822825): Remove explicit check once XR toolbar crash is resolved. + if (XrUtils.isXrDevice()) return false; + return ChromeFeatureList.sGridTabSwitcherUpdate.isEnabled() || ThemeModuleUtils.isForceEnableDependencies(); }
diff --git a/chrome/browser/keyboard_accessory/android/address_accessory_controller_impl.h b/chrome/browser/keyboard_accessory/android/address_accessory_controller_impl.h index 2e3df93..dbf4a86 100644 --- a/chrome/browser/keyboard_accessory/android/address_accessory_controller_impl.h +++ b/chrome/browser/keyboard_accessory/android/address_accessory_controller_impl.h
@@ -17,7 +17,6 @@ #include "components/autofill/core/browser/data_manager/addresses/address_data_manager.h" #include "components/autofill/core/common/unique_ids.h" #include "content/public/browser/web_contents_user_data.h" -#include "url/gurl.h" class ManualFillingController;
diff --git a/chrome/browser/nearby_sharing/network_traversal_ice_config_fetcher.h b/chrome/browser/nearby_sharing/network_traversal_ice_config_fetcher.h index cab1692..28e6f617 100644 --- a/chrome/browser/nearby_sharing/network_traversal_ice_config_fetcher.h +++ b/chrome/browser/nearby_sharing/network_traversal_ice_config_fetcher.h
@@ -8,7 +8,6 @@ #include "base/functional/callback_forward.h" #include "base/memory/scoped_refptr.h" #include "chromeos/ash/services/nearby/public/mojom/webrtc.mojom.h" -#include "url/gurl.h" namespace network { class SharedURLLoaderFactory;
diff --git a/chrome/browser/nearby_sharing/transfer_metadata.h b/chrome/browser/nearby_sharing/transfer_metadata.h index 3a3f437..4b366b12 100644 --- a/chrome/browser/nearby_sharing/transfer_metadata.h +++ b/chrome/browser/nearby_sharing/transfer_metadata.h
@@ -9,7 +9,6 @@ #include <string> #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h" -#include "url/gurl.h" // Metadata about an ongoing transfer. Wraps transient data like status and // progress. This is used to refresh the UI with error messages and show
diff --git a/chrome/browser/offline_pages/recent_tab_helper.h b/chrome/browser/offline_pages/recent_tab_helper.h index 719ffc9..e601a76 100644 --- a/chrome/browser/offline_pages/recent_tab_helper.h +++ b/chrome/browser/offline_pages/recent_tab_helper.h
@@ -15,7 +15,6 @@ #include "components/offline_pages/core/snapshot_controller.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" -#include "url/gurl.h" namespace content { class NavigationHandle;
diff --git a/chrome/browser/on_device_translation/on_device_translation_browsertest.cc b/chrome/browser/on_device_translation/on_device_translation_browsertest.cc index a5f4108..92aa958 100644 --- a/chrome/browser/on_device_translation/on_device_translation_browsertest.cc +++ b/chrome/browser/on_device_translation/on_device_translation_browsertest.cc
@@ -1311,7 +1311,7 @@ public: OnDeviceTranslationCrashingLangBrowserTest() { // Need to set TranslationAPIAcceptLanguagesCheck to false to use a fake - // language code `cause_crash` to trigger a crash. + // language code `crash` to trigger a crash. scoped_feature_list_.InitWithFeaturesAndParameters( {{blink::features::kTranslationAPI, {{"TranslationAPIAcceptLanguagesCheck", "false"}}}}, @@ -1322,10 +1322,10 @@ void SetUpCommandLine(base::CommandLine* command_line) override { OnDeviceTranslationBrowserTest::SetUpCommandLine(command_line); // Need to set the language pack path to the command line to accept the - // fake language code `cause_crash`. + // fake language code `crash`. command_line->AppendSwitchASCII( "translate-kit-packages", - base::StrCat({"cause_crash,ja,", GetTempDir().AsUTF8Unsafe()})); + base::StrCat({"crash,ja,", GetTempDir().AsUTF8Unsafe()})); } private: @@ -1342,12 +1342,12 @@ auto console_observer = CreateConsoleObserver("The translation service crashed."); - // Tries to create a translator for the fake language code `cause_crash`. This + // Tries to create a translator for the fake language code `crash`. This // causes a crash in the mock TranslateKit component. See comments in // mock_translate_kit_lib.cc. EXPECT_EQ(EvalJsCatchingError(R"( const translator = await Translator.create({ - sourceLanguage: 'cause_crash', + sourceLanguage: 'crash', targetLanguage: 'ja', }); )"), @@ -1367,10 +1367,10 @@ mock_component_manager.InstallMockTranslateKitComponent(); NavigateToEmptyPage(); - // Tries to call availability() for the fake language code `cause_crash`. This + // Tries to call availability() for the fake language code `crash`. This // causes a crash in the mock TranslateKit component. See comments in // mock_translate_kit_lib.cc. - TestCanTranslateResult("cause_crash", "ja", + TestCanTranslateResult("crash", "ja", CanCreateTranslatorResult::kNoServiceCrashed); }
diff --git a/chrome/browser/on_device_translation/translation_manager_impl.cc b/chrome/browser/on_device_translation/translation_manager_impl.cc index 4efd852..baf6ec2 100644 --- a/chrome/browser/on_device_translation/translation_manager_impl.cc +++ b/chrome/browser/on_device_translation/translation_manager_impl.cc
@@ -46,6 +46,15 @@ using blink::mojom::TranslatorLanguageCodePtr; using content::BrowserContext; +// TODO(crbug.com/419848973): This is a workaround until the "he" language code +// is fully supported. +std::string SwitchLanguageCodeToIwIfHe(std::string language_code) { + if (language_code == "he") { + return "iw"; + } + return language_code; +} + } // namespace TranslationManagerImpl* TranslationManagerImpl::translation_manager_for_test_ = @@ -160,8 +169,10 @@ TranslatorLanguageCodePtr source_lang, TranslatorLanguageCodePtr target_lang, CanCreateTranslatorCallback callback) { - const std::string source_language = source_lang->code; - const std::string target_language = target_lang->code; + const std::string source_language = + SwitchLanguageCodeToIwIfHe(source_lang->code); + const std::string target_language = + SwitchLanguageCodeToIwIfHe(target_lang->code); RecordTranslationAPICallForLanguagePair("CanTranslate", source_language, target_language); @@ -246,8 +257,10 @@ void TranslationManagerImpl::CreateTranslator( mojo::PendingRemote<TranslationManagerCreateTranslatorClient> client, blink::mojom::TranslatorCreateOptionsPtr options) { - const std::string source_language = options->source_lang->code; - const std::string target_language = options->target_lang->code; + const std::string source_language = + SwitchLanguageCodeToIwIfHe(options->source_lang->code); + const std::string target_language = + SwitchLanguageCodeToIwIfHe(options->target_lang->code); RecordTranslationAPICallForLanguagePair("Create", source_language, target_language); @@ -330,8 +343,10 @@ TranslatorLanguageCodePtr source_lang, TranslatorLanguageCodePtr target_lang, TranslationAvailableCallback callback) { - const std::string source_language = std::move(source_lang->code); - const std::string target_language = std::move(target_lang->code); + const std::string source_language = + SwitchLanguageCodeToIwIfHe(std::move(source_lang->code)); + const std::string target_language = + SwitchLanguageCodeToIwIfHe(std::move(target_lang->code)); RecordTranslationAPICallForLanguagePair("Availability", source_language, target_language);
diff --git a/chrome/browser/password_manager/password_change_delegate.h b/chrome/browser/password_manager/password_change_delegate.h index d346332..029db57 100644 --- a/chrome/browser/password_manager/password_change_delegate.h +++ b/chrome/browser/password_manager/password_change_delegate.h
@@ -8,7 +8,6 @@ #include <string> #include "base/observer_list_types.h" -#include "url/gurl.h" namespace content { class WebContents;
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc index bf4a45c7..0c4d03b 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -539,6 +539,8 @@ auto data = std::make_unique<enterprise_management::PolicyData>(); data->set_request_token("fake token"); data->set_device_id("fake client id"); + data->set_cec_enabled(true); + data->set_command_invalidation_topic("fake-topic"); mock_store_->set_policy_data_for_testing(std::move(data)); // Since there is a signed-in user expect a policy fetch to be started to @@ -694,6 +696,8 @@ auto data = std::make_unique<enterprise_management::PolicyData>(); data->set_request_token("fake token"); data->set_device_id("fake client id"); + data->set_cec_enabled(true); + data->set_command_invalidation_topic("fake-topic"); mock_store_->set_policy_data_for_testing(std::move(data)); // Since there is a signed-in user expect a policy fetch to be started to @@ -899,9 +903,7 @@ // `FetchPolicyForSignedInUser()` will create a new registered client and // fetch policies with it. - DeviceManagementService::JobConfiguration::JobType job_type_1 = - DeviceManagementService::JobConfiguration::TYPE_INVALID; - DeviceManagementService::JobConfiguration::JobType job_type_2 = + DeviceManagementService::JobConfiguration::JobType job_type = DeviceManagementService::JobConfiguration::TYPE_INVALID; em::DeviceManagementRequest policy_fetch_request; DeviceManagementService::JobForTesting job; @@ -911,10 +913,8 @@ std::string user_affiliation_id = "user-affiliation_id"; EXPECT_CALL(job_creation_handler_, OnJobCreation) - .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type_1), - SaveArg<0>(&job))) .WillOnce(DoAll( - device_management_service_.CaptureJobType(&job_type_2), + device_management_service_.CaptureJobType(&job_type), device_management_service_.CaptureRequest(&policy_fetch_request), SaveArg<0>(&job))); EXPECT_CALL(device_dm_token_callback, @@ -938,10 +938,8 @@ // Let it execute. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(&job_creation_handler_); - EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_REMOTE_COMMANDS, - job_type_1); EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH, - job_type_2); + job_type); EXPECT_EQ( device_dm_token,
diff --git a/chrome/browser/predictors/loading_stats_collector.h b/chrome/browser/predictors/loading_stats_collector.h index a297be8..b5bd83d 100644 --- a/chrome/browser/predictors/loading_stats_collector.h +++ b/chrome/browser/predictors/loading_stats_collector.h
@@ -13,7 +13,6 @@ #include "base/memory/raw_ptr.h" #include "base/strings/string_util.h" #include "base/time/time.h" -#include "url/gurl.h" namespace predictors {
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_speculation_host_delegate.h b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_speculation_host_delegate.h index a1feb929..9e043c6d 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_speculation_host_delegate.h +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_speculation_host_delegate.h
@@ -10,7 +10,6 @@ #include "base/memory/raw_ref.h" #include "content/public/browser/speculation_host_delegate.h" #include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom.h" -#include "url/gurl.h" namespace content { class RenderFrameHost;
diff --git a/chrome/browser/regional_capabilities/regional_capabilities_service_client.cc b/chrome/browser/regional_capabilities/regional_capabilities_service_client.cc index f720261b..924681e 100644 --- a/chrome/browser/regional_capabilities/regional_capabilities_service_client.cc +++ b/chrome/browser/regional_capabilities/regional_capabilities_service_client.cc
@@ -45,7 +45,7 @@ return {}; } - const std::string vpd_region = base::ToUpperASCII( + std::string vpd_region = base::ToUpperASCII( sys_info->GetMachineStatistic(ash::system::kRegionKey).value_or("")); if (vpd_region == "GCC" || vpd_region == "LATAM-ES-419" || vpd_region == "NORDIC") { @@ -58,8 +58,13 @@ base::UmaHistogramEnumeration(kCrOSMissingVariationData, kRegionTooShort); return {}; } else if (vpd_region.size() > 2) { - base::UmaHistogramEnumeration(kCrOSMissingVariationData, kRegionTooLong); - return {}; + if (vpd_region[2] != '.') { + base::UmaHistogramEnumeration(kCrOSMissingVariationData, kRegionTooLong); + return {}; + } + vpd_region = vpd_region.substr(0, 2); + base::UmaHistogramEnumeration(kCrOSMissingVariationData, + kStrippedSubkeyInformation); } const CountryId country_code(vpd_region);
diff --git a/chrome/browser/regional_capabilities/regional_capabilities_service_client.h b/chrome/browser/regional_capabilities/regional_capabilities_service_client.h index e01d9ef..4bbea006 100644 --- a/chrome/browser/regional_capabilities/regional_capabilities_service_client.h +++ b/chrome/browser/regional_capabilities/regional_capabilities_service_client.h
@@ -26,7 +26,8 @@ kRegionTooShort = 3, kRegionTooLong = 4, kValidCountryCode = 5, - kMaxValue = kValidCountryCode, + kStrippedSubkeyInformation = 6, + kMaxValue = kStrippedSubkeyInformation, }; // LINT.ThenChange(//tools/metrics/histograms/metadata/chromeos/enums.xml:ChromeOSFallbackCountry) #endif
diff --git a/chrome/browser/regional_capabilities/regional_capabilities_service_client_unittest.cc b/chrome/browser/regional_capabilities/regional_capabilities_service_client_unittest.cc index 21b076dc..99ed4aa2 100644 --- a/chrome/browser/regional_capabilities/regional_capabilities_service_client_unittest.cc +++ b/chrome/browser/regional_capabilities/regional_capabilities_service_client_unittest.cc
@@ -201,6 +201,29 @@ histogram_tester().ExpectUniqueSample( kCrOSMissingVariationData, ChromeOSFallbackCountry::kValidCountryCode, 1); } + +TEST_F(RegionalCapabilitiesServiceClientTest, + GetFallbackCountryId_StripKeyboardLayout) { + RegionalCapabilitiesServiceClient client(/* variations_service= */ nullptr); + SetLoadingState(ash::system::StatisticsProvider::LoadingState::kFinished); + + histogram_tester().ExpectUniqueSample( + kCrOSMissingVariationData, ChromeOSFallbackCountry::kValidCountryCode, 0); + std::string country_code = "DE"; + if (country_code == country_codes::GetCurrentCountryID().CountryCode()) { + country_code = "BE"; + } + const std::string country_with_layout_info = country_code + ".us-intl"; + SetRegion(country_with_layout_info); + const CountryId fallback_id = client.GetFallbackCountryId(); + ASSERT_NE(fallback_id, country_codes::GetCurrentCountryID()); + EXPECT_EQ(fallback_id, country_codes::CountryId(country_code)); + histogram_tester().ExpectBucketCount( + kCrOSMissingVariationData, ChromeOSFallbackCountry::kValidCountryCode, 1); + histogram_tester().ExpectBucketCount( + kCrOSMissingVariationData, + ChromeOSFallbackCountry::kStrippedSubkeyInformation, 1); +} #endif TEST_F(RegionalCapabilitiesServiceClientTest, GetFallbackCountryId) {
diff --git a/chrome/browser/resource_coordinator/tab_helper.h b/chrome/browser/resource_coordinator/tab_helper.h index 8e5cdb7..707e72ef 100644 --- a/chrome/browser/resource_coordinator/tab_helper.h +++ b/chrome/browser/resource_coordinator/tab_helper.h
@@ -11,7 +11,6 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "services/metrics/public/cpp/ukm_source_id.h" -#include "url/gurl.h" namespace resource_coordinator {
diff --git a/chrome/browser/resources/ash/inline_login/BUILD.gn b/chrome/browser/resources/ash/inline_login/BUILD.gn index d906736e..035376d 100644 --- a/chrome/browser/resources/ash/inline_login/BUILD.gn +++ b/chrome/browser/resources/ash/inline_login/BUILD.gn
@@ -33,6 +33,9 @@ "//third_party/polymer/v3_0:library", "//ui/webui/resources/js:build_ts", ] + ts_extra_deps = [ + "//chrome/browser/resources/chromeos/account_manager:css_wrapper_files", + ] ts_path_mappings = [ "chrome://chrome-signin/gaia_action_buttons/gaia_action_buttons.js|" + rebase_path(
diff --git a/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.css b/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.css index f14afad..ffe6cdc4 100644 --- a/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.css +++ b/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.css
@@ -8,19 +8,21 @@ * #import=chrome://resources/cr_elements/cr_icons_lit.css.js * #import=chrome://resources/cr_elements/cr_hidden_style_lit.css.js * #import=chrome://resources/cr_elements/cr_shared_style_lit.css.js - * #include=cr-hidden-style-lit cr-shared-style-lit cr-icons-lit + * #import=chrome://resources/cr_elements/action_link_lit.css.js + * #include=cr-hidden-style-lit cr-shared-style-lit cr-icons-lit action-link-lit * #css_wrapper_metadata_end */ :host { --zero-state-promo-background-color: var(--color-button-foreground); --zero-state-promo-foreground-color: var(--color-button-background); + --container-gap: 8px; --top-container-padding: 20px; border-radius: 12px; display: flex; flex-direction: column; justify-content: center; - gap: 8px; + gap: var(--container-gap); padding: 20px; width: 300px; background-color: var(--zero-state-promo-background-color); @@ -56,12 +58,41 @@ padding-bottom: 4px; } -#labelContainer { +#labelContainer, #buttonContainer { display: flex; flex-direction: row; + gap: var(--container-gap); +} + +#labelContainer { flex-wrap: wrap; - gap: 8px; - padding: 0px; + padding: 0; --color-chip-foreground: var(--zero-state-promo-foreground-color); --color-chip-icon: var(--color-sys-inverse-primary); } + +#anchorContainer { + display: block; + font-size: 14px; + line-height: 20px; + padding-top: 4px; + width: calc(100% - var(--top-container-padding) * 2); +} + +#anchorContainer a { + --cr-link-color: var(--zero-state-promo-foreground-color); +} + +#buttonContainer { + justify-content: flex-end; + padding-top: 8px; +} + +#closeButton { + --cr-button-text-color: var(--zero-state-promo-foreground-color); +} + +#customActionButton { + --cr-button-background-color: var(--zero-state-promo-foreground-color); + --cr-button-text-color: var(--zero-state-promo-background-color); +}
diff --git a/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.html.ts b/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.html.ts index aa985d7..1d674692 100644 --- a/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.html.ts +++ b/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.html.ts
@@ -17,31 +17,60 @@ @click="${this.onDismissButtonClick_}"> </cr-icon-button> </div> -<div id="sectionHeaderContainer"> - $i18nRaw{extensionsZeroStateChipsIphDesc} -</div> -<div id="labelContainer"> - <cr-chip id="couponsButton" chip-role="link" - @click="${this.onCouponsButtonClick_}"> - <cr-icon icon="zero-state-promo:coupons"></cr-icon> - $i18n{extensionsZeroStateIphShoppingCategoryLabel} - </cr-chip> - <cr-chip id="writingButton" chip-role="link" - @click="${this.onWritingButtonClick_}"> - <cr-icon icon="zero-state-promo:writing"></cr-icon> - $i18n{extensionsZeroStateIphWritingHelpCollectionLabel} - </cr-chip> - <cr-chip id="productivityButton" - @click="${this.onProductivityButtonClick_}"> - <cr-icon icon="zero-state-promo:productivity"></cr-icon> - $i18n{extensionsZeroStateIphProductivityCategoryLabel} - </cr-chip> - <cr-chip id="aiButton" - @click="${this.onAiButtonClick_}"> - <cr-icon icon="zero-state-promo:ai"></cr-icon> - $i18n{extensionsZeroStateIphAiProductivityCollectionLabel} - </cr-chip> -</div> +${this.showChipsUi_ ? html` + <div id="sectionHeaderContainer"> + $i18nRaw{extensionsZeroStateChipsIphDesc} + </div> + <div id="labelContainer"> + <cr-chip id="couponsButton" chip-role="link" + @click="${this.onCouponsButtonClick_}"> + <cr-icon icon="zero-state-promo:coupons"></cr-icon> + $i18n{extensionsZeroStateIphShoppingCategoryLabel} + </cr-chip> + <cr-chip id="writingButton" chip-role="link" + @click="${this.onWritingButtonClick_}"> + <cr-icon icon="zero-state-promo:writing"></cr-icon> + $i18n{extensionsZeroStateIphWritingHelpCollectionLabel} + </cr-chip> + <cr-chip id="productivityButton" + @click="${this.onProductivityButtonClick_}"> + <cr-icon icon="zero-state-promo:productivity"></cr-icon> + $i18n{extensionsZeroStateIphProductivityCategoryLabel} + </cr-chip> + <cr-chip id="aiButton" + @click="${this.onAiButtonClick_}"> + <cr-icon icon="zero-state-promo:ai"></cr-icon> + $i18n{extensionsZeroStateIphAiProductivityCollectionLabel} + </cr-chip> + </div>` : html` + <div id="anchorContainer"> + $i18nRaw{extensionsZeroStatePlainLinkIphDesc} + <a id="couponsLink" @click="${this.onCouponsButtonClick_}" + is="action-link"> + $i18n{extensionsZeroStateIphShoppingCategoryLink}, + </a> + <a id="writingLink" @click="${this.onWritingButtonClick_}" + is="action-link"> + $i18n{extensionsZeroStateIphWritingHelpCollectionLink}, + </a> + <a id="productivityLink" @click="${this.onProductivityButtonClick_}" + is="action-link"> + $i18n{extensionsZeroStateIphProductivityCategoryLink}, + </a> + <a id="aiLink" @click="${this.onAiButtonClick_}" is="action-link"> + $i18n{extensionsZeroStateIphAiProductivityCollectionLink} + </a> + </div> + <div id="buttonContainer"> + <cr-button id="closeButton" + @click="${this.onDismissButtonClick_}"> + $i18n{extensionsZeroStateIphCloseButtonLabel} + </cr-button> + <cr-button id="customActionButton" + @click="${this.onChromeWebStoreButtonClick_}"> + $i18n{extensionsZeroStateIphCustomActionButtonLabel} + </cr-button> + </div>`} <!--_html_template_end_-->`; // clang-format on }
diff --git a/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.ts b/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.ts index 52553737..9186e99b 100644 --- a/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.ts +++ b/chrome/browser/resources/extensions_zero_state_promo/zero_state_promo_app.ts
@@ -6,12 +6,13 @@ import 'chrome://resources/cr_elements/cr_chip/cr_chip.js'; import 'chrome://resources/cr_elements/cr_icon/cr_icon.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; +import 'chrome://resources/js/action_link.js'; +import '/strings.m.js'; import type {CustomHelpBubbleHandlerInterface} from 'chrome://resources/cr_components/help_bubble/custom_help_bubble.mojom-webui.js'; import {CustomHelpBubbleUserAction} from 'chrome://resources/cr_components/help_bubble/custom_help_bubble.mojom-webui.js'; import {CustomHelpBubbleProxyImpl} from 'chrome://resources/cr_components/help_bubble/custom_help_bubble_proxy.js'; -import type {CrChipElement} from 'chrome://resources/cr_elements/cr_chip/cr_chip.js'; -import type {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import {WebStoreLinkClicked} from './zero_state_promo.mojom-webui.js'; @@ -20,16 +21,6 @@ import type {ZeroStatePromoBrowserProxy} from './zero_state_promo_browser_proxy.js'; import {ZeroStatePromoBrowserProxyImpl} from './zero_state_promo_browser_proxy.js'; -export interface ZeroStatePromoAppElement { - $: { - dismissButton: CrIconButtonElement, - couponsButton: CrChipElement, - writingButton: CrChipElement, - productivityButton: CrChipElement, - aiButton: CrChipElement, - }; -} - export class ZeroStatePromoAppElement extends CrLitElement { static get is() { return 'extensions-zero-state-promo-app'; @@ -43,12 +34,21 @@ return getHtml.bind(this)(); } + static override get properties() { + return { + showChipsUi_: {type: Boolean}, + }; + } + private apiProxy_: ZeroStatePromoBrowserProxy = ZeroStatePromoBrowserProxyImpl.getInstance(); private customHelpBubbleHandler_: CustomHelpBubbleHandlerInterface = CustomHelpBubbleProxyImpl.getInstance().getHandler(); - protected onChromeWebStoreLinkClick_() { + protected accessor showChipsUi_: boolean = + loadTimeData.getBoolean('showChipsUi'); + + protected onChromeWebStoreButtonClick_() { this.apiProxy_.launchWebStoreLink(WebStoreLinkClicked.kDiscoverExtension); this.customHelpBubbleHandler_.notifyUserAction( CustomHelpBubbleUserAction.kAction);
diff --git a/chrome/browser/resources/lens/overlay/region_selection.ts b/chrome/browser/resources/lens/overlay/region_selection.ts index 3a02c476..25ffca14 100644 --- a/chrome/browser/resources/lens/overlay/region_selection.ts +++ b/chrome/browser/resources/lens/overlay/region_selection.ts
@@ -109,6 +109,8 @@ private readonly gradientRegionStrokeEnabled: boolean = loadTimeData.getBoolean('enableGradientRegionStroke'); + private readonly whiteRegionStrokeEnabled: boolean = + loadTimeData.getBoolean('enableWhiteRegionStroke'); // The tap region dimensions are the height and width that the region should // have when the user taps instead of drag. private readonly tapRegionHeight: number = @@ -224,13 +226,25 @@ let gradient; if (this.gradientRegionStrokeEnabled) { + // Use AIM style GLIF color gradient. gradient = this.context.createConicGradient(0, centerX, centerY); gradient.addColorStop(0, GLIF_HEX_COLORS.blue); gradient.addColorStop(0.45, GLIF_HEX_COLORS.blue); gradient.addColorStop(0.6, GLIF_HEX_COLORS.red); gradient.addColorStop(0.76, GLIF_HEX_COLORS.yellow); gradient.addColorStop(0.92, GLIF_HEX_COLORS.green); + } else if (this.whiteRegionStrokeEnabled) { + // Use white gradient. + gradient = this.context.createLinearGradient( + left, + bottom, + right, + top, + ); + gradient.addColorStop(0, 'rgba(255, 255, 255, 1)'); + gradient.addColorStop(0.92, 'rgba(255, 255, 255, 0.5)'); } else { + // Use dynamic theme color gradient. gradient = this.context.createLinearGradient( left, bottom,
diff --git a/chrome/browser/resources/pdf/elements/bottom_toolbar_shared.css b/chrome/browser/resources/pdf/elements/bottom_toolbar_shared.css index 26a27adc..df697f9 100644 --- a/chrome/browser/resources/pdf/elements/bottom_toolbar_shared.css +++ b/chrome/browser/resources/pdf/elements/bottom_toolbar_shared.css
@@ -8,12 +8,13 @@ * #css_wrapper_metadata_end */ :host { + --toolbar-item-gap: 10px; align-items: center; background-color: var(--viewer-side-background-color); bottom: 0; - border-radius: 28px 28px 0 0; + border-radius: 24px 24px 0 0; display: flex; - padding: 8px; + padding: 12px; position: absolute; } @@ -21,6 +22,18 @@ padding: 20px; } +.toolbar-icon { + padding: 2px; +} + +.toolbar-icon:not(:first-child) { + padding-inline-start: 4px; +} + +.toolbar-icon:not(:last-child) { + padding-inline-end: 4px; +} + .color-chip { background: var(--ink-brush-color, magenta); border: 1px solid var(--viewer-icon-ink-background-color);
diff --git a/chrome/browser/resources/pdf/elements/text_styles_selector.css b/chrome/browser/resources/pdf/elements/text_styles_selector.css index b09c589..c9108407 100644 --- a/chrome/browser/resources/pdf/elements/text_styles_selector.css +++ b/chrome/browser/resources/pdf/elements/text_styles_selector.css
@@ -9,7 +9,7 @@ :host { display: flex; - gap: 16px; + gap: var(--text-styles-selector-gap, 16px); } cr-icon-button {
diff --git a/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.css b/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.css index 0404f3c..abddb324 100644 --- a/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.css +++ b/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.css
@@ -18,12 +18,11 @@ #vertical-separator { background: rgba(255, 255, 255, 0.3); height: 20px; - margin-inline: 12px; + margin-inline: var(--toolbar-item-gap); width: 1px; } ink-brush-selector { - --ink-brush-button-gap: 4px; - --ink-brush-button-size: 40px; - padding: 4px; + --ink-brush-button-gap: 8px; + --ink-brush-button-size: 32px; }
diff --git a/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.html.ts b/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.html.ts index 7b6250c..99688a5 100644 --- a/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.html.ts +++ b/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar.html.ts
@@ -16,12 +16,12 @@ export function getHtml(this: ViewerBottomToolbarElement) { // clang-format off return html`<!--_html_template_start_--> - <ink-brush-selector .currentType="${this.currentType}" + <ink-brush-selector class="toolbar-icon" .currentType="${this.currentType}" @current-type-changed="${this.onCurrentTypeChanged}"> </ink-brush-selector> <span id="vertical-separator"></span> ${this.shouldShowBrushOptions_() ? html` - <viewer-bottom-toolbar-dropdown id="size" + <viewer-bottom-toolbar-dropdown id="size" class="toolbar-icon" .buttonTitle="${this.getSizeTitle_()}"> <cr-icon slot="icon" icon="${this.getSizeIcon_()}"></cr-icon> <ink-size-selector slot="menu" .currentSize="${this.currentSize}" @@ -29,7 +29,7 @@ @current-size-changed="${this.onCurrentSizeChanged}"> </ink-size-selector> </viewer-bottom-toolbar-dropdown> - <viewer-bottom-toolbar-dropdown id="color" + <viewer-bottom-toolbar-dropdown id="color" class="toolbar-icon" .buttonTitle="${this.getColorTitle_()}"> <div slot="icon" class="color-chip"></div> <ink-color-selector slot="menu" label="$i18n{ink2Color}"
diff --git a/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar_dropdown.css b/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar_dropdown.css index 4f3cf15..ef50f2f 100644 --- a/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar_dropdown.css +++ b/chrome/browser/resources/pdf/elements/viewer_bottom_toolbar_dropdown.css
@@ -10,7 +10,8 @@ * #css_wrapper_metadata_end */ :host { - --dropdown-button-size: 40px; + --dropdown-button-size: 32px; + display: flex; position: relative; } @@ -20,7 +21,7 @@ border: none; height: var(--dropdown-button-size); width: var(--dropdown-button-size); - margin: 4px; + margin: 0; min-width: auto; } @@ -31,7 +32,7 @@ div { background-color: var(--viewer-side-background-color); - bottom: 56px; + bottom: 48px; border-radius: 8px; left: 50%; padding: 0 8px;
diff --git a/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css b/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css index f97646a..85f8c98 100644 --- a/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css +++ b/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css
@@ -13,20 +13,21 @@ :host { --cr-focus-outline-color: var(--viewer-icon-focus-outline-color); - display: flex; + border-radius: 16px 16px 0 0; } .md-select { - --md-select-width: 120px; - margin-inline-end: 4px; + --md-select-width: 130px; + margin-inline-end: 8px; } .md-select.size-select { - --md-select-width: 60px; + --md-select-width: 64px; + margin-inline-end: var(--toolbar-item-gap); } text-styles-selector { - padding: 0 12px; + --text-styles-selector-gap: 8px; } text-alignment-selector {
diff --git a/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.html.ts b/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.html.ts index 6fcfc4c..6fecb416 100644 --- a/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.html.ts +++ b/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.html.ts
@@ -31,13 +31,13 @@ ${size} </option>`)} </select> - <text-styles-selector></text-styles-selector> - <viewer-bottom-toolbar-dropdown id="alignment" + <text-styles-selector class="toolbar-icon"></text-styles-selector> + <viewer-bottom-toolbar-dropdown id="alignment" class="toolbar-icon" button-title="$i18n{ink2TextAlignment}"> <cr-icon slot="icon" icon="${this.getAlignmentIcon_()}"></cr-icon> <text-alignment-selector slot="menu"></text-alignment-selector> </viewer-bottom-toolbar-dropdown> - <viewer-bottom-toolbar-dropdown id="color" + <viewer-bottom-toolbar-dropdown id="color" class="toolbar-icon" button-title="$i18n{ink2TextColor}"> <div slot="icon" class="color-chip"></div> <ink-color-selector slot="menu" label="$i18n{ink2TextColor}"
diff --git a/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts b/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts index cac673ca..0af5c1b4 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts
@@ -279,7 +279,6 @@ private moveGranularity_() { this.model_.setIsSpeechBeingRepositioned(true); - this.speech_.cancel(); this.highlighter_.resetPreviousHighlight(); // Reset the word boundary index whenever we move the granularity position. @@ -289,7 +288,6 @@ private resumeSpeech_(selection: Selection|null) { let playedFromSelection = false; if (this.hasSelection_(selection)) { - this.speech_.cancel(); this.wordBoundaries_.resetToDefaultState(); playedFromSelection = this.playFromSelection_(selection); } @@ -301,7 +299,6 @@ // restarting the current message. this.speech_.resume(); } else { - this.speech_.cancel(); if (!this.highlightAndPlayInterruptedMessage_()) { // Ensure we're updating Read Aloud state if there's no text to // speak. @@ -550,7 +547,6 @@ // the accessible text length boundaries to shorten the text. Even // if this gives a much smaller sentence than TTS would have supported, // this is still preferable to no speech. - this.speech_.cancel(); this.playTextWithBoundaries_( utteranceText, true, this.getUtteranceEndBoundary_(utteranceText, true)); @@ -898,6 +894,8 @@ private speakWithDefaults_(message: SpeechSynthesisUtterance) { message.lang = chrome.readingMode.baseLanguageForSpeech; message.rate = getCurrentSpeechRate(); + // Cancel any pending utterances that may be happening in other tabs. + this.speech_.cancel(); this.speech_.speak(message); }
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request.h b/chrome/browser/safe_browsing/download_protection/check_client_download_request.h index 8c6d68e7..dc25227d 100644 --- a/chrome/browser/safe_browsing/download_protection/check_client_download_request.h +++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request.h
@@ -23,7 +23,6 @@ #include "components/download/public/common/download_item.h" #include "components/safe_browsing/core/browser/download_check_result.h" #include "content/public/browser/browser_thread.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/safe_browsing/download_protection/check_file_system_access_write_request.h b/chrome/browser/safe_browsing/download_protection/check_file_system_access_write_request.h index 7388049..61e33bbb 100644 --- a/chrome/browser/safe_browsing/download_protection/check_file_system_access_write_request.h +++ b/chrome/browser/safe_browsing/download_protection/check_file_system_access_write_request.h
@@ -20,7 +20,6 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/file_system_access_write_item.h" -#include "url/gurl.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/extension_telemetry/remote_host_contacted_signal_processor.h b/chrome/browser/safe_browsing/extension_telemetry/remote_host_contacted_signal_processor.h index 17a0950..79feb1da 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/remote_host_contacted_signal_processor.h +++ b/chrome/browser/safe_browsing/extension_telemetry/remote_host_contacted_signal_processor.h
@@ -12,7 +12,6 @@ #include "chrome/browser/safe_browsing/extension_telemetry/extension_signal_processor.h" #include "chrome/browser/safe_browsing/extension_telemetry/remote_host_contacted_signal.h" #include "components/safe_browsing/core/common/proto/csd.pb.h" -#include "url/gurl.h" namespace safe_browsing {
diff --git a/chrome/browser/serial/serial_chooser_context.h b/chrome/browser/serial/serial_chooser_context.h index 866385f..2ea855b 100644 --- a/chrome/browser/serial/serial_chooser_context.h +++ b/chrome/browser/serial/serial_chooser_context.h
@@ -25,7 +25,6 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/device/public/mojom/serial.mojom-forward.h" #include "third_party/blink/public/mojom/serial/serial.mojom.h" -#include "url/gurl.h" #include "url/origin.h" class Profile;
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h b/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h index f9e8955..6f37bf6a 100644 --- a/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h +++ b/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h
@@ -17,7 +17,6 @@ #include "components/sharing_message/sharing_metrics.h" #include "components/sharing_message/sharing_service.h" #include "content/public/browser/web_contents_user_data.h" -#include "url/gurl.h" #include "url/origin.h" namespace content {
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher.h b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher.h index e69e2794..c4f60cb 100644 --- a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher.h +++ b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher.h
@@ -9,7 +9,6 @@ #include "chrome/browser/signin/bound_session_credentials/bound_session_params.pb.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" -#include "url/gurl.h" // This class makes the network request to the DBSC registration endpoint to // get the registration instructions. A new fetcher instance should be created
diff --git a/chrome/browser/sync/test/integration/sync_test_utils_android.h b/chrome/browser/sync/test/integration/sync_test_utils_android.h index 0b81d5b..ce50815e 100644 --- a/chrome/browser/sync/test/integration/sync_test_utils_android.h +++ b/chrome/browser/sync/test/integration/sync_test_utils_android.h
@@ -13,7 +13,6 @@ #include "components/signin/public/base/consent_level.h" #include "components/tab_groups/tab_group_color.h" #include "google_apis/gaia/gaia_id.h" -#include "url/gurl.h" // Utilities that interface with Java to support Sync testing on Android.
diff --git a/chrome/browser/translate/fake_translate_agent.h b/chrome/browser/translate/fake_translate_agent.h index f78745c..3a98fbf 100644 --- a/chrome/browser/translate/fake_translate_agent.h +++ b/chrome/browser/translate/fake_translate_agent.h
@@ -37,7 +37,6 @@ #include "content/public/test/test_renderer_host.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" -#include "url/gurl.h" class FakeTranslateAgent : public translate::mojom::TranslateAgent { public:
diff --git a/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java b/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java index 75f717d..c922694ab3 100644 --- a/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java +++ b/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java
@@ -226,6 +226,7 @@ .when(mInsetObserver) .updateBottomInsetForEdgeToEdge(anyInt()); + EdgeToEdgeUtils.setObservedTappableNavigationBarForTesting(false); mEdgeToEdgeControllerImpl = new EdgeToEdgeControllerImpl( mActivity, @@ -1092,6 +1093,34 @@ mEdgeToEdgeControllerImpl.getAppliedContentViewPaddingForTesting()); } + @Test + @DisableFeatures(ChromeFeatureList.EDGE_TO_EDGE_MONITOR_CONFIGURATIONS) + public void hasSeenTappableNavigationBarInsets_disabled() { + Window window = mockWindowWithRootInsets(SYSTEM_BARS_WITH_TAPPABLE_NAVBAR); + assertTrue( + "Insets should be considered has tappable nav bar.", + EdgeToEdgeUtils.hasTappableNavigationBar(window)); + + window = mockWindowWithRootInsets(SYSTEM_BARS_WINDOW_INSETS); + assertFalse( + "Insets should be considered not has tappable nav bar.", + EdgeToEdgeUtils.hasTappableNavigationBar(window)); + } + + @Test + @EnableFeatures(ChromeFeatureList.EDGE_TO_EDGE_MONITOR_CONFIGURATIONS) + public void hasSeenTappableNavigationBarInsets() { + Window window = mockWindowWithRootInsets(SYSTEM_BARS_WITH_TAPPABLE_NAVBAR); + assertTrue( + "Insets should be considered has tappable nav bar.", + EdgeToEdgeUtils.hasTappableNavigationBar(window)); + + window = mockWindowWithRootInsets(SYSTEM_BARS_WINDOW_INSETS); + assertTrue( + "Has tappable nav bar is seen, so check should be true.", + EdgeToEdgeUtils.hasTappableNavigationBar(window)); + } + void assertToEdgeExpectations() { // Pad the top only, bottom is ToEdge. verify(mOsWrapper, atLeastOnce()) @@ -1126,6 +1155,15 @@ "Bottom insets for safe area does not match.", bottomInset, safeAreaRect.bottom); } + Window mockWindowWithRootInsets(WindowInsetsCompat rootInsets) { + View mockView = Mockito.mock(View.class); + doReturn(rootInsets.toWindowInsets()).when(mockView).getRootWindowInsets(); + + Window mockWindow = Mockito.mock(Window.class); + doReturn(mockView).when(mockWindow).getDecorView(); + return mockWindow; + } + // TODO: Verify that the value of the updated insets returned from the // OnApplyWindowInsetsListener is correct.
diff --git a/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeUtils.java b/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeUtils.java index 340d4f9a..54a7703 100644 --- a/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeUtils.java +++ b/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeUtils.java
@@ -42,6 +42,7 @@ public class EdgeToEdgeUtils { private static final String TAG = "E2E_Utils"; private static @Nullable Boolean sIsTargetSdkEnforceEdgeToEdge; + private static boolean sObservedTappableNavigationBar; private static boolean sAlwaysDrawWebEdgeToEdgeForTesting; private static final String ELIGIBLE_HISTOGRAM = "Android.EdgeToEdge.Eligible"; @@ -189,7 +190,6 @@ public static boolean recordEligibility(Activity activity) { boolean eligible = true; - // TODO(crbug.com/397756951): Replace with hasTappableNavigationBar() if (hasTappableNavigationBar(activity.getWindow())) { eligible = false; RecordHistogram.recordEnumeratedHistogram( @@ -333,6 +333,11 @@ * @return whether the given window's insets indicate a tappable navigation bar. */ static boolean hasTappableNavigationBar(Window window) { + if (sObservedTappableNavigationBar + && ChromeFeatureList.sEdgeToEdgeMonitorConfigurations.isEnabled()) { + return true; + } + var rootInsets = window.getDecorView().getRootWindowInsets(); assert rootInsets != null; Insets navigationBarInsets = @@ -342,9 +347,12 @@ WindowInsetsCompat.toWindowInsetsCompat(rootInsets) .getInsets(WindowInsetsCompat.Type.tappableElement()); // Return whether there is any overlap in navigation bar and tappable element insets. - return (navigationBarInsets.bottom > 0 && tappableElementInsets.bottom > 0) - || (navigationBarInsets.left > 0 && tappableElementInsets.left > 0) - || (navigationBarInsets.right > 0 && tappableElementInsets.right > 0); + boolean hasTappableNavBar = + (navigationBarInsets.bottom > 0 && tappableElementInsets.bottom > 0) + || (navigationBarInsets.left > 0 && tappableElementInsets.left > 0) + || (navigationBarInsets.right > 0 && tappableElementInsets.right > 0); + sObservedTappableNavigationBar |= hasTappableNavBar; + return hasTappableNavBar; } /** @@ -367,4 +375,9 @@ public static boolean pushSafeAreaInsetsForNonOptInPages() { return ChromeFeatureList.sDynamicSafeAreaInsets.isEnabled(); } + + public static void setObservedTappableNavigationBarForTesting(boolean observed) { + sObservedTappableNavigationBar = observed; + ResettersForTesting.register(() -> sObservedTappableNavigationBar = false); + } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java index e109521..6561f148 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
@@ -289,6 +289,7 @@ @SuppressWarnings("NullAway") /* package */ void destroy() { + mCallbackController.destroy(); if (mTemplateUrlServiceSupplier.hasValue()) { mTemplateUrlServiceSupplier.get().removeObserver(this); } @@ -336,17 +337,13 @@ && mLocationBarDataProvider.hasTab() && !mLocationBarDataProvider.isIncognito()) { if (mTemplateUrlServiceSupplier.hasValue()) { - if (mTemplateUrlServiceSupplier.get().isDefaultSearchEngineGoogle()) { - GeolocationHeader.primeLocationForGeoHeaderIfEnabled( - mProfileSupplier.get(), mTemplateUrlServiceSupplier.get()); - } + GeolocationHeader.primeLocationForGeoHeaderIfEnabled( + mProfileSupplier.get(), mTemplateUrlServiceSupplier.get()); } else { mTemplateUrlServiceSupplier.onAvailable( (templateUrlService) -> { - if (templateUrlService.isDefaultSearchEngineGoogle()) { - GeolocationHeader.primeLocationForGeoHeaderIfEnabled( - mProfileSupplier.get(), templateUrlService); - } + GeolocationHeader.primeLocationForGeoHeaderIfEnabled( + mProfileSupplier.get(), templateUrlService); }); } } // Focus change caused by a closed tab may result in there not being an active tab. @@ -361,14 +358,12 @@ mNativeInitialized = true; mOmniboxPrerender = new OmniboxPrerender(); mTemplateUrlServiceSupplier.onAvailable( - (templateUrlService) -> { - templateUrlService.addObserver(this); - if (OmniboxFeatures.sUseFusedLocationProvider.isEnabled() - && templateUrlService.isDefaultSearchEngineGoogle()) { - GeolocationHeader.primeLocationForGeoHeaderIfEnabled( - mProfileSupplier.get(), mTemplateUrlServiceSupplier.get()); - } - }); + mCallbackController.makeCancelable( + (templateUrlService) -> { + templateUrlService.addObserver(this); + GeolocationHeader.primeLocationForGeoHeaderIfEnabled( + mProfileSupplier.get(), mTemplateUrlServiceSupplier.get()); + })); mLocationBarLayout.onFinishNativeInitialization(); if (mProfileSupplier.hasValue()) setProfile(mProfileSupplier.get()); @@ -1382,8 +1377,10 @@ @Override public void onTemplateURLServiceChanged() { sLastCachedIsLensOnOmniboxEnabled = Boolean.valueOf(isLensEnabled(LensEntryPoint.OMNIBOX)); - mUrlCoordinator.setUrlBarHintText( - SearchEngineUtils.getForProfile(mProfileSupplier.get()).getSearchBoxHintText()); + if (mProfileSupplier.hasValue()) { + mUrlCoordinator.setUrlBarHintText( + SearchEngineUtils.getForProfile(mProfileSupplier.get()).getSearchBoxHintText()); + } } // OmniboxStub implementation.
diff --git a/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_progress_bar.xml b/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_progress_bar.xml index ec15a951..d5f31874 100644 --- a/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_progress_bar.xml +++ b/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_progress_bar.xml
@@ -7,7 +7,7 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="@dimen/toolbar_progress_bar_height"> + android:layout_height="wrap_content"> <org.chromium.chrome.browser.toolbar.ToolbarProgressBar android:layout_width="match_parent" android:layout_height="match_parent"
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java index 16b85cb..2b58a83 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java
@@ -80,9 +80,14 @@ activity.setContentView(view, params); Resources res = activity.getResources(); - int heightPx = - res.getDimensionPixelSize( - R.dimen.toolbar_progress_bar_height); + int heightPx; + if (ChromeFeatureList.sAndroidProgressBarVisualUpdate.isEnabled()) { + heightPx = res.getDimensionPixelSize( + R.dimen.toolbar_progress_bar_increased_height); + } else { + heightPx = res.getDimensionPixelSize( + R.dimen.toolbar_progress_bar_height); + } View anchor = new View(activity); view.addView(
diff --git a/chrome/browser/ui/ash/birch/birch_last_active_provider.h b/chrome/browser/ui/ash/birch/birch_last_active_provider.h index 3afbf9b..31105ae 100644 --- a/chrome/browser/ui/ash/birch/birch_last_active_provider.h +++ b/chrome/browser/ui/ash/birch/birch_last_active_provider.h
@@ -10,7 +10,6 @@ #include "base/memory/weak_ptr.h" #include "base/task/cancelable_task_tracker.h" #include "components/history/core/browser/history_types.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/ui/ash/birch/birch_most_visited_provider.h b/chrome/browser/ui/ash/birch/birch_most_visited_provider.h index ab4b4704..fd10d98 100644 --- a/chrome/browser/ui/ash/birch/birch_most_visited_provider.h +++ b/chrome/browser/ui/ash/birch/birch_most_visited_provider.h
@@ -10,7 +10,6 @@ #include "base/memory/weak_ptr.h" #include "base/task/cancelable_task_tracker.h" #include "components/history/core/browser/history_types.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.h b/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.h index b49537a..dd2bc8f 100644 --- a/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.h +++ b/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.h
@@ -23,7 +23,6 @@ #include "chrome/browser/ash/login/session/user_session_manager.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "ui/base/ime/text_input_client.h" -#include "url/gurl.h" class Profile; class ChromeSearchResult;
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index 0ca624c..02a4ad2 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -1749,7 +1749,8 @@ #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) command_updater_.UpdateCommandEnabled( - IDC_CREATE_SHORTCUT, shortcuts::CanCreateDesktopShortcut(browser_)); + IDC_CREATE_SHORTCUT, + shortcuts::CanCreateDesktopShortcut(current_web_contents)); #else command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUT, can_create_web_app);
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 7e73d74..34e59b4 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -1179,10 +1179,19 @@ Browser::Create(Browser::CreateParams(browser->profile(), true)); } + tab_groups::TabGroupSyncService* tab_group_service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile(browser->profile()); + std::unique_ptr<tab_groups::ScopedLocalObservationPauser> observation_pauser; + + if (tab_group_service && tab_group_service->GetGroup(group)) { + observation_pauser = tab_group_service->CreateScopedLocalObserverPauser(); + } + std::unique_ptr<DetachedTabCollection> detached_group = browser->tab_strip_model()->DetachTabGroupForInsertion(group); new_browser->tab_strip_model()->InsertDetachedTabGroupAt( std::move(detached_group), 0); + new_browser->window()->Show(); } @@ -1308,10 +1317,20 @@ Browser* target, tab_groups::TabGroupId group) { CHECK(source->tab_strip_model()->group_model()->ContainsTabGroup(group)); + + tab_groups::TabGroupSyncService* tab_group_service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile(source->profile()); + + std::unique_ptr<tab_groups::ScopedLocalObservationPauser> observation_pauser; + if (tab_group_service && tab_group_service->GetGroup(group)) { + observation_pauser = tab_group_service->CreateScopedLocalObserverPauser(); + } + std::unique_ptr<DetachedTabCollection> detached_group = source->tab_strip_model()->DetachTabGroupForInsertion(group); target->tab_strip_model()->InsertDetachedTabGroupAt(std::move(detached_group), 0); + target->window()->Show(); }
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index 001a364..02b6d6d9 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -53,6 +53,7 @@ #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_node.h" #include "components/commerce/core/commerce_constants.h" +#include "components/data_sharing/public/features.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/privacy_sandbox/privacy_sandbox_features.h" #include "components/safe_browsing/core/common/safe_browsing_settings_metrics.h" @@ -631,6 +632,12 @@ ShowSingletonTabIgnorePathOverwriteNTP(browser, GURL(kChromeUIManagementURL)); } +void ShowSharedTabGroupActivity(Profile* profile) { + Browser* browser = GetOrCreateBrowserForProfile(profile); + ShowSingletonTab(browser, + GURL(data_sharing::features::kActivityLogsURL.Get())); +} + #if BUILDFLAG(IS_CHROMEOS) void ShowAppManagementPage(Profile* profile, const std::string& app_id,
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h index 7183c062..0ea1d15f 100644 --- a/chrome/browser/ui/chrome_pages.h +++ b/chrome/browser/ui/chrome_pages.h
@@ -143,6 +143,9 @@ Browser* browser, const std::string& rws_owner_host_name); +// Shows all recent shared tab group activities. +void ShowSharedTabGroupActivity(Profile* profile); + // Shows the enterprise management info page in a browser tab. void ShowEnterpriseManagementPageInTabbedBrowser(Browser* browser);
diff --git a/chrome/browser/ui/commerce/add_to_comparison_table_sub_menu_model.h b/chrome/browser/ui/commerce/add_to_comparison_table_sub_menu_model.h index ad4cb9c2..c67106a 100644 --- a/chrome/browser/ui/commerce/add_to_comparison_table_sub_menu_model.h +++ b/chrome/browser/ui/commerce/add_to_comparison_table_sub_menu_model.h
@@ -8,7 +8,6 @@ #include "base/uuid.h" #include "components/commerce/core/product_specifications/product_specifications_service.h" #include "ui/menus/simple_menu_model.h" -#include "url/gurl.h" class Browser;
diff --git a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc index 0c3836a8..5e8494877 100644 --- a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc +++ b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
@@ -247,6 +247,9 @@ "enableGradientRegionStroke", lens::features::GetVisualSelectionUpdatesEnableGradientRegionStroke()); html_source->AddBoolean( + "enableWhiteRegionStroke", + lens::features::GetVisualSelectionUpdatesEnableWhiteRegionStroke()); + html_source->AddBoolean( "enableRegionSelectedGlow", lens::features::GetVisualSelectionUpdatesEnableRegionSelectedGlow()); html_source->AddBoolean("autoFocusSearchbox",
diff --git a/chrome/browser/ui/login/login_tab_helper.h b/chrome/browser/ui/login/login_tab_helper.h index 31a05fb6..b495153e 100644 --- a/chrome/browser/ui/login/login_tab_helper.h +++ b/chrome/browser/ui/login/login_tab_helper.h
@@ -12,7 +12,6 @@ #include "content/public/browser/web_contents_user_data.h" #include "net/base/auth.h" #include "net/base/network_anonymization_key.h" -#include "url/gurl.h" namespace content { class NavigationHandle;
diff --git a/chrome/browser/ui/passwords/manage_passwords_state.h b/chrome/browser/ui/passwords/manage_passwords_state.h index dcefb63..199886b 100644 --- a/chrome/browser/ui/passwords/manage_passwords_state.h +++ b/chrome/browser/ui/passwords/manage_passwords_state.h
@@ -15,7 +15,6 @@ #include "components/password_manager/core/browser/password_store/password_store_change.h" #include "components/password_manager/core/common/credential_manager_types.h" #include "components/password_manager/core/common/password_manager_ui.h" -#include "url/gurl.h" namespace password_manager { class PasswordFormManagerForUI;
diff --git a/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.cc b/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.cc index 59b67af2..f3e03a5 100644 --- a/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.cc +++ b/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.cc
@@ -5,7 +5,8 @@ #include "chrome/browser/ui/shortcuts/desktop_shortcuts_utils.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window/public/browser_window_interface.h" +#include "components/tabs/public/tab_interface.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #include "content/public/common/page_type.h" @@ -18,8 +19,19 @@ namespace shortcuts { -bool CanCreateDesktopShortcut(Browser* browser) { - Profile* profile = browser->profile(); +bool CanCreateDesktopShortcut(content::WebContents* web_contents) { + // Do not allow if the web_contents appear to be crashing. + if (!web_contents || web_contents->IsCrashed()) { + return false; + } + + auto* const tab = tabs::TabInterface::MaybeGetFromContents(web_contents); + if (!tab || !tab->GetBrowserWindowInterface()) { + return false; + } + + auto* browser_window_interface = tab->GetBrowserWindowInterface(); + Profile* profile = browser_window_interface->GetProfile(); // Do not allow for Guest or OTR profiles. // System profiles have not been introduced here because they do not have a @@ -28,13 +40,6 @@ return false; } - // Do not allow if the web_contents appear to be crashing. - content::WebContents* web_contents = - browser->tab_strip_model()->GetActiveWebContents(); - if (!web_contents || web_contents->IsCrashed()) { - return false; - } - // Do not allow for error pages (like network errors etc). content::NavigationEntry* entry = web_contents->GetController().GetLastCommittedEntry();
diff --git a/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.h b/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.h index 17481a2..095d260 100644 --- a/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.h +++ b/chrome/browser/ui/shortcuts/desktop_shortcuts_utils.h
@@ -5,13 +5,15 @@ #ifndef CHROME_BROWSER_UI_SHORTCUTS_DESKTOP_SHORTCUTS_UTILS_H_ #define CHROME_BROWSER_UI_SHORTCUTS_DESKTOP_SHORTCUTS_UTILS_H_ -class Browser; +namespace content { +class WebContents; +} namespace shortcuts { // Returns whether a desktop shortcut can be created for the active web // contents. -bool CanCreateDesktopShortcut(Browser* browser); +bool CanCreateDesktopShortcut(content::WebContents* web_contents); } // namespace shortcuts
diff --git a/chrome/browser/ui/tabs/pinned_tab_codec.h b/chrome/browser/ui/tabs/pinned_tab_codec.h index da2055cb..4197f77 100644 --- a/chrome/browser/ui/tabs/pinned_tab_codec.h +++ b/chrome/browser/ui/tabs/pinned_tab_codec.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_UI_TABS_PINNED_TAB_CODEC_H_ #include "chrome/browser/ui/startup/startup_tab.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/ui/test/test_app_window_icon_observer.cc b/chrome/browser/ui/test/test_app_window_icon_observer.cc index 03fa25ab..fcd1f37 100644 --- a/chrome/browser/ui/test/test_app_window_icon_observer.cc +++ b/chrome/browser/ui/test/test_app_window_icon_observer.cc
@@ -8,7 +8,6 @@ #include <string_view> #include <utility> -#include "base/hash/md5.h" #include "base/run_loop.h" #include "extensions/browser/app_window/app_window.h" #include "ui/aura/client/aura_constants.h" @@ -75,7 +74,7 @@ return; } - std::string app_icon_hash; + std::array<uint8_t, crypto::hash::kSha256Size> app_icon_hash; const gfx::ImageSkia* image = window->GetProperty(aura::client::kAppIconKey); last_app_icon_ = image ? *image : gfx::ImageSkia(); @@ -85,18 +84,15 @@ // The window icon property changes more frequently than the image itself // leading to test flakiness. Just record instances where the image actually // changes. - base::MD5Context ctx; - base::MD5Init(&ctx); + crypto::hash::Hasher hash(crypto::hash::HashKind::kSha256); const size_t row_width = bitmap->bytesPerPixel() * bitmap->width(); for (int y = 0; y < bitmap->height(); ++y) { - base::MD5Update( - &ctx, - std::string_view(reinterpret_cast<const char*>(bitmap->getAddr(0, y)), - row_width)); + // SAFETY: Skia guarantees that SkBitmap->getAddr(0, y) will return a + // pointer into the buffer with at least row_width bytes left. + UNSAFE_BUFFERS(hash.Update(base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(bitmap->getAddr(0, y)), row_width));) } - base::MD5Digest digest; - base::MD5Final(&digest, &ctx); - app_icon_hash = base::MD5DigestToBase16(digest); + hash.Finish(app_icon_hash); } if (app_icon_hash == last_app_icon_hash_map_[window]) {
diff --git a/chrome/browser/ui/test/test_app_window_icon_observer.h b/chrome/browser/ui/test/test_app_window_icon_observer.h index 53bf6b1..c8dcb3d 100644 --- a/chrome/browser/ui/test/test_app_window_icon_observer.h +++ b/chrome/browser/ui/test/test_app_window_icon_observer.h
@@ -11,6 +11,7 @@ #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" +#include "crypto/hash.h" #include "extensions/browser/app_window/app_window_registry.h" #include "ui/aura/window_observer.h" #include "ui/gfx/image/image_skia.h" @@ -57,7 +58,8 @@ int icon_updates_ = 0; int expected_icon_updates_ = 0; std::vector<raw_ptr<aura::Window, VectorExperimental>> windows_; - std::map<aura::Window*, std::string> last_app_icon_hash_map_; + std::map<aura::Window*, std::array<uint8_t, crypto::hash::kSha256Size>> + last_app_icon_hash_map_; base::OnceClosure icon_updated_callback_; gfx::ImageSkia last_app_icon_; gfx::ImageSkia expected_image_skia_;
diff --git a/chrome/browser/ui/toolbar/chrome_labs/chrome_labs_model.cc b/chrome/browser/ui/toolbar/chrome_labs/chrome_labs_model.cc index 9d144fe..212eb46 100644 --- a/chrome/browser/ui/toolbar/chrome_labs/chrome_labs_model.cc +++ b/chrome/browser/ui/toolbar/chrome_labs/chrome_labs_model.cc
@@ -38,21 +38,8 @@ return GetTestData().value(); } - static const base::NoDestructor<std::vector<LabInfo>> lab_info_([]() { - std::vector<LabInfo> lab_info; - - // Thumbnail Tab Strip for Windows. -#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && BUILDFLAG(IS_WIN) - lab_info.emplace_back( - flag_descriptions::kWebUITabStripFlagId, - l10n_util::GetStringUTF16(IDS_THUMBNAIL_TAB_STRIP_EXPERIMENT_NAME), - l10n_util::GetStringUTF16( - IDS_THUMBNAIL_TAB_STRIP_EXPERIMENT_DESCRIPTION), - "chrome-labs-thumbnail-tab-strip", version_info::Channel::BETA); -#endif - - return lab_info; - }()); + static const base::NoDestructor<std::vector<LabInfo>> lab_info_( + []() { return std::vector<LabInfo>(); }()); return *lab_info_; }
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc index cddb6a8..9b73ebb2 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc +++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -80,12 +80,21 @@ } // namespace -class CaptionBubbleControllerViewsTest : public InProcessBrowserTest { +class CaptionBubbleControllerViewsTest + : public InProcessBrowserTest, + public ::testing::WithParamInterface<bool> { public: CaptionBubbleControllerViewsTest() { - scoped_feature_list_.InitWithFeatures( - {media::kLiveTranslate, media::kFeatureManagementLiveTranslateCrOS}, - {}); + if (GetParam()) { + scoped_feature_list_.InitWithFeatures( + {media::kLiveTranslate, media::kFeatureManagementLiveTranslateCrOS, + captions::kLiveCaptionScrollable}, + {}); + } else { + scoped_feature_list_.InitWithFeatures( + {media::kLiveTranslate, media::kFeatureManagementLiveTranslateCrOS}, + {captions::kLiveCaptionScrollable}); + } } ~CaptionBubbleControllerViewsTest() override = default; @@ -133,6 +142,11 @@ return controller_ ? controller_->GetCaptionBubbleForTesting() : nullptr; } + views::ScrollView* GetScrollView() { + return controller_ ? controller_->caption_bubble_->GetScrollViewForTesting() + : nullptr; + } + views::Label* GetLabel() { return controller_ ? controller_->caption_bubble_->GetLabelForTesting() : nullptr; @@ -203,6 +217,12 @@ : nullptr; } + views::MdTextButton* GetScrollLockButton() { + return controller_ + ? controller_->caption_bubble_->GetScrollLockButtonForTesting() + : nullptr; + } + views::View* GetTranslateIconAndText() { return controller_ ? controller_->caption_bubble_ ->GetTranslationViewWrapperForTesting() @@ -406,7 +426,7 @@ std::unique_ptr<CaptionBubbleContext> caption_bubble_context2_; }; -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ShowsCaptionInBubble) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, ShowsCaptionInBubble) { OnPartialTranscription("Taylor"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("Taylor", GetLabelText()); @@ -430,7 +450,7 @@ GetLabelText()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, LaysOutCaptionLabel) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, LaysOutCaptionLabel) { // A short caption is bottom-aligned with the bubble. The bubble bounds // are inset by 18 dip on the the sides and 24 dip on the bottom. The label // top can change, but the bubble height and width should not change. @@ -461,14 +481,21 @@ EXPECT_EQ(bubble_width, bubble_bounds.width()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, CaptionTitleShownAtFirst) { - // With one line of text, the title is visible and positioned between the - // top of the bubble and top of the label. OnPartialTranscription("Cats rock"); EXPECT_TRUE(GetTitle()->GetVisible()); - EXPECT_EQ(GetTitle()->GetBoundsInScreen().bottom(), - GetLabel()->GetBoundsInScreen().y()); + if (GetParam()) { + // Scrolling enabled. With one line of text, the title is visible and + // positioned between the top of the bubble and top of the scrollable. + EXPECT_EQ(GetTitle()->GetBoundsInScreen().bottom(), + GetScrollView()->GetBoundsInScreen().y()); + } else { + // Scrolling disabled. With one line of text, the title is visible and + // positioned between the top of the bubble and top of the label. + EXPECT_EQ(GetTitle()->GetBoundsInScreen().bottom(), + GetLabel()->GetBoundsInScreen().y()); + } OnPartialTranscription("Cats rock\nDogs too"); EXPECT_FALSE(GetTitle()->GetVisible()); @@ -489,7 +516,7 @@ #else #define MAYBE_BubblePositioning BubblePositioning #endif -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, MAYBE_BubblePositioning) { int bubble_width = 536; gfx::Insets bubble_margins(6); @@ -539,7 +566,7 @@ EXPECT_EQ(GetBubble()->margins(), bubble_margins); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, BubblePositioningSmallBrowserContext) { auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); SetWindowBounds({{0, 0}, {300, 100}}); @@ -553,7 +580,7 @@ EXPECT_LT(bubble_bounds.y(), web_contents_bounds_in_screen.bottom()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, BubblePositioningSmallNonBrowserContext) { auto context_widget = MakeWebViewWidget(browser()->profile(), {{0, 0}, {300, 100}}); @@ -567,7 +594,7 @@ EXPECT_GT(bubble_bounds.y(), widget_bounds_in_screen.bottom()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ShowsAndHidesError) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, ShowsAndHidesError) { OnPartialTranscription("Elephants' trunks average 6 feet long."); EXPECT_TRUE(GetTitle()->GetVisible()); EXPECT_TRUE(GetLabel()->GetVisible()); @@ -602,7 +629,7 @@ EXPECT_TRUE(GetErrorMessage()->GetVisible()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, CloseButtonCloses) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, CloseButtonCloses) { bool success = OnPartialTranscription("Elephants have 3-4 toenails per foot"); EXPECT_TRUE(success); EXPECT_TRUE(GetCaptionWidget()); @@ -617,7 +644,7 @@ EXPECT_EQ("", GetLabelText()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, ClosesOnAudioStreamEnd) { OnPartialTranscription("Giraffes have black tongues that grow to 53 cm."); EXPECT_TRUE(GetCaptionWidget()); @@ -630,7 +657,7 @@ // TODO(crbug.com/40119836): Re-enable this test once it is passing. Tab // traversal works in app but doesn't work in tests right now. -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, DISABLED_FocusableInTabOrder) { OnPartialTranscription( "A narwhal's tusk is an enlarged tooth containing " @@ -683,7 +710,7 @@ EXPECT_TRUE(GetCloseButton()->HasFocus()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, UpdateCaptionStyleTextSize) { int text_size = 16; int line_height = 24; @@ -761,7 +788,7 @@ EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width / 2); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, UpdateCaptionStyleFontFamily) { #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) std::string default_font = "Roboto"; @@ -812,7 +839,7 @@ GetErrorText()->font_list().GetPrimaryFont().GetFontName()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, UpdateCaptionStyleTextColor) { browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveTranslateEnabled, true); @@ -903,7 +930,7 @@ EXPECT_EQ(language_label_color, GetTargetLanguageLabel()->GetEnabledColor()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, UpdateCaptionStyleBackgroundColor) { SkColor default_color = browser()->window()->GetColorProvider()->GetColor( ui::kColorLiveCaptionBubbleBackgroundDefault); @@ -990,7 +1017,7 @@ EXPECT_EQ(SK_ColorGREEN, GetBubble()->background_color()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, PartialAndFinalTranscriptions) { OnPartialTranscription("No"); EXPECT_EQ("No", GetLabelText()); @@ -1008,7 +1035,7 @@ EXPECT_EQ("No human has ever seen a living giant squid", GetLabelText()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ShowsAndHidesBubble) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, ShowsAndHidesBubble) { // Bubble isn't shown when controller is created. GetController(); EXPECT_FALSE(IsWidgetVisible()); @@ -1040,7 +1067,7 @@ EXPECT_FALSE(IsWidgetVisible()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ChangeMedia) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, ChangeMedia) { // This test has two medias. // Media 0 has the text "Polar bears are the largest carnivores on land". // Media 1 has the text "A snail can sleep for two years". @@ -1077,26 +1104,45 @@ EXPECT_FALSE(IsWidgetVisible()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, TruncatesFinalText) { - // Make a string with 30 lines of 500 characters each. - std::string text; - std::string line(497, 'a'); - for (int i = 10; i < 40; i++) { - text += base::NumberToString(i) + line + " "; +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, TruncatesFinalText) { + if (GetParam()) { + // Scrolling enabled, make a string with 501 lines of 500 characters each. + std::string text; + std::string line(497, 'a'); + for (int i = 10; i < 511; i++) { + text += base::NumberToString(i) + line + " "; + } + OnPartialTranscription(text); + OnFinalTranscription(text); + EXPECT_EQ(text.substr(125661, 125250), GetLabelText()); + EXPECT_EQ(250u, GetNumLinesInLabel()); + OnPartialTranscription(text); + EXPECT_EQ(text.substr(125661, 125250) + text, GetLabelText()); + EXPECT_EQ(751u, GetNumLinesInLabel()); + OnFinalTranscription("a "); + EXPECT_EQ(text.substr(126162, 124751) + "a ", GetLabelText()); + EXPECT_EQ(250u, GetNumLinesInLabel()); + } else { + // Scrolling disabled, make a string with 30 lines of 500 characters each. + std::string text; + std::string line(497, 'a'); + for (int i = 10; i < 40; i++) { + text += base::NumberToString(i) + line + " "; + } + OnPartialTranscription(text); + OnFinalTranscription(text); + EXPECT_EQ(text.substr(10500, 15000), GetLabelText()); + EXPECT_EQ(9u, GetNumLinesInLabel()); + OnPartialTranscription(text); + EXPECT_EQ(text.substr(10500, 15000) + text, GetLabelText()); + EXPECT_EQ(39u, GetNumLinesInLabel()); + OnFinalTranscription("a "); + EXPECT_EQ(text.substr(11000, 15000) + "a ", GetLabelText()); + EXPECT_EQ(9u, GetNumLinesInLabel()); } - OnPartialTranscription(text); - OnFinalTranscription(text); - EXPECT_EQ(text.substr(10500, 15000), GetLabelText()); - EXPECT_EQ(9u, GetNumLinesInLabel()); - OnPartialTranscription(text); - EXPECT_EQ(text.substr(10500, 15000) + text, GetLabelText()); - EXPECT_EQ(39u, GetNumLinesInLabel()); - OnFinalTranscription("a "); - EXPECT_EQ(text.substr(11000, 15000) + "a ", GetLabelText()); - EXPECT_EQ(9u, GetNumLinesInLabel()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, DestroysWithoutCrashing) { // Test passes if destroying the controller does not crash. OnPartialTranscription("Deer have a four-chambered stomach"); @@ -1107,7 +1153,7 @@ DestroyController(); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ExpandsAndCollapses) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, ExpandsAndCollapses) { int line_height = 24; EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( prefs::kLiveCaptionBubbleExpanded)); @@ -1155,7 +1201,7 @@ EXPECT_EQ(line_height, GetLabel()->GetBoundsInScreen().height()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, AccessibleProperties) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AccessibleProperties) { base::ScopedMockTimeMessageLoopTaskRunner test_task_runner; OnPartialTranscription( "Sea otters have the densest fur of any mammal at about 1 million " @@ -1203,7 +1249,7 @@ GetBubble()->GetAccessibleWindowTitle()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, NonAsciiCharacter) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, NonAsciiCharacter) { OnPartialTranscription("犬は最高です"); EXPECT_EQ("犬は最高です", GetLabelText()); @@ -1211,7 +1257,7 @@ EXPECT_EQ("猫も大丈夫", GetLabelText()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, AccessibleTextSetUp) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AccessibleTextSetUp) { OnPartialTranscription("Capybaras are the world's largest rodents."); // The label is a readonly document. @@ -1232,7 +1278,7 @@ ax::mojom::StringAttribute::kName)); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AccessibleTextSplitsIntoNodesByLine) { // Make a line of 500 characters. std::string line(499, 'a'); @@ -1250,7 +1296,7 @@ EXPECT_EQ(line, GetAXLineText()[0]); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AccessibleTextClearsWhenBubbleCloses) { OnPartialTranscription("Dogs' noses are wet to help them smell."); EXPECT_EQ(1u, GetAXLineText().size()); @@ -1259,7 +1305,7 @@ EXPECT_EQ(0u, GetAXLineText().size()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AccessibleTextChangesWhenMediaChanges) { CaptionBubbleContext* media_0 = GetCaptionBubbleContext(); @@ -1277,37 +1323,67 @@ EXPECT_EQ("3 dogs survived the Titanic sinking.", GetAXLineText()[0]); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AccessibleTextTruncates) { - // Make a string with 30 lines of 500 characters each. - std::string text; - std::string line(497, 'a'); - for (int i = 10; i < 40; i++) { - text += base::NumberToString(i) + line + " "; + if (GetParam()) { + // Scrolling enabled, make a string with 501 lines of 500 characters each. + std::string text; + std::string line(497, 'a'); + for (int i = 10; i < 511; i++) { + text += base::NumberToString(i) + line + " "; + } + OnPartialTranscription(text); + OnFinalTranscription(text); + EXPECT_EQ(250u, GetAXLineText().size()); + for (int i = 0; i < 9; i++) { + EXPECT_EQ(base::NumberToString(i + 261) + line + " ", GetAXLineText()[i]); + } + OnPartialTranscription(text); + EXPECT_EQ(751u, GetAXLineText().size()); + for (int i = 0; i < 9; i++) { + EXPECT_EQ(base::NumberToString(i + 261) + line + " ", GetAXLineText()[i]); + } + for (int i = 10; i < 40; i++) { + EXPECT_EQ(base::NumberToString(i + 260) + line + " ", + GetAXLineText()[i - 1]); + } + OnFinalTranscription("a "); + EXPECT_EQ(250u, GetAXLineText().size()); + for (int i = 0; i < 249; i++) { + EXPECT_EQ(base::NumberToString(i + 262) + line + " ", GetAXLineText()[i]); + } + EXPECT_EQ("a ", GetAXLineText()[249]); + } else { + // Scrolling disabled, make a string with 30 lines of 500 characters each. + std::string text; + std::string line(497, 'a'); + for (int i = 10; i < 40; i++) { + text += base::NumberToString(i) + line + " "; + } + OnPartialTranscription(text); + OnFinalTranscription(text); + EXPECT_EQ(9u, GetAXLineText().size()); + for (int i = 0; i < 9; i++) { + EXPECT_EQ(base::NumberToString(i + 31) + line + " ", GetAXLineText()[i]); + } + OnPartialTranscription(text); + EXPECT_EQ(39u, GetAXLineText().size()); + for (int i = 0; i < 9; i++) { + EXPECT_EQ(base::NumberToString(i + 31) + line + " ", GetAXLineText()[i]); + } + for (int i = 10; i < 40; i++) { + EXPECT_EQ(base::NumberToString(i) + line + " ", GetAXLineText()[i - 1]); + } + OnFinalTranscription("a "); + EXPECT_EQ(9u, GetAXLineText().size()); + for (int i = 0; i < 8; i++) { + EXPECT_EQ(base::NumberToString(i + 32) + line + " ", GetAXLineText()[i]); + } + EXPECT_EQ("a ", GetAXLineText()[8]); } - OnPartialTranscription(text); - OnFinalTranscription(text); - EXPECT_EQ(9u, GetAXLineText().size()); - for (int i = 0; i < 9; i++) { - EXPECT_EQ(base::NumberToString(i + 31) + line + " ", GetAXLineText()[i]); - } - OnPartialTranscription(text); - EXPECT_EQ(39u, GetAXLineText().size()); - for (int i = 0; i < 9; i++) { - EXPECT_EQ(base::NumberToString(i + 31) + line + " ", GetAXLineText()[i]); - } - for (int i = 10; i < 40; i++) { - EXPECT_EQ(base::NumberToString(i) + line + " ", GetAXLineText()[i - 1]); - } - OnFinalTranscription("a "); - EXPECT_EQ(9u, GetAXLineText().size()); - for (int i = 0; i < 8; i++) { - EXPECT_EQ(base::NumberToString(i + 32) + line + " ", GetAXLineText()[i]); - } - EXPECT_EQ("a ", GetAXLineText()[8]); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AccessibleTextIsSometimesFocusable) { OnPartialTranscription("Capybaras can sleep in water."); @@ -1324,7 +1400,7 @@ #endif } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, HasAccessibleWindowTitle) { OnPartialTranscription("A turtle's shell is part of its skeleton."); EXPECT_FALSE(GetAccessibleWindowTitle().empty()); @@ -1332,7 +1408,7 @@ base::UTF16ToUTF8(GetTitle()->GetText())); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, BackToTabButtonActivatesTab) { OnPartialTranscription("Whale sharks are the world's largest fish."); ASSERT_FALSE(GetBackToTabButton()->GetVisible()); @@ -1347,7 +1423,7 @@ // app but the tests aren't working. } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, LiveTranslateLabel) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, LiveTranslateLabel) { int line_height = 18; browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveTranslateEnabled, @@ -1363,6 +1439,9 @@ ASSERT_FALSE(GetTranslateIconAndText()->GetVisible()); ASSERT_FALSE(GetTranslateArrowIcon()->GetVisible()); ASSERT_FALSE(GetTargetLanguageButton()->GetVisible()); + if (GetParam()) { + ASSERT_FALSE(GetScrollLockButton()->GetVisible()); + } browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveTranslateEnabled, true); @@ -1371,6 +1450,9 @@ ASSERT_FALSE(GetTranslateArrowIcon()->GetVisible()); ASSERT_TRUE(GetTargetLanguageButton()->GetVisible()); EXPECT_EQ("English", base::UTF16ToUTF8(GetTargetLanguageButton()->GetText())); + if (GetParam()) { + ASSERT_FALSE(GetScrollLockButton()->GetVisible()); + } browser()->profile()->GetPrefs()->SetString(prefs::kLiveCaptionLanguageCode, "fr"); @@ -1380,6 +1462,9 @@ ASSERT_TRUE(GetTranslateIconAndText()->GetVisible()); ASSERT_TRUE(GetTranslateArrowIcon()->GetVisible()); ASSERT_TRUE(GetTargetLanguageButton()->GetVisible()); + if (GetParam()) { + ASSERT_FALSE(GetScrollLockButton()->GetVisible()); + } EXPECT_EQ("French", base::UTF16ToUTF8(GetSourceLanguageButton()->GetText())); EXPECT_EQ("English", base::UTF16ToUTF8(GetTargetLanguageButton()->GetText())); EXPECT_EQ(line_height, GetSourceLanguageLabel()->GetLineHeight()); @@ -1400,7 +1485,7 @@ ASSERT_TRUE(GetSourceLanguageButton()->GetVisible()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, HeaderView) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, HeaderView) { OnPartialTranscription( "Stoats are able to change their fur color from brown to white in the " "winter."); @@ -1410,9 +1495,9 @@ views::View* left_header_container = GetHeader()->children()[0]; // The left header container should contain the translate - // header{{icon, text}, source language button, arrow icon, and - // target language button}. - EXPECT_EQ(1u, left_header_container->children().size()); + // header{{icon, text}, source language button, arrow icon, + // target language button and scroll/lock button, if scrolling enabled}. + EXPECT_EQ(GetParam() ? 2u : 1u, left_header_container->children().size()); views::View* translate_header_container = left_header_container->children()[0]; EXPECT_EQ(4u, translate_header_container->children().size()); @@ -1425,6 +1510,9 @@ ASSERT_FALSE(GetTranslateIconAndText()->GetVisible()); ASSERT_FALSE(GetTranslateArrowIcon()->GetVisible()); ASSERT_FALSE(GetTargetLanguageButton()->GetVisible()); + if (GetParam()) { + ASSERT_FALSE(GetScrollLockButton()->GetVisible()); + } ASSERT_EQ(4, static_cast<views::BoxLayout*>( left_header_container->GetLayoutManager()) ->inside_border_insets() @@ -1471,7 +1559,7 @@ EXPECT_EQ(u"English (auto-detected)", translate_language_button->GetText()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, NavigateToCaptionSettings) { OnPartialTranscription( "Whale songs are so low in frequency that they can travel for thousands " @@ -1497,7 +1585,7 @@ ASSERT_EQ(GetCaptionSettingsUrl(), new_web_contents->GetLastCommittedURL()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, LabelTextDirection) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, LabelTextDirection) { browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveTranslateEnabled, true); browser()->profile()->GetPrefs()->SetString( @@ -1521,7 +1609,7 @@ GetLabel()->GetHorizontalAlignment()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, TranslateSynonyms) { +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, TranslateSynonyms) { browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveTranslateEnabled, true); browser()->profile()->GetPrefs()->SetString( @@ -1534,6 +1622,9 @@ "grams."); EXPECT_TRUE(IsWidgetVisible()); ASSERT_TRUE(GetTargetLanguageButton()->GetVisible()); + if (GetParam()) { + ASSERT_FALSE(GetScrollLockButton()->GetVisible()); + } auto* target_language_label = GetTargetLanguageLabel(); ASSERT_EQ(u"English", target_language_label->GetText()); @@ -1566,7 +1657,7 @@ } #if !BUILDFLAG(IS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, DownloadProgressLabel) { speech::SodaInstaller::GetInstance()->NeverDownloadSodaForTesting(); GetController(); @@ -1600,7 +1691,7 @@ ASSERT_FALSE(GetDownloadProgressLabel()->GetVisible()); } -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, AutomaticLanguageDownload) { OnLanguageIdentificationEvent("fr-FR"); OnSodaProgress(12); @@ -1612,7 +1703,7 @@ } #endif // !BUILDFLAG(IS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, +IN_PROC_BROWSER_TEST_P(CaptionBubbleControllerViewsTest, SpaceBetweenFinalAndPartial) { OnFinalTranscription( "Sea otters hold hands while they sleep so they don't drift apart."); @@ -1627,4 +1718,9 @@ "weather.", GetLabelText()); } + +INSTANTIATE_TEST_SUITE_P(CaptionBubbleControllerViewsSuite, + CaptionBubbleControllerViewsTest, + ::testing::Bool()); + } // namespace captions
diff --git a/chrome/browser/ui/views/extensions/extension_popup.h b/chrome/browser/ui/views/extensions/extension_popup.h index 74d16adf..a3dd6a257 100644 --- a/chrome/browser/ui/views/extensions/extension_popup.h +++ b/chrome/browser/ui/views/extensions/extension_popup.h
@@ -20,7 +20,6 @@ #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/widget/widget_observer.h" -#include "url/gurl.h" class Browser; class ExtensionViewViews;
diff --git a/chrome/browser/ui/views/infobars/infobar_view_browsertest.cc b/chrome/browser/ui/views/infobars/infobar_view_browsertest.cc new file mode 100644 index 0000000..f2c5aa6 --- /dev/null +++ b/chrome/browser/ui/views/infobars/infobar_view_browsertest.cc
@@ -0,0 +1,68 @@ +// 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 "chrome/browser/ui/views/infobars/infobar_view.h" + +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/infobars/infobar_container_view.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/infobars/content/content_infobar_manager.h" +#include "content/public/test/browser_test.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/test/ax_event_counter.h" +#include "ui/views/test/views_test_base.h" + +class TestInfoBarDelegate : public infobars::InfoBarDelegate { + public: + static InfoBarView* Create(infobars::ContentInfoBarManager* infobar_manager) { + return static_cast<InfoBarView*>( + infobar_manager->AddInfoBar(std::make_unique<InfoBarView>( + std::make_unique<TestInfoBarDelegate>()))); + } + + // infobars::InfoBarDelegate: + InfoBarIdentifier GetIdentifier() const override { return TEST_INFOBAR; } +}; + +class InfoBarViewBrowserTest : public InProcessBrowserTest { + protected: + infobars::ContentInfoBarManager* infobar_manager() { + return infobars::ContentInfoBarManager::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents()); + } + + InfoBarContainerView* info_bar_container_view() { + return BrowserView::GetBrowserViewForBrowser(browser()) + ->infobar_container(); + } +}; + +IN_PROC_BROWSER_TEST_F(InfoBarViewBrowserTest, AlertAccessibleEvent) { + views::test::AXEventCounter counter(views::AXUpdateNotifier::Get()); + EXPECT_EQ(0, counter.GetCount(ax::mojom::Event::kAlert)); + TestInfoBarDelegate::Create(infobar_manager()); + EXPECT_EQ(1, counter.GetCount(ax::mojom::Event::kAlert)); +} + +IN_PROC_BROWSER_TEST_F(InfoBarViewBrowserTest, AccessibleProperties) { + // InfoBarView accessible properties test. + InfoBarView* view = TestInfoBarDelegate::Create(infobar_manager()); + ui::AXNodeData data; + + view->GetViewAccessibility().GetAccessibleNodeData(&data); + EXPECT_EQ(ax::mojom::Role::kAlertDialog, data.role); + EXPECT_EQ(l10n_util::GetStringUTF8(IDS_ACCNAME_INFOBAR), + data.GetStringAttribute(ax::mojom::StringAttribute::kName)); + + // InfoBarContainerView accessible properties test. + auto* container = info_bar_container_view(); + + data = ui::AXNodeData(); + container->GetViewAccessibility().GetAccessibleNodeData(&data); + EXPECT_EQ(ax::mojom::Role::kGroup, data.role); + EXPECT_EQ(l10n_util::GetStringUTF8(IDS_ACCNAME_INFOBAR_CONTAINER), + data.GetStringAttribute(ax::mojom::StringAttribute::kName)); +}
diff --git a/chrome/browser/ui/views/infobars/infobar_view_unittest.cc b/chrome/browser/ui/views/infobars/infobar_view_unittest.cc deleted file mode 100644 index cb63f1cab..0000000 --- a/chrome/browser/ui/views/infobars/infobar_view_unittest.cc +++ /dev/null
@@ -1,123 +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 "chrome/browser/ui/views/infobars/infobar_view.h" - -#include "chrome/browser/ui/views/infobars/infobar_container_view.h" -#include "chrome/grit/generated_resources.h" -#include "chrome/test/base/browser_with_test_window_test.h" -#include "components/infobars/content/content_infobar_manager.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/views/accessibility/view_accessibility.h" -#include "ui/views/test/ax_event_counter.h" -#include "ui/views/test/views_test_base.h" -#include "ui/views/test/widget_test.h" -#include "ui/views/widget/unique_widget_ptr.h" - -class TestInfoBarDelegate : public infobars::InfoBarDelegate { - public: - static InfoBarView* Create(infobars::ContentInfoBarManager* infobar_manager) { - return static_cast<InfoBarView*>( - infobar_manager->AddInfoBar(std::make_unique<InfoBarView>( - std::make_unique<TestInfoBarDelegate>()))); - } - - // infobars::InfoBarDelegate: - InfoBarIdentifier GetIdentifier() const override { return TEST_INFOBAR; } -}; - -class InfoBarViewTest : public BrowserWithTestWindowTest { - public: - InfoBarViewTest() = default; - - InfoBarViewTest(const InfoBarViewTest&) = delete; - InfoBarViewTest& operator=(const InfoBarViewTest&) = delete; - - ~InfoBarViewTest() override = default; - - // ChromeViewsTestBase: - void SetUp() override { - BrowserWithTestWindowTest::SetUp(); - - AddTab(browser(), GURL("about:blank")); - widget_ = std::make_unique<views::Widget>(); - views::Widget::InitParams params = - CreateParams(views::Widget::InitParams::CLIENT_OWNS_WIDGET, - views::Widget::InitParams::TYPE_POPUP); - params.bounds = gfx::Rect(50, 50, 650, 650); - widget_->Init(std::move(params)); - auto* root = widget_->GetRootView(); - - // Accessible events will not fire until View is added to a RootView's tree. - auto* added_container = - root->AddChildView(std::make_unique<InfoBarContainerView>(nullptr)); - - infobar_container_view_ = added_container; - infobar_container_view_->ChangeInfoBarManager(infobar_manager()); - - widget_->Show(); - } - - void TearDown() override { - DetachContainer(); - infobar_container_view_ = nullptr; - widget_.reset(); - BrowserWithTestWindowTest::TearDown(); - } - - infobars::ContentInfoBarManager* infobar_manager() { - return infobars::ContentInfoBarManager::FromWebContents( - browser()->tab_strip_model()->GetWebContentsAt(0)); - } - - views::Widget::InitParams CreateParams( - views::Widget::InitParams::Ownership ownership, - views::Widget::InitParams::Type type) { - views::Widget::InitParams params(ownership, type); - params.context = GetContext(); - return params; - } - - InfoBarContainerView* info_bar_container_view() { - return infobar_container_view_; - } - - // Detaches |infobar_container_view_| from infobar_manager(), so that newly- - // created infobars will not be placed in a container. This can be used to - // simulate creating an infobar in a background tab. - void DetachContainer() { - infobar_container_view_->ChangeInfoBarManager(nullptr); - } - - private: - raw_ptr<InfoBarContainerView> infobar_container_view_ = nullptr; - views::UniqueWidgetPtr widget_; -}; - -TEST_F(InfoBarViewTest, AlertAccessibleEvent) { - views::test::AXEventCounter counter(views::AXUpdateNotifier::Get()); - EXPECT_EQ(0, counter.GetCount(ax::mojom::Event::kAlert)); - TestInfoBarDelegate::Create(infobar_manager()); - EXPECT_EQ(1, counter.GetCount(ax::mojom::Event::kAlert)); -} - -TEST_F(InfoBarViewTest, AccessibleProperties) { - // InfoBarView accessible properties test. - InfoBarView* view = TestInfoBarDelegate::Create(infobar_manager()); - ui::AXNodeData data; - - view->GetViewAccessibility().GetAccessibleNodeData(&data); - EXPECT_EQ(ax::mojom::Role::kAlertDialog, data.role); - EXPECT_EQ(l10n_util::GetStringUTF8(IDS_ACCNAME_INFOBAR), - data.GetStringAttribute(ax::mojom::StringAttribute::kName)); - - // InfoBarContainerView accessible properties test. - auto* container = info_bar_container_view(); - - data = ui::AXNodeData(); - container->GetViewAccessibility().GetAccessibleNodeData(&data); - EXPECT_EQ(ax::mojom::Role::kGroup, data.role); - EXPECT_EQ(l10n_util::GetStringUTF8(IDS_ACCNAME_INFOBAR_CONTAINER), - data.GetStringAttribute(ax::mojom::StringAttribute::kName)); -}
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_controller.h b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_controller.h index acb7e212..9a25238 100644 --- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_controller.h +++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_controller.h
@@ -16,7 +16,6 @@ #include "components/content_settings/core/common/cookie_controls_enforcement.h" #include "components/content_settings/core/common/cookie_controls_state.h" #include "components/favicon_base/favicon_types.h" -#include "url/gurl.h" class CookieControlsBubbleView;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc index 9b8ed61..954dfa7 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -156,11 +156,14 @@ void Click(ui_controls::MouseButton button, const gfx::Point& press_location, const gfx::Point& release_location) { - ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(press_location)); + auto browser_window = browser()->window()->GetNativeWindow(); + ASSERT_TRUE( + ui_test_utils::SendMouseMoveSync(press_location, browser_window)); ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(button, ui_controls::DOWN)); if (press_location != release_location) { - ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(release_location)); + ASSERT_TRUE( + ui_test_utils::SendMouseMoveSync(release_location, browser_window)); } ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(button, ui_controls::UP)); }
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h index 0087876..dca59c9 100644 --- a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h +++ b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_CUSTOMIZE_CHROME_CUSTOMIZE_CHROME_UTILS_H_ #include "chrome/browser/profiles/profile.h" -#include "url/gurl.h" namespace content { class BrowserContext;
diff --git a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc index 95e9fb2..10e29fd 100644 --- a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc +++ b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/image_fetcher/image_fetcher_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" +#include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_metrics.h" #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h" @@ -45,6 +46,7 @@ #include "components/tabs/public/tab_interface.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/base/mojom/menu_source_type.mojom.h" #include "ui/compositor/layer.h" #include "ui/gfx/canvas.h" #include "ui/gfx/favicon_size.h" @@ -52,7 +54,11 @@ #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/controls/menu/menu_runner.h" +#include "ui/views/controls/menu/menu_types.h" #include "ui/views/controls/styled_label.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/layout/flex_layout.h" @@ -164,8 +170,6 @@ group_activity_log_(group_activity_log), profile_(profile) { SetProperty(views::kElementIdentifierKey, kRecentActivityBubbleDialogId); - SetTitle(l10n_util::GetStringUTF16(IDS_DATA_SHARING_RECENT_ACTIVITY_TITLE)); - SetShowCloseButton(true); SetButtons(static_cast<int>(ui::mojom::DialogButton::kNone)); SetLayoutManager(std::make_unique<views::FlexLayout>()) ->SetOrientation(views::LayoutOrientation::kVertical) @@ -174,6 +178,8 @@ views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); set_margins(gfx::Insets(bubble_content_margin_px)); + CreateTitleView(); + if (tab_activity_log.empty() && group_activity_log.empty()) { CreateEmptyState(); } @@ -196,6 +202,102 @@ RecentActivityBubbleDialogView::~RecentActivityBubbleDialogView() = default; +// TODO(crbug.com/410609387): Update the bubble dialog view to replace the +// options menu button with a secondary button, and revert the custom title view +// back to using the default title and close button provided by the bubble +// dialog. +void RecentActivityBubbleDialogView::CreateTitleView() { + // Create title view. + auto title_view = std::make_unique<views::View>(); + title_view->SetBorder( + views::CreateEmptyBorder(gfx::Insets::TLBR(12, 0, 8, 0))); + auto* box_layout = + title_view->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, gfx::Insets())); + title_view->SetID(TITLE_VIEW_ID); + + // Add title. + auto* title = title_view->AddChildView(std::make_unique<views::Label>( + l10n_util::GetStringUTF16(IDS_DATA_SHARING_RECENT_ACTIVITY_TITLE), + views::style::CONTEXT_DIALOG_TITLE, views::style::STYLE_PRIMARY)); + title->SetID(TITLE_ID); + + // Add spacer that fills the space between title and the menu button. + auto* spacer = title_view->AddChildView(std::make_unique<views::View>()); + box_layout->SetFlexForView(spacer, 1); + + // Add buttons container for menu button and close button. + const ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get(); + const int button_horizontal_spacing = layout_provider->GetDistanceMetric( + views::DISTANCE_RELATED_BUTTON_HORIZONTAL); + auto* buttons_container = + title_view->AddChildView(std::make_unique<views::View>()); + buttons_container->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), + button_horizontal_spacing)); + + buttons_container->AddChildView(CreateOptionsMenuButton()); + buttons_container->AddChildView(CreateCloseButton()); + + // Add title view to bubble dialog view. + AddChildView(std::move(title_view)); +} + +std::unique_ptr<views::Button> +RecentActivityBubbleDialogView::CreateCloseButton() { + auto close_button = + views::BubbleFrameView::CreateCloseButton(base::BindRepeating( + [](views::View* view) { + view->GetWidget()->CloseWithReason( + views::Widget::ClosedReason::kCloseButtonClicked); + }, + base::Unretained(this))); + close_button->SetVisible(true); + return close_button; +} + +std::unique_ptr<views::Button> +RecentActivityBubbleDialogView::CreateOptionsMenuButton() { + auto menu_button = views::CreateVectorImageButtonWithNativeTheme( + views::Button::PressedCallback(), kBrowserToolsIcon); + menu_button->SetCallback(base::BindRepeating( + &RecentActivityBubbleDialogView::ShowOptionsMenu, base::Unretained(this), + base::Unretained(menu_button.get()))); + + InstallCircleHighlightPathGenerator(menu_button.get()); + + menu_button->GetViewAccessibility().SetName( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_MORE_ACTIONS)); + menu_button->SetVisible(true); + return menu_button; +} + +void RecentActivityBubbleDialogView::ShowOptionsMenu(views::Button* source) { + options_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this); + + options_menu_model_->AddItemWithStringId( + OptionsMenuItem::SEE_ALL_ACTIVITY, + IDS_DATA_SHARING_MANAGE_ACTIVITY_LOG_OPTION); + + options_menu_runner_ = std::make_unique<views::MenuRunner>( + options_menu_model_.get(), views::MenuRunner::COMBOBOX); + gfx::Rect screen_bounds = source->GetAnchorBoundsInScreen(); + options_menu_runner_->RunMenuAt(source->GetWidget(), nullptr, screen_bounds, + views::MenuAnchorPosition::kTopRight, + ui::mojom::MenuSourceType::kMouse); +} + +void RecentActivityBubbleDialogView::ExecuteCommand(int command_id, + int event_flags) { + switch (command_id) { + case OptionsMenuItem::SEE_ALL_ACTIVITY: + chrome::ShowSharedTabGroupActivity(profile_); + break; + default: + NOTREACHED(); + } +} + void RecentActivityBubbleDialogView::CreateEmptyState() { // No activity to show. Fill in the empty state label and return early. auto* label = AddChildView(std::make_unique<views::Label>( @@ -330,6 +432,16 @@ LocationBarBubbleDelegateView::CloseBubble(); } +std::u16string RecentActivityBubbleDialogView::GetTitleForTesting() { + views::View* title_view = + views::AsViewClass<views::View>(GetViewByID(TITLE_VIEW_ID)); + views::Label* title = + title_view + ? views::AsViewClass<views::Label>(title_view->GetViewByID(TITLE_ID)) + : nullptr; + return title ? std::u16string(title->GetText()) : std::u16string(); +} + RecentActivityRowView* RecentActivityBubbleDialogView::GetRowForTesting(int n) { int tab_activity_size = tab_activity_container()->children().size(); int group_activity_size = group_activity_container()->children().size();
diff --git a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.h b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.h index 3898e4a..67d9795 100644 --- a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.h +++ b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.h
@@ -29,10 +29,16 @@ // The bubble dialog view housing the Shared Tab Group Recent Activity. // Shows at most kMaxNumberRows of the activity_log parameter. -class RecentActivityBubbleDialogView : public LocationBarBubbleDelegateView { +class RecentActivityBubbleDialogView : public LocationBarBubbleDelegateView, + public ui::SimpleMenuModel::Delegate { METADATA_HEADER(RecentActivityBubbleDialogView, LocationBarBubbleDelegateView) public: + enum OptionsMenuItem { SEE_ALL_ACTIVITY }; + + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kCloseButtonId); + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kSeeAllActivityId); + RecentActivityBubbleDialogView( View* anchor_view, content::WebContents* web_contents, @@ -41,6 +47,9 @@ Profile* profile); ~RecentActivityBubbleDialogView() override; + // ui::SimpleMenuModel::Delegate: + void ExecuteCommand(int command_id, int event_flags) override; + // The maximum number of rows that can be displayed in this dialog. static constexpr int kMaxNumberRows = 5; @@ -53,6 +62,10 @@ // Creates a view containing the most recent activity for the group. void CreateGroupActivity(); + // Returns the title view container including the title, the menu button, and + // the close button. + std::u16string GetTitleForTesting(); + // Returns the row's view at the given index. This will look in both // the tab activity container and the group activity container. RecentActivityRowView* GetRowForTesting(int n); @@ -65,9 +78,32 @@ } private: + // View IDs used for selecting views in tests. + enum RecentActivityViewID { + TITLE_VIEW_ID, + TITLE_ID, + }; + // Close this bubble. void Close(); + // Creates a button view for the close button. + std::unique_ptr<views::Button> CreateCloseButton(); + + // Creates a button view for the 3-dot menu button. + std::unique_ptr<views::Button> CreateOptionsMenuButton(); + + // Creates the top row of the dialog, including the title of the dialog, the + // 3-dot menu button, and the close button. + void CreateTitleView(); + + // Displays a context menu anchored to |source|, allowing users to access + // additional actions like "See All Activity". + void ShowOptionsMenu(views::Button* source); + + std::unique_ptr<ui::SimpleMenuModel> options_menu_model_; + std::unique_ptr<views::MenuRunner> options_menu_runner_; + // Containers will always be non-null. Visibility is toggled based on // whether rows are added to each container. raw_ptr<views::View> tab_activity_container_ = nullptr;
diff --git a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc index efad66a46..cdad29e 100644 --- a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc
@@ -247,9 +247,9 @@ // All dialogs have 4 children, except for empty state dialog, which // also contains the label for the empty state. if (test_name == "InvokeUi_Empty") { - EXPECT_EQ(5u, children.size()); + EXPECT_EQ(6u, children.size()); } else { - EXPECT_EQ(4u, children.size()); + EXPECT_EQ(5u, children.size()); } // Tab container empty and hidden. @@ -320,9 +320,9 @@ #if BUILDFLAG(IS_MAC) // Initial caps on Mac. - EXPECT_EQ(bubble->GetWindowTitle(), u"Recent Activity"); + EXPECT_EQ(bubble->GetTitleForTesting(), u"Recent Activity"); #else - EXPECT_EQ(bubble->GetWindowTitle(), u"Recent activity"); + EXPECT_EQ(bubble->GetTitleForTesting(), u"Recent activity"); #endif EXPECT_EQ(bubble->GetRowForTesting(0)->GetAccessibleName(),
diff --git a/chrome/browser/ui/views/tabs/tab_strip_action_container_browsertest.cc b/chrome/browser/ui/views/tabs/tab_strip_action_container_browsertest.cc index baf3be7..c479cc8 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_action_container_browsertest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_action_container_browsertest.cc
@@ -58,6 +58,7 @@ #if BUILDFLAG(ENABLE_GLIC) features::kGlic, features::kGlicRollout, + features::kGlicFreWarming, #endif features::kTabstripComboButton, features::kTabstripDeclutter,
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs/chrome_labs_view_controller.cc b/chrome/browser/ui/views/toolbar/chrome_labs/chrome_labs_view_controller.cc index dbdd53a..86bae18 100644 --- a/chrome/browser/ui/views/toolbar/chrome_labs/chrome_labs_view_controller.cc +++ b/chrome/browser/ui/views/toolbar/chrome_labs/chrome_labs_view_controller.cc
@@ -54,7 +54,7 @@ // kTabScrollingSelected = 3, // kSidePanelSelected = 4, // kLensRegionSearchSelected = 5, - kWebUITabStripSelected = 6, + // kWebUITabStripSelected = 6, // kTabSearchMediaTabsSelected = 7, // kChromeRefresh2023Selected = 8, // kTabGroupsSaveSelected = 9, @@ -82,12 +82,6 @@ }; const auto get_enum = [](const std::string& internal_name) { -#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && \ - (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)) - if (internal_name == flag_descriptions::kWebUITabStripFlagId) - return ChromeLabsSelectedLab::kWebUITabStripSelected; -#endif - return ChromeLabsSelectedLab::kUnspecifiedSelected; };
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc index 4be6640..c070e575 100644 --- a/chrome/browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc
@@ -73,14 +73,8 @@ gfx::NativeView help_bubble_native_view_ = gfx::NativeView(); }; -// TODO(crbug.com/419801487): Fix flaky test and re-enable. -#if BUILDFLAG(IS_WIN) -#define MAYBE_ToggleFocusForAccessibility DISABLED_ToggleFocusForAccessibility -#else -#define MAYBE_ToggleFocusForAccessibility ToggleFocusForAccessibility -#endif IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryViewsUiTest, - MAYBE_ToggleFocusForAccessibility) { + ToggleFocusForAccessibility) { RunTestSequence(ObserveState(views::test::kCurrentWidgetFocus), // A help bubble without buttons should not start focused. CreateHelpBubble(kToolbarAppMenuButtonElementId, @@ -98,16 +92,8 @@ CloseHelpBubble()); } -// TODO(crbug.com/419801487): Fix flaky test and re-enable. -#if BUILDFLAG(IS_WIN) -#define MAYBE_ToggleFocusForAccessibilityStartsFocused \ - DISABLED_ToggleFocusForAccessibilityStartsFocused -#else -#define MAYBE_ToggleFocusForAccessibilityStartsFocused \ - ToggleFocusForAccessibilityStartsFocused -#endif IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryViewsUiTest, - MAYBE_ToggleFocusForAccessibilityStartsFocused) { + ToggleFocusForAccessibilityStartsFocused) { auto params = GetDefaultHelpBubbleParams(); user_education::HelpBubbleButtonParams button_params; button_params.text = u"Button"; @@ -129,14 +115,8 @@ CloseHelpBubble()); } -// TODO(crbug.com/419801487): Fix flaky test and re-enable. -#if BUILDFLAG(IS_WIN) -#define MAYBE_ToggleFocusViaAccelerator DISABLED_ToggleFocusViaAccelerator -#else -#define MAYBE_ToggleFocusViaAccelerator ToggleFocusViaAccelerator -#endif IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryViewsUiTest, - MAYBE_ToggleFocusViaAccelerator) { + ToggleFocusViaAccelerator) { ui::Accelerator next_pane; ASSERT_TRUE(BrowserView::GetBrowserViewForBrowser(browser())->GetAccelerator( IDC_FOCUS_NEXT_PANE, &next_pane));
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc index eefdc2b..a9fc88f 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc
@@ -16,6 +16,8 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service.h" #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service_factory.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_controller.h" @@ -82,9 +84,19 @@ return user_education::FeaturePromoResult::kBlockedByUi; } + Browser& browser = *browser_view_->browser(); + + // Turn off IPH while the browser is showing fullscreen content (like a + // video). See https://crbug.com/411475424. + auto* const fullscreen_controller = + browser.exclusive_access_manager()->fullscreen_controller(); + if (fullscreen_controller->IsWindowFullscreenForTabOrPending() || + fullscreen_controller->IsExtensionFullscreenOrPending()) { + return user_education::FeaturePromoResult::kBlockedByUi; + } + // Turn off IPH while a required search engine choice dialog is visible or // pending. - Browser& browser = *browser_view_->browser(); SearchEngineChoiceDialogService* search_engine_choice_dialog_service = SearchEngineChoiceDialogServiceFactory::GetForProfile(browser.profile()); if (search_engine_choice_dialog_service &&
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.h b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.h index 9d3042e..eb2dd41 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.h +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.h
@@ -57,8 +57,7 @@ ~BrowserFeaturePromoController20() override; protected: - FRIEND_TEST_ALL_PREFIXES(BrowserFeaturePromoController20ActivationUiTest, - CanShowPromoForElement); + friend class BrowserFeaturePromoController20CanShowPromoForElementUiTest; // FeaturePromoController: ui::ElementContext GetAnchorContext() const override;
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_25.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_25.cc index 9347891..4a1588b 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_25.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_25.cc
@@ -88,6 +88,10 @@ std::make_unique<OmniboxNotOpenPrecondition>(*browser_view_); CHECK(shared_preconditions_.emplace(ptr->GetIdentifier(), std::move(ptr)) .second); + ptr = std::make_unique<ContentNotFullscreenPrecondition>( + *browser_view_->browser()); + CHECK(shared_preconditions_.emplace(ptr->GetIdentifier(), std::move(ptr)) + .second); ptr = std::make_unique<ToolbarNotCollapsedPrecondition>(*browser_view_); CHECK(shared_preconditions_.emplace(ptr->GetIdentifier(), std::move(ptr)) .second); @@ -171,6 +175,9 @@ } }; + // Promos shouldn't show when content is fullscreen. + maybe_add_shared_precondition(kContentNotFullscreenPrecondition); + // Most promos are blocked by an open omnibox to prevent z-fighting // issues. maybe_add_shared_precondition(kOmniboxNotOpenPrecondition);
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc index 14bff23..52b1e847 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc
@@ -17,8 +17,11 @@ #include "base/time/time.h" #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/toolbar_controller_util.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/contents_web_view.h" #include "chrome/browser/ui/views/frame/test_with_browser_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_controller.h" @@ -542,32 +545,45 @@ // Using the base interactive browser test re-enables window activation // checking. This is only 2.0 since activation precondition is tested elsewhere. -class BrowserFeaturePromoController20ActivationUiTest +class BrowserFeaturePromoController20CanShowPromoForElementUiTest : public InteractiveBrowserTest { public: - BrowserFeaturePromoController20ActivationUiTest() { + BrowserFeaturePromoController20CanShowPromoForElementUiTest() { feature_list_.InitAndDisableFeature( user_education::features::kUserEducationExperienceVersion2Point5); } + ~BrowserFeaturePromoController20CanShowPromoForElementUiTest() override = + default; + + auto CheckCanShowPromoForElement( + ElementSpecifier spec, + user_education::FeaturePromoResult expected) { + return CheckElement( + spec, + [this](ui::TrackedElement* anchor) { + return static_cast<BrowserFeaturePromoController20*>( + browser()->window()->GetFeaturePromoControllerForTesting()) + ->CanShowPromoForElement(anchor); + }, + expected); + } private: base::test::ScopedFeatureList feature_list_; }; +using BrowserFeaturePromoController20ActivationUiTest = + BrowserFeaturePromoController20CanShowPromoForElementUiTest; + IN_PROC_BROWSER_TEST_F(BrowserFeaturePromoController20ActivationUiTest, CanShowPromoForElement) { auto widget = std::make_unique<views::Widget>(); - auto can_show_promo = [this](ui::TrackedElement* anchor) { - return static_cast<BrowserFeaturePromoController20*>( - browser()->window()->GetFeaturePromoControllerForTesting()) - ->CanShowPromoForElement(anchor); - }; - RunTestSequence( // Verify that at first, we can show the promo on the browser. - CheckElement(kToolbarAppMenuButtonElementId, can_show_promo, - user_education::FeaturePromoResult::Success()), + CheckCanShowPromoForElement( + kToolbarAppMenuButtonElementId, + user_education::FeaturePromoResult::Success()), // Start observing widget focus, and create the widget. ObserveState(views::test::kCurrentWidgetFocus), // Create a second widget and give it focus. We can't guarantee that we @@ -593,11 +609,97 @@ [&widget]() { return widget->GetNativeView(); }), // Verify that we can no longer show the promo, since the browser is not // the active window. - CheckElement( - kToolbarAppMenuButtonElementId, can_show_promo, + CheckCanShowPromoForElement( + kToolbarAppMenuButtonElementId, user_education::FeaturePromoResult::kAnchorSurfaceNotActive)); } +using BrowserFeaturePromoController20FullscreenUiTest = + BrowserFeaturePromoController20CanShowPromoForElementUiTest; + +IN_PROC_BROWSER_TEST_F(BrowserFeaturePromoController20FullscreenUiTest, + NotFullscreen) { + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); + RunTestSequence( + InstrumentTab(kTabId), + NavigateWebContents(kTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + CheckCanShowPromoForElement( + // Need to choose an element that will be visible in fullscreen. + ContentsWebView::kContentsWebViewElementId, + user_education::FeaturePromoResult::Success())); +} + +IN_PROC_BROWSER_TEST_F(BrowserFeaturePromoController20FullscreenUiTest, + Fullscreen) { + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); + RunTestSequence( + InstrumentTab(kTabId), + NavigateWebContents(kTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + WithElement(kTabId, + [this](ui::TrackedElement* tab) { + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab( + AsInstrumentedWebContents(tab) + ->web_contents() + ->GetPrimaryMainFrame()); + }), + CheckResult( + [this]() { + return browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsTabFullscreen(); + }, + true), + CheckCanShowPromoForElement( + // Need to choose an element that will be visible in fullscreen. + ContentsWebView::kContentsWebViewElementId, + user_education::FeaturePromoResult::kBlockedByUi)); +} + +IN_PROC_BROWSER_TEST_F(BrowserFeaturePromoController20FullscreenUiTest, + ExitFullscreen) { + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); + RunTestSequence( + InstrumentTab(kTabId), + NavigateWebContents(kTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + WithElement(kTabId, + [this](ui::TrackedElement* tab) { + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab( + AsInstrumentedWebContents(tab) + ->web_contents() + ->GetPrimaryMainFrame()); + }), + WithElement(kTabId, + [this](ui::TrackedElement* tab) { + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab( + AsInstrumentedWebContents(tab)->web_contents()); + }), + CheckResult( + [this]() { + return browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsTabFullscreen(); + }, + false), + CheckCanShowPromoForElement( + // Need to choose an element that will be visible in fullscreen. + ContentsWebView::kContentsWebViewElementId, + user_education::FeaturePromoResult::Success())); +} + namespace { BASE_FEATURE(kIPHExemptFromOmniboxFeature,
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc index d66abae8..0b5e24c 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc
@@ -10,6 +10,8 @@ #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service.h" #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service_factory.h" #include "chrome/browser/ui/browser_element_identifiers.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/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" @@ -32,6 +34,8 @@ #include "ui/views/widget/widget.h" DEFINE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE(kWindowActivePrecondition); +DEFINE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE( + kContentNotFullscreenPrecondition); DEFINE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE(kOmniboxNotOpenPrecondition); DEFINE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE( kToolbarNotCollapsedPrecondition); @@ -75,6 +79,24 @@ : user_education::FeaturePromoResult::kAnchorSurfaceNotActive; } +ContentNotFullscreenPrecondition::ContentNotFullscreenPrecondition( + Browser& browser) + : FeaturePromoPreconditionBase(kContentNotFullscreenPrecondition, + "Content is not fullscreen"), + browser_(browser) {} +ContentNotFullscreenPrecondition::~ContentNotFullscreenPrecondition() = default; + +user_education::FeaturePromoResult +ContentNotFullscreenPrecondition::CheckPrecondition(ComputedData& data) const { + auto* const fullscreen_controller = + browser_->exclusive_access_manager()->fullscreen_controller(); + if (fullscreen_controller->IsWindowFullscreenForTabOrPending() || + fullscreen_controller->IsExtensionFullscreenOrPending()) { + return user_education::FeaturePromoResult::kBlockedByUi; + } + return user_education::FeaturePromoResult::Success(); +} + OmniboxNotOpenPrecondition::OmniboxNotOpenPrecondition( const BrowserView& browser_view) : FeaturePromoPreconditionBase(kOmniboxNotOpenPrecondition,
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.h b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.h index 780d731b..81aa1da 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.h +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.h
@@ -24,6 +24,8 @@ DECLARE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE(kWindowActivePrecondition); DECLARE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE( + kContentNotFullscreenPrecondition); +DECLARE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE( kOmniboxNotOpenPrecondition); DECLARE_FEATURE_PROMO_PRECONDITION_IDENTIFIER_VALUE( kToolbarNotCollapsedPrecondition); @@ -45,6 +47,21 @@ ComputedData& data) const override; }; +// Requires that the window isn't in content-fullscreen. +class ContentNotFullscreenPrecondition + : public user_education::FeaturePromoPreconditionBase { + public: + explicit ContentNotFullscreenPrecondition(Browser& browser); + ~ContentNotFullscreenPrecondition() override; + + // FeaturePromoPreconditionBase: + user_education::FeaturePromoResult CheckPrecondition( + ComputedData& data) const override; + + private: + const raw_ref<Browser> browser_; +}; + // Precondition that the Omnibox isn't open. class OmniboxNotOpenPrecondition : public user_education::FeaturePromoPreconditionBase {
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc index 34c0cc413..a1e7ca2 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc
@@ -13,6 +13,8 @@ #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/toolbar_controller_util.h" #include "chrome/browser/ui/views/frame/contents_web_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" @@ -56,6 +58,12 @@ BrowserFeaturePromoPreconditionsUiTest() = default; ~BrowserFeaturePromoPreconditionsUiTest() override = default; + void SetUpOnMainThread() override { + InteractiveBrowserTest::SetUpOnMainThread(); + g_browser_process->local_state()->SetBoolean( + chrome_urls::kInternalOnlyUisEnabled, true); + } + protected: auto CaptureAnchor(ui::ElementIdentifier id) { return AfterShow(id, [this](ui::TrackedElement* el) { @@ -80,18 +88,7 @@ user_education::AnchorElementPrecondition::kAnchorElement}; }; -class WindowActivePreconditionUiTest - : public BrowserFeaturePromoPreconditionsUiTest { - public: - WindowActivePreconditionUiTest() = default; - ~WindowActivePreconditionUiTest() override = default; - - void SetUpOnMainThread() override { - BrowserFeaturePromoPreconditionsUiTest::SetUpOnMainThread(); - g_browser_process->local_state()->SetBoolean( - chrome_urls::kInternalOnlyUisEnabled, true); - } -}; +using WindowActivePreconditionUiTest = BrowserFeaturePromoPreconditionsUiTest; IN_PROC_BROWSER_TEST_F(WindowActivePreconditionUiTest, ElementInActiveBrowser) { RunTestSequence( @@ -148,6 +145,115 @@ CheckWindowActiveResult(user_education::FeaturePromoResult::Success())); } +using ContentNotFullscreenPreconditionUiTest = + BrowserFeaturePromoPreconditionsUiTest; + +IN_PROC_BROWSER_TEST_F(ContentNotFullscreenPreconditionUiTest, NotFullscreen) { + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); + RunTestSequence( + InstrumentTab(kTabId), + NavigateWebContents(kTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + CheckResult( + [this]() { + ContentNotFullscreenPrecondition precond(*browser()); + user_education::FeaturePromoPrecondition::ComputedData data; + return precond.CheckPrecondition(data); + }, + user_education::FeaturePromoResult::Success())); +} + +IN_PROC_BROWSER_TEST_F(ContentNotFullscreenPreconditionUiTest, + MaximizedNotFullscreen) { + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); + RunTestSequence( + InstrumentTab(kTabId), + NavigateWebContents(kTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + Do([this]() { browser()->window()->Maximize(); }), + CheckResult( + [this]() { + ContentNotFullscreenPrecondition precond(*browser()); + user_education::FeaturePromoPrecondition::ComputedData data; + return precond.CheckPrecondition(data); + }, + user_education::FeaturePromoResult::Success())); +} + +IN_PROC_BROWSER_TEST_F(ContentNotFullscreenPreconditionUiTest, Fullscreen) { + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); + RunTestSequence( + InstrumentTab(kTabId), + NavigateWebContents(kTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + WithElement(kTabId, + [this](ui::TrackedElement* tab) { + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab( + AsInstrumentedWebContents(tab) + ->web_contents() + ->GetPrimaryMainFrame()); + }), + CheckResult( + [this]() { + return browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsTabFullscreen(); + }, + true), + CheckResult( + [this]() { + ContentNotFullscreenPrecondition precond(*browser()); + user_education::FeaturePromoPrecondition::ComputedData data; + return precond.CheckPrecondition(data); + }, + user_education::FeaturePromoResult::kBlockedByUi)); +} + +IN_PROC_BROWSER_TEST_F(ContentNotFullscreenPreconditionUiTest, ExitFullscreen) { + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); + RunTestSequence( + InstrumentTab(kTabId), + NavigateWebContents(kTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + WithElement(kTabId, + [this](ui::TrackedElement* tab) { + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab( + AsInstrumentedWebContents(tab) + ->web_contents() + ->GetPrimaryMainFrame()); + }), + WithElement(kTabId, + [this](ui::TrackedElement* tab) { + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab( + AsInstrumentedWebContents(tab)->web_contents()); + }), + CheckResult( + [this]() { + return browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsTabFullscreen(); + }, + false), + CheckResult( + [this]() { + ContentNotFullscreenPrecondition precond(*browser()); + user_education::FeaturePromoPrecondition::ComputedData data; + return precond.CheckPrecondition(data); + }, + user_education::FeaturePromoResult::Success())); +} + using OmniboxNotOpenPreconditionUiTest = BrowserFeaturePromoPreconditionsUiTest; IN_PROC_BROWSER_TEST_F(OmniboxNotOpenPreconditionUiTest,
diff --git a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h index 2f1d4ac..9792bca 100644 --- a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h +++ b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h
@@ -14,7 +14,6 @@ #include "chrome/browser/ui/web_applications/web_app_dialogs.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "components/webapps/common/web_app_id.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h index 9a12a9b..9b641103 100644 --- a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h +++ b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h
@@ -24,7 +24,6 @@ #include "ui/gfx/image/image_skia.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/window/dialog_delegate.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/ui/webui/access_code_cast/access_code_cast_dialog.h b/chrome/browser/ui/webui/access_code_cast/access_code_cast_dialog.h index a5d62ac2..6d41157 100644 --- a/chrome/browser/ui/webui/access_code_cast/access_code_cast_dialog.h +++ b/chrome/browser/ui/webui/access_code_cast/access_code_cast_dialog.h
@@ -17,7 +17,6 @@ #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" #include "ui/web_dialogs/web_dialog_delegate.h" -#include "url/gurl.h" namespace content { class WebContents;
diff --git a/chrome/browser/ui/webui/ash/floating_workspace/floating_workspace_dialog.cc b/chrome/browser/ui/webui/ash/floating_workspace/floating_workspace_dialog.cc index c31bf08..c28d8e4 100644 --- a/chrome/browser/ui/webui/ash/floating_workspace/floating_workspace_dialog.cc +++ b/chrome/browser/ui/webui/ash/floating_workspace/floating_workspace_dialog.cc
@@ -6,6 +6,7 @@ #include <string> +#include "chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.h" #include "chrome/browser/ash/floating_workspace/floating_workspace_service.h" #include "chrome/browser/ash/floating_workspace/floating_workspace_service_factory.h" #include "chrome/browser/ui/ash/login/oobe_dialog_size_utils.h" @@ -72,7 +73,15 @@ if (service) { service->StopRestoringSession(); } - } else if (!json_retval.empty()) { + floating_workspace_metrics_util:: + RecordFloatingWorkspaceStartupUiClosureReason( + floating_workspace_metrics_util::StartupUiClosureReason::kManual); + } else if (json_retval.empty()) { + floating_workspace_metrics_util:: + RecordFloatingWorkspaceStartupUiClosureReason( + floating_workspace_metrics_util::StartupUiClosureReason:: + kAutomatic); + } else { NOTREACHED(); }
diff --git a/chrome/browser/ui/webui/commerce/product_specifications_ui.h b/chrome/browser/ui/webui/commerce/product_specifications_ui.h index a346160..799c712 100644 --- a/chrome/browser/ui/webui/commerce/product_specifications_ui.h +++ b/chrome/browser/ui/webui/commerce/product_specifications_ui.h
@@ -13,7 +13,6 @@ #include "ui/web_dialogs/web_dialog_ui.h" #include "ui/webui/mojo_web_ui_controller.h" #include "ui/webui/resources/cr_components/color_change_listener/color_change_listener.mojom.h" -#include "url/gurl.h" namespace base { class RefCountedMemory;
diff --git a/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc b/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc index 95b8aaa..8ab9bcd 100644 --- a/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc +++ b/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc
@@ -12,14 +12,11 @@ #include "components/user_education/views/help_bubble_view.h" #include "content/public/test/browser_test.h" #include "extensions/common/extension_urls.h" -#include "ui/base/interaction/polling_state_observer.h" namespace { DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kFirstTabContents); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kSecondTabContents); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kZeroStatePromoWebUiIphId); -DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ui::test::PollingStateObserver<int>, - kTabCountState); } // namespace class ExtensionsZeroStatePromoTestBase : public InteractiveFeaturePromoTest { @@ -43,14 +40,6 @@ InProcessBrowserTest::PreRunTestOnMainThread(); } - auto WaitForTabCount(int expected_count) { - return Steps( - PollState(kTabCountState, - [this]() { return browser()->tab_strip_model()->count(); }), - WaitForState(kTabCountState, expected_count), - StopObservingState(kTabCountState)); - } - auto CheckZeroStatePromoClosedReason( user_education::FeaturePromoClosedReason closeReason) { return Do([this, closeReason]() { @@ -86,15 +75,15 @@ // Test showing the zero state promo custom action IPH to users with no // extensions installed. Clicking on the custom action opens a page to the // Chrome Web Store. +// TODO(crbug.com/419854475): Re-enable this test once the bug is fixed. IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomActionIphTest, - ShowingZeroStatePromoCustomActionIph) { + DISABLED_ShowingZeroStatePromoCustomActionIph) { RunTestSequence( InstrumentTab(kFirstTabContents), NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), InAnyContext(WaitForPromo( feature_engagement::kIPHExtensionsZeroStatePromoFeature)), - PressDefaultPromoButton(), WaitForTabCount(2), - InstrumentTab(kSecondTabContents, 1), + InstrumentNextTab(kSecondTabContents), PressDefaultPromoButton(), WaitForWebContentsReady(kSecondTabContents, extension_urls::GetWebstoreLaunchURL())); } @@ -121,8 +110,9 @@ // Test showing the zero state promo custom ui IPH (chips variant) with no // extensions installed. Clicking on the coupon chip button should open a // page to the Chrome Web Store. +// TODO(crbug.com/419854475): Re-enable this test once the bug is fixed. IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiChipIphTest, - ClickCouponChipOnZeroStatePromoIph) { + DISABLED_ClickCouponChipOnZeroStatePromoIph) { RunTestSequence( InstrumentTab(kFirstTabContents, 0), NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), @@ -134,13 +124,13 @@ GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kCoupon, 0), + InstrumentNextTab(kSecondTabContents), ClickElement(kZeroStatePromoWebUiIphId, kCouponButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - WaitForTabCount(2), InstrumentTab(kSecondTabContents, 1), - WaitForWebContentsReady(kSecondTabContents, - GURL("https://chromewebstore.google.com/category/" - "extensions/lifestyle/shopping")), + WaitForWebContentsReady( + kSecondTabContents, + GURL(zero_state_promo::mojom::kCouponWebStoreUrl)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kCoupon, 1)); } @@ -148,8 +138,9 @@ // Test showing the zero state promo custom ui IPH (chips variant) with no // extensions installed. Clicking on the writing chip button should open a // page to the Chrome Web Store. +// TODO(crbug.com/419854475): Re-enable this test once the bug is fixed. IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiChipIphTest, - ClickWritingChipOnZeroStatePromoIph) { + DISABLED_ClickWritingChipOnZeroStatePromoIph) { RunTestSequence( InstrumentTab(kFirstTabContents, 0), NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), @@ -161,13 +152,13 @@ GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kWriting, 0), + InstrumentNextTab(kSecondTabContents), ClickElement(kZeroStatePromoWebUiIphId, kWritingButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - WaitForTabCount(2), InstrumentTab(kSecondTabContents, 1), - WaitForWebContentsReady(kSecondTabContents, - GURL("https://chromewebstore.google.com/" - "collection/writing_essentials")), + WaitForWebContentsReady( + kSecondTabContents, + GURL(zero_state_promo::mojom::kWritingWebStoreUrl)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kWriting, 1)); } @@ -175,8 +166,9 @@ // Test showing the zero state promo custom ui IPH (chips variant) with no // extensions installed. Clicking on the productivity chip button should open a // page to the Chrome Web Store. +// TODO(crbug.com/419854475): Re-enable this test once the bug is fixed. IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiChipIphTest, - ClickProductivityChipOnZeroStatePromoIph) { + DISABLED_ClickProductivityChipOnZeroStatePromoIph) { RunTestSequence( InstrumentTab(kFirstTabContents, 0), NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), @@ -188,13 +180,13 @@ GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kProductivity, 0), + InstrumentNextTab(kSecondTabContents), ClickElement(kZeroStatePromoWebUiIphId, kProductivityButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - WaitForTabCount(2), InstrumentTab(kSecondTabContents, 1), - WaitForWebContentsReady(kSecondTabContents, - GURL("https://chromewebstore.google.com/category/" - "extensions/productivity/workflow")), + WaitForWebContentsReady( + kSecondTabContents, + GURL(zero_state_promo::mojom::kProductivityWebStoreUrl)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kProductivity, 1)); } @@ -202,8 +194,9 @@ // Test showing the zero state promo custom ui IPH (chips variant) with no // extensions installed. Clicking on the ai chip button should open a // page to the Chrome Web Store. +// TODO(crbug.com/419854475): Re-enable this test once the bug is fixed. IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiChipIphTest, - ClickAiChipOnZeroStatePromoIph) { + DISABLED_ClickAiChipOnZeroStatePromoIph) { RunTestSequence( InstrumentTab(kFirstTabContents, 0), NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), @@ -215,18 +208,183 @@ GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kAi, 0), + InstrumentNextTab(kSecondTabContents), ClickElement(kZeroStatePromoWebUiIphId, kAiButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - WaitForTabCount(2), InstrumentTab(kSecondTabContents, 1), - WaitForWebContentsReady( - kSecondTabContents, - GURL("https://chromewebstore.google.com/collection/ai_productivity")), + WaitForWebContentsReady(kSecondTabContents, + GURL(zero_state_promo::mojom::kAiWebStoreUrl)), CheckZeroStatePromoLinkClickCount( zero_state_promo::mojom::WebStoreLinkClicked::kAi, 1)); } +// TODO(crbug.com/419854475): Re-enable this test once the bug is fixed. IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiChipIphTest, + DISABLED_DismissPromoIph) { + RunTestSequence( + InstrumentTab(kFirstTabContents, 0), + NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), + WaitForShow(CustomWebUIHelpBubble::kHelpBubbleIdForTesting), + InstrumentNonTabWebView(kZeroStatePromoWebUiIphId, + CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kZeroStatePromoWebUiIphId, + GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), + ClickElement(kZeroStatePromoWebUiIphId, kDismissButton, + ExecuteJsMode::kFireAndForget), + WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), + CheckResult( + [this] { return browser()->tab_strip_model()->GetTabCount(); }, 1, + "CheckTabCount"), + CheckZeroStatePromoClosedReason( + user_education::FeaturePromoClosedReason::kDismiss)); +} + +class ExtensionsZeroStateCustomUiPlainLinkIphTest + : public ExtensionsZeroStatePromoTestBase { + public: + ExtensionsZeroStateCustomUiPlainLinkIphTest() + : ExtensionsZeroStatePromoTestBase( + feature_engagement::IPHExtensionsZeroStatePromoVariant:: + kCustomUIPlainLinkIph) {} + + const DeepQuery kDismissButton{"extensions-zero-state-promo-app", + "#dismissButton"}; + const DeepQuery kCouponLink{"extensions-zero-state-promo-app", + "#couponsLink"}; + const DeepQuery kWritingLink{"extensions-zero-state-promo-app", + "#writingLink"}; + const DeepQuery kProductivityLink{"extensions-zero-state-promo-app", + "#productivityLink"}; + const DeepQuery kAiLink{"extensions-zero-state-promo-app", "#aiLink"}; + const DeepQuery kCloseButton{"extensions-zero-state-promo-app", + "#closeButton"}; + const DeepQuery kDiscoverExtensionsButton{"extensions-zero-state-promo-app", + "#customActionButton"}; + const DeepQuery kGotItButton{"extensions-zero-state-promo-app", + "#closeButton"}; +}; + +IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiPlainLinkIphTest, + ClickCouponLinkOnZeroStatePromoIph) { + RunTestSequence( + InstrumentTab(kFirstTabContents, 0), + NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), + WaitForShow(CustomWebUIHelpBubble::kHelpBubbleIdForTesting), + InstrumentNonTabWebView(kZeroStatePromoWebUiIphId, + CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kZeroStatePromoWebUiIphId, + GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kCoupon, 0), + InstrumentNextTab(kSecondTabContents), + ClickElement(kZeroStatePromoWebUiIphId, kCouponLink, + ExecuteJsMode::kFireAndForget), + WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kSecondTabContents, + GURL(zero_state_promo::mojom::kCouponWebStoreUrl)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kCoupon, 1)); +} + +IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiPlainLinkIphTest, + ClickWritingLinkOnZeroStatePromoIph) { + RunTestSequence( + InstrumentTab(kFirstTabContents, 0), + NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), + WaitForShow(CustomWebUIHelpBubble::kHelpBubbleIdForTesting), + InstrumentNonTabWebView(kZeroStatePromoWebUiIphId, + CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kZeroStatePromoWebUiIphId, + GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kWriting, 0), + InstrumentNextTab(kSecondTabContents), + ClickElement(kZeroStatePromoWebUiIphId, kWritingLink, + ExecuteJsMode::kFireAndForget), + WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kSecondTabContents, + GURL(zero_state_promo::mojom::kWritingWebStoreUrl)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kWriting, 1)); +} + +IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiPlainLinkIphTest, + ClickProductivityLinkOnZeroStatePromoIph) { + RunTestSequence( + InstrumentTab(kFirstTabContents, 0), + NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), + WaitForShow(CustomWebUIHelpBubble::kHelpBubbleIdForTesting), + InstrumentNonTabWebView(kZeroStatePromoWebUiIphId, + CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kZeroStatePromoWebUiIphId, + GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kProductivity, 0), + InstrumentNextTab(kSecondTabContents), + ClickElement(kZeroStatePromoWebUiIphId, kProductivityLink, + ExecuteJsMode::kFireAndForget), + WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kSecondTabContents, + GURL(zero_state_promo::mojom::kProductivityWebStoreUrl)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kProductivity, 1)); +} + +IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiPlainLinkIphTest, + ClickAiLinkOnZeroStatePromoIph) { + RunTestSequence( + InstrumentTab(kFirstTabContents, 0), + NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), + WaitForShow(CustomWebUIHelpBubble::kHelpBubbleIdForTesting), + InstrumentNonTabWebView(kZeroStatePromoWebUiIphId, + CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kZeroStatePromoWebUiIphId, + GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kAi, 0), + InstrumentNextTab(kSecondTabContents), + ClickElement(kZeroStatePromoWebUiIphId, kAiLink, + ExecuteJsMode::kFireAndForget), + WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady(kSecondTabContents, + GURL(zero_state_promo::mojom::kAiWebStoreUrl)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kAi, 1)); +} + +IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiPlainLinkIphTest, + ClickDiscoverExtensionsButtonOnZeroStatePromoIph) { + RunTestSequence( + InstrumentTab(kFirstTabContents, 0), + NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), + WaitForShow(CustomWebUIHelpBubble::kHelpBubbleIdForTesting), + InstrumentNonTabWebView(kZeroStatePromoWebUiIphId, + CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kZeroStatePromoWebUiIphId, + GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kDiscoverExtension, 0), + InstrumentNextTab(kSecondTabContents), + ClickElement(kZeroStatePromoWebUiIphId, kDiscoverExtensionsButton, + ExecuteJsMode::kFireAndForget), + WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kSecondTabContents, + GURL(zero_state_promo::mojom::kDiscoverExtensionWebStoreUrl)), + CheckZeroStatePromoLinkClickCount( + zero_state_promo::mojom::WebStoreLinkClicked::kDiscoverExtension, 1)); +} + +IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiPlainLinkIphTest, DismissPromoIph) { RunTestSequence( InstrumentTab(kFirstTabContents, 0), @@ -246,3 +404,24 @@ CheckZeroStatePromoClosedReason( user_education::FeaturePromoClosedReason::kDismiss)); } + +IN_PROC_BROWSER_TEST_F(ExtensionsZeroStateCustomUiPlainLinkIphTest, + ClickGotItButton) { + RunTestSequence( + InstrumentTab(kFirstTabContents, 0), + NavigateWebContents(kFirstTabContents, GURL(chrome ::kChromeUIAboutURL)), + WaitForShow(CustomWebUIHelpBubble::kHelpBubbleIdForTesting), + InstrumentNonTabWebView(kZeroStatePromoWebUiIphId, + CustomWebUIHelpBubble::kWebViewIdForTesting), + WaitForWebContentsReady( + kZeroStatePromoWebUiIphId, + GURL(chrome::kChromeUIExtensionsZeroStatePromoURL)), + ClickElement(kZeroStatePromoWebUiIphId, kGotItButton, + ExecuteJsMode::kFireAndForget), + WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), + CheckResult( + [this] { return browser()->tab_strip_model()->GetTabCount(); }, 1, + "CheckTabCount"), + CheckZeroStatePromoClosedReason( + user_education::FeaturePromoClosedReason::kDismiss)); +}
diff --git a/chrome/browser/ui/webui/extensions_zero_state_promo/zero_state_promo_ui.cc b/chrome/browser/ui/webui/extensions_zero_state_promo/zero_state_promo_ui.cc index 13bdbd1b..840f1536 100644 --- a/chrome/browser/ui/webui/extensions_zero_state_promo/zero_state_promo_ui.cc +++ b/chrome/browser/ui/webui/extensions_zero_state_promo/zero_state_promo_ui.cc
@@ -37,6 +37,8 @@ {"extensionsZeroStateIphHeader", IDS_EXTENSIONS_ZERO_STATE_IPH_HEADER}, {"extensionsZeroStateChipsIphDesc", IDS_EXTENSIONS_ZERO_STATE_CHIPS_IPH_DESCRIPTION}, + {"extensionsZeroStatePlainLinkIphDesc", + IDS_EXTENSIONS_ZERO_STATE_PLAIN_LINK_IPH_DESCRIPTION}, {"extensionsZeroStateIphShoppingCategoryLabel", IDS_EXTENSIONS_ZERO_STATE_IPH_SHOPPING_CATEGORY_LABEL}, {"extensionsZeroStateIphWritingHelpCollectionLabel", @@ -47,9 +49,27 @@ IDS_EXTENSIONS_ZERO_STATE_IPH_AI_PRODUCTIVITY_COLLECTION_LABEL}, {"extensionsZeroStateIphDismissButtonTitle", IDS_EXTENSIONS_ZERO_STATE_IPH_DISMISS_BUTTON_TITLE}, + {"extensionsZeroStateIphShoppingCategoryLink", + IDS_EXTENSIONS_ZERO_STATE_IPH_SHOPPING_CATEGORY_LINK}, + {"extensionsZeroStateIphWritingHelpCollectionLink", + IDS_EXTENSIONS_ZERO_STATE_IPH_WRITING_HELP_COLLECTION_LINK}, + {"extensionsZeroStateIphProductivityCategoryLink", + IDS_EXTENSIONS_ZERO_STATE_IPH_PRODUCTIVITY_CATEGORY_LINK}, + {"extensionsZeroStateIphAiProductivityCollectionLink", + IDS_EXTENSIONS_ZERO_STATE_IPH_AI_PRODUCTIVITY_COLLECTION_LINK}, + {"extensionsZeroStateIphCloseButtonLabel", + IDS_EXTENSIONS_ZERO_STATE_IPH_DISMISS_BUTTON_TEXT}, + {"extensionsZeroStateIphCustomActionButtonLabel", + IDS_EXTENSIONS_ZERO_STATE_PROMO_CUSTOM_ACTION_IPH_ACCEPT}, }; source->AddLocalizedStrings(kLocalizedStrings); + feature_engagement::IPHExtensionsZeroStatePromoVariant promoVariant = + feature_engagement::kIPHExtensionsZeroStatePromoVariantParam.Get(); + source->AddBoolean("showChipsUi", + feature_engagement::IPHExtensionsZeroStatePromoVariant:: + kCustomUiChipIph == promoVariant); + webui::SetupWebUIDataSource( source, kExtensionsZeroStatePromoResources, IDR_EXTENSIONS_ZERO_STATE_PROMO_ZERO_STATE_PROMO_HTML);
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.h b/chrome/browser/ui/webui/management/management_ui_handler.h index af389f9..fefde130 100644 --- a/chrome/browser/ui/webui/management/management_ui_handler.h +++ b/chrome/browser/ui/webui/management/management_ui_handler.h
@@ -20,7 +20,6 @@ #include "extensions/browser/extension_registry_observer.h" #include "extensions/buildflags/buildflags.h" #include "extensions/common/extension_id.h" -#include "url/gurl.h" namespace extensions { class Extension;
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc index cb5606f..fd17d77 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc
@@ -15,9 +15,11 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h" #include "chrome/browser/ui/tabs/tab_group_model.h" #include "chrome/browser/ui/tabs/tab_model.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui.h" +#include "components/saved_tab_groups/public/tab_group_sync_service.h" #include "components/tab_groups/tab_group_id.h" #include "components/tabs/public/tab_group.h" #include "content/public/browser/web_contents.h" @@ -82,6 +84,15 @@ return; } + tab_groups::TabGroupSyncService* tab_group_service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile( + source_browser->profile()); + + std::unique_ptr<tab_groups::ScopedLocalObservationPauser> observation_pauser; + if (tab_group_service && tab_group_service->GetGroup(group_id)) { + observation_pauser = tab_group_service->CreateScopedLocalObserverPauser(); + } + std::unique_ptr<DetachedTabCollection> detached_group = source_browser->tab_strip_model()->DetachTabGroupForInsertion(group_id); target_browser->tab_strip_model()->InsertDetachedTabGroupAt(
diff --git a/chrome/browser/web_applications/app_service/web_apps.h b/chrome/browser/web_applications/app_service/web_apps.h index b1104e87..d7cda7c 100644 --- a/chrome/browser/web_applications/app_service/web_apps.h +++ b/chrome/browser/web_applications/app_service/web_apps.h
@@ -27,7 +27,6 @@ #include "components/services/app_service/public/cpp/permission.h" #include "components/webapps/common/web_app_id.h" #include "ui/base/resource/resource_scale_factor.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/web_applications/commands/external_app_resolution_command.h b/chrome/browser/web_applications/commands/external_app_resolution_command.h index 651e1be..6dfadf3 100644 --- a/chrome/browser/web_applications/commands/external_app_resolution_command.h +++ b/chrome/browser/web_applications/commands/external_app_resolution_command.h
@@ -29,7 +29,6 @@ #include "components/webapps/browser/installable/installable_logging.h" #include "components/webapps/browser/installable/installable_metrics.h" #include "components/webapps/browser/uninstall_result_code.h" -#include "url/gurl.h" class Browser; class Profile;
diff --git a/chrome/browser/web_applications/isolated_web_apps/commands/isolated_web_app_install_command_helper.h b/chrome/browser/web_applications/isolated_web_apps/commands/isolated_web_app_install_command_helper.h index 53ed90e0..8232c4e 100644 --- a/chrome/browser/web_applications/isolated_web_apps/commands/isolated_web_app_install_command_helper.h +++ b/chrome/browser/web_applications/isolated_web_apps/commands/isolated_web_app_install_command_helper.h
@@ -24,7 +24,6 @@ #include "components/web_package/signed_web_bundles/signed_web_bundle_integrity_block.h" #include "components/webapps/browser/installable/installable_logging.h" #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h" -#include "url/gurl.h" class Profile;
diff --git a/chrome/browser/web_applications/test/mock_data_retriever.h b/chrome/browser/web_applications/test/mock_data_retriever.h index 1c49c172..b2f77b5 100644 --- a/chrome/browser/web_applications/test/mock_data_retriever.h +++ b/chrome/browser/web_applications/test/mock_data_retriever.h
@@ -12,7 +12,6 @@ #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h" #include "components/webapps/browser/installable/installable_params.h" #include "testing/gmock/include/gmock/gmock.h" -#include "url/gurl.h" namespace content { class WebContents;
diff --git a/chrome/browser/web_applications/web_app_icon_generator.h b/chrome/browser/web_applications/web_app_icon_generator.h index 9640c64c..5e20cc7 100644 --- a/chrome/browser/web_applications/web_app_icon_generator.h +++ b/chrome/browser/web_applications/web_app_icon_generator.h
@@ -15,7 +15,6 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/image/image_skia.h" -#include "url/gurl.h" namespace web_app {
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index d1f0021..964dccd 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1748019711-187a71f3331a40aaaa690eec6e1a01e9126eeee1-2d9957d4d1ba001c88be55b67fa22e8aba370d93.profdata +chrome-android64-main-1748032011-dbffd8dc5b1b85a36c2de32da763a2c17f10555d-63d8cf65e0af7bf716c61edce2309a5a0560abc2.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 1ad0ddb7..cd282f42 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1748001307-c50a15e17d641d792a4328408b1bcd9f5c41ccf7-234cda4f8d93a139ddc7594ad3e92323a331dcb2.profdata +chrome-linux-main-1748023160-6912b11625363174257527d8c32469719d905bf3-ba5d54c843a7dd86a525dab79eeddcc4197e83f1.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index cd92b65c..27c5b4f 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1748023160-b5833ec68f910664fa0982de950c574f971396f5-ba5d54c843a7dd86a525dab79eeddcc4197e83f1.profdata +chrome-mac-arm-main-1748037570-cfe1362215d6ee32e345ff24d989b6f317d43601-5ddc939d88d9ee020121b6038bdedafa2cdcb2ed.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index f2e51cb..3265908 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1748001307-919b141d44dbfe7c1221b431cbd69e602c383a6e-234cda4f8d93a139ddc7594ad3e92323a331dcb2.profdata +chrome-mac-main-1748023160-fe59b69a042be0216c6f0a8a95529056f6c8603d-ba5d54c843a7dd86a525dab79eeddcc4197e83f1.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 32edc7c..fc85eda 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1748001307-d7754fbdf498f25978b4ad08c8d6c8190d0b2d4b-234cda4f8d93a139ddc7594ad3e92323a331dcb2.profdata +chrome-win-arm64-main-1748023160-af09f874a5ebd13e1dbf6f2bb43cd35bb183148d-ba5d54c843a7dd86a525dab79eeddcc4197e83f1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 977f010..94e939c 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1748001307-df1533fe61af95a74a599c2d305a848fef4d3e0f-234cda4f8d93a139ddc7594ad3e92323a331dcb2.profdata +chrome-win64-main-1748012379-5e5500e448e071e42fa7f2e63fafb93942bfb9f0-08f878bf998d241cb2d8232c69708cd33d48225f.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 4feab9a3..4c21e30 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -391,14 +391,25 @@ BASE_FEATURE(kGlicURLConfig, "GlicURLConfig", base::FEATURE_DISABLED_BY_DEFAULT); -const base::FeatureParam<std::string> kGlicGuestURL{&kGlicURLConfig, - "glic-guest-url", ""}; +const base::FeatureParam<std::string> kGlicGuestURL{ + &kGlicURLConfig, "glic-guest-url", +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + "https://gemini.google.com/glic" +#else + "" +#endif +}; BASE_FEATURE_PARAM(std::string, kGlicUserStatusUrl, &kGlicUserStatusCheck, "glic-user-status-url", - ""); +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + "https://geminiweb-pa.googleapis.com/v1/glicStatus" +#else + "" +#endif +); BASE_FEATURE_PARAM(base::TimeDelta, kGlicUserStatusRequestDelay, @@ -410,7 +421,7 @@ kGeminiOAuth2Scope, &kGlicUserStatusCheck, "glic-user-status-oauth2-scope", - ""); + "https://www.googleapis.com/auth/gemini"); BASE_FEATURE(kGlicFreURLConfig, "GlicFreURLConfig", @@ -419,7 +430,12 @@ kGlicFreURL, &kGlicFreURLConfig, "glic-fre-url", - ""); +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + "https://gemini.google.com/glic/intro?" +#else + "" +#endif +); BASE_FEATURE(kGlicLearnMoreURLConfig, "GlicLearnMoreURLConfig", @@ -504,7 +520,11 @@ "GlicSizingFitWindow", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kGlicWarming, "GlicWarming", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kGlicWarming, "GlicWarming", base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kGlicDisableWarming, + "GlicDisableWarming", + base::FEATURE_ENABLED_BY_DEFAULT); // Controls the amount of time from the GlicButtonController scheduling // preload to the start of preloading (if preloading is possible). @@ -518,7 +538,7 @@ BASE_FEATURE(kGlicFreWarming, "GlicFreWarming", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kGlicWarmMultiple, "GlicWarmMultiple",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index dfd1bbff..2adec6ec 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -287,6 +287,8 @@ COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicWarming); +COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicDisableWarming); + COMPONENT_EXPORT(CHROME_FEATURES) extern const base::FeatureParam<int> kGlicWarmingDelayMs; COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index 7b03616..56bfc2ac 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h
@@ -10,7 +10,6 @@ #include "base/files/file_path.h" #include "build/build_config.h" #include "chrome/common/buildflags.h" -#include "url/gurl.h" namespace extension_urls { @@ -290,6 +289,8 @@ // Path to preinstalled eSpeak-NG speech synthesis extension. inline constexpr char kEspeakSpeechSynthesisExtensionPath[] = "/usr/share/chromeos-assets/speech_synthesis/espeak-ng"; +inline constexpr char kEspeakManifestV3SpeechSynthesisExtensionPath[] = + "/usr/share/chromeos-assets/speech_synthesis/espeak-ng-mv3"; // The extension id of the eSpeak-NG speech synthesis extension. inline constexpr char kEspeakSpeechSynthesisExtensionId[] = "dakbfdmgjiabojdgbiljlhgjbokobjpg";
diff --git a/chrome/enterprise_companion/crash_client.cc b/chrome/enterprise_companion/crash_client.cc index 451a6844..190c264 100644 --- a/chrome/enterprise_companion/crash_client.cc +++ b/chrome/enterprise_companion/crash_client.cc
@@ -200,7 +200,7 @@ // Save dereferenced memory from all registers on the crashing thread. // Crashpad saves up to 512 bytes per CPU register, and in the worst case, // ARM64 has 32 registers. - constexpr uint32_t kIndirectMemoryLimit = 32 * 512; + static constexpr uint32_t kIndirectMemoryLimit = 32 * 512; crashpad::CrashpadInfo::GetCrashpadInfo() ->set_gather_indirectly_referenced_memory(crashpad::TriState::kEnabled, kIndirectMemoryLimit);
diff --git a/chrome/enterprise_companion/test/test_utils.cc b/chrome/enterprise_companion/test/test_utils.cc index bf784d0..3e5d214 100644 --- a/chrome/enterprise_companion/test/test_utils.cc +++ b/chrome/enterprise_companion/test/test_utils.cc
@@ -53,7 +53,7 @@ bool WaitFor(base::FunctionRef<bool()> predicate, base::FunctionRef<void()> still_waiting) { - constexpr base::TimeDelta kOutputInterval = base::Seconds(10); + static constexpr base::TimeDelta kOutputInterval = base::Seconds(10); auto notify_next = base::TimeTicks::Now() + kOutputInterval; const auto deadline = base::TimeTicks::Now() + TestTimeouts::action_timeout(); while (base::TimeTicks::Now() < deadline) {
diff --git a/chrome/renderer/worker_content_settings_client.h b/chrome/renderer/worker_content_settings_client.h index c3ae92129..2e1012a 100644 --- a/chrome/renderer/worker_content_settings_client.h +++ b/chrome/renderer/worker_content_settings_client.h
@@ -10,7 +10,6 @@ #include "net/cookies/site_for_cookies.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/platform/web_content_settings_client.h" -#include "url/gurl.h" #include "url/origin.h" namespace content {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 40cd21f..6aa495d 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3479,6 +3479,7 @@ "../browser/ui/views/frame/system_menu_model_builder_browsertest.cc", "../browser/ui/views/hats/hats_browsertest.cc", "../browser/ui/views/incognito_clear_browsing_data_dialog_browsertest.cc", + "../browser/ui/views/infobars/infobar_view_browsertest.cc", "../browser/ui/views/intent_picker_bubble_view_browsertest.cc", "../browser/ui/views/intent_picker_dialog_browsertest.cc", "../browser/ui/views/location_bar/intent_chip_button_browsertest.cc", @@ -10193,7 +10194,6 @@ "../browser/ui/views/global_media_controls/media_toolbar_button_contextual_menu_unittest.cc", "../browser/ui/views/hats/hats_next_web_dialog_unittest.cc", "../browser/ui/views/hover_button_unittest.cc", - "../browser/ui/views/infobars/infobar_view_unittest.cc", "../browser/ui/views/intent_picker_bubble_view_unittest.cc", "../browser/ui/views/layout_provider_unittest.cc", "../browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java index a7ce26a7..b0c4f521 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java
@@ -39,20 +39,13 @@ } /** Expect no history to be displayed in the history pane. */ - public EmptyHistoryFacility expectEmptyState() { - return enterFacilitySync(new EmptyHistoryFacility(), /* trigger= */ null); - } - - /** Empty state of the history pane. */ - public static class EmptyHistoryFacility extends Facility<HistoryPaneStation> { - public EmptyHistoryFacility() { - declareView(withText("You’ll find your history here")); - declareView( - withText( - "You can see the pages you’ve visited or delete them from your" - + " history")); - declareNoView(withId(R.id.history_page_recycler_view)); - } + public void expectEmptyState() { + var emptyHistory = new Facility<>("EmptyState"); + emptyHistory.declareView(withText("You’ll find your history here")); + emptyHistory.declareView( + withText("You can see the pages you’ve visited or delete them from your history")); + emptyHistory.declareNoView(withId(R.id.history_page_recycler_view)); + enterFacilitySync(emptyHistory, /* trigger= */ null); } /** Non-empty state of the history pane. */
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java index 36e18c8..8923ace 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java
@@ -145,14 +145,27 @@ moreOptionsElement.getClickTrigger()); } - public SearchHistoryDisambiguiationFacility expectSearchHistoryDisambiguation(boolean shown) { - return mHostStation.enterFacilitySync( - new SearchHistoryDisambiguiationFacility(shown), /* trigger= */ null); + public void expectSearchHistoryDisambiguation(boolean shown) { + var facility = new Facility<>("SearchHistoryDisambiguation" + (shown ? "Shown" : "Hidden")); + ViewSpec<View> spec = dialogElement.descendant(withId(R.id.search_history_disambiguation)); + if (shown) { + facility.declareView(spec); + } else { + facility.declareNoView(spec); + } + mHostStation.enterFacilitySync(facility, /* trigger= */ null); } - public SitesSubtitleFacility expectMoreOnSyncedDevices(boolean shown) { - return mHostStation.enterFacilitySync( - new SitesSubtitleFacility(shown), /* trigger= */ null); + public void expectMoreOnSyncedDevices(boolean shown) { + var facility = new Facility<>("MoreOnSyncedDevices" + (shown ? "Shown" : "Hidden")); + ViewSpec<View> spec = + dialogElement.descendant(withId(R.id.quick_delete_history_row_subtitle)); + if (shown) { + facility.declareView(spec); + } else { + facility.declareNoView(spec); + } + mHostStation.enterFacilitySync(facility, /* trigger= */ null); } private class TimePeriodSelectedCondition extends UiThreadCondition { @@ -177,29 +190,4 @@ return "Spinner selected TimePeriod " + mTimePeriod; } } - - public class SearchHistoryDisambiguiationFacility - extends Facility<Station<ChromeTabbedActivity>> { - public SearchHistoryDisambiguiationFacility(boolean expectPresent) { - ViewSpec<View> spec = - dialogElement.descendant(withId(R.id.search_history_disambiguation)); - if (expectPresent) { - declareView(spec); - } else { - declareNoView(spec); - } - } - } - - public class SitesSubtitleFacility extends Facility<Station<ChromeTabbedActivity>> { - public SitesSubtitleFacility(boolean expectPresent) { - ViewSpec<View> spec = - dialogElement.descendant(withId(R.id.quick_delete_history_row_subtitle)); - if (expectPresent) { - declareView(spec); - } else { - declareNoView(spec); - } - } - } }
diff --git a/chrome/test/base/chrome_test_utils.h b/chrome/test/base/chrome_test_utils.h index 2ba666a..2e3bbd93 100644 --- a/chrome/test/base/chrome_test_utils.h +++ b/chrome/test/base/chrome_test_utils.h
@@ -7,7 +7,6 @@ #include "build/build_config.h" #include "chrome/test/base/platform_browser_test.h" -#include "url/gurl.h" namespace content { class WebContents;
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.h b/chrome/test/chromedriver/chrome/devtools_client_impl.h index a83380d2..d66ccea 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.h +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.h
@@ -18,7 +18,6 @@ #include "base/values.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/net/timeout.h" -#include "url/gurl.h" class DevToolsEventListener; class Status;
diff --git a/chrome/test/data/webui/extensions_zero_state/zero_state_promo_app_test.ts b/chrome/test/data/webui/extensions_zero_state/zero_state_promo_app_test.ts index 98a6946a..d3aa596 100644 --- a/chrome/test/data/webui/extensions_zero_state/zero_state_promo_app_test.ts +++ b/chrome/test/data/webui/extensions_zero_state/zero_state_promo_app_test.ts
@@ -11,8 +11,10 @@ import type {CustomHelpBubbleHandlerInterface} from 'chrome://resources/cr_components/help_bubble/custom_help_bubble.mojom-webui.js'; import type {CustomHelpBubbleProxy} from 'chrome://resources/cr_components/help_bubble/custom_help_bubble_proxy.js'; import {CustomHelpBubbleProxyImpl} from 'chrome://resources/cr_components/help_bubble/custom_help_bubble_proxy.js'; -import {assertEquals} from 'chrome://webui-test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; +import {isVisible} from 'chrome://webui-test/test_util.js'; + export class TestBubbleHandler extends TestBrowserProxy implements CustomHelpBubbleHandlerInterface { @@ -66,8 +68,28 @@ document.body.appendChild(zeroStatePromoApp); }); + function queryAppSelector(selector: string): HTMLElement|null { + return zeroStatePromoApp.shadowRoot.querySelector<HTMLElement>(selector); + } + + test('UiElementVisibility', () => { + assertTrue(isVisible(queryAppSelector('#dismissButton'))); + assertTrue(isVisible(queryAppSelector('#couponsButton'))); + assertTrue(isVisible(queryAppSelector('#writingButton'))); + assertTrue(isVisible(queryAppSelector('#productivityButton'))); + assertTrue(isVisible(queryAppSelector('#aiButton'))); + assertFalse(isVisible(queryAppSelector('#couponsLink'))); + assertFalse(isVisible(queryAppSelector('#writingLink'))); + assertFalse(isVisible(queryAppSelector('#productivityLink'))); + assertFalse(isVisible(queryAppSelector('#aiLink'))); + assertFalse(isVisible(queryAppSelector('#closeButton'))); + assertFalse(isVisible(queryAppSelector('#customActionButton'))); + }); + test('ClickCouponsChip', async () => { - zeroStatePromoApp.$.couponsButton.click(); + const chip = queryAppSelector('#couponsButton'); + assertTrue(!!chip); + chip.click(); assertEquals( WebStoreLinkClicked.kCoupon, @@ -78,7 +100,9 @@ }); test('ClickWritingChip', async () => { - zeroStatePromoApp.$.writingButton.click(); + const chip = queryAppSelector('#writingButton'); + assertTrue(!!chip); + chip.click(); assertEquals( WebStoreLinkClicked.kWriting, @@ -89,7 +113,9 @@ }); test('ClickProductivityChip', async () => { - zeroStatePromoApp.$.productivityButton.click(); + const chip = queryAppSelector('#productivityButton'); + assertTrue(!!chip); + chip.click(); assertEquals( WebStoreLinkClicked.kProductivity, @@ -100,7 +126,9 @@ }); test('ClickAiChip', async () => { - zeroStatePromoApp.$.aiButton.click(); + const chip = queryAppSelector('#aiButton'); + assertTrue(!!chip); + chip.click(); assertEquals( WebStoreLinkClicked.kAi, @@ -111,7 +139,131 @@ }); test('ClickDismissButton', async () => { - zeroStatePromoApp.$.dismissButton.click(); + const button = queryAppSelector('#dismissButton'); + assertTrue(!!button); + button.click(); + + assertEquals( + CustomHelpBubbleUserAction.kDismiss, + await bubbleHandler.whenCalled('notifyUserAction')); + }); +}); + +suite('PlainLinkUiTest', () => { + let bubbleHandler: TestBubbleHandler; + let zeroStatePromoApp: ZeroStatePromoAppElement; + let promoProxy: TestPromoProxy; + + setup(() => { + bubbleHandler = new TestBubbleHandler(); + CustomHelpBubbleProxyImpl.setInstance(new TestBubbleProxy(bubbleHandler)); + + promoProxy = new TestPromoProxy(); + ZeroStatePromoBrowserProxyImpl.setInstance(promoProxy); + + document.body.innerHTML = window.trustedTypes!.emptyHTML; + zeroStatePromoApp = + document.createElement('extensions-zero-state-promo-app'); + document.body.appendChild(zeroStatePromoApp); + }); + + function queryAppSelector(selector: string): HTMLElement|null { + return zeroStatePromoApp.shadowRoot.querySelector<HTMLElement>(selector); + } + + test('UiElementVisibility', () => { + assertTrue(isVisible(queryAppSelector('#dismissButton'))); + assertTrue(isVisible(queryAppSelector('#couponsLink'))); + assertTrue(isVisible(queryAppSelector('#writingLink'))); + assertTrue(isVisible(queryAppSelector('#productivityLink'))); + assertTrue(isVisible(queryAppSelector('#aiLink'))); + assertTrue(isVisible(queryAppSelector('#closeButton'))); + assertTrue(isVisible(queryAppSelector('#customActionButton'))); + assertFalse(isVisible(queryAppSelector('#couponsButton'))); + assertFalse(isVisible(queryAppSelector('#writingButton'))); + assertFalse(isVisible(queryAppSelector('#productivityButton'))); + assertFalse(isVisible(queryAppSelector('#aiButton'))); + }); + + test('ClickCouponsLink', async () => { + const link = queryAppSelector('#couponsLink'); + assertTrue(!!link); + link.click(); + + assertEquals( + WebStoreLinkClicked.kCoupon, + await promoProxy.whenCalled('launchWebStoreLink')); + assertEquals( + CustomHelpBubbleUserAction.kAction, + await bubbleHandler.whenCalled('notifyUserAction')); + }); + + test('ClickWritingLink', async () => { + const link = queryAppSelector('#writingLink'); + assertTrue(!!link); + link.click(); + + assertEquals( + WebStoreLinkClicked.kWriting, + await promoProxy.whenCalled('launchWebStoreLink')); + assertEquals( + CustomHelpBubbleUserAction.kAction, + await bubbleHandler.whenCalled('notifyUserAction')); + }); + + test('ClickProductivityLink', async () => { + const link = queryAppSelector('#productivityLink'); + assertTrue(!!link); + link.click(); + + assertEquals( + WebStoreLinkClicked.kProductivity, + await promoProxy.whenCalled('launchWebStoreLink')); + assertEquals( + CustomHelpBubbleUserAction.kAction, + await bubbleHandler.whenCalled('notifyUserAction')); + }); + + test('ClickAiLink', async () => { + const link = queryAppSelector('#aiLink'); + assertTrue(!!link); + link.click(); + + assertEquals( + WebStoreLinkClicked.kAi, + await promoProxy.whenCalled('launchWebStoreLink')); + assertEquals( + CustomHelpBubbleUserAction.kAction, + await bubbleHandler.whenCalled('notifyUserAction')); + }); + + test('ClickCustomActionButton', async () => { + const button = queryAppSelector('#customActionButton'); + assertTrue(!!button); + button.click(); + + assertEquals( + WebStoreLinkClicked.kDiscoverExtension, + await promoProxy.whenCalled('launchWebStoreLink')); + assertEquals( + CustomHelpBubbleUserAction.kAction, + await bubbleHandler.whenCalled('notifyUserAction')); + }); + + test('ClickDismissButton', async () => { + const button = queryAppSelector('#dismissButton'); + assertTrue(!!button); + button.click(); + + assertEquals( + CustomHelpBubbleUserAction.kDismiss, + await bubbleHandler.whenCalled('notifyUserAction')); + }); + + test('ClickCloseButton', async () => { + const button = queryAppSelector('#closeButton'); + assertTrue(!!button); + button.click(); assertEquals( CustomHelpBubbleUserAction.kDismiss,
diff --git a/chrome/test/data/webui/extensions_zero_state/zero_state_promo_browsertest.cc b/chrome/test/data/webui/extensions_zero_state/zero_state_promo_browsertest.cc index 9efd0810..95049f4 100644 --- a/chrome/test/data/webui/extensions_zero_state/zero_state_promo_browsertest.cc +++ b/chrome/test/data/webui/extensions_zero_state/zero_state_promo_browsertest.cc
@@ -32,5 +32,27 @@ IN_PROC_BROWSER_TEST_F(ZeroStatePromoChipsUiTest, AllTests) { ZeroStatePromoBrowserTest::RunTest( - "extensions_zero_state/zero_state_promo_app_test.js", "mocha.run()"); + "extensions_zero_state/zero_state_promo_app_test.js", + "runMochaSuite('ChipsUiTest');"); +} + +class ZeroStatePromoPlainLinkUiTest : public ZeroStatePromoBrowserTest { + protected: + ZeroStatePromoPlainLinkUiTest() : ZeroStatePromoBrowserTest() { + feature_list_.InitAndEnableFeatureWithParameters( + feature_engagement::kIPHExtensionsZeroStatePromoFeature, + {{feature_engagement::kIPHExtensionsZeroStatePromoVariantParam.name, + feature_engagement::kIPHExtensionsZeroStatePromoVariantParam.GetName( + feature_engagement::IPHExtensionsZeroStatePromoVariant:: + kCustomUIPlainLinkIph)}}); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(ZeroStatePromoPlainLinkUiTest, AllTests) { + ZeroStatePromoBrowserTest::RunTest( + "extensions_zero_state/zero_state_promo_app_test.js", + "runMochaSuite('PlainLinkUiTest');"); }
diff --git a/chrome/test/data/webui/print_preview/custom_margins_test.ts b/chrome/test/data/webui/print_preview/custom_margins_test.ts index 3277ba26..9a0fb7c 100644 --- a/chrome/test/data/webui/print_preview/custom_margins_test.ts +++ b/chrome/test/data/webui/print_preview/custom_margins_test.ts
@@ -494,33 +494,32 @@ // Test that if there is a custom margins sticky setting, it is restored // when margin setting changes. - test( - 'RestoreStickyMarginsAfterDefault', function() { - const marginValues = setupCustomMargins(); - return finishSetup().then(() => { - // Simulate setting custom margins. - const controls = getControls(); - model.setSetting('margins', MarginsType.CUSTOM); + test('RestoreStickyMarginsAfterDefault', function() { + const marginValues = setupCustomMargins(); + return finishSetup().then(() => { + // Simulate setting custom margins. + const controls = getControls(); + model.setSetting('margins', MarginsType.CUSTOM); - // Validate control positions are set based on the custom values. - controls.forEach((control, index) => { - const side = sides[index]!; - assertEquals(side, control.side); - assertEquals(marginValues.get(side), control.getPositionInPts()); - }); - - // Simulate setting minimum margins. - model.setSetting('margins', MarginsType.MINIMUM); - - // Validate control positions still reflect the custom values. - controls.forEach((control, index) => { - const side = sides[index]!; - assertEquals(side, control.side); - assertEquals(marginValues.get(side), control.getPositionInPts()); - }); - }); + // Validate control positions are set based on the custom values. + controls.forEach((control, index) => { + const side = sides[index]!; + assertEquals(side, control.side); + assertEquals(marginValues.get(side), control.getPositionInPts()); }); + // Simulate setting minimum margins. + model.setSetting('margins', MarginsType.MINIMUM); + + // Validate control positions still reflect the custom values. + controls.forEach((control, index) => { + const side = sides[index]!; + assertEquals(side, control.side); + assertEquals(marginValues.get(side), control.getPositionInPts()); + }); + }); + }); + // Test that if the media size changes, the custom margins are cleared. test('MediaSizeClearsCustomMargins', async function() { await validateMarginsClearedForSetting( @@ -559,14 +558,13 @@ // Test that if the margins are not available, the custom margins setting is // not updated based on the document margins - i.e. PDFs do not change the // custom margins state. - test( - 'IgnoreDocumentMarginsFromPDF', function() { - model.setSettingAvailableForTesting('margins', false); - return finishSetup().then(() => { - assertEquals( - '{}', JSON.stringify(container.getSettingValue('customMargins'))); - }); - }); + test('IgnoreDocumentMarginsFromPDF', function() { + model.setSettingAvailableForTesting('margins', false); + return finishSetup().then(() => { + assertEquals( + '{}', JSON.stringify(container.getSettingValue('customMargins'))); + }); + }); // Test that if margins are not available but the user changes the media // size, the custom margins are cleared.
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.ts b/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.ts index 806af17..6c79020a 100644 --- a/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.ts +++ b/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.ts
@@ -60,53 +60,50 @@ // Tests that pressing the escape key while the search box is focused // closes the dialog if and only if the query is empty. - test( - 'EscapeSearchBox', function() { - const searchBox = dialog.$.searchBox; - const searchInput = searchBox.getSearchInput(); - assertTrue(!!searchInput); - const whenFocusDone = eventToPromise('focus', searchInput); - dialog.destinationStore!.startLoadAllDestinations(); - dialog.show(); - return whenFocusDone - .then(() => { - assertTrue(dialog.$.dialog.open); + test('EscapeSearchBox', function() { + const searchBox = dialog.$.searchBox; + const searchInput = searchBox.getSearchInput(); + assertTrue(!!searchInput); + const whenFocusDone = eventToPromise('focus', searchInput); + dialog.destinationStore!.startLoadAllDestinations(); + dialog.show(); + return whenFocusDone + .then(() => { + assertTrue(dialog.$.dialog.open); - // Put something in the search box. - const whenSearchChanged = - eventToPromise('search-changed', searchBox); - searchBox.setValue('query'); - return whenSearchChanged; - }) - .then(() => { - assertEquals('query', searchInput.value); + // Put something in the search box. + const whenSearchChanged = eventToPromise('search-changed', searchBox); + searchBox.setValue('query'); + return whenSearchChanged; + }) + .then(() => { + assertEquals('query', searchInput.value); - // Simulate escape - const whenKeyDown = eventToPromise('keydown', dialog); - keyDownOn(searchInput, 19, [], 'Escape'); - return whenKeyDown; - }) - .then(() => { - // Dialog should still be open. - assertTrue(dialog.$.dialog.open); + // Simulate escape + const whenKeyDown = eventToPromise('keydown', dialog); + keyDownOn(searchInput, 19, [], 'Escape'); + return whenKeyDown; + }) + .then(() => { + // Dialog should still be open. + assertTrue(dialog.$.dialog.open); - // Clear the search box. - const whenSearchChanged = - eventToPromise('search-changed', searchBox); - searchBox.setValue(''); - return whenSearchChanged; - }) - .then(() => { - assertEquals('', searchInput.value); + // Clear the search box. + const whenSearchChanged = eventToPromise('search-changed', searchBox); + searchBox.setValue(''); + return whenSearchChanged; + }) + .then(() => { + assertEquals('', searchInput.value); - // Simulate escape - const whenKeyDown = eventToPromise('keydown', dialog); - keyDownOn(searchInput, 19, [], 'Escape'); - return whenKeyDown; - }) - .then(() => { - // Dialog is closed. - assertFalse(dialog.$.dialog.open); - }); - }); + // Simulate escape + const whenKeyDown = eventToPromise('keydown', dialog); + keyDownOn(searchInput, 19, [], 'Escape'); + return whenKeyDown; + }) + .then(() => { + // Dialog is closed. + assertFalse(dialog.$.dialog.open); + }); + }); });
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_test.ts b/chrome/test/data/webui/print_preview/destination_dialog_test.ts index 69c89c18..06f0ed1 100644 --- a/chrome/test/data/webui/print_preview/destination_dialog_test.ts +++ b/chrome/test/data/webui/print_preview/destination_dialog_test.ts
@@ -94,20 +94,19 @@ // Test that destinations are correctly displayed in the lists when all // printers have been preloaded before the dialog is opened. Regression test // for https://crbug.com/1330678. - test( - 'PrinterListPreloaded', async () => { - // All printers are fetched at startup since both native and extension - // printers are recent. - const whenAllPreloaded = nativeLayer.waitForGetPrinters(2); - destinationStore.init( - false /* pdfPrinterDisabled */, 'FooDevice' /* printerName */, - '' /* serializedDefaultDestinationSelectionRulesStr */, [ - makeRecentDestination(destinations[4]!), - makeRecentDestination(extensionDestinations[0]!), - ] /* recentDestinations */); - await whenAllPreloaded; - finishSetup(); - await microtasksFinished(); - validatePrinterList(); - }); + test('PrinterListPreloaded', async () => { + // All printers are fetched at startup since both native and extension + // printers are recent. + const whenAllPreloaded = nativeLayer.waitForGetPrinters(2); + destinationStore.init( + false /* pdfPrinterDisabled */, 'FooDevice' /* printerName */, + '' /* serializedDefaultDestinationSelectionRulesStr */, [ + makeRecentDestination(destinations[4]!), + makeRecentDestination(extensionDestinations[0]!), + ] /* recentDestinations */); + await whenAllPreloaded; + finishSetup(); + await microtasksFinished(); + validatePrinterList(); + }); });
diff --git a/chrome/test/data/webui/print_preview/destination_list_test.ts b/chrome/test/data/webui/print_preview/destination_list_test.ts index fe9f147..81658b7 100644 --- a/chrome/test/data/webui/print_preview/destination_list_test.ts +++ b/chrome/test/data/webui/print_preview/destination_list_test.ts
@@ -119,23 +119,21 @@ // Tests that the list correctly fires the destination selected event when // the destination is clicked or the enter key is pressed. - test( - 'FireDestinationSelected', function() { - const items = list.shadowRoot.querySelectorAll( - 'print-preview-destination-list-item'); - let whenDestinationSelected = - eventToPromise('destination-selected', list); - items[0]!.click(); - return whenDestinationSelected - .then(event => { - assertEquals(items[0]!.destination, event.detail); - whenDestinationSelected = - eventToPromise('destination-selected', list); - keyEventOn(items[1]!, 'keydown', 13, undefined, 'Enter'); - return whenDestinationSelected; - }) - .then(event => { - assertEquals(items[1]!.destination, event.detail); - }); - }); + test('FireDestinationSelected', function() { + const items = + list.shadowRoot.querySelectorAll('print-preview-destination-list-item'); + let whenDestinationSelected = eventToPromise('destination-selected', list); + items[0]!.click(); + return whenDestinationSelected + .then(event => { + assertEquals(items[0]!.destination, event.detail); + whenDestinationSelected = + eventToPromise('destination-selected', list); + keyEventOn(items[1]!, 'keydown', 13, undefined, 'Enter'); + return whenDestinationSelected; + }) + .then(event => { + assertEquals(items[1]!.destination, event.detail); + }); + }); });
diff --git a/chrome/test/data/webui/print_preview/destination_search_test.ts b/chrome/test/data/webui/print_preview/destination_search_test.ts index 4eae85f..aa878fde 100644 --- a/chrome/test/data/webui/print_preview/destination_search_test.ts +++ b/chrome/test/data/webui/print_preview/destination_search_test.ts
@@ -60,23 +60,22 @@ // Tests that a destination is selected if the user clicks on it and // capabilities fetch succeeds. - test( - 'GetCapabilitiesSucceeds', async function() { - const destId = '00112233DEADBEEF'; - nativeLayer.setLocalDestinationCapabilities(getCddTemplate(destId)); + test('GetCapabilitiesSucceeds', async function() { + const destId = '00112233DEADBEEF'; + nativeLayer.setLocalDestinationCapabilities(getCddTemplate(destId)); - const waiter = eventToPromise( - DestinationStoreEventType.DESTINATION_SELECT, destinationStore); - simulateDestinationSelect(destId); - const results = await Promise.all( - [nativeLayer.whenCalled('getPrinterCapabilities'), waiter]); - const actualId = results[0].destinationId; - assertEquals(destId, actualId); - // After setup or capabilities fetch succeeds, the destination - // should be selected. - assertNotEquals(null, destinationStore.selectedDestination); - assertEquals(destId, destinationStore.selectedDestination!.id); - }); + const waiter = eventToPromise( + DestinationStoreEventType.DESTINATION_SELECT, destinationStore); + simulateDestinationSelect(destId); + const results = await Promise.all( + [nativeLayer.whenCalled('getPrinterCapabilities'), waiter]); + const actualId = results[0].destinationId; + assertEquals(destId, actualId); + // After setup or capabilities fetch succeeds, the destination + // should be selected. + assertNotEquals(null, destinationStore.selectedDestination); + assertEquals(destId, destinationStore.selectedDestination!.id); + }); // Tests what happens when capabilities cannot be retrieved for the chosen // destination. The destination will still be selected in this case.
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.ts b/chrome/test/data/webui/print_preview/destination_settings_test.ts index 329cd37..391ceee9 100644 --- a/chrome/test/data/webui/print_preview/destination_settings_test.ts +++ b/chrome/test/data/webui/print_preview/destination_settings_test.ts
@@ -55,79 +55,78 @@ // Tests that the dropdown is enabled or disabled correctly based on // the state. - test( - 'ChangeDropdownState', function() { - const dropdown = destinationSettings.$.destinationSelect; - // Initial state: No destination store means that there is no - // destination yet. - assertFalse(dropdown.loaded); + test('ChangeDropdownState', function() { + const dropdown = destinationSettings.$.destinationSelect; + // Initial state: No destination store means that there is no + // destination yet. + assertFalse(dropdown.loaded); - // Set up the destination store, but no destination yet. Dropdown is - // still not loaded. - destinationSettings.init( - 'FooDevice' /* printerName */, false /* pdfPrinterDisabled */, - '' /* serializedDefaultDestinationSelectionRulesStr */); - assertFalse(dropdown.loaded); + // Set up the destination store, but no destination yet. Dropdown is + // still not loaded. + destinationSettings.init( + 'FooDevice' /* printerName */, false /* pdfPrinterDisabled */, + '' /* serializedDefaultDestinationSelectionRulesStr */); + assertFalse(dropdown.loaded); - return eventToPromise( - DestinationStoreEventType - .SELECTED_DESTINATION_CAPABILITIES_READY, - destinationSettings.getDestinationStoreForTest()) - .then(async () => { - // The capabilities ready event results in |destinationState| - // changing to SELECTED, which enables and shows the dropdown even - // though |state| has not yet transitioned to READY. This is to - // prevent brief losses of focus when the destination changes. - await microtasksFinished(); - assertFalse(dropdown.disabled); - assertTrue(dropdown.loaded); - destinationSettings.state = State.READY; - destinationSettings.disabled = false; - await microtasksFinished(); + return eventToPromise( + DestinationStoreEventType + .SELECTED_DESTINATION_CAPABILITIES_READY, + destinationSettings.getDestinationStoreForTest()) + .then(async () => { + // The capabilities ready event results in |destinationState| + // changing to SELECTED, which enables and shows the dropdown even + // though |state| has not yet transitioned to READY. This is to + // prevent brief losses of focus when the destination changes. + await microtasksFinished(); + assertFalse(dropdown.disabled); + assertTrue(dropdown.loaded); + destinationSettings.state = State.READY; + destinationSettings.disabled = false; + await microtasksFinished(); - // Simulate setting a setting to an invalid value. Dropdown is - // disabled due to validation error on another control. - destinationSettings.state = State.ERROR; - destinationSettings.disabled = true; - await microtasksFinished(); - assertTrue(dropdown.disabled); + // Simulate setting a setting to an invalid value. Dropdown is + // disabled due to validation error on another control. + destinationSettings.state = State.ERROR; + destinationSettings.disabled = true; + await microtasksFinished(); + assertTrue(dropdown.disabled); - // Simulate the user fixing the validation error, and then - // selecting an invalid printer. Dropdown is enabled, so that the - // user can fix the error. - destinationSettings.state = State.READY; - destinationSettings.disabled = false; - await microtasksFinished(); - destinationSettings.getDestinationStoreForTest().dispatchEvent( - new CustomEvent( - DestinationStoreEventType.ERROR, - {detail: DestinationErrorType.INVALID})); - await microtasksFinished(); + // Simulate the user fixing the validation error, and then + // selecting an invalid printer. Dropdown is enabled, so that the + // user can fix the error. + destinationSettings.state = State.READY; + destinationSettings.disabled = false; + await microtasksFinished(); + destinationSettings.getDestinationStoreForTest().dispatchEvent( + new CustomEvent( + DestinationStoreEventType.ERROR, + {detail: DestinationErrorType.INVALID})); + await microtasksFinished(); - assertEquals( - DestinationState.ERROR, destinationSettings.destinationState); - assertEquals(Error.INVALID_PRINTER, destinationSettings.error); - destinationSettings.state = State.ERROR; - destinationSettings.disabled = true; - await microtasksFinished(); - assertFalse(dropdown.disabled); + assertEquals( + DestinationState.ERROR, destinationSettings.destinationState); + assertEquals(Error.INVALID_PRINTER, destinationSettings.error); + destinationSettings.state = State.ERROR; + destinationSettings.disabled = true; + await microtasksFinished(); + assertFalse(dropdown.disabled); - // Simulate the user having no printers. - destinationSettings.getDestinationStoreForTest().dispatchEvent( - new CustomEvent( - DestinationStoreEventType.ERROR, - {detail: DestinationErrorType.NO_DESTINATIONS})); - await microtasksFinished(); + // Simulate the user having no printers. + destinationSettings.getDestinationStoreForTest().dispatchEvent( + new CustomEvent( + DestinationStoreEventType.ERROR, + {detail: DestinationErrorType.NO_DESTINATIONS})); + await microtasksFinished(); - assertEquals( - DestinationState.ERROR, destinationSettings.destinationState); - assertEquals(Error.NO_DESTINATIONS, destinationSettings.error); - destinationSettings.state = State.FATAL_ERROR; - destinationSettings.disabled = true; - await microtasksFinished(); - assertTrue(dropdown.disabled); - }); - }); + assertEquals( + DestinationState.ERROR, destinationSettings.destinationState); + assertEquals(Error.NO_DESTINATIONS, destinationSettings.error); + destinationSettings.state = State.FATAL_ERROR; + destinationSettings.disabled = true; + await microtasksFinished(); + assertTrue(dropdown.disabled); + }); + }); function getLocalOrigin(): DestinationOrigin { return DestinationOrigin.LOCAL; @@ -193,51 +192,50 @@ // Tests that the dropdown contains the appropriate destinations when there // are 5 recent destinations. - test( - 'RecentDestinations', function() { - recentDestinations = destinations.slice(0, 5).map( - destination => makeRecentDestination(destination)); + test('RecentDestinations', function() { + recentDestinations = destinations.slice(0, 5).map( + destination => makeRecentDestination(destination)); - // Wait for the destinations to be inserted into the store. - return initialize().then( - () => { - // This will result in the destination store setting the most - // recent destination. - assertTrue(!!destinationSettings.destination); - assertEquals('ID1', destinationSettings.destination.id); - assertFalse(destinationSettings.$.destinationSelect.disabled); - const dropdownItems = [ - makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID2'), - makeLocalDestinationKey('ID3'), 'Save as PDF/local/', - ]; - assertDropdownItems(dropdownItems); - }); - }); + // Wait for the destinations to be inserted into the store. + return initialize().then(() => { + // This will result in the destination store setting the most + // recent destination. + assertTrue(!!destinationSettings.destination); + assertEquals('ID1', destinationSettings.destination.id); + assertFalse(destinationSettings.$.destinationSelect.disabled); + const dropdownItems = [ + makeLocalDestinationKey('ID1'), + makeLocalDestinationKey('ID2'), + makeLocalDestinationKey('ID3'), + 'Save as PDF/local/', + ]; + assertDropdownItems(dropdownItems); + }); + }); // Tests that the dropdown contains the appropriate destinations when one of // the destinations can no longer be found. - test( - 'RecentDestinationsMissing', function() { - recentDestinations = destinations.slice(0, 5).map( - destination => makeRecentDestination(destination)); - localDestinations.splice(1, 1); - nativeLayer.setLocalDestinations(localDestinations); + test('RecentDestinationsMissing', function() { + recentDestinations = destinations.slice(0, 5).map( + destination => makeRecentDestination(destination)); + localDestinations.splice(1, 1); + nativeLayer.setLocalDestinations(localDestinations); - // Wait for the destinations to be inserted into the store. - return initialize().then( - () => { - // This will result in the destination store setting the most - // recent destination. - assertTrue(!!destinationSettings.destination); - assertEquals('ID1', destinationSettings.destination.id); - assertFalse(destinationSettings.$.destinationSelect.disabled); - const dropdownItems = [ - makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID3'), - 'Save as PDF/local/', - ]; - assertDropdownItems(dropdownItems); - }); - }); + // Wait for the destinations to be inserted into the store. + return initialize().then(() => { + // This will result in the destination store setting the most + // recent destination. + assertTrue(!!destinationSettings.destination); + assertEquals('ID1', destinationSettings.destination.id); + assertFalse(destinationSettings.$.destinationSelect.disabled); + const dropdownItems = [ + makeLocalDestinationKey('ID1'), + makeLocalDestinationKey('ID3'), + 'Save as PDF/local/', + ]; + assertDropdownItems(dropdownItems); + }); + }); // Tests that the dropdown contains the appropriate destinations when Save // as PDF is one of the recent destinations. @@ -310,41 +308,42 @@ // Tests that selecting a recent destination results in the // DESTINATION_SELECT event firing, with the recent destination set as the // current destination. - test( - 'SelectRecentDestination', function() { - recentDestinations = destinations.slice(0, 5).map( - destination => makeRecentDestination(destination)); - const dropdown = destinationSettings.$.destinationSelect; + test('SelectRecentDestination', function() { + recentDestinations = destinations.slice(0, 5).map( + destination => makeRecentDestination(destination)); + const dropdown = destinationSettings.$.destinationSelect; - return initialize() - .then(() => { - // This will result in the destination store setting the most - // recent destination. - assertTrue(!!destinationSettings.destination); - assertEquals('ID1', destinationSettings.destination.id); - assertFalse(dropdown.disabled); - const dropdownItems = [ - makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID2'), - makeLocalDestinationKey('ID3'), 'Save as PDF/local/', - ]; - assertDropdownItems(dropdownItems); + return initialize() + .then(() => { + // This will result in the destination store setting the most + // recent destination. + assertTrue(!!destinationSettings.destination); + assertEquals('ID1', destinationSettings.destination.id); + assertFalse(dropdown.disabled); + const dropdownItems = [ + makeLocalDestinationKey('ID1'), + makeLocalDestinationKey('ID2'), + makeLocalDestinationKey('ID3'), + 'Save as PDF/local/', + ]; + assertDropdownItems(dropdownItems); - // Simulate selection of Save as PDF printer. - const whenDestinationSelect = eventToPromise( - DestinationStoreEventType.DESTINATION_SELECT, - destinationSettings.getDestinationStoreForTest()); - dropdown.dispatchEvent(new CustomEvent('selected-option-change', { - bubbles: true, - composed: true, - detail: makeLocalDestinationKey('ID2'), - })); - return whenDestinationSelect; - }) - .then(() => { - assertTrue(!!destinationSettings.destination); - assertEquals('ID2', destinationSettings.destination.id); - }); - }); + // Simulate selection of Save as PDF printer. + const whenDestinationSelect = eventToPromise( + DestinationStoreEventType.DESTINATION_SELECT, + destinationSettings.getDestinationStoreForTest()); + dropdown.dispatchEvent(new CustomEvent('selected-option-change', { + bubbles: true, + composed: true, + detail: makeLocalDestinationKey('ID2'), + })); + return whenDestinationSelect; + }) + .then(() => { + assertTrue(!!destinationSettings.destination); + assertEquals('ID2', destinationSettings.destination.id); + }); + }); // Tests that selecting the 'see more' option opens the dialog. test('OpenDialog', function() { @@ -405,92 +404,85 @@ * Tests that the destination being set correctly updates the recent * destinations array. */ - test( - 'UpdateRecentDestinations', async function() { - // Recent destinations start out empty. - assertRecentDestinations([]); - assertEquals(0, nativeLayer.getCallCount('getPrinterCapabilities')); + test('UpdateRecentDestinations', async function() { + // Recent destinations start out empty. + assertRecentDestinations([]); + assertEquals(0, nativeLayer.getCallCount('getPrinterCapabilities')); - return initialize() - .then(() => { - assertRecentDestinations(['Save as PDF']); - assertEquals( - 1, nativeLayer.getCallCount('getPrinterCapabilities')); + return initialize() + .then(() => { + assertRecentDestinations(['Save as PDF']); + assertEquals(1, nativeLayer.getCallCount('getPrinterCapabilities')); - // Add printers to store. - nativeLayer.resetResolver('getPrinterCapabilities'); - destinationSettings.getDestinationStoreForTest() - .startLoadAllDestinations(); - return nativeLayer.whenCalled('getPrinters'); - }) - .then(() => { - nativeLayer.resetResolver('getPrinterCapabilities'); - // Simulate setting a destination from the dialog. - return selectDestination(destinations[0]!); - }) - .then(async () => { - assertRecentDestinations(['ID1', 'Save as PDF']); - assertEquals( - 1, nativeLayer.getCallCount('getPrinterCapabilities')); + // Add printers to store. + nativeLayer.resetResolver('getPrinterCapabilities'); + destinationSettings.getDestinationStoreForTest() + .startLoadAllDestinations(); + return nativeLayer.whenCalled('getPrinters'); + }) + .then(() => { + nativeLayer.resetResolver('getPrinterCapabilities'); + // Simulate setting a destination from the dialog. + return selectDestination(destinations[0]!); + }) + .then(async () => { + assertRecentDestinations(['ID1', 'Save as PDF']); + assertEquals(1, nativeLayer.getCallCount('getPrinterCapabilities')); - // Reselect a recent destination. Still 2 destinations, but in a - // different order. - nativeLayer.resetResolver('getPrinterCapabilities'); - destinationSettings.$.destinationSelect.dispatchEvent( - new CustomEvent('selected-option-change', { - bubbles: true, - composed: true, - detail: 'Save as PDF/local/', - })); - await microtasksFinished(); - assertRecentDestinations(['Save as PDF', 'ID1']); - // No additional capabilities call, since the destination was - // previously selected. - assertEquals( - 0, nativeLayer.getCallCount('getPrinterCapabilities')); + // Reselect a recent destination. Still 2 destinations, but in a + // different order. + nativeLayer.resetResolver('getPrinterCapabilities'); + destinationSettings.$.destinationSelect.dispatchEvent( + new CustomEvent('selected-option-change', { + bubbles: true, + composed: true, + detail: 'Save as PDF/local/', + })); + await microtasksFinished(); + assertRecentDestinations(['Save as PDF', 'ID1']); + // No additional capabilities call, since the destination was + // previously selected. + assertEquals(0, nativeLayer.getCallCount('getPrinterCapabilities')); - // Select a third destination. - return selectDestination(destinations[1]!); - }) - .then(() => { - assertRecentDestinations(['ID2', 'Save as PDF', 'ID1']); - assertEquals( - 1, nativeLayer.getCallCount('getPrinterCapabilities')); - nativeLayer.resetResolver('getPrinterCapabilities'); - // Fill recent destinations up to the cap, then add a couple - // more destinations. Make sure the length of the list does not - // exceed NUM_PERSISTED_DESTINATIONS. - const whenCapabilitiesDone = - nativeLayer.waitForMultipleCapabilities( - NUM_PERSISTED_DESTINATIONS); - for (const destination of extraDestinations) { - selectDestination(destination); - } - return whenCapabilitiesDone; - }) - .then(() => { - assertRecentDestinations( - extraDestinations.map(dest => dest.id).reverse()); - assertEquals( - NUM_PERSISTED_DESTINATIONS, - nativeLayer.getCallCount('getPrinterCapabilities')); - }); - }); + // Select a third destination. + return selectDestination(destinations[1]!); + }) + .then(() => { + assertRecentDestinations(['ID2', 'Save as PDF', 'ID1']); + assertEquals(1, nativeLayer.getCallCount('getPrinterCapabilities')); + nativeLayer.resetResolver('getPrinterCapabilities'); + // Fill recent destinations up to the cap, then add a couple + // more destinations. Make sure the length of the list does not + // exceed NUM_PERSISTED_DESTINATIONS. + const whenCapabilitiesDone = nativeLayer.waitForMultipleCapabilities( + NUM_PERSISTED_DESTINATIONS); + for (const destination of extraDestinations) { + selectDestination(destination); + } + return whenCapabilitiesDone; + }) + .then(() => { + assertRecentDestinations( + extraDestinations.map(dest => dest.id).reverse()); + assertEquals( + NUM_PERSISTED_DESTINATIONS, + nativeLayer.getCallCount('getPrinterCapabilities')); + }); + }); // Tests that disabling the Save as PDF destination hides the corresponding // dropdown item. - test( - 'DisabledSaveAsPdf', function() { - // Initialize destination settings with the PDF printer disabled. - pdfPrinterDisabled = true; + test('DisabledSaveAsPdf', function() { + // Initialize destination settings with the PDF printer disabled. + pdfPrinterDisabled = true; - return initialize().then(() => { - // Because the 'Save as PDF' fallback is unavailable, the first - // destination is selected. - const expectedDestination = makeLocalDestinationKey('ID1'); - assertDropdownItems([expectedDestination]); - }); - }); + return initialize().then(() => { + // Because the 'Save as PDF' fallback is unavailable, the first + // destination is selected. + const expectedDestination = makeLocalDestinationKey('ID1'); + assertDropdownItems([expectedDestination]); + }); + }); // Tests that disabling the 'Save as PDF' destination and exposing no // printers to the native layer results in a 'No destinations' option in the
diff --git a/chrome/test/data/webui/print_preview/destination_store_test.ts b/chrome/test/data/webui/print_preview/destination_store_test.ts index f1a6285..f20d5ce2 100644 --- a/chrome/test/data/webui/print_preview/destination_store_test.ts +++ b/chrome/test/data/webui/print_preview/destination_store_test.ts
@@ -81,163 +81,155 @@ * Tests that if the user has a single valid recent destination the * destination is automatically reselected. */ - test( - 'SingleRecentDestination', function() { - const recentDestination = makeRecentDestination(destinations[0]!); - initialSettings.serializedAppStateStr = JSON.stringify({ - version: 2, - recentDestinations: [recentDestination], - }); + test('SingleRecentDestination', function() { + const recentDestination = makeRecentDestination(destinations[0]!); + initialSettings.serializedAppStateStr = JSON.stringify({ + version: 2, + recentDestinations: [recentDestination], + }); - return setInitialSettings(false).then(args => { - assertTrue(!!args); - assertEquals('ID1', args.destinationId); - assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); - assertEquals('ID1', destinationStore.selectedDestination!.id); - }); - }); + return setInitialSettings(false).then(args => { + assertTrue(!!args); + assertEquals('ID1', args.destinationId); + assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); + assertEquals('ID1', destinationStore.selectedDestination!.id); + }); + }); /** * Tests that if the user has multiple valid recent destinations the most * recent destination is automatically reselected and its capabilities are * fetched. */ - test( - 'MultipleRecentDestinations', function() { - const recentDestinations = destinations.slice(0, 3).map( - destination => makeRecentDestination(destination)); + test('MultipleRecentDestinations', function() { + const recentDestinations = destinations.slice(0, 3).map( + destination => makeRecentDestination(destination)); - initialSettings.serializedAppStateStr = JSON.stringify({ - version: 2, - recentDestinations: recentDestinations, - }); + initialSettings.serializedAppStateStr = JSON.stringify({ + version: 2, + recentDestinations: recentDestinations, + }); - return setInitialSettings(false).then(function(args) { - assertTrue(!!args); - // Should have loaded ID1 as the selected printer, since it was most - // recent. - assertEquals('ID1', args.destinationId); - assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); - assertEquals('ID1', destinationStore.selectedDestination!.id); - // Verify that all local printers have been added to the store. - const reportedPrinters = destinationStore.destinations(); - destinations.forEach(destination => { - const match = reportedPrinters.find((reportedPrinter) => { - return reportedPrinter.id === destination.id; - }); - assertFalse(typeof match === 'undefined'); - }); + return setInitialSettings(false).then(function(args) { + assertTrue(!!args); + // Should have loaded ID1 as the selected printer, since it was most + // recent. + assertEquals('ID1', args.destinationId); + assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); + assertEquals('ID1', destinationStore.selectedDestination!.id); + // Verify that all local printers have been added to the store. + const reportedPrinters = destinationStore.destinations(); + destinations.forEach(destination => { + const match = reportedPrinters.find((reportedPrinter) => { + return reportedPrinter.id === destination.id; }); + assertFalse(typeof match === 'undefined'); }); + }); + }); /** * Tests that if there are no recent destinations, we fall back to Save As * PDF. */ - test( - 'RecentDestinationsFallback', function() { - initialSettings.serializedAppStateStr = JSON.stringify({ - version: 2, - recentDestinations: [], - }); - localDestinations = []; + test('RecentDestinationsFallback', function() { + initialSettings.serializedAppStateStr = JSON.stringify({ + version: 2, + recentDestinations: [], + }); + localDestinations = []; - return setInitialSettings(false).then(() => { - assertEquals( - GooglePromotedDestinationId.SAVE_AS_PDF, - destinationStore.selectedDestination!.id); - }); - }); + return setInitialSettings(false).then(() => { + assertEquals( + GooglePromotedDestinationId.SAVE_AS_PDF, + destinationStore.selectedDestination!.id); + }); + }); /** * Tests that if the user has multiple valid recent destinations, the * correct destination is selected for the preview request. * For crbug.com/666595. */ - test( - 'MultipleRecentDestinationsOneRequest', function() { - const recentDestinations = destinations.slice(0, 3).map( - destination => makeRecentDestination(destination)); + test('MultipleRecentDestinationsOneRequest', function() { + const recentDestinations = destinations.slice(0, 3).map( + destination => makeRecentDestination(destination)); - initialSettings.serializedAppStateStr = JSON.stringify({ - version: 2, - recentDestinations: recentDestinations, - }); + initialSettings.serializedAppStateStr = JSON.stringify({ + version: 2, + recentDestinations: recentDestinations, + }); - return setInitialSettings(false).then(function(args) { - assertTrue(!!args); - // Should have loaded ID1 as the selected printer, since it was most - // recent. - assertEquals('ID1', args.destinationId); - assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); - assertEquals('ID1', destinationStore.selectedDestination!.id); + return setInitialSettings(false).then(function(args) { + assertTrue(!!args); + // Should have loaded ID1 as the selected printer, since it was most + // recent. + assertEquals('ID1', args.destinationId); + assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); + assertEquals('ID1', destinationStore.selectedDestination!.id); - // The other local destinations should be in the store, but only one - // should have been selected so there was only one preview request. - const reportedPrinters = destinationStore.destinations(); - assertEquals(6, reportedPrinters.length); - destinations.forEach(destination => { - assertTrue(reportedPrinters.some(p => p.id === destination.id)); - }); - assertEquals(1, numPrintersSelected); - }); + // The other local destinations should be in the store, but only one + // should have been selected so there was only one preview request. + const reportedPrinters = destinationStore.destinations(); + assertEquals(6, reportedPrinters.length); + destinations.forEach(destination => { + assertTrue(reportedPrinters.some(p => p.id === destination.id)); }); + assertEquals(1, numPrintersSelected); + }); + }); /** * Tests that if there are default destination selection rules they are * respected and a matching destination is automatically selected. */ - test( - 'DefaultDestinationSelectionRules', function() { - initialSettings.serializedDefaultDestinationSelectionRulesStr = - JSON.stringify({namePattern: '.*Four.*'}); - initialSettings.serializedAppStateStr = ''; - return setInitialSettings(false).then(function(args) { - assertTrue(!!args); - // Should have loaded ID4 as the selected printer, since it matches - // the rules. - assertEquals('ID4', args.destinationId); - assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); - assertEquals('ID4', destinationStore.selectedDestination!.id); - }); - }); + test('DefaultDestinationSelectionRules', function() { + initialSettings.serializedDefaultDestinationSelectionRulesStr = + JSON.stringify({namePattern: '.*Four.*'}); + initialSettings.serializedAppStateStr = ''; + return setInitialSettings(false).then(function(args) { + assertTrue(!!args); + // Should have loaded ID4 as the selected printer, since it matches + // the rules. + assertEquals('ID4', args.destinationId); + assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); + assertEquals('ID4', destinationStore.selectedDestination!.id); + }); + }); /** * Tests that if the system default printer policy is enabled the system * default printer is automatically selected even if the user has recent * destinations. */ - test( - 'SystemDefaultPrinterPolicy', function() { - // Set the policy in loadTimeData. - loadTimeData.overrideValues({useSystemDefaultPrinter: true}); + test('SystemDefaultPrinterPolicy', function() { + // Set the policy in loadTimeData. + loadTimeData.overrideValues({useSystemDefaultPrinter: true}); - // Setup some recent destinations to ensure they are not selected. - const recentDestinations: RecentDestination[] = []; - destinations.slice(0, 3).forEach(destination => { - recentDestinations.push(makeRecentDestination(destination)); + // Setup some recent destinations to ensure they are not selected. + const recentDestinations: RecentDestination[] = []; + destinations.slice(0, 3).forEach(destination => { + recentDestinations.push(makeRecentDestination(destination)); + }); + + initialSettings.serializedAppStateStr = JSON.stringify({ + version: 2, + recentDestinations: recentDestinations, + }); + + return Promise + .all([ + setInitialSettings(false), + eventToPromise( + DestinationStoreEventType.SELECTED_DESTINATION_CAPABILITIES_READY, + destinationStore), + ]) + .then(() => { + // Need to load FooDevice as the printer, since it is the system + // default. + assertEquals('FooDevice', destinationStore.selectedDestination!.id); }); - - initialSettings.serializedAppStateStr = JSON.stringify({ - version: 2, - recentDestinations: recentDestinations, - }); - - return Promise - .all([ - setInitialSettings(false), - eventToPromise( - DestinationStoreEventType - .SELECTED_DESTINATION_CAPABILITIES_READY, - destinationStore), - ]) - .then(() => { - // Need to load FooDevice as the printer, since it is the system - // default. - assertEquals( - 'FooDevice', destinationStore.selectedDestination!.id); - }); - }); + }); /** * Tests that if there is no system default destination, the default @@ -245,22 +237,21 @@ * is in app kiosk mode (so no PDF printer), the first destination returned * from printer fetch is selected. */ - test( - 'KioskModeSelectsFirstPrinter', function() { - initialSettings.serializedDefaultDestinationSelectionRulesStr = ''; - initialSettings.serializedAppStateStr = ''; - initialSettings.pdfPrinterDisabled = true; - initialSettings.printerName = ''; + test('KioskModeSelectsFirstPrinter', function() { + initialSettings.serializedDefaultDestinationSelectionRulesStr = ''; + initialSettings.serializedAppStateStr = ''; + initialSettings.pdfPrinterDisabled = true; + initialSettings.printerName = ''; - return setInitialSettings(false).then(function(args) { - assertTrue(!!args); - // Should have loaded the first destination as the selected printer. - assertEquals(destinations[0]!.id, args.destinationId); - assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); - assertEquals( - destinations[0]!.id, destinationStore.selectedDestination!.id); - }); - }); + return setInitialSettings(false).then(function(args) { + assertTrue(!!args); + // Should have loaded the first destination as the selected printer. + assertEquals(destinations[0]!.id, args.destinationId); + assertEquals(PrinterType.LOCAL_PRINTER, args.printerType); + assertEquals( + destinations[0]!.id, destinationStore.selectedDestination!.id); + }); + }); /** * Tests that if there is no system default destination, the default @@ -269,26 +260,24 @@ * destinations found, the NO_DESTINATIONS error is fired and the selected * destination is null. */ - test( - 'NoPrintersShowsError', function() { - initialSettings.serializedDefaultDestinationSelectionRulesStr = ''; - initialSettings.serializedAppStateStr = ''; - initialSettings.pdfPrinterDisabled = true; - initialSettings.printerName = ''; - localDestinations = []; + test('NoPrintersShowsError', function() { + initialSettings.serializedDefaultDestinationSelectionRulesStr = ''; + initialSettings.serializedAppStateStr = ''; + initialSettings.pdfPrinterDisabled = true; + initialSettings.printerName = ''; + localDestinations = []; - return Promise - .all([ - setInitialSettings(true), - eventToPromise(DestinationStoreEventType.ERROR, destinationStore), - ]) - .then(function(argsArray) { - const errorEvent = argsArray[1]; - assertEquals( - DestinationErrorType.NO_DESTINATIONS, errorEvent.detail); - assertEquals(null, destinationStore.selectedDestination); - }); - }); + return Promise + .all([ + setInitialSettings(true), + eventToPromise(DestinationStoreEventType.ERROR, destinationStore), + ]) + .then(function(argsArray) { + const errorEvent = argsArray[1]; + assertEquals(DestinationErrorType.NO_DESTINATIONS, errorEvent.detail); + assertEquals(null, destinationStore.selectedDestination); + }); + }); /** * Tests that if the user has a recent destination that is already in the @@ -322,50 +311,49 @@ * Tests that if the user has a single valid recent destination the * destination is automatically reselected. */ - test( - 'LoadAndSelectDestination', function() { - destinations = getDestinations(localDestinations); - initialSettings.printerName = ''; - const id1 = 'ID1'; - const name1 = 'One'; - let destination: Destination; + test('LoadAndSelectDestination', function() { + destinations = getDestinations(localDestinations); + initialSettings.printerName = ''; + const id1 = 'ID1'; + const name1 = 'One'; + let destination: Destination; - return setInitialSettings(false) - .then(function(args) { - assertTrue(!!args); - assertEquals( - GooglePromotedDestinationId.SAVE_AS_PDF, args.destinationId); - assertEquals(PrinterType.PDF_PRINTER, args.printerType); - assertEquals( - GooglePromotedDestinationId.SAVE_AS_PDF, - destinationStore.selectedDestination!.id); - const localDestinationInfo = { - deviceName: id1, - printerName: name1, - }; - // Typecast localDestinationInfo to work around the fact that - // policy types are only defined on Chrome OS. - nativeLayer.setLocalDestinationCapabilities({ - printer: localDestinationInfo, - capabilities: getCddTemplate(id1, name1).capabilities, - }); - destinationStore.startLoadAllDestinations(); - return nativeLayer.whenCalled('getPrinters'); - }) - .then(() => { - destination = - destinationStore.destinations().find(d => d.id === id1)!; - // No capabilities or policies yet. - assertFalse(!!destination.capabilities); - destinationStore.selectDestination(destination); - return nativeLayer.whenCalled('getPrinterCapabilities'); - }) - .then(() => { - assertEquals(destination, destinationStore.selectedDestination); - // Capabilities are updated. - assertTrue(!!destination.capabilities); - }); - }); + return setInitialSettings(false) + .then(function(args) { + assertTrue(!!args); + assertEquals( + GooglePromotedDestinationId.SAVE_AS_PDF, args.destinationId); + assertEquals(PrinterType.PDF_PRINTER, args.printerType); + assertEquals( + GooglePromotedDestinationId.SAVE_AS_PDF, + destinationStore.selectedDestination!.id); + const localDestinationInfo = { + deviceName: id1, + printerName: name1, + }; + // Typecast localDestinationInfo to work around the fact that + // policy types are only defined on Chrome OS. + nativeLayer.setLocalDestinationCapabilities({ + printer: localDestinationInfo, + capabilities: getCddTemplate(id1, name1).capabilities, + }); + destinationStore.startLoadAllDestinations(); + return nativeLayer.whenCalled('getPrinters'); + }) + .then(() => { + destination = + destinationStore.destinations().find(d => d.id === id1)!; + // No capabilities or policies yet. + assertFalse(!!destination.capabilities); + destinationStore.selectDestination(destination); + return nativeLayer.whenCalled('getPrinterCapabilities'); + }) + .then(() => { + assertEquals(destination, destinationStore.selectedDestination); + // Capabilities are updated. + assertTrue(!!destination.capabilities); + }); + }); /** * Tests that the destination store will not allow the selected destination
diff --git a/chrome/test/data/webui/print_preview/key_event_test.ts b/chrome/test/data/webui/print_preview/key_event_test.ts index 2d7c521..a3892c80 100644 --- a/chrome/test/data/webui/print_preview/key_event_test.ts +++ b/chrome/test/data/webui/print_preview/key_event_test.ts
@@ -77,17 +77,16 @@ // Tests that the enter key does not trigger a call to print if the event // comes from a dropdown. - test( - 'EnterOnDropdownDoesNotPrint', function() { - const whenKeyEventFired = eventToPromise('keydown', page); - keyEventOn( - page.shadowRoot.querySelector('print-preview-sidebar')!.shadowRoot - .querySelector('print-preview-layout-settings')!.shadowRoot - .querySelector<HTMLSelectElement>('.md-select')!, - 'keydown', 0, [], 'Enter'); - return whenKeyEventFired.then( - () => assertEquals(0, nativeLayer.getCallCount('doPrint'))); - }); + test('EnterOnDropdownDoesNotPrint', function() { + const whenKeyEventFired = eventToPromise('keydown', page); + keyEventOn( + page.shadowRoot.querySelector('print-preview-sidebar')!.shadowRoot + .querySelector('print-preview-layout-settings')!.shadowRoot + .querySelector<HTMLSelectElement>('.md-select')!, + 'keydown', 0, [], 'Enter'); + return whenKeyEventFired.then( + () => assertEquals(0, nativeLayer.getCallCount('doPrint'))); + }); // Tests that the enter key does not trigger a call to print if the event // comes from a button. @@ -109,65 +108,61 @@ // Tests that the enter key does not trigger a call to print if the event // comes from a checkbox. - test( - 'EnterOnCheckboxDoesNotPrint', function() { - const moreSettingsElement = - page.shadowRoot.querySelector('print-preview-sidebar')!.shadowRoot - .querySelector('print-preview-more-settings')!; - moreSettingsElement.$.label.click(); - const whenKeyEventFired = eventToPromise('keydown', page); - keyEventOn( - page.shadowRoot.querySelector('print-preview-sidebar')!.shadowRoot - .querySelector('print-preview-other-options-settings')! - .shadowRoot.querySelector('cr-checkbox')!, - 'keydown', 0, [], 'Enter'); - return whenKeyEventFired.then( - () => assertEquals(0, nativeLayer.getCallCount('doPrint'))); - }); + test('EnterOnCheckboxDoesNotPrint', function() { + const moreSettingsElement = + page.shadowRoot.querySelector('print-preview-sidebar')!.shadowRoot + .querySelector('print-preview-more-settings')!; + moreSettingsElement.$.label.click(); + const whenKeyEventFired = eventToPromise('keydown', page); + keyEventOn( + page.shadowRoot.querySelector('print-preview-sidebar')!.shadowRoot + .querySelector('print-preview-other-options-settings')!.shadowRoot + .querySelector('cr-checkbox')!, + 'keydown', 0, [], 'Enter'); + return whenKeyEventFired.then( + () => assertEquals(0, nativeLayer.getCallCount('doPrint'))); + }); // Tests that escape closes the dialog only on Mac. - test( - 'EscapeClosesDialogOnMacOnly', function() { - const promise = isMac ? - nativeLayer.whenCalled('dialogClose') : - eventToPromise('keydown', page).then(() => { - assertEquals(0, nativeLayer.getCallCount('dialogClose')); - }); - keyEventOn(page, 'keydown', 0, [], 'Escape'); - return promise; - }); + test('EscapeClosesDialogOnMacOnly', function() { + const promise = isMac ? + nativeLayer.whenCalled('dialogClose') : + eventToPromise('keydown', page).then(() => { + assertEquals(0, nativeLayer.getCallCount('dialogClose')); + }); + keyEventOn(page, 'keydown', 0, [], 'Escape'); + return promise; + }); // Tests that Cmd + Period closes the dialog only on Mac - test( - 'CmdPeriodClosesDialogOnMacOnly', function() { - const promise = isMac ? - nativeLayer.whenCalled('dialogClose') : - eventToPromise('keydown', page).then(() => { - assertEquals(0, nativeLayer.getCallCount('dialogClose')); - }); - keyEventOn(page, 'keydown', 0, ['meta'], '.'); - return promise; - }); + test('CmdPeriodClosesDialogOnMacOnly', function() { + const promise = isMac ? + nativeLayer.whenCalled('dialogClose') : + eventToPromise('keydown', page).then(() => { + assertEquals(0, nativeLayer.getCallCount('dialogClose')); + }); + keyEventOn(page, 'keydown', 0, ['meta'], '.'); + return promise; + }); // Tests that Ctrl+Shift+P opens the system dialog. - test( - 'CtrlShiftPOpensSystemDialog', function() { - let promise: Promise<void>; - if (isChromeOS) { - // Chrome OS doesn't have a system dialog. Just make sure the key - // event does not trigger a crash. - promise = Promise.resolve(); - } else if (isWindows) { - promise = nativeLayer.whenCalled('doPrint').then((printTicket) => { - assertTrue(JSON.parse(printTicket).showSystemDialog); - }); - } else { - promise = nativeLayer.whenCalled('showSystemDialog'); - } - const modifiers: ModifiersParam = - isMac ? ['meta', 'alt'] : ['ctrl', 'shift']; - const key = isMac ? '\u03c0' : 'P'; - keyEventOn(page, 'keydown', 0, modifiers, key); - return promise; + test('CtrlShiftPOpensSystemDialog', function() { + let promise: Promise<void>; + if (isChromeOS) { + // Chrome OS doesn't have a system dialog. Just make sure the key + // event does not trigger a crash. + promise = Promise.resolve(); + } else if (isWindows) { + promise = nativeLayer.whenCalled('doPrint').then((printTicket) => { + assertTrue(JSON.parse(printTicket).showSystemDialog); }); + } else { + promise = nativeLayer.whenCalled('showSystemDialog'); + } + const modifiers: ModifiersParam = + isMac ? ['meta', 'alt'] : ['ctrl', 'shift']; + const key = isMac ? '\u03c0' : 'P'; + keyEventOn(page, 'keydown', 0, modifiers, key); + return promise; + }); });
diff --git a/chrome/test/data/webui/print_preview/link_container_test.ts b/chrome/test/data/webui/print_preview/link_container_test.ts index de86d44..392fbe5 100644 --- a/chrome/test/data/webui/print_preview/link_container_test.ts +++ b/chrome/test/data/webui/print_preview/link_container_test.ts
@@ -108,16 +108,15 @@ * Test that clicking the open in preview link correctly results in a * property change and that the throbber appears. Mac only. */ - test( - 'OpenInPreviewLinkClick', function() { - const throbber = linkContainer.$.openPdfInPreviewThrobber; - assertTrue(throbber.hidden); - const promise = eventToPromise('open-pdf-in-preview', linkContainer); + test('OpenInPreviewLinkClick', function() { + const throbber = linkContainer.$.openPdfInPreviewThrobber; + assertTrue(throbber.hidden); + const promise = eventToPromise('open-pdf-in-preview', linkContainer); - linkContainer.$.openPdfInPreviewLink.click(); - return promise.then(function() { - assertFalse(throbber.hidden); - }); - }); + linkContainer.$.openPdfInPreviewLink.click(); + return promise.then(function() { + assertFalse(throbber.hidden); + }); + }); // </if> });
diff --git a/chrome/test/data/webui/print_preview/pages_settings_test.ts b/chrome/test/data/webui/print_preview/pages_settings_test.ts index 3c8cfd30..f1a9d47 100644 --- a/chrome/test/data/webui/print_preview/pages_settings_test.ts +++ b/chrome/test/data/webui/print_preview/pages_settings_test.ts
@@ -387,76 +387,74 @@ // Verifies that the input is never disabled when the validity of the // setting changes. - test( - 'InputNotDisabledOnValidityChange', async () => { - pagesSection.pageCount = 3; - // In the real UI, the print preview app listens for this event from - // this section and others and sets disabled to true if any change from - // true to false is detected. Imitate this here. Since we are only - // interacting with the pages input, at no point should the input be - // disabled, as it will lose focus. - pagesSection.addEventListener('setting-valid-changed', function(e) { - assertFalse(pagesSection.$.pageSettingsCustomInput.disabled); - pagesSection.disabled = !(e as CustomEvent<boolean>).detail; - assertFalse(pagesSection.$.pageSettingsCustomInput.disabled); - }); + test('InputNotDisabledOnValidityChange', async () => { + pagesSection.pageCount = 3; + // In the real UI, the print preview app listens for this event from + // this section and others and sets disabled to true if any change from + // true to false is detected. Imitate this here. Since we are only + // interacting with the pages input, at no point should the input be + // disabled, as it will lose focus. + pagesSection.addEventListener('setting-valid-changed', function(e) { + assertFalse(pagesSection.$.pageSettingsCustomInput.disabled); + pagesSection.disabled = !(e as CustomEvent<boolean>).detail; + assertFalse(pagesSection.$.pageSettingsCustomInput.disabled); + }); - await selectOption(pagesSection, PagesValue.CUSTOM.toString()); - await setCustomInput('1'); - validateState([1], [{from: 1, to: 1}], '', false); + await selectOption(pagesSection, PagesValue.CUSTOM.toString()); + await setCustomInput('1'); + validateState([1], [{from: 1, to: 1}], '', false); - await setCustomInput('12'); - validateState([1], [{from: 1, to: 1}], limitError + '3', true); + await setCustomInput('12'); + validateState([1], [{from: 1, to: 1}], limitError + '3', true); - // Restore valid input - await setCustomInput('1'); - validateState([1], [{from: 1, to: 1}], '', false); + // Restore valid input + await setCustomInput('1'); + validateState([1], [{from: 1, to: 1}], '', false); - // Invalid input again - await setCustomInput('8'); - validateState([1], [{from: 1, to: 1}], limitError + '3', true); + // Invalid input again + await setCustomInput('8'); + validateState([1], [{from: 1, to: 1}], limitError + '3', true); - // Clear input - await setCustomInput(''); - validateState([1], [{from: 1, to: 1}], '', false); + // Clear input + await setCustomInput(''); + validateState([1], [{from: 1, to: 1}], '', false); - // Set valid input - await setCustomInput('2'); - validateState([2], [{from: 2, to: 2}], '', false); - }); + // Set valid input + await setCustomInput('2'); + validateState([2], [{from: 2, to: 2}], '', false); + }); // Verifies that the enter key event is bubbled to the pages settings // element, so that it will be bubbled to the print preview app to trigger a // print. - test( - 'EnterOnInputTriggersPrint', async () => { - pagesSection.pageCount = 3; - const input = pagesSection.$.pageSettingsCustomInput.inputElement; - const whenPrintReceived = eventToPromise('keydown', pagesSection); + test('EnterOnInputTriggersPrint', async () => { + pagesSection.pageCount = 3; + const input = pagesSection.$.pageSettingsCustomInput.inputElement; + const whenPrintReceived = eventToPromise('keydown', pagesSection); - // Setup an empty input by selecting custom.. - const customValue = PagesValue.CUSTOM.toString(); - const pagesSelect = pagesSection.shadowRoot.querySelector('select')!; - await Promise.all([ - selectOption(pagesSection, customValue), - eventToPromise('focus', input), - ]); - assertEquals(customValue, pagesSelect.value); - keyEventOn(input, 'keydown', 0, [], 'Enter'); + // Setup an empty input by selecting custom.. + const customValue = PagesValue.CUSTOM.toString(); + const pagesSelect = pagesSection.shadowRoot.querySelector('select')!; + await Promise.all([ + selectOption(pagesSection, customValue), + eventToPromise('focus', input), + ]); + assertEquals(customValue, pagesSelect.value); + keyEventOn(input, 'keydown', 0, [], 'Enter'); - await whenPrintReceived; - // Keep custom selected, but pages to print should still be all. - assertEquals(customValue, pagesSelect.value); - validateState([1, 2, 3], [], '', false); + await whenPrintReceived; + // Keep custom selected, but pages to print should still be all. + assertEquals(customValue, pagesSelect.value); + validateState([1, 2, 3], [], '', false); - // Select a custom input of 1. - await setCustomInput('1'); - assertEquals(customValue, pagesSelect.value); - const whenSecondPrintReceived = eventToPromise('keydown', pagesSection); - keyEventOn(input, 'keydown', 0, [], 'Enter'); + // Select a custom input of 1. + await setCustomInput('1'); + assertEquals(customValue, pagesSelect.value); + const whenSecondPrintReceived = eventToPromise('keydown', pagesSection); + keyEventOn(input, 'keydown', 0, [], 'Enter'); - await whenSecondPrintReceived; - assertEquals(customValue, pagesSelect.value); - validateState([1], [{from: 1, to: 1}], '', false); - }); + await whenSecondPrintReceived; + assertEquals(customValue, pagesSelect.value); + validateState([1], [{from: 1, to: 1}], '', false); + }); });
diff --git a/chrome/test/data/webui/print_preview/preview_generation_test.ts b/chrome/test/data/webui/print_preview/preview_generation_test.ts index a046245..70d7711 100644 --- a/chrome/test/data/webui/print_preview/preview_generation_test.ts +++ b/chrome/test/data/webui/print_preview/preview_generation_test.ts
@@ -218,42 +218,37 @@ * Validate changing the pages per sheet updates the preview, and resets * margins to MarginsType.DEFAULT. */ - test( - 'ChangeMarginsByPagesPerSheet', function() { - return initialize() - .then(function(args) { - const originalTicket: PreviewTicket = - JSON.parse(args.printTicket); - assertEquals(0, originalTicket.requestID); - assertEquals(MarginsType.DEFAULT, originalTicket['marginsType']); - assertEquals( - MarginsType.DEFAULT, page.getSettingValue('margins')); - assertEquals(1, page.getSettingValue('pagesPerSheet')); - assertEquals(1, originalTicket['pagesPerSheet']); - nativeLayer.resetResolver('getPreview'); - page.setSetting('margins', MarginsType.MINIMUM); - return nativeLayer.whenCalled('getPreview'); - }) - .then(function(args) { - assertEquals( - MarginsType.MINIMUM, page.getSettingValue('margins')); - const ticket: PreviewTicket = JSON.parse(args.printTicket); - assertEquals(MarginsType.MINIMUM, ticket['marginsType']); - nativeLayer.resetResolver('getPreview'); - assertEquals(1, ticket.requestID); - page.setSetting('pagesPerSheet', 4); - return nativeLayer.whenCalled('getPreview'); - }) - .then(function(args) { - assertEquals( - MarginsType.DEFAULT, page.getSettingValue('margins')); - assertEquals(4, page.getSettingValue('pagesPerSheet')); - const ticket: PreviewTicket = JSON.parse(args.printTicket); - assertEquals(MarginsType.DEFAULT, ticket['marginsType']); - assertEquals(4, ticket['pagesPerSheet']); - assertEquals(2, ticket.requestID); - }); - }); + test('ChangeMarginsByPagesPerSheet', function() { + return initialize() + .then(function(args) { + const originalTicket: PreviewTicket = JSON.parse(args.printTicket); + assertEquals(0, originalTicket.requestID); + assertEquals(MarginsType.DEFAULT, originalTicket['marginsType']); + assertEquals(MarginsType.DEFAULT, page.getSettingValue('margins')); + assertEquals(1, page.getSettingValue('pagesPerSheet')); + assertEquals(1, originalTicket['pagesPerSheet']); + nativeLayer.resetResolver('getPreview'); + page.setSetting('margins', MarginsType.MINIMUM); + return nativeLayer.whenCalled('getPreview'); + }) + .then(function(args) { + assertEquals(MarginsType.MINIMUM, page.getSettingValue('margins')); + const ticket: PreviewTicket = JSON.parse(args.printTicket); + assertEquals(MarginsType.MINIMUM, ticket['marginsType']); + nativeLayer.resetResolver('getPreview'); + assertEquals(1, ticket.requestID); + page.setSetting('pagesPerSheet', 4); + return nativeLayer.whenCalled('getPreview'); + }) + .then(function(args) { + assertEquals(MarginsType.DEFAULT, page.getSettingValue('margins')); + assertEquals(4, page.getSettingValue('pagesPerSheet')); + const ticket: PreviewTicket = JSON.parse(args.printTicket); + assertEquals(MarginsType.DEFAULT, ticket['marginsType']); + assertEquals(4, ticket['pagesPerSheet']); + assertEquals(2, ticket.requestID); + }); + }); /** Validate changing the paper size updates the preview. */ test('MediaSize', function() { @@ -603,81 +598,79 @@ * Validate that if the document layout has 0 default margins, the * header/footer setting is set to false. */ - test( - 'ZeroDefaultMarginsClearsHeaderFooter', async () => { - /** - * @param ticket The parsed print ticket - * @param expectedId The expected ticket request ID - * @param expectedMargins The expected ticket margins type - * @param expectedHeaderFooter The expected ticket - * header/footer value - */ - function assertMarginsFooter( - ticket: PreviewTicket, expectedId: number, - expectedMargins: MarginsType, expectedHeaderFooter: boolean) { - assertEquals(expectedId, ticket.requestID); - assertEquals(expectedMargins, ticket.marginsType); - assertEquals(expectedHeaderFooter, ticket.headerFooterEnabled); - } + test('ZeroDefaultMarginsClearsHeaderFooter', async () => { + /** + * @param ticket The parsed print ticket + * @param expectedId The expected ticket request ID + * @param expectedMargins The expected ticket margins type + * @param expectedHeaderFooter The expected ticket + * header/footer value + */ + function assertMarginsFooter( + ticket: PreviewTicket, expectedId: number, expectedMargins: MarginsType, + expectedHeaderFooter: boolean) { + assertEquals(expectedId, ticket.requestID); + assertEquals(expectedMargins, ticket.marginsType); + assertEquals(expectedHeaderFooter, ticket.headerFooterEnabled); + } - nativeLayer.setPageLayoutInfo({ - marginTop: 0, - marginLeft: 0, - marginBottom: 0, - marginRight: 0, - contentWidth: 612, - contentHeight: 792, - printableAreaX: 0, - printableAreaY: 0, - printableAreaWidth: 612, - printableAreaHeight: 792, - }); + nativeLayer.setPageLayoutInfo({ + marginTop: 0, + marginLeft: 0, + marginBottom: 0, + marginRight: 0, + contentWidth: 612, + contentHeight: 792, + printableAreaX: 0, + printableAreaY: 0, + printableAreaWidth: 612, + printableAreaHeight: 792, + }); - let previewArgs = await initialize(); - let ticket: PreviewTicket = JSON.parse(previewArgs.printTicket); + let previewArgs = await initialize(); + let ticket: PreviewTicket = JSON.parse(previewArgs.printTicket); - // The ticket recorded here is the original, which requests default - // margins with headers and footers (Print Preview defaults). - assertMarginsFooter(ticket, 0, MarginsType.DEFAULT, true); + // The ticket recorded here is the original, which requests default + // margins with headers and footers (Print Preview defaults). + assertMarginsFooter(ticket, 0, MarginsType.DEFAULT, true); - // After getting the new layout, a second request should have been - // sent. Need to wait for a cycle since the 2nd request is issued - // asynchronously in app.ts. - await microtasksFinished(); - assertEquals(2, nativeLayer.getCallCount('getPreview')); - assertEquals(MarginsType.DEFAULT, page.getSettingValue('margins')); - assertFalse(page.getSettingValue('headerFooter')); + // After getting the new layout, a second request should have been + // sent. Need to wait for a cycle since the 2nd request is issued + // asynchronously in app.ts. + await microtasksFinished(); + assertEquals(2, nativeLayer.getCallCount('getPreview')); + assertEquals(MarginsType.DEFAULT, page.getSettingValue('margins')); + assertFalse(page.getSettingValue('headerFooter')); - // Check the last ticket sent by the preview area. It should not - // have the same settings as the original (headers and footers - // should have been turned off). - const previewArea = - page.shadowRoot.querySelector('print-preview-preview-area')!; - assertMarginsFooter( - previewArea.getLastTicketForTest()!, 1, MarginsType.DEFAULT, false); - nativeLayer.resetResolver('getPreview'); - page.setSetting('margins', MarginsType.MINIMUM); - previewArgs = await nativeLayer.whenCalled('getPreview'); + // Check the last ticket sent by the preview area. It should not + // have the same settings as the original (headers and footers + // should have been turned off). + const previewArea = + page.shadowRoot.querySelector('print-preview-preview-area')!; + assertMarginsFooter( + previewArea.getLastTicketForTest()!, 1, MarginsType.DEFAULT, false); + nativeLayer.resetResolver('getPreview'); + page.setSetting('margins', MarginsType.MINIMUM); + previewArgs = await nativeLayer.whenCalled('getPreview'); - // Setting minimum margins allows space for the headers and footers, - // so they should be enabled again. - ticket = JSON.parse(previewArgs.printTicket); - assertMarginsFooter(ticket, 2, MarginsType.MINIMUM, true); - assertEquals( - MarginsType.MINIMUM, - page.getSettingValue('margins') as MarginsType); - assertTrue(page.getSettingValue('headerFooter') as boolean); - nativeLayer.resetResolver('getPreview'); - page.setSetting('margins', MarginsType.DEFAULT); - previewArgs = await nativeLayer.whenCalled('getPreview'); + // Setting minimum margins allows space for the headers and footers, + // so they should be enabled again. + ticket = JSON.parse(previewArgs.printTicket); + assertMarginsFooter(ticket, 2, MarginsType.MINIMUM, true); + assertEquals( + MarginsType.MINIMUM, page.getSettingValue('margins') as MarginsType); + assertTrue(page.getSettingValue('headerFooter') as boolean); + nativeLayer.resetResolver('getPreview'); + page.setSetting('margins', MarginsType.DEFAULT); + previewArgs = await nativeLayer.whenCalled('getPreview'); - // With default margins, there is no space for headers/footers, so - // they are removed. - ticket = JSON.parse(previewArgs.printTicket); - assertMarginsFooter(ticket, 3, MarginsType.DEFAULT, false); - assertEquals(MarginsType.DEFAULT, page.getSettingValue('margins')); - assertEquals(false, page.getSettingValue('headerFooter')); - }); + // With default margins, there is no space for headers/footers, so + // they are removed. + ticket = JSON.parse(previewArgs.printTicket); + assertMarginsFooter(ticket, 3, MarginsType.DEFAULT, false); + assertEquals(MarginsType.DEFAULT, page.getSettingValue('margins')); + assertEquals(false, page.getSettingValue('headerFooter')); + }); /** * Validate that the page size calculation handles floating numbers correctly.
diff --git a/chrome/test/data/webui/print_preview/restore_state_test.ts b/chrome/test/data/webui/print_preview/restore_state_test.ts index 7ed889d..66020f3 100644 --- a/chrome/test/data/webui/print_preview/restore_state_test.ts +++ b/chrome/test/data/webui/print_preview/restore_state_test.ts
@@ -97,78 +97,76 @@ * Tests state restoration with all boolean settings set to true, scaling = * 90, dpi = 100, custom square paper, and custom margins. */ - test( - 'RestoreTrueValues', async function() { - const stickySettings: SerializedSettings = { - version: 2, - recentDestinations: [], - dpi: {horizontal_dpi: 100, vertical_dpi: 100}, - mediaSize: { - name: 'CUSTOM', - width_microns: 215900, - height_microns: 215900, - custom_display_name: 'CUSTOM_SQUARE', - }, - customMargins: { - marginTop: 74, - marginRight: 74, - marginBottom: 74, - marginLeft: 74, - }, - vendorOptions: { - paperType: 1, - printArea: 6, - }, - marginsType: 3, /* custom */ - scaling: '90', - scalingType: ScalingType.CUSTOM, - scalingTypePdf: ScalingType.FIT_TO_PAGE, - isHeaderFooterEnabled: true, - isCssBackgroundEnabled: true, - isCollateEnabled: true, - isDuplexEnabled: true, - isDuplexShortEdge: true, - isLandscapeEnabled: true, - isColorEnabled: true, - }; - await testInitializeWithStickySettings(stickySettings); - }); + test('RestoreTrueValues', async function() { + const stickySettings: SerializedSettings = { + version: 2, + recentDestinations: [], + dpi: {horizontal_dpi: 100, vertical_dpi: 100}, + mediaSize: { + name: 'CUSTOM', + width_microns: 215900, + height_microns: 215900, + custom_display_name: 'CUSTOM_SQUARE', + }, + customMargins: { + marginTop: 74, + marginRight: 74, + marginBottom: 74, + marginLeft: 74, + }, + vendorOptions: { + paperType: 1, + printArea: 6, + }, + marginsType: 3, /* custom */ + scaling: '90', + scalingType: ScalingType.CUSTOM, + scalingTypePdf: ScalingType.FIT_TO_PAGE, + isHeaderFooterEnabled: true, + isCssBackgroundEnabled: true, + isCollateEnabled: true, + isDuplexEnabled: true, + isDuplexShortEdge: true, + isLandscapeEnabled: true, + isColorEnabled: true, + }; + await testInitializeWithStickySettings(stickySettings); + }); /** * Tests state restoration with all boolean settings set to false, scaling = * 120, dpi = 200, letter paper and default margins. */ - test( - 'RestoreFalseValues', async function() { - const stickySettings: SerializedSettings = { - version: 2, - recentDestinations: [], - dpi: {horizontal_dpi: 200, vertical_dpi: 200}, - mediaSize: { - name: 'NA_LETTER', - width_microns: 215900, - height_microns: 279400, - is_default: true, - custom_display_name: 'Letter', - }, - vendorOptions: { - paperType: 0, - printArea: 4, - }, - marginsType: 0, /* default */ - scaling: '120', - scalingType: ScalingType.DEFAULT, - scalingTypePdf: ScalingType.DEFAULT, - isHeaderFooterEnabled: false, - isCssBackgroundEnabled: false, - isCollateEnabled: false, - isDuplexEnabled: false, - isDuplexShortEdge: false, - isLandscapeEnabled: false, - isColorEnabled: false, - }; - await testInitializeWithStickySettings(stickySettings); - }); + test('RestoreFalseValues', async function() { + const stickySettings: SerializedSettings = { + version: 2, + recentDestinations: [], + dpi: {horizontal_dpi: 200, vertical_dpi: 200}, + mediaSize: { + name: 'NA_LETTER', + width_microns: 215900, + height_microns: 279400, + is_default: true, + custom_display_name: 'Letter', + }, + vendorOptions: { + paperType: 0, + printArea: 4, + }, + marginsType: 0, /* default */ + scaling: '120', + scalingType: ScalingType.DEFAULT, + scalingTypePdf: ScalingType.DEFAULT, + isHeaderFooterEnabled: false, + isCssBackgroundEnabled: false, + isCollateEnabled: false, + isDuplexEnabled: false, + isDuplexShortEdge: false, + isLandscapeEnabled: false, + isColorEnabled: false, + }; + await testInitializeWithStickySettings(stickySettings); + }); /** * Tests that setting the settings values results in the correct serialized
diff --git a/chrome/test/data/webui/print_preview/scaling_settings_interactive_test.ts b/chrome/test/data/webui/print_preview/scaling_settings_interactive_test.ts index f5ce11f..7086ac0 100644 --- a/chrome/test/data/webui/print_preview/scaling_settings_interactive_test.ts +++ b/chrome/test/data/webui/print_preview/scaling_settings_interactive_test.ts
@@ -29,42 +29,40 @@ document.body.appendChild(scalingSection); }); - test( - 'auto focus input', async () => { - const scalingInput = - scalingSection.shadowRoot - .querySelector('print-preview-number-settings-section')!.$ - .userValue.inputElement; - const collapse = - scalingSection.shadowRoot.querySelector('cr-collapse')!; + test('auto focus input', async () => { + const scalingInput = + scalingSection.shadowRoot + .querySelector('print-preview-number-settings-section')!.$.userValue + .inputElement; + const collapse = scalingSection.shadowRoot.querySelector('cr-collapse')!; - assertFalse(collapse.opened); - assertEquals( - ScalingType.DEFAULT, scalingSection.getSettingValue('scalingType')); + assertFalse(collapse.opened); + assertEquals( + ScalingType.DEFAULT, scalingSection.getSettingValue('scalingType')); - // Select custom with the dropdown. This should autofocus the input. - await Promise.all([ - selectOption(scalingSection, ScalingType.CUSTOM.toString()), - eventToPromise('transitionend', collapse), - ]); - assertTrue(collapse.opened); - assertEquals(scalingInput, getDeepActiveElement()); + // Select custom with the dropdown. This should autofocus the input. + await Promise.all([ + selectOption(scalingSection, ScalingType.CUSTOM.toString()), + eventToPromise('transitionend', collapse), + ]); + assertTrue(collapse.opened); + assertEquals(scalingInput, getDeepActiveElement()); - // Blur and select default. - scalingInput.blur(); - await Promise.all([ - selectOption(scalingSection, ScalingType.DEFAULT.toString()), - eventToPromise('transitionend', collapse), - ]); - assertEquals( - ScalingType.DEFAULT, scalingSection.getSettingValue('scalingType')); - assertFalse(collapse.opened); + // Blur and select default. + scalingInput.blur(); + await Promise.all([ + selectOption(scalingSection, ScalingType.DEFAULT.toString()), + eventToPromise('transitionend', collapse), + ]); + assertEquals( + ScalingType.DEFAULT, scalingSection.getSettingValue('scalingType')); + assertFalse(collapse.opened); - // Set custom in JS, which happens when we set the sticky settings. This - // should not autofocus the input. - scalingSection.setSetting('scalingType', ScalingType.CUSTOM); - await eventToPromise('transitionend', collapse); - assertTrue(collapse.opened); - assertNotEquals(scalingInput, getDeepActiveElement()); - }); + // Set custom in JS, which happens when we set the sticky settings. This + // should not autofocus the input. + scalingSection.setSetting('scalingType', ScalingType.CUSTOM); + await eventToPromise('transitionend', collapse); + assertTrue(collapse.opened); + assertNotEquals(scalingInput, getDeepActiveElement()); + }); });
diff --git a/chrome/test/data/webui/print_preview/scaling_settings_test.ts b/chrome/test/data/webui/print_preview/scaling_settings_test.ts index cb2fd95..cbb33165 100644 --- a/chrome/test/data/webui/print_preview/scaling_settings_test.ts +++ b/chrome/test/data/webui/print_preview/scaling_settings_test.ts
@@ -187,44 +187,43 @@ // Verifies that the input is never disabled when the validity of the // setting changes. - test( - 'InputNotDisabledOnValidityChange', async () => { - const numberSection = scalingSection.shadowRoot.querySelector( - 'print-preview-number-settings-section')!; - const input = numberSection.getInput(); + test('InputNotDisabledOnValidityChange', async () => { + const numberSection = scalingSection.shadowRoot.querySelector( + 'print-preview-number-settings-section')!; + const input = numberSection.getInput(); - // In the real UI, the print preview app listens for this event from - // this section and others and sets disabled to true if any change from - // true to false is detected. Imitate this here. Since we are only - // interacting with the scaling input, at no point should the input be - // disabled, as it will lose focus. - model.addEventListener('setting-valid-changed', function() { - assertFalse(input.disabled); - }); + // In the real UI, the print preview app listens for this event from + // this section and others and sets disabled to true if any change from + // true to false is detected. Imitate this here. Since we are only + // interacting with the scaling input, at no point should the input be + // disabled, as it will lose focus. + model.addEventListener('setting-valid-changed', function() { + assertFalse(input.disabled); + }); - await selectOption(scalingSection, ScalingType.CUSTOM.toString()); - await input.updateComplete; - await triggerInputEvent(input, '90', scalingSection); - validateState('90', true, ScalingType.CUSTOM, ScalingType.CUSTOM, '90'); + await selectOption(scalingSection, ScalingType.CUSTOM.toString()); + await input.updateComplete; + await triggerInputEvent(input, '90', scalingSection); + validateState('90', true, ScalingType.CUSTOM, ScalingType.CUSTOM, '90'); - // Set invalid input - await triggerInputEvent(input, '9', scalingSection); - validateState('90', false, ScalingType.CUSTOM, ScalingType.CUSTOM, '9'); + // Set invalid input + await triggerInputEvent(input, '9', scalingSection); + validateState('90', false, ScalingType.CUSTOM, ScalingType.CUSTOM, '9'); - // Restore valid input - await triggerInputEvent(input, '90', scalingSection); - validateState('90', true, ScalingType.CUSTOM, ScalingType.CUSTOM, '90'); + // Restore valid input + await triggerInputEvent(input, '90', scalingSection); + validateState('90', true, ScalingType.CUSTOM, ScalingType.CUSTOM, '90'); - // Invalid input again - await triggerInputEvent(input, '9', scalingSection); - validateState('90', false, ScalingType.CUSTOM, ScalingType.CUSTOM, '9'); + // Invalid input again + await triggerInputEvent(input, '9', scalingSection); + validateState('90', false, ScalingType.CUSTOM, ScalingType.CUSTOM, '9'); - // Clear input - await triggerInputEvent(input, '', scalingSection); - validateState('90', true, ScalingType.CUSTOM, ScalingType.CUSTOM, ''); + // Clear input + await triggerInputEvent(input, '', scalingSection); + validateState('90', true, ScalingType.CUSTOM, ScalingType.CUSTOM, ''); - // Set valid input - await triggerInputEvent(input, '50', scalingSection); - validateState('50', true, ScalingType.CUSTOM, ScalingType.CUSTOM, '50'); - }); + // Set valid input + await triggerInputEvent(input, '50', scalingSection); + validateState('50', true, ScalingType.CUSTOM, ScalingType.CUSTOM, '50'); + }); });
diff --git a/chrome/test/payments/payment_request_platform_browsertest_base.h b/chrome/test/payments/payment_request_platform_browsertest_base.h index 3aafa82c..a742ab1 100644 --- a/chrome/test/payments/payment_request_platform_browsertest_base.h +++ b/chrome/test/payments/payment_request_platform_browsertest_base.h
@@ -24,7 +24,6 @@ #include "content/public/test/content_mock_cert_verifier.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "url/gurl.h" namespace content { class RenderFrameHost;
diff --git a/chrome/updater/test/data/offline_manifest.gup b/chrome/updater/test/data/offline_manifest.gup new file mode 100644 index 0000000..41e60c98 --- /dev/null +++ b/chrome/updater/test/data/offline_manifest.gup
@@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<response protocol="3.0"> + <systemrequirements platform="win" + arch="${ARCH_REQUIREMENT}" + min_os_version="6.1"/> + <app appid="${APP_ID}" + status="ok"> + <updatecheck status="ok"> + <urls> + <url codebase="https://dl.google.com/install/${INSTALLER_VERSION}/"/> + </urls> + <manifest version="${INSTALLER_VERSION}"> + <packages> + <package name="${INSTALLER_FILENAME}" + hash_sha256="${INSTALLER_HASH_SHA256}" + size="${INSTALLER_SIZE}" + required="true"/> + </packages> + <actions> + <action event="install" + run="${INSTALLER_FILENAME}" + arguments="" + needsadmin="false"/> + <action event="postinstall" + onsuccess="exitsilentlyonlaunchcmd"/> + </actions> + </manifest> + </updatecheck> + </app> +</response>
diff --git a/chrome/updater/test/data/tag.exe b/chrome/updater/test/data/tag.exe new file mode 100755 index 0000000..ec5d50b --- /dev/null +++ b/chrome/updater/test/data/tag.exe Binary files differ
diff --git a/chrome/updater/test/data/test_certificate.pfx b/chrome/updater/test/data/test_certificate.pfx new file mode 100644 index 0000000..77da144 --- /dev/null +++ b/chrome/updater/test/data/test_certificate.pfx Binary files differ
diff --git a/chrome/updater/test/test_installer/BUILD.gn b/chrome/updater/test/test_installer/BUILD.gn index 260fabe..455412a 100644 --- a/chrome/updater/test/test_installer/BUILD.gn +++ b/chrome/updater/test/test_installer/BUILD.gn
@@ -8,6 +8,8 @@ import("//components/crx_file/crx3.gni") if (is_win) { + import("//build/toolchain/win/toolchain.gni") + executable("test_meta_installer") { testonly = true @@ -29,7 +31,9 @@ sources = [ "$root_build_dir/test_meta_installer.exe", "//chrome/tools/build/win/resedit.py", + "//chrome/updater/win/signing/sign.py", "create_test_installer_gn_wrapper.py", + "create_test_standalone_msi_installer_gn_wrapper.py", "embed_install_scripts.py", ] @@ -189,6 +193,62 @@ deps = [ ":copy_test_msi_installer2.0.0.0" ] } + if (host_os == "win") { + action("test_standalone_msi_installer") { + testonly = true + base_dir = "$root_build_dir/test_installer" + msi_base_name = "TestSystemMsiInstaller" + certificate_path = "//chrome/updater/test/data/test_certificate.pfx" + offline_manifest = "//chrome/updater/test/data/offline_manifest.gup" + tag_exe = "//chrome/updater/test/data/tag.exe" + appid = "{c28fcf72-bcf2-45c5-8def-31a74ac02012}" + script = "$base_dir/create_test_standalone_msi_installer_gn_wrapper.py" + output = "$base_dir/${msi_base_name}StandaloneSetup.exe" + + inputs = + [ script ] + get_target_outputs(":copy_test_msi_installer2.0.0.0") + outputs = [ output ] + + deps = [ + ":copy_test_msi_installer2.0.0.0", + ":test_installer", + "//chrome/updater/tools:tag", + "//chrome/updater/win/installer:installer_test", + ] + + data = [ + certificate_path, + offline_manifest, + tag_exe, + ] + + args = [ + "--in_file", + "UpdaterSetup_test.exe", + "--out_file", + rebase_path(output, root_build_dir), + "--certificate_file_path", + rebase_path(certificate_path, root_build_dir), + "--appid", + appid, + "--installer_path", + rebase_path("$base_dir/${msi_base_name}.msi", root_build_dir), + "--manifest_path", + rebase_path(offline_manifest, root_build_dir), + "--lzma_7z", + rebase_path("//third_party/lzma_sdk/bin/win64/7za.exe", root_build_dir), + "--signtool", + rebase_path( + "$windows_sdk_path/bin/$windows_sdk_version/x64/signtool.exe", + root_build_dir), + "--tagging_exe", + rebase_path(tag_exe, root_build_dir), + "--manifest_dict_replacements", + "{'\${INSTALLER_VERSION}':'2.0.0.0', '\${ARCH_REQUIREMENT}':'x86'}", + ] + } + } + group("app_installers") { testonly = true @@ -199,6 +259,11 @@ ":test_msi_installer1.0.0.0", ":test_msi_installer_crx", ] + + # The resource editing script only works on Windows. + if (host_os == "win") { + data_deps += [ ":test_standalone_msi_installer" ] + } } } else { copy("test_installer") {
diff --git a/chrome/updater/test/test_installer/create_test_standalone_msi_installer_gn_wrapper.py b/chrome/updater/test/test_installer/create_test_standalone_msi_installer_gn_wrapper.py new file mode 100755 index 0000000..900fd09 --- /dev/null +++ b/chrome/updater/test/test_installer/create_test_standalone_msi_installer_gn_wrapper.py
@@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# GN runs python scripts with the native interpreter, but `sign.py` needs to run +# with `vpython` to be able to run `resedit`, so this wrapper is needed. + +import os +import subprocess +import sys + +if __name__ == '__main__': + subprocess.run([ + 'vpython3.bat', + os.path.join(os.path.dirname(os.path.abspath(__file__)), 'sign.py') + ] + sys.argv[1:])
diff --git a/chrome/updater/win/signing/sign.py b/chrome/updater/win/signing/sign.py index fe16f52a..59a5c46 100755 --- a/chrome/updater/win/signing/sign.py +++ b/chrome/updater/win/signing/sign.py
@@ -113,9 +113,9 @@ command += flags if self._certificate_file_path: command += ['/f', self._certificate_file_path] - if self._certificate_password: - command += ['/p', self._certificate_password] - if self._identity: + if self._certificate_password: + command += ['/p', self._certificate_password] + elif self._identity: command += ['/s', 'My', '/n', self._identity] command += [in_file]
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 5c6b851..325bf5d7b 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -662,7 +662,7 @@ lint_baseline_file = "android/lint-baseline.xml" lint_suppressions_file = "android/lint-suppressions.xml" - apk_name = "CastShell" + apk_name = "CastBrowser" android_manifest = "$root_gen_dir/cast_shell_manifest/AndroidManifest.xml" android_manifest_dep = "//chromecast/browser/android:cast_shell_manifest"
diff --git a/chromecast/build/BUILD.gn b/chromecast/build/BUILD.gn index 00d8b11..018de4b 100644 --- a/chromecast/build/BUILD.gn +++ b/chromecast/build/BUILD.gn
@@ -8,8 +8,8 @@ artifact_type_suffix = "$cast_build_incremental-$target_cpu" copy("archive_public_cast_apk") { - sources = [ "$root_out_dir/apks/CastShell.apk" ] - outputs = [ "$root_out_dir/archive/CastShell-$artifact_type_suffix.apk" ] + sources = [ "$root_out_dir/apks/CastBrowser.apk" ] + outputs = [ "$root_out_dir/archive/CastBrowser-$artifact_type_suffix.apk" ] deps = [ "//chromecast:cast_browser_apk" ] } }
diff --git a/chromeos/ash/components/boca/BUILD.gn b/chromeos/ash/components/boca/BUILD.gn index c09f0ab..7e599b13 100644 --- a/chromeos/ash/components/boca/BUILD.gn +++ b/chromeos/ash/components/boca/BUILD.gn
@@ -28,6 +28,7 @@ "//ash/public/cpp", "//ash/resources/vector_icons", "//base", + "//chromeos/ash/components/boca:spotlight_lib", "//chromeos/ash/components/boca/babelorca:soda_installer", "//chromeos/ash/components/boca/proto", "//chromeos/ash/components/boca/session_api", @@ -41,6 +42,8 @@ "//components/signin/public/identity_manager", "//components/user_manager", "//google_apis/common", + "//remoting/client/common", + "//remoting/protocol", "//ui/base", "//ui/message_center", ] @@ -106,6 +109,22 @@ ] } +static_library("spotlight_lib") { + sources = [ + "spotlight/fake_spotlight_oauth_token_fetcher.cc", + "spotlight/fake_spotlight_oauth_token_fetcher.h", + "spotlight/spotlight_frame_consumer.cc", + "spotlight/spotlight_frame_consumer.h", + "spotlight/spotlight_oauth_token_fetcher.h", + ] + deps = [ + "//base", + "//remoting/client/common", + "//remoting/protocol", + "//third_party/webrtc_overrides:webrtc_component", + ] +} + source_set("unit_tests") { testonly = true @@ -134,6 +153,7 @@ "//ash/constants", "//base", "//base/test:test_support", + "//chromeos/ash/components/boca:spotlight_lib", "//chromeos/ash/components/boca/babelorca:soda_installer", "//chromeos/ash/components/boca/babelorca:soda_test_support", "//chromeos/ash/components/boca/proto",
diff --git a/chromeos/ash/components/boca/DEPS b/chromeos/ash/components/boca/DEPS index c4c7ec3..4b456de 100644 --- a/chromeos/ash/components/boca/DEPS +++ b/chromeos/ash/components/boca/DEPS
@@ -12,6 +12,9 @@ "+components/user_manager", "+content/public/test", "+google_apis/common", + "+remoting/client/common/remoting_client.h", + "+remoting/protocol/frame_consumer.h", + "+third_party/webrtc/modules/desktop_capture/desktop_frame.h", "+ui/base/l10n/l10n_util.h", "+ui/message_center/fake_message_center.h", "+ui/message_center/message_center.h",
diff --git a/chromeos/ash/components/boca/babelorca/BUILD.gn b/chromeos/ash/components/boca/babelorca/BUILD.gn index 9f8aba6c..75cee28 100644 --- a/chromeos/ash/components/boca/babelorca/BUILD.gn +++ b/chromeos/ash/components/boca/babelorca/BUILD.gn
@@ -61,6 +61,8 @@ "transcript_sender_impl.h", "transcript_sender_rate_limiter.cc", "transcript_sender_rate_limiter.h", + "translation_view_wrapper_impl.cc", + "translation_view_wrapper_impl.h", ] deps = [ @@ -72,6 +74,7 @@ "//chromeos/ash/components/boca/proto", "//chromeos/ash/components/boca/session_api", "//chromeos/ash/services/boca/babelorca/mojom", + "//chromeos/strings:strings_grit", "//components/live_caption", "//components/live_caption:constants", "//components/live_caption:live_translate", @@ -88,7 +91,9 @@ "//mojo/public/cpp/bindings", "//net", "//services/network/public/cpp", + "//ui/base", "//ui/native_theme", + "//ui/views", ] } @@ -190,6 +195,7 @@ "transcript_receiver_unittest.cc", "transcript_sender_impl_unittest.cc", "transcript_sender_rate_limiter_unittest.cc", + "translation_view_wrapper_impl_unittest.cc", ] deps = [ @@ -206,6 +212,7 @@ "//chromeos/ash/components/boca/proto", "//chromeos/ash/components/boca/session_api", "//chromeos/ash/services/boca/babelorca/mojom", + "//chromeos/strings:strings_grit", "//components/live_caption", "//components/live_caption:constants", "//components/prefs", @@ -223,6 +230,9 @@ "//services/network/public/cpp", "//testing/gmock", "//testing/gtest", + "//ui/base", + "//ui/events:test_support", "//ui/native_theme", + "//ui/views", ] }
diff --git a/chromeos/ash/components/boca/babelorca/DEPS b/chromeos/ash/components/boca/babelorca/DEPS index 3154b75e..1b5d8e9 100644 --- a/chromeos/ash/components/boca/babelorca/DEPS +++ b/chromeos/ash/components/boca/babelorca/DEPS
@@ -9,4 +9,5 @@ "+media/mojo/mojom/speech_recognition.mojom.h", "+media/mojo/mojom/speech_recognition_result.h", "+ui/native_theme", + "+ui/views", ]
diff --git a/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.cc b/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.cc index 0659cd0..1f45f88d 100644 --- a/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.cc +++ b/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.cc
@@ -57,7 +57,7 @@ } bool CaptionBubbleSettingsImpl::GetLiveTranslateEnabled() { - return translate_enabled_; + return translate_allowed_ && translate_enabled_; } std::string CaptionBubbleSettingsImpl::GetLiveCaptionLanguageCode() { @@ -96,4 +96,17 @@ observer_->OnLiveTranslateEnabledChanged(); } +void CaptionBubbleSettingsImpl::SetTranslateAllowed(bool allowed) { + bool allowed_changed = translate_allowed_ != allowed; + translate_allowed_ = allowed; + if (!allowed_changed || !observer_) { + return; + } + observer_->OnLiveTranslateEnabledChanged(); +} + +bool CaptionBubbleSettingsImpl::GetTranslateAllowed() { + return translate_allowed_; +} + } // namespace ash::babelorca
diff --git a/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.h b/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.h index 610e5696..c944296 100644 --- a/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.h +++ b/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.h
@@ -47,10 +47,13 @@ bool ShouldAdjustPositionOnExpand() override; void SetLiveTranslateEnabled(bool enabled); + void SetTranslateAllowed(bool allowed); + bool GetTranslateAllowed(); private: const raw_ptr<PrefService> profile_prefs_; std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; + bool translate_allowed_ = true; bool translate_enabled_ = false; const std::string caption_language_code_; const base::RepeatingClosure on_local_caption_closed_cb_;
diff --git a/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl_unittest.cc b/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl_unittest.cc index 0925f59a..be85efa 100644 --- a/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl_unittest.cc +++ b/chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl_unittest.cc
@@ -168,5 +168,35 @@ EXPECT_FALSE(caption_bubble_settings.ShouldAdjustPositionOnExpand()); } +TEST_F(CaptionBubbleSettingsImplTest, ToggleTranslateAllowed) { + CaptionBubbleSettingsImpl caption_bubble_settings( + &pref_service_, kEnglishLanguage, base::DoNothing()); + caption_bubble_settings.SetObserver(observer_weak_ptr_factory_.GetWeakPtr()); + + EXPECT_CALL(observer_, OnLiveTranslateEnabledChanged).Times(1); + caption_bubble_settings.SetTranslateAllowed(false); + EXPECT_FALSE(caption_bubble_settings.GetTranslateAllowed()); + + EXPECT_CALL(observer_, OnLiveTranslateEnabledChanged).Times(1); + caption_bubble_settings.SetTranslateAllowed(true); + EXPECT_TRUE(caption_bubble_settings.GetTranslateAllowed()); +} + +TEST_F(CaptionBubbleSettingsImplTest, GetLiveTranslateEnabled) { + CaptionBubbleSettingsImpl caption_bubble_settings( + &pref_service_, kEnglishLanguage, base::DoNothing()); + EXPECT_FALSE(caption_bubble_settings.GetLiveTranslateEnabled()); + + // CanEnableTranslate() is initially true. + caption_bubble_settings.SetLiveTranslateEnabled(true); + EXPECT_TRUE(caption_bubble_settings.GetLiveTranslateEnabled()); + + caption_bubble_settings.SetTranslateAllowed(false); + EXPECT_FALSE(caption_bubble_settings.GetLiveTranslateEnabled()); + + caption_bubble_settings.SetLiveTranslateEnabled(false); + EXPECT_FALSE(caption_bubble_settings.GetLiveTranslateEnabled()); +} + } // namespace } // namespace ash::babelorca
diff --git a/chromeos/ash/components/boca/babelorca/caption_controller_unittest.cc b/chromeos/ash/components/boca/babelorca/caption_controller_unittest.cc index 7c9ef61..db10dcf 100644 --- a/chromeos/ash/components/boca/babelorca/caption_controller_unittest.cc +++ b/chromeos/ash/components/boca/babelorca/caption_controller_unittest.cc
@@ -9,6 +9,7 @@ #include <string> #include <utility> +#include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.h" #include "chromeos/ash/components/boca/babelorca/fakes/fake_caption_controller_delegate.h"
diff --git a/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.cc b/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.cc new file mode 100644 index 0000000..1f3b2e4 --- /dev/null +++ b/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.cc
@@ -0,0 +1,72 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.h" + +#include <string> + +#include "chromeos/strings/grit/chromeos_strings.h" +#include "components/live_caption/views/translation_view_wrapper_base.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/controls/button/md_text_button.h" + +namespace ash::babelorca { + +TranslationViewWrapperImpl::TranslationViewWrapperImpl( + CaptionBubbleSettingsImpl* caption_bubble_settings) + : caption_bubble_settings_(caption_bubble_settings) {} + +TranslationViewWrapperImpl::~TranslationViewWrapperImpl() = default; + +views::MdTextButton* +TranslationViewWrapperImpl::GetTranslateToggleButtonForTesting() { + return button(translate_toggle_button_index_); +} + +void TranslationViewWrapperImpl:: + SimulateTranslateToggleButtonClickForTesting() { + OnTranslateToggleButtonPressed(); +} + +captions::CaptionBubbleSettings* +TranslationViewWrapperImpl::caption_bubble_settings() { + return caption_bubble_settings_; +} + +void TranslationViewWrapperImpl::MaybeAddChildViews( + views::View* translate_container) { + translate_toggle_button_index_ = AddLanguageTextButton( + translate_container, + base::BindRepeating( + &TranslationViewWrapperImpl::OnTranslateToggleButtonPressed, + weak_ptr_factory_.GetWeakPtr())); +} + +void TranslationViewWrapperImpl::UpdateLanguageLabelInternal() { + captions::TranslationViewWrapperBase::UpdateLanguageLabelInternal(); + button(translate_toggle_button_index_) + ->SetText(caption_bubble_settings_->GetLiveTranslateEnabled() + ? l10n_util::GetStringUTF16( + IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT) + : l10n_util::GetStringUTF16( + IDS_BOCA_CAPTIONS_TRANSLATION_AVAILABLE_BUTTON_TEXT)); +} + +void TranslationViewWrapperImpl::SetTranslationsViewVisible( + bool live_translate_enabled) { + captions::TranslationViewWrapperBase::SetTranslationsViewVisible( + live_translate_enabled); + button(translate_toggle_button_index_) + ->SetVisible(caption_bubble_settings_->GetTranslateAllowed()); + if (!live_translate_enabled) { + source_language_button()->SetVisible(false); + } +} + +void TranslationViewWrapperImpl::OnTranslateToggleButtonPressed() { + caption_bubble_settings_->SetLiveTranslateEnabled( + !caption_bubble_settings_->GetLiveTranslateEnabled()); +} + +} // namespace ash::babelorca
diff --git a/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.h b/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.h new file mode 100644 index 0000000..bde37cd --- /dev/null +++ b/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.h
@@ -0,0 +1,49 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TRANSLATION_VIEW_WRAPPER_IMPL_H_ +#define CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TRANSLATION_VIEW_WRAPPER_IMPL_H_ + +#include "base/memory/weak_ptr.h" +#include "chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.h" +#include "components/live_caption/views/translation_view_wrapper_base.h" + +namespace views { +class MdTextButton; +class View; +} // namespace views + +namespace ash::babelorca { + +class TranslationViewWrapperImpl : public captions::TranslationViewWrapperBase { + public: + explicit TranslationViewWrapperImpl( + CaptionBubbleSettingsImpl* caption_bubble_settings); + + TranslationViewWrapperImpl(const TranslationViewWrapperImpl&) = delete; + TranslationViewWrapperImpl& operator=(const TranslationViewWrapperImpl&) = + delete; + + ~TranslationViewWrapperImpl() override; + + views::MdTextButton* GetTranslateToggleButtonForTesting(); + void SimulateTranslateToggleButtonClickForTesting(); + + private: + // captions::TranslationViewWrapperBase: + captions::CaptionBubbleSettings* caption_bubble_settings() override; + void MaybeAddChildViews(views::View* translate_container) override; + void UpdateLanguageLabelInternal() override; + void SetTranslationsViewVisible(bool live_translate_enabled) override; + + void OnTranslateToggleButtonPressed(); + + const raw_ptr<CaptionBubbleSettingsImpl> caption_bubble_settings_; + int translate_toggle_button_index_ = -1; + base::WeakPtrFactory<TranslationViewWrapperImpl> weak_ptr_factory_{this}; +}; + +} // namespace ash::babelorca + +#endif // CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TRANSLATION_VIEW_WRAPPER_IMPL_H_
diff --git a/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl_unittest.cc b/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl_unittest.cc new file mode 100644 index 0000000..45e2e00 --- /dev/null +++ b/chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl_unittest.cc
@@ -0,0 +1,181 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/boca/babelorca/translation_view_wrapper_impl.h" + +#include <memory> +#include <string> + +#include "base/functional/callback_helpers.h" +#include "base/memory/raw_ptr.h" +#include "chromeos/ash/components/boca/babelorca/caption_bubble_settings_impl.h" +#include "chromeos/ash/components/boca/babelorca/pref_names.h" +#include "chromeos/strings/grit/chromeos_strings.h" +#include "components/live_caption/caption_bubble_settings.h" +#include "components/live_caption/views/translation_view_wrapper_base.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/controls/button/md_text_button.h" +#include "ui/views/view.h" + +namespace ash::babelorca { +namespace { + +const std::string kEnglishLanguage = "en-US"; +const std::string kFrenchLanguage = "fr"; + +class TranslationViewWrapperImplBaseTest + : public captions::TranslationViewWrapperBase::Delegate { + protected: + TranslationViewWrapperImplBaseTest() + : caption_bubble_settings_(InitPrefService(), + kEnglishLanguage, + base::DoNothing()) {} + + void OnLanguageChanged(const std::string& display_language) override {} + void UpdateLanguageDirection(const std::string& display_language) override {} + void CaptionSettingsButtonPressed() override {} + + void VerifyTranslationItemsVisible( + TranslationViewWrapperImpl* translation_view_wrapper, + bool source_language_visible, + bool target_language_visible) { + EXPECT_EQ(translation_view_wrapper->GetSourceLanguageButtonForTesting() + ->GetVisible(), + source_language_visible); + EXPECT_EQ(translation_view_wrapper->GetTranslateIconAndTextForTesting() + ->GetVisible(), + source_language_visible); + EXPECT_EQ(translation_view_wrapper->GetTranslateArrowIconForTesting() + ->GetVisible(), + source_language_visible); + EXPECT_EQ(translation_view_wrapper->GetTargetLanguageButtonForTesting() + ->GetVisible(), + target_language_visible); + } + + TestingPrefServiceSimple* InitPrefService() { + pref_service_.registry()->RegisterBooleanPref(prefs::kCaptionBubbleExpanded, + false); + pref_service_.registry()->RegisterStringPref( + prefs::kTranslateTargetLanguageCode, kEnglishLanguage); + return &pref_service_; + } + + views::LayoutProvider layout_provider_; + TestingPrefServiceSimple pref_service_; + CaptionBubbleSettingsImpl caption_bubble_settings_; +}; + +struct TranslationViewWrapperImplTestCase { + std::string test_name; + bool translate_allowed; + bool translate_enabled; + std::string target_language_code = kFrenchLanguage; + int toggle_text_id = IDS_BOCA_CAPTIONS_TRANSLATION_AVAILABLE_BUTTON_TEXT; +}; + +class TranslationViewWrapperImplTest + : public TranslationViewWrapperImplBaseTest, + public testing::TestWithParam<TranslationViewWrapperImplTestCase> { + protected: + TranslationViewWrapperImplTest() + : translation_view_wrapper_(&caption_bubble_settings_) {} + + views::View translation_container_; + TranslationViewWrapperImpl translation_view_wrapper_; +}; + +TEST_P(TranslationViewWrapperImplTest, Init) { + caption_bubble_settings_.SetTranslateAllowed(GetParam().translate_allowed); + caption_bubble_settings_.SetLiveTranslateEnabled( + GetParam().translate_enabled); + caption_bubble_settings_.SetLiveTranslateTargetLanguageCode( + GetParam().target_language_code); + + translation_view_wrapper_.Init(&translation_container_, this); + views::MdTextButton* const translate_toggle = + translation_view_wrapper_.GetTranslateToggleButtonForTesting(); + + bool languages_match = GetParam().target_language_code == kEnglishLanguage; + bool translate_enabled = + GetParam().translate_allowed && GetParam().translate_enabled; + VerifyTranslationItemsVisible( + &translation_view_wrapper_, + /*source_language_visible=*/translate_enabled && !languages_match, + /*target_language_visible=*/translate_enabled); + EXPECT_EQ(translate_toggle->GetVisible(), GetParam().translate_allowed); + EXPECT_EQ(translate_toggle->GetText(), + l10n_util::GetStringUTF16(GetParam().toggle_text_id)); +} + +TEST_F(TranslationViewWrapperImplTest, ClickToStartTranslation) { + caption_bubble_settings_.SetTranslateAllowed(true); + caption_bubble_settings_.SetLiveTranslateEnabled(false); + caption_bubble_settings_.SetLiveTranslateTargetLanguageCode(kFrenchLanguage); + + translation_view_wrapper_.Init(&translation_container_, this); + translation_view_wrapper_.SimulateTranslateToggleButtonClickForTesting(); + views::MdTextButton* const translate_toggle = + translation_view_wrapper_.GetTranslateToggleButtonForTesting(); + + VerifyTranslationItemsVisible(&translation_view_wrapper_, + /*source_language_visible=*/true, + /*target_language_visible=*/true); + EXPECT_EQ(translate_toggle->GetVisible(), true); + EXPECT_EQ(translate_toggle->GetText(), + l10n_util::GetStringUTF16( + IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT)); +} + +TEST_F(TranslationViewWrapperImplTest, ClickToStopTranslation) { + caption_bubble_settings_.SetTranslateAllowed(true); + caption_bubble_settings_.SetLiveTranslateEnabled(true); + caption_bubble_settings_.SetLiveTranslateTargetLanguageCode(kFrenchLanguage); + + translation_view_wrapper_.Init(&translation_container_, this); + translation_view_wrapper_.SimulateTranslateToggleButtonClickForTesting(); + views::MdTextButton* const translate_toggle = + translation_view_wrapper_.GetTranslateToggleButtonForTesting(); + + VerifyTranslationItemsVisible(&translation_view_wrapper_, + /*source_language_visible=*/false, + /*target_language_visible=*/false); + EXPECT_EQ(translate_toggle->GetVisible(), true); + EXPECT_EQ(translate_toggle->GetText(), + l10n_util::GetStringUTF16( + IDS_BOCA_CAPTIONS_TRANSLATION_AVAILABLE_BUTTON_TEXT)); +} + +INSTANTIATE_TEST_SUITE_P( + TranslationViewWrapperImplTestSuite, + TranslationViewWrapperImplTest, + testing::ValuesIn<TranslationViewWrapperImplTestCase>({ + {.test_name = "AllDisabled", + .translate_allowed = false, + .translate_enabled = false}, + {.test_name = "TranslateDisabledAndAllowed", + .translate_allowed = true, + .translate_enabled = false}, + {.test_name = "TranslateEnabledAndDisallowed", + .translate_allowed = false, + .translate_enabled = true}, + {.test_name = "TranslateEnabledAndAllowed", + .translate_allowed = true, + .translate_enabled = true, + .toggle_text_id = IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT}, + {.test_name = "TranslateEnabledAndAllowedSameLanguage", + .translate_allowed = true, + .translate_enabled = true, + .target_language_code = kEnglishLanguage, + .toggle_text_id = IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT}, + }), + [](const testing::TestParamInfo<TranslationViewWrapperImplTest::ParamType>& + info) { return info.param.test_name; }); + +} // namespace +} // namespace ash::babelorca
diff --git a/chromeos/ash/components/boca/boca_session_manager.cc b/chromeos/ash/components/boca/boca_session_manager.cc index 3c38be7..a3df9e1 100644 --- a/chromeos/ash/components/boca/boca_session_manager.cc +++ b/chromeos/ash/components/boca/boca_session_manager.cc
@@ -11,6 +11,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/network_config_service.h" +#include "base/check.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/logging.h" @@ -31,11 +32,14 @@ #include "chromeos/ash/components/boca/session_api/session_client_impl.h" #include "chromeos/ash/components/boca/session_api/student_heartbeat_request.h" #include "chromeos/ash/components/boca/session_api/update_student_activities_request.h" +#include "chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.h" #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "components/session_manager/core/session_manager.h" #include "components/user_manager/user_manager.h" #include "google_apis/common/api_error_codes.h" +#include "remoting/client/common/remoting_client.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "ui/base/l10n/l10n_util.h" #include "ui/message_center/message_center.h" @@ -110,6 +114,10 @@ } } +void BocaSessionManager::Reset() { + spotlight_token_fetcher_ = nullptr; +} + void BocaSessionManager::Observer::OnSessionMetadataUpdated( const std::string& session_id) {} @@ -387,6 +395,40 @@ return SodaStatus::kUninstalled; } +void BocaSessionManager::StartCrdClientForTeacher( + base::OnceClosure done_callback, + SpotlightFrameConsumer::FrameReceivedCallback frame_received_callback, + std::string connection_code) { + CHECK(ash::features::IsBocaSpotlightRobotRequesterEnabled()); + CHECK_EQ(connection_code.length(), 12u); + + if (remoting_client_) { + LOG(WARNING) << "[Boca] Tried to initiate a Spotight session while another " + "was in progress"; + return; + } + frame_consumer_ = std::make_unique<SpotlightFrameConsumer>( + std::move(frame_received_callback)); + remoting_client_ = std::make_unique<remoting::RemotingClient>( + std::move(done_callback), frame_consumer_.get(), + BocaAppClient::Get()->GetURLLoaderFactory()); + FetchSpotlightOAuthToken( + base::BindOnce(&BocaSessionManager::StartCrdSessionForTeacherInternal, + weak_factory_.GetWeakPtr(), std::move(connection_code))); +} + +void BocaSessionManager::EndSpotlightSession() { + if (remoting_client_) { + remoting_client_->StopSession(); + remoting_client_.reset(); + frame_consumer_.reset(); + } +} + +std::string BocaSessionManager::GetDeviceRobotEmail() { + return spotlight_token_fetcher_->GetDeviceRobotEmail(); +} + void BocaSessionManager::LoadInitialNetworkState() { cros_network_config_->GetNetworkStateList( chromeos::network_config::mojom::NetworkFilter::New( @@ -777,4 +819,24 @@ } } +void BocaSessionManager::StartCrdSessionForTeacherInternal( + std::string connection_code, + std::optional<std::string> oauth_token) { + if (!oauth_token.has_value() || oauth_token->empty()) { + LOG(ERROR) << "[Boca] Failed to retrieve OAuth token for Spotlight"; + return; + } + VLOG(1) << "[Boca] Starting CRD client for teacher"; + remoting_client_->StartSession( + connection_code, + {oauth_token.value(), spotlight_token_fetcher_->GetDeviceRobotEmail()}); +} + +void BocaSessionManager::FetchSpotlightOAuthToken( + SpotlightOAuthTokenFetcher::OAuthTokenCallback callback) { + CHECK(spotlight_token_fetcher_); + + spotlight_token_fetcher_->Start(std::move(callback)); +} + } // namespace ash::boca
diff --git a/chromeos/ash/components/boca/boca_session_manager.h b/chromeos/ash/components/boca/boca_session_manager.h index 0e772611..ad09200d 100644 --- a/chromeos/ash/components/boca/boca_session_manager.h +++ b/chromeos/ash/components/boca/boca_session_manager.h
@@ -6,6 +6,7 @@ #define CHROMEOS_ASH_COMPONENTS_BOCA_BOCA_SESSION_MANAGER_H_ #include <memory> +#include <optional> #include <string> #include <vector> @@ -20,6 +21,8 @@ #include "chromeos/ash/components/boca/notifications/boca_notification_handler.h" #include "chromeos/ash/components/boca/proto/session.pb.h" #include "chromeos/ash/components/boca/session_api/session_client_impl.h" +#include "chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.h" +#include "chromeos/ash/components/boca/spotlight/spotlight_oauth_token_fetcher.h" #include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h" #include "components/account_id/account_id.h" #include "components/prefs/pref_service.h" @@ -41,6 +44,10 @@ enum ApiErrorCode; } +namespace remoting { +class RemotingClient; +} + namespace session_manager { class SessionManager; } // namespace session_manager @@ -108,6 +115,8 @@ BocaSessionManager& operator=(const BocaSessionManager&) = delete; ~BocaSessionManager() override; + void Reset(); + // Interface for observing events. class Observer : public base::CheckedObserver { public: @@ -220,6 +229,19 @@ soda_installer_ = soda_installer; } SodaStatus GetSodaStatus(); + + void set_spotlight_token_fetcher( + SpotlightOAuthTokenFetcher* spotlight_token_fetcher) { + spotlight_token_fetcher_ = spotlight_token_fetcher; + } + bool HasSpotlightTokenFetcher() { return spotlight_token_fetcher_; } + void StartCrdClientForTeacher( + base::OnceClosure done_callback, + SpotlightFrameConsumer::FrameReceivedCallback frame_received_callback, + std::string connection_code); + void EndSpotlightSession(); + std::string GetDeviceRobotEmail(); + base::ObserverList<Observer>& observers() { return observers_; } AccountId& account_id() { return account_id_; } @@ -272,6 +294,12 @@ void CloseAllCaptions(); + void StartCrdSessionForTeacherInternal( + std::string connection_code, + std::optional<std::string> oauth_token); + void FetchSpotlightOAuthToken( + SpotlightOAuthTokenFetcher::OAuthTokenCallback callback); + const bool is_producer_; base::OnceClosure end_session_callback_for_testing_; base::TimeDelta in_session_polling_interval_; @@ -301,6 +329,8 @@ std::unique_ptr<::boca::Session> current_session_; std::unique_ptr<::boca::Session> previous_session_; + std::unique_ptr<SpotlightFrameConsumer> frame_consumer_; + std::unique_ptr<remoting::RemotingClient> remoting_client_; bool is_network_connected_ = false; bool disabled_on_non_managed_network_ = false; // Remote for sending requests to the CrosNetworkConfig service. @@ -315,6 +345,7 @@ raw_ptr<SessionClientImpl> session_client_impl_; raw_ptr<signin::IdentityManager> identity_manager_; raw_ptr<babelorca::SodaInstaller> soda_installer_; + raw_ptr<SpotlightOAuthTokenFetcher> spotlight_token_fetcher_; bool is_local_caption_enabled_ = false; SessionCaptionInitializer session_caption_initializer_; net::BackoffEntry student_heartbeat_retry_backoff_;
diff --git a/chromeos/ash/components/boca/boca_session_manager_unittest.cc b/chromeos/ash/components/boca/boca_session_manager_unittest.cc index 5f64d1de..f4f1182e3 100644 --- a/chromeos/ash/components/boca/boca_session_manager_unittest.cc +++ b/chromeos/ash/components/boca/boca_session_manager_unittest.cc
@@ -28,6 +28,7 @@ #include "chromeos/ash/components/boca/session_api/get_session_request.h" #include "chromeos/ash/components/boca/session_api/student_heartbeat_request.h" #include "chromeos/ash/components/boca/session_api/update_student_activities_request.h" +#include "chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.h" #include "chromeos/ash/components/network/network_ui_data.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/fake_cros_settings_provider.h" @@ -1602,6 +1603,16 @@ device_session_manger_.SetSessionState(session_manager::SessionState::ACTIVE); } +TEST_F(BocaSessionManagerTest, SetsSpotlightOAuthTokenRequester) { + ASSERT_FALSE(boca_session_manager()->HasSpotlightTokenFetcher()); + + std::unique_ptr<FakeSpotlightOAuthTokenFetcher> token_manager = + std::make_unique<FakeSpotlightOAuthTokenFetcher>("token", "robot_email"); + boca_session_manager()->set_spotlight_token_fetcher(token_manager.get()); + ASSERT_TRUE(boca_session_manager()->HasSpotlightTokenFetcher()); + boca_session_manager()->Reset(); +} + class BocaSessionManagerSodaTest : public BocaSessionManagerTestBase { protected: void SetUp() override {
diff --git a/chromeos/ash/components/boca/on_task/notification_constants.cc b/chromeos/ash/components/boca/on_task/notification_constants.cc index 6121371..b1a0c788 100644 --- a/chromeos/ash/components/boca/on_task/notification_constants.cc +++ b/chromeos/ash/components/boca/on_task/notification_constants.cc
@@ -10,9 +10,11 @@ namespace ash::boca { base::flat_set<std::string> GetAllowlistedNotificationIdsForLockedMode() { - return {kOnTaskEnterLockedModeNotificationId, kOnTaskSessionEndNotificationId, + return {kOnTaskEnterLockedModeNotificationId, + kOnTaskSessionEndNotificationId, kOnTaskBundleContentAddedNotificationId, kOnTaskBundleContentRemovedNotificationId, + kOnTaskResourceNotSupportedInLockedModeNotificationId, kSpotlightStartedNotificationId}; }
diff --git a/chromeos/ash/components/boca/on_task/notification_constants.h b/chromeos/ash/components/boca/on_task/notification_constants.h index 2eed9cb7..4313501d 100644 --- a/chromeos/ash/components/boca/on_task/notification_constants.h +++ b/chromeos/ash/components/boca/on_task/notification_constants.h
@@ -44,6 +44,11 @@ inline constexpr char kOnTaskBundleContentRemovedNotificationId[] = "boca.on_task.bundle_content_removed_notification"; +// Notification id for the notification shown when resource is not supported in +// locked mode. +inline constexpr char kOnTaskResourceNotSupportedInLockedModeNotificationId[] = + "boca.on_task.resource_not_supported_in_locked_mode_notification"; + // Returns the allowlisted notifications for OnTask in locked mode. base::flat_set<std::string> GetAllowlistedNotificationIdsForLockedMode();
diff --git a/chromeos/ash/components/boca/on_task/on_task_notifications_manager.cc b/chromeos/ash/components/boca/on_task/on_task_notifications_manager.cc index 20456497..d6b98a9 100644 --- a/chromeos/ash/components/boca/on_task/on_task_notifications_manager.cc +++ b/chromeos/ash/components/boca/on_task/on_task_notifications_manager.cc
@@ -19,7 +19,6 @@ #include "chromeos/ash/components/boca/on_task/notification_constants.h" #include "chromeos/ash/components/boca/on_task/on_task_notification_blocker.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/public/cpp/notification_types.h" #include "ui/message_center/public/cpp/notifier_id.h" @@ -227,9 +226,8 @@ // When the countdown finishes, immediately clear the last countdown // notification. ClearNotification(params.id); - } else { - StopProcessingNotification(params.id); } + StopProcessingNotification(params.id); return; }
diff --git a/chromeos/ash/components/boca/on_task/on_task_notifications_manager_unittest.cc b/chromeos/ash/components/boca/on_task/on_task_notifications_manager_unittest.cc index fe0b0f89..fd36bbda 100644 --- a/chromeos/ash/components/boca/on_task/on_task_notifications_manager_unittest.cc +++ b/chromeos/ash/components/boca/on_task/on_task_notifications_manager_unittest.cc
@@ -61,9 +61,7 @@ ++notification_count_; } void ClearNotification(const std::string& id) override { - if (GetNotificationCount() > 0u) { - --notification_count_; - } + notification_count_ = 0; } size_t GetToastCount() { return toast_count_.load(); } @@ -226,14 +224,14 @@ TEST_F(OnTaskNotificationsManagerTest, TriggerCompletionCallbackOnNotificationCountdownEnd) { - bool callback_triggered = false; + int callback_counter = 0; OnTaskNotificationsManager::NotificationCreateParams create_params( /*id=*/kTestNotificationId, /*title=*/std::u16string{kTestNotificationTitle}, /*message_id=*/kTestCountdownNotificationMessageId, /*notifier_id=*/NotifierId(), /*completion_callback=*/base::BindLambdaForTesting([&]() { - callback_triggered = true; + ++callback_counter; }), /*countdown_period=*/kNotificationCountdownPeriod, /*is_counting_down=*/true); @@ -242,16 +240,21 @@ // Verify notification is shown after a 1 second delay. task_environment_.FastForwardBy(kOnTaskNotificationCountdownInterval); ASSERT_EQ(fake_delegate_ptr_->GetNotificationCount(), 1u); - ASSERT_FALSE(callback_triggered); + EXPECT_EQ(callback_counter, 0); // Notifications remain visible before count down. task_environment_.FastForwardBy(kOnTaskNotificationCountdownInterval); ASSERT_EQ(fake_delegate_ptr_->GetNotificationCount(), 2u); - ASSERT_FALSE(callback_triggered); + EXPECT_EQ(callback_counter, 0); // Verify callback is triggered after the countdown period. task_environment_.FastForwardBy(kNotificationCountdownPeriod); - EXPECT_TRUE(callback_triggered); + EXPECT_EQ(callback_counter, 1); + EXPECT_EQ(fake_delegate_ptr_->GetNotificationCount(), 0u); + + // Verify notification stops processing after the callback is triggered. + task_environment_.FastForwardBy(kOnTaskNotificationCountdownInterval); + EXPECT_EQ(callback_counter, 1); } TEST_F(OnTaskNotificationsManagerTest,
diff --git a/chromeos/ash/components/boca/session_api/session_parser.cc b/chromeos/ash/components/boca/session_api/session_parser.cc index 7a31bad..f780764 100644 --- a/chromeos/ash/components/boca/session_api/session_parser.cc +++ b/chromeos/ash/components/boca/session_api/session_parser.cc
@@ -5,6 +5,7 @@ #include "chromeos/ash/components/boca/session_api/session_parser.h" #include "ash/constants/ash_features.h" +#include "base/strings/string_number_conversions.h" #include "chromeos/ash/components/boca/proto/session.pb.h" #include "chromeos/ash/components/boca/session_api/constants.h" #include "google_apis/common/base_requests.h"
diff --git a/chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.cc b/chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.cc new file mode 100644 index 0000000..4a28982 --- /dev/null +++ b/chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.cc
@@ -0,0 +1,28 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.h" + +#include <optional> +#include <string> + +#include "base/functional/callback.h" + +namespace ash::boca { + +FakeSpotlightOAuthTokenFetcher::FakeSpotlightOAuthTokenFetcher( + std::optional<std::string> oauth_token, + std::string robot_email) + : oauth_token_(oauth_token), robot_email_(robot_email) {} + +FakeSpotlightOAuthTokenFetcher::~FakeSpotlightOAuthTokenFetcher() = default; + +void FakeSpotlightOAuthTokenFetcher::Start(OAuthTokenCallback done_callback) { + std::move(done_callback).Run(oauth_token_); +} + +std::string FakeSpotlightOAuthTokenFetcher::GetDeviceRobotEmail() { + return robot_email_; +} +} // namespace ash::boca
diff --git a/chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.h b/chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.h new file mode 100644 index 0000000..6ed25c9 --- /dev/null +++ b/chromeos/ash/components/boca/spotlight/fake_spotlight_oauth_token_fetcher.h
@@ -0,0 +1,32 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_FAKE_SPOTLIGHT_OAUTH_TOKEN_FETCHER_H_ +#define CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_FAKE_SPOTLIGHT_OAUTH_TOKEN_FETCHER_H_ + +#include <optional> +#include <string> + +#include "chromeos/ash/components/boca/spotlight/spotlight_oauth_token_fetcher.h" +namespace ash::boca { + +class FakeSpotlightOAuthTokenFetcher : public SpotlightOAuthTokenFetcher { + public: + explicit FakeSpotlightOAuthTokenFetcher( + std::optional<std::string> oauth_token, + std::string robot_email); + ~FakeSpotlightOAuthTokenFetcher() override; + + void Start(OAuthTokenCallback done_callback) override; + + std::string GetDeviceRobotEmail() override; + + private: + std::optional<std::string> oauth_token_; + std::string robot_email_; +}; + +} // namespace ash::boca + +#endif // CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_FAKE_SPOTLIGHT_OAUTH_TOKEN_FETCHER_H_
diff --git a/chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.cc b/chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.cc new file mode 100644 index 0000000..3268e4c --- /dev/null +++ b/chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.cc
@@ -0,0 +1,37 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.h" + +#include <memory> +#include <utility> + +#include "base/functional/callback.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" + +namespace ash::boca { + +SpotlightFrameConsumer::SpotlightFrameConsumer(FrameReceivedCallback callback) + : callback_(std::move(callback)) {} + +SpotlightFrameConsumer::~SpotlightFrameConsumer() = default; + +std::unique_ptr<webrtc::DesktopFrame> SpotlightFrameConsumer::AllocateFrame( + const webrtc::DesktopSize& size) { + return std::make_unique<webrtc::BasicDesktopFrame>(size); +} +void SpotlightFrameConsumer::DrawFrame( + std::unique_ptr<webrtc::DesktopFrame> frame, + base::OnceClosure done) { + std::move(done).Run(); + + // TODO: dorianbrandon@google.com - Process frame and send to Boca UI. +} + +remoting::protocol::FrameConsumer::PixelFormat +SpotlightFrameConsumer::GetPixelFormat() { + return FORMAT_BGRA; +} + +} // namespace ash::boca
diff --git a/chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.h b/chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.h new file mode 100644 index 0000000..0bb45a8 --- /dev/null +++ b/chromeos/ash/components/boca/spotlight/spotlight_frame_consumer.h
@@ -0,0 +1,44 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_SPOTLIGHT_FRAME_CONSUMER_H_ +#define CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_SPOTLIGHT_FRAME_CONSUMER_H_ + +#include <memory> + +#include "base/functional/callback.h" +#include "remoting/protocol/frame_consumer.h" + +namespace webrtc { +class DesktopFrame; +} + +namespace ash::boca { +// Consumes the frame data from a CRD client session. +class SpotlightFrameConsumer : public remoting::protocol::FrameConsumer { + public: + using FrameReceivedCallback = + base::RepeatingCallback<void(const std::string&)>; + + explicit SpotlightFrameConsumer(FrameReceivedCallback callback); + + SpotlightFrameConsumer(const SpotlightFrameConsumer&) = delete; + SpotlightFrameConsumer& operator=(const SpotlightFrameConsumer&) = delete; + + ~SpotlightFrameConsumer() override; + + // remoting::protocol::FrameConsumer interface. + std::unique_ptr<webrtc::DesktopFrame> AllocateFrame( + const webrtc::DesktopSize& size) override; + void DrawFrame(std::unique_ptr<webrtc::DesktopFrame> frame, + base::OnceClosure done) override; + PixelFormat GetPixelFormat() override; + + private: + FrameReceivedCallback callback_; +}; + +} // namespace ash::boca + +#endif // CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_SPOTLIGHT_FRAME_CONSUMER_H_
diff --git a/chromeos/ash/components/boca/spotlight/spotlight_oauth_token_fetcher.h b/chromeos/ash/components/boca/spotlight/spotlight_oauth_token_fetcher.h new file mode 100644 index 0000000..7ba34d4 --- /dev/null +++ b/chromeos/ash/components/boca/spotlight/spotlight_oauth_token_fetcher.h
@@ -0,0 +1,34 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_SPOTLIGHT_OAUTH_TOKEN_FETCHER_H_ +#define CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_SPOTLIGHT_OAUTH_TOKEN_FETCHER_H_ + +#include <optional> +#include <string> + +#include "base/functional/callback_forward.h" +namespace ash::boca { + +class SpotlightOAuthTokenFetcher { + public: + using OAuthTokenCallback = + base::OnceCallback<void(std::optional<std::string>)>; + + SpotlightOAuthTokenFetcher(const SpotlightOAuthTokenFetcher&) = delete; + SpotlightOAuthTokenFetcher& operator=(const SpotlightOAuthTokenFetcher&) = + delete; + virtual ~SpotlightOAuthTokenFetcher() = default; + + virtual void Start(OAuthTokenCallback done_callback) = 0; + + virtual std::string GetDeviceRobotEmail() = 0; + + protected: + SpotlightOAuthTokenFetcher() = default; +}; + +} // namespace ash::boca + +#endif // CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_SPOTLIGHT_OAUTH_TOKEN_FETCHER_H_
diff --git a/chromeos/ash/components/boca/spotlight/spotlight_service.cc b/chromeos/ash/components/boca/spotlight/spotlight_service.cc index d390905..9458a6a 100644 --- a/chromeos/ash/components/boca/spotlight/spotlight_service.cc +++ b/chromeos/ash/components/boca/spotlight/spotlight_service.cc
@@ -8,6 +8,7 @@ #include <optional> #include <vector> +#include "ash/constants/ash_features.h" #include "base/task/thread_pool.h" #include "chromeos/ash/components/boca/boca_app_client.h" #include "chromeos/ash/components/boca/proto/session.pb.h" @@ -72,9 +73,16 @@ // TODO: crbug.com/386420367 - Support multiple devices. Currently only view // screen from first device in student device, + std::optional<std::string> device_robot_email = + ash::features::IsBocaSpotlightRobotRequesterEnabled() + ? std::optional(BocaAppClient::Get() + ->GetSessionManager() + ->GetDeviceRobotEmail()) + : std::nullopt; ViewScreenParam view_screen_param{ current_session->teacher().gaia_id(), BocaAppClient::Get()->GetDeviceId(), - std::move(student_gaia_id), std::move(student_device_id.value())}; + std::move(device_robot_email), std::move(student_gaia_id), + std::move(student_device_id.value())}; auto view_screen_request = std::make_unique<ViewScreenRequest>( sender_.get(), current_session->session_id(), std::move(view_screen_param), std::move(url_base), std::move(callback));
diff --git a/chromeos/ash/components/boca/spotlight/spotlight_service_unittest.cc b/chromeos/ash/components/boca/spotlight/spotlight_service_unittest.cc index d74b940..e61985f 100644 --- a/chromeos/ash/components/boca/spotlight/spotlight_service_unittest.cc +++ b/chromeos/ash/components/boca/spotlight/spotlight_service_unittest.cc
@@ -4,12 +4,17 @@ #include "chromeos/ash/components/boca/spotlight/spotlight_service.h" +#include <memory> + +#include "ash/constants/ash_features.h" +#include "base/test/scoped_feature_list.h" #include "base/test/test_future.h" #include "chromeos/ash/components/boca/boca_app_client.h" #include "chromeos/ash/components/boca/proto/session.pb.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_environment.h" #include "content/public/test/browser_task_environment.h" +#include "fake_spotlight_oauth_token_fetcher.h" #include "google_apis/common/dummy_auth_service.h" #include "google_apis/common/request_sender.h" #include "google_apis/gaia/gaia_id.h" @@ -17,6 +22,7 @@ #include "net/test/embedded_test_server/http_request.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/test/test_shared_url_loader_factory.h" +#include "spotlight_oauth_token_fetcher.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -93,6 +99,8 @@ AccountId::FromUserEmailGaiaId(kUserEmail, GaiaId(kGaiaId)), /*=is_producer*/ false) {} MOCK_METHOD((::boca::Session*), GetCurrentSession, (), (override)); + // MOCK_METHOD(SetSpotlightTokenFetcher, (SpotlightOAuthTokenFetcher + // fetcher), (override)); ~MockSessionManager() override = default; }; @@ -101,6 +109,9 @@ public: SpotlightServiceTest() = default; void SetUp() override { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{ash::features::kBoca}, + /*disabled_features=*/{ash::features::kBocaSpotlightRobotRequester}); ON_CALL(boca_app_client_, GetIdentityManager()) .WillByDefault(Return(identity_test_env_.identity_manager())); @@ -128,6 +139,7 @@ content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME, base::test::TaskEnvironment::MainThreadType::IO}; + base::test::ScopedFeatureList scoped_feature_list_; scoped_refptr<network::TestSharedURLLoaderFactory> test_shared_loader_factory_ = base::MakeRefCounted<network::TestSharedURLLoaderFactory>( @@ -169,6 +181,46 @@ EXPECT_TRUE(result.value()); } +TEST_F(SpotlightServiceTest, TestViewScreenSucceedWithRobotEmail) { + scoped_feature_list_.Reset(); + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{ash::features::kBoca, + ash::features::kBocaSpotlightRobotRequester}, + /*disabled_features=*/{}); + std::unique_ptr<FakeSpotlightOAuthTokenFetcher> fake_token_fetcher = + std::make_unique<FakeSpotlightOAuthTokenFetcher>("token", + "robot@email.com"); + boca_session_manager_->set_spotlight_token_fetcher(fake_token_fetcher.get()); + auto session = GetCommonTestSession(); + EXPECT_CALL(*boca_session_manager_, GetCurrentSession()) + .WillOnce(Return(&session)); + base::test::TestFuture<base::expected<bool, google_apis::ApiErrorCode>> + future; + + net::test_server::HttpRequest http_request; + EXPECT_CALL(request_handler_, HandleRequest(_)) + .WillOnce(DoAll(SaveArg<0>(&http_request), + Return(MockRequestHandler::CreateSuccessfulResponse()))); + spotlight_service_.ViewScreen(kStudentId, test_server_.base_url().spec(), + future.GetCallback()); + auto result = future.Get(); + EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); + + EXPECT_EQ("/v1/sessions/session_id/viewScreen:initiate", + http_request.relative_url); + EXPECT_EQ("application/json", http_request.headers["Content-Type"]); + auto* contentData = + "{\"hostDevice\":{\"deviceInfo\":{\"deviceId\":\"device1\"},\"user\":{" + "\"gaiaId\":\"student\"}},\"teacherClientDevice\":{\"deviceInfo\":{" + "\"deviceId\":\"device0\"},\"serviceAccount\":{" + "\"email\":\"robot@email.com\"},\"user\":{\"gaiaId\":\"123\"}}}"; + ASSERT_TRUE(http_request.has_content); + EXPECT_EQ(contentData, http_request.content); + EXPECT_TRUE(result.value()); + + boca_session_manager_->set_spotlight_token_fetcher(nullptr); +} + TEST_F(SpotlightServiceTest, TestViewScreenWithEmptySession) { EXPECT_CALL(*boca_session_manager_, GetCurrentSession()) .WillOnce(Return(nullptr));
diff --git a/chromeos/ash/components/boca/spotlight/view_screen_request.cc b/chromeos/ash/components/boca/spotlight/view_screen_request.cc index 86dccac..05767c1b 100644 --- a/chromeos/ash/components/boca/spotlight/view_screen_request.cc +++ b/chromeos/ash/components/boca/spotlight/view_screen_request.cc
@@ -8,6 +8,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <optional> #include <string> #include "base/json/json_writer.h" @@ -27,17 +28,21 @@ } } // namespace -ViewScreenParam::ViewScreenParam(std::string teacher_gaia_id_param, - std::string teacher_device_id_param, - std::string student_gaia_id_param, - std::string student_device_id_param) +ViewScreenParam::ViewScreenParam( + std::string teacher_gaia_id_param, + std::string teacher_device_id_param, + std::optional<std::string> teacher_device_robot_id_param, + std::string student_gaia_id_param, + std::string student_device_id_param) : teacher_gaia_id(teacher_gaia_id_param), teacher_device_id(teacher_device_id_param), + teacher_device_robot_id(teacher_device_robot_id_param), student_gaia_id(student_gaia_id_param), student_device_id(student_device_id_param) {} ViewScreenParam::ViewScreenParam(ViewScreenParam&& param) : teacher_gaia_id(std::move(param.teacher_gaia_id)), teacher_device_id(std::move(param.teacher_device_id)), + teacher_device_robot_id(std::move(param.teacher_device_robot_id)), student_gaia_id(std::move(param.student_gaia_id)), student_device_id(std::move(param.student_device_id)) {} ViewScreenParam& ViewScreenParam::ViewScreenParam::operator=( @@ -93,6 +98,13 @@ teacher_device.Set(kDeviceId, view_screen_param_.teacher_device_id); teacher_info.Set(kDeviceInfo, std::move(teacher_device)); + if (view_screen_param_.teacher_device_robot_id.has_value()) { + base::Value::Dict teacher_service_account; + teacher_service_account.Set( + kEmail, view_screen_param_.teacher_device_robot_id.value()); + teacher_info.Set(kServiceAccount, std::move(teacher_service_account)); + } + root.Set(kTeacherClientDevice, std::move(teacher_info)); base::Value::Dict host_device_info;
diff --git a/chromeos/ash/components/boca/spotlight/view_screen_request.h b/chromeos/ash/components/boca/spotlight/view_screen_request.h index dfad8b6..62ba55ca 100644 --- a/chromeos/ash/components/boca/spotlight/view_screen_request.h +++ b/chromeos/ash/components/boca/spotlight/view_screen_request.h
@@ -6,6 +6,7 @@ #define CHROMEOS_ASH_COMPONENTS_BOCA_SPOTLIGHT_VIEW_SCREEN_REQUEST_H_ #include <memory> +#include <optional> #include <string> #include "base/types/expected.h" @@ -21,10 +22,12 @@ struct ViewScreenParam { std::string teacher_gaia_id; std::string teacher_device_id; + std::optional<std::string> teacher_device_robot_id; std::string student_gaia_id; std::string student_device_id; ViewScreenParam(std::string teacher_gaia_id_param, std::string teacher_device_id_param, + std::optional<std::string> teacher_device_robot_id_param, std::string student_gaia_id_param, std::string student_device_id_param); ViewScreenParam(ViewScreenParam&&);
diff --git a/chromeos/ash/components/boca/spotlight/view_screen_request_unittest.cc b/chromeos/ash/components/boca/spotlight/view_screen_request_unittest.cc index 05d2e704..ea09a60 100644 --- a/chromeos/ash/components/boca/spotlight/view_screen_request_unittest.cc +++ b/chromeos/ash/components/boca/spotlight/view_screen_request_unittest.cc
@@ -5,6 +5,7 @@ #include "chromeos/ash/components/boca/spotlight/view_screen_request.h" #include <memory> +#include <optional> #include "base/functional/bind.h" #include "base/test/task_environment.h" @@ -113,10 +114,45 @@ future; std::unique_ptr<ViewScreenRequest> request = - std::make_unique<ViewScreenRequest>(request_sender(), - std::move(session_id), - ViewScreenParam("1", "d1", "2", "d2"), - "https://test", future.GetCallback()); + std::make_unique<ViewScreenRequest>( + request_sender(), std::move(session_id), + ViewScreenParam("1", "d1", "robot@email.com", "2", "d2"), + "https://test", future.GetCallback()); + + request->OverrideURLForTesting(test_server_.base_url().spec()); + request_sender()->StartRequestWithAuthRetry(std::move(request)); + + ASSERT_TRUE(future.Wait()); + auto result = future.Get(); + EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); + + EXPECT_EQ("/v1/sessions/session_id/viewScreen:initiate", + http_request.relative_url); + EXPECT_EQ("application/json", http_request.headers["Content-Type"]); + auto* contentData = + "{\"hostDevice\":{\"deviceInfo\":{\"deviceId\":\"d2\"},\"user\":{" + "\"gaiaId\":\"2\"}},\"teacherClientDevice\":{\"deviceInfo\":{" + "\"deviceId\":\"d1\"},\"serviceAccount\":{" + "\"email\":\"robot@email.com\"},\"user\":{\"gaiaId\":\"1\"}}}"; + ASSERT_TRUE(http_request.has_content); + EXPECT_EQ(contentData, http_request.content); + EXPECT_EQ(true, result.value()); +} + +TEST_F(ViewScreenRequestTest, InitViewScreenRequestSucceedWithoutRobotId) { + net::test_server::HttpRequest http_request; + EXPECT_CALL(request_handler(), HandleRequest(_)) + .WillOnce(DoAll(SaveArg<0>(&http_request), + Return(MockRequestHandler::CreateSuccessfulResponse()))); + std::string session_id = "session_id"; + base::test::TestFuture<base::expected<bool, google_apis::ApiErrorCode>> + future; + + std::unique_ptr<ViewScreenRequest> request = + std::make_unique<ViewScreenRequest>( + request_sender(), std::move(session_id), + ViewScreenParam("1", "d1", std::nullopt, "2", "d2"), "https://test", + future.GetCallback()); request->OverrideURLForTesting(test_server_.base_url().spec()); request_sender()->StartRequestWithAuthRetry(std::move(request)); @@ -147,10 +183,10 @@ future; std::unique_ptr<ViewScreenRequest> request = - std::make_unique<ViewScreenRequest>(request_sender(), - std::move(session_id), - ViewScreenParam("1", "d1", "2", "d2"), - "https://test", future.GetCallback()); + std::make_unique<ViewScreenRequest>( + request_sender(), std::move(session_id), + ViewScreenParam("1", "d1", std::nullopt, "2", "d2"), "https://test", + future.GetCallback()); request->OverrideURLForTesting(test_server_.base_url().spec());
diff --git a/chromeos/ash/components/camera_presence_notifier/camera_presence_notifier_unittest.cc b/chromeos/ash/components/camera_presence_notifier/camera_presence_notifier_unittest.cc index 194053f1..15e3ad5 100644 --- a/chromeos/ash/components/camera_presence_notifier/camera_presence_notifier_unittest.cc +++ b/chromeos/ash/components/camera_presence_notifier/camera_presence_notifier_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/capture_mode/fake_video_source_provider.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/gmock_callback_support.h" #include "content/public/browser/video_capture_service.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chromeos/ash/components/dbus/typecd/fake_typecd_client.cc b/chromeos/ash/components/dbus/typecd/fake_typecd_client.cc index bbef18b..30183f8 100644 --- a/chromeos/ash/components/dbus/typecd/fake_typecd_client.cc +++ b/chromeos/ash/components/dbus/typecd/fake_typecd_client.cc
@@ -19,6 +19,10 @@ NotifyOnCableWarning(type); } +void FakeTypecdClient::EmitUsbLimitSignal(typecd::UsbLimitType type) { + NotifyOnUsbLimit(type); +} + void FakeTypecdClient::SetPeripheralDataAccessPermissionState(bool permitted) { }
diff --git a/chromeos/ash/components/dbus/typecd/fake_typecd_client.h b/chromeos/ash/components/dbus/typecd/fake_typecd_client.h index 20e5c78..156c66f 100644 --- a/chromeos/ash/components/dbus/typecd/fake_typecd_client.h +++ b/chromeos/ash/components/dbus/typecd/fake_typecd_client.h
@@ -22,6 +22,7 @@ // signal. void EmitThunderboltDeviceConnectedSignal(bool is_thunderbolt_only); void EmitCableWarningSignal(typecd::CableWarningType type); + void EmitUsbLimitSignal(typecd::UsbLimitType type); // TypecdClient: void SetPeripheralDataAccessPermissionState(bool permitted) override;
diff --git a/chromeos/ash/components/dbus/typecd/typecd_client.cc b/chromeos/ash/components/dbus/typecd/typecd_client.cc index b96a9ad..ca3fd5b 100644 --- a/chromeos/ash/components/dbus/typecd/typecd_client.cc +++ b/chromeos/ash/components/dbus/typecd/typecd_client.cc
@@ -37,6 +37,7 @@ private: void ThunderboltDeviceConnectedReceived(dbus::Signal* signal); void CableWarningReceived(dbus::Signal* signal); + void UsbLimitReceived(dbus::Signal* signal); void OnSignalConnected(const std::string& interface_name, const std::string& signal_name, bool success); @@ -55,7 +56,8 @@ const std::pair<const char*, SignalMethod> kSignalMethods[] = { {typecd::kTypecdDeviceConnected, &TypecdClientImpl::ThunderboltDeviceConnectedReceived}, - {typecd::kTypecdCableWarning, &TypecdClientImpl::CableWarningReceived}}; + {typecd::kTypecdCableWarning, &TypecdClientImpl::CableWarningReceived}, + {typecd::kTypecdUsbLimit, &TypecdClientImpl::UsbLimitReceived}}; auto on_connected_callback = base::BindRepeating( &TypecdClientImpl::OnSignalConnected, weak_ptr_factory_.GetWeakPtr()); @@ -100,6 +102,21 @@ NotifyOnCableWarning(cable_warning_type); } +void TypecdClientImpl::UsbLimitReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + uint32_t usb_limit_signal = 0u; + if (!reader.PopUint32(&usb_limit_signal)) { + LOG(ERROR) << "Typecd: Unable to decode USB limit type from" + << typecd::kTypecdUsbLimit << " signal."; + return; + } + typecd::UsbLimitType usb_limit_type = + static_cast<typecd::UsbLimitType>(usb_limit_signal); + VLOG(1) << "Typecd: Received USB limit signal with " + << "UsbLimitType: " << usb_limit_signal; + NotifyOnUsbLimit(usb_limit_type); +} + void TypecdClientImpl::OnSignalConnected(const std::string& interface_name, const std::string& signal_name, bool success) { @@ -155,6 +172,12 @@ observer.OnCableWarning(cable_warning_type); } +void TypecdClient::NotifyOnUsbLimit(typecd::UsbLimitType usb_limit_type) { + for (auto& observer : observer_list_) { + observer.OnUsbLimit(usb_limit_type); + } +} + TypecdClient::TypecdClient() { CHECK(!g_instance); g_instance = this;
diff --git a/chromeos/ash/components/dbus/typecd/typecd_client.h b/chromeos/ash/components/dbus/typecd/typecd_client.h index ac356e9..2f17e0b 100644 --- a/chromeos/ash/components/dbus/typecd/typecd_client.h +++ b/chromeos/ash/components/dbus/typecd/typecd_client.h
@@ -27,6 +27,7 @@ virtual void OnThunderboltDeviceConnected(bool is_thunderbolt_only) = 0; virtual void OnCableWarning( typecd::CableWarningType cable_warning_type) = 0; + virtual void OnUsbLimit(typecd::UsbLimitType usb_limit_type) = 0; }; void AddObserver(Observer* observer); @@ -61,6 +62,7 @@ void NotifyOnThunderboltDeviceConnected(bool is_thunderbolt_only); void NotifyOnCableWarning(typecd::CableWarningType cable_warning_type); + void NotifyOnUsbLimit(typecd::UsbLimitType usb_limit_type); private: base::ObserverList<Observer> observer_list_;
diff --git a/chromeos/ash/components/fwupd/firmware_update_manager.cc b/chromeos/ash/components/fwupd/firmware_update_manager.cc index e7868e6..c69f0d0 100644 --- a/chromeos/ash/components/fwupd/firmware_update_manager.cc +++ b/chromeos/ash/components/fwupd/firmware_update_manager.cc
@@ -23,6 +23,7 @@ #include "base/files/scoped_file.h" #include "base/json/json_reader.h" #include "base/path_service.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h"
diff --git a/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc b/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc index 0c222ae1..d276e71 100644 --- a/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc +++ b/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc
@@ -20,6 +20,7 @@ #include "base/memory/raw_ptr.h" #include "base/path_service.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h"
diff --git a/chromeos/ash/components/growth/campaigns_matcher.cc b/chromeos/ash/components/growth/campaigns_matcher.cc index 6be7ce0..dd9092b 100644 --- a/chromeos/ash/components/growth/campaigns_matcher.cc +++ b/chromeos/ash/components/growth/campaigns_matcher.cc
@@ -17,6 +17,7 @@ #include "base/feature_list.h" #include "base/features.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/system/sys_info.h" #include "base/time/time.h"
diff --git a/chromeos/ash/components/hid_detection/bluetooth_hid_detector_impl_unittest.cc b/chromeos/ash/components/hid_detection/bluetooth_hid_detector_impl_unittest.cc index 9cbaff8a..266f6170 100644 --- a/chromeos/ash/components/hid_detection/bluetooth_hid_detector_impl_unittest.cc +++ b/chromeos/ash/components/hid_detection/bluetooth_hid_detector_impl_unittest.cc
@@ -7,6 +7,7 @@ #include "ash/constants/ash_features.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h"
diff --git a/chromeos/ash/components/network/hotspot_configuration_handler_unittest.cc b/chromeos/ash/components/network/hotspot_configuration_handler_unittest.cc index f5131b5..1f671ae 100644 --- a/chromeos/ash/components/network/hotspot_configuration_handler_unittest.cc +++ b/chromeos/ash/components/network/hotspot_configuration_handler_unittest.cc
@@ -4,6 +4,7 @@ #include "chromeos/ash/components/network/hotspot_configuration_handler.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h"
diff --git a/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.cc b/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.cc index 5d8b509..5e3d434 100644 --- a/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.cc +++ b/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.cc
@@ -187,6 +187,22 @@ observer.OnSpeedLimitingCableWarning(); } +void PeripheralNotificationManager::OnUsbLimit( + typecd::UsbLimitType usb_limit_type) { + if (usb_limit_type == typecd::UsbLimitType::kDeviceLimit || + usb_limit_type == typecd::UsbLimitType::kEndpointLimit) { + NotifyUsbDeviceOrEndpointLimit(); + RecordConnectivityMetric( + PeripheralConnectivityResults::kUsbDeviceOrEndpointLimit); + } +} + +void PeripheralNotificationManager::NotifyUsbDeviceOrEndpointLimit() { + for (auto& observer : observer_list_) { + observer.OnUsbDeviceOrEndpointLimit(); + } +} + void PeripheralNotificationManager::OnDeviceConnected( device::mojom::UsbDeviceInfo* device) { if (device->class_code == kBillboardDeviceClassCode) {
diff --git a/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h b/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h index bc3a6338..f305a99 100644 --- a/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h +++ b/chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h
@@ -80,6 +80,10 @@ // 40 Gbps data transmission because of the cable. Transmissions speeds will // decrease to 20 Gbps, 10 Gbps or 5 Gbps. virtual void OnSpeedLimitingCableWarning() = 0; + + // Called to notify the user when their device has reached a USB device or + // endpoint limit, and any more connected USB devices may not work. + virtual void OnUsbDeviceOrEndpointLimit() = 0; }; // These values are persisted to logs. Entries should not be renumbered and @@ -97,7 +101,8 @@ kInvalidUSB4Cable = 9, kInvalidTBTCable = 10, kSpeedLimitingCable = 11, - kMaxValue = kSpeedLimitingCable, + kUsbDeviceOrEndpointLimit = 12, + kMaxValue = kUsbDeviceOrEndpointLimit, }; // Sets the global instance. Must be called before any calls to Get(). @@ -132,6 +137,7 @@ // TypecdClient::Observer: void OnThunderboltDeviceConnected(bool is_thunderbolt_only) override; void OnCableWarning(typecd::CableWarningType cable_warning_type) override; + void OnUsbLimit(typecd::UsbLimitType usb_limit_type) override; // PciguardClient::Observer: void OnBlockedThunderboltDeviceConnected( @@ -147,6 +153,7 @@ void NotifyInvalidUSB4CableWarning(); void NotifyInvalidTBTCableWarning(); void NotifySpeedLimitingCableWarning(); + void NotifyUsbDeviceOrEndpointLimit(); // Called by unit tests to set up root_prefix_ for simulating the existence // of a system folder.
diff --git a/chromeos/ash/components/peripheral_notification/peripheral_notification_manager_unittest.cc b/chromeos/ash/components/peripheral_notification/peripheral_notification_manager_unittest.cc index 9ce1da6..4be96bd 100644 --- a/chromeos/ash/components/peripheral_notification/peripheral_notification_manager_unittest.cc +++ b/chromeos/ash/components/peripheral_notification/peripheral_notification_manager_unittest.cc
@@ -75,6 +75,10 @@ return num_speed_limiting_cable_notification_calls_; } + size_t num_usb_device_or_endpoint_limit_notification_calls() const { + return num_usb_device_or_endpoint_limit_notification_calls_; + } + bool is_current_guest_device_tbt_only() const { return is_current_guest_device_tbt_only_; } @@ -117,6 +121,10 @@ ++num_speed_limiting_cable_notification_calls_; } + void OnUsbDeviceOrEndpointLimit() override { + ++num_usb_device_or_endpoint_limit_notification_calls_; + } + private: size_t num_limited_performance_notification_calls_ = 0u; size_t num_guest_notification_calls_ = 0u; @@ -127,6 +135,7 @@ size_t num_invalid_usb4_cable_notification_calls_ = 0u; size_t num_invalid_tbt_cable_notification_calls_ = 0u; size_t num_speed_limiting_cable_notification_calls_ = 0u; + size_t num_usb_device_or_endpoint_limit_notification_calls_ = 0u; bool is_current_guest_device_tbt_only_ = false; }; @@ -209,6 +218,10 @@ return fake_observer_.num_speed_limiting_cable_notification_calls(); } + size_t GetUsbDeviceOrEndpointLimitNotificationObserverCalls() { + return fake_observer_.num_usb_device_or_endpoint_limit_notification_calls(); + } + bool GetIsCurrentGuestDeviceTbtOnly() { return fake_observer_.is_current_guest_device_tbt_only(); } @@ -607,4 +620,44 @@ 1); } +TEST_F(PeripheralNotificationManagerTest, UsbDeviceLimitWarning) { + InitializeManager(/*is_guest_profile=*/false, + /*is_pcie_tunneling_allowed=*/false); + EXPECT_EQ(0u, GetUsbDeviceOrEndpointLimitNotificationObserverCalls()); + histogram_tester_.ExpectBucketCount( + "Ash.Peripheral.ConnectivityResults", + PeripheralNotificationManager::PeripheralConnectivityResults:: + kUsbDeviceOrEndpointLimit, + 0); + + typecd::UsbLimitType usb_limit_type = typecd::UsbLimitType::kDeviceLimit; + fake_typecd_client()->EmitUsbLimitSignal(usb_limit_type); + EXPECT_EQ(1u, GetUsbDeviceOrEndpointLimitNotificationObserverCalls()); + histogram_tester_.ExpectBucketCount( + "Ash.Peripheral.ConnectivityResults", + PeripheralNotificationManager::PeripheralConnectivityResults:: + kUsbDeviceOrEndpointLimit, + 1); +} + +TEST_F(PeripheralNotificationManagerTest, UsbEndpointLimitWarning) { + InitializeManager(/*is_guest_profile=*/false, + /*is_pcie_tunneling_allowed=*/false); + EXPECT_EQ(0u, GetUsbDeviceOrEndpointLimitNotificationObserverCalls()); + histogram_tester_.ExpectBucketCount( + "Ash.Peripheral.ConnectivityResults", + PeripheralNotificationManager::PeripheralConnectivityResults:: + kUsbDeviceOrEndpointLimit, + 0); + + typecd::UsbLimitType usb_limit_type = typecd::UsbLimitType::kEndpointLimit; + fake_typecd_client()->EmitUsbLimitSignal(usb_limit_type); + EXPECT_EQ(1u, GetUsbDeviceOrEndpointLimitNotificationObserverCalls()); + histogram_tester_.ExpectBucketCount( + "Ash.Peripheral.ConnectivityResults", + PeripheralNotificationManager::PeripheralConnectivityResults:: + kUsbDeviceOrEndpointLimit, + 1); +} + } // namespace ash
diff --git a/chromeos/ash/components/phonehub/phone_status_processor.cc b/chromeos/ash/components/phonehub/phone_status_processor.cc index a00a80478..1d1c564 100644 --- a/chromeos/ash/components/phonehub/phone_status_processor.cc +++ b/chromeos/ash/components/phonehub/phone_status_processor.cc
@@ -12,6 +12,7 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "base/containers/flat_set.h" #include "base/metrics/histogram_functions.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/ash/components/multidevice/logging/logging.h" #include "chromeos/ash/components/phonehub/app_stream_manager.h"
diff --git a/chromeos/ash/components/quick_start/quick_start_requests.cc b/chromeos/ash/components/quick_start/quick_start_requests.cc index 86eb5a2..0922100 100644 --- a/chromeos/ash/components/quick_start/quick_start_requests.cc +++ b/chromeos/ash/components/quick_start/quick_start_requests.cc
@@ -5,6 +5,7 @@ #include "chromeos/ash/components/quick_start/quick_start_requests.h" #include "base/base64.h" +#include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chromeos/ash/components/quick_start/quick_start_message.h" #include "chromeos/ash/components/quick_start/quick_start_message_type.h"
diff --git a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc index fc621e444..88ea104 100644 --- a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc +++ b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc
@@ -33,6 +33,7 @@ #include "base/posix/safe_strerror.h" #include "base/process/process_metrics.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/task/current_thread.h"
diff --git a/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl.cc b/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl.cc index ff707e8..989385a 100644 --- a/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl.cc +++ b/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl.cc
@@ -4,6 +4,7 @@ #include "chromeos/ash/services/bluetooth_config/device_pairing_handler_impl.h" +#include "base/strings/string_number_conversions.h" #include "base/task/single_thread_task_runner.h" #include "chromeos/ash/services/bluetooth_config/device_conversion_util.h" #include "components/device_event_log/device_event_log.h"
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 900406e..c73e0f8 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -7192,6 +7192,9 @@ <message name="IDS_ON_TASK_BUNDLE_CONTENT_REMOVED_MESSAGE" desc="Notification message telling students that their teacher has removed content from the bundle."> Your teacher has removed content in Class Tools </message> + <message name="IDS_ON_TASK_CANNOT_OPEN_UNSUPPORTED_RESOURCES_IN_LOCKED_MODE_MESSAGE" desc="Notification message telling students that the provided resource is unsupported in locked mode. Let the students tell the teacher the issue."> + Your teacher has sent an unsupported resource. Let them know. + </message> <!-- Strings for the OnTask pod --> <message name="IDS_ON_TASK_POD_ACCESSIBLE_NAME" desc="Accessible name for the OnTask pod widget."> @@ -7251,6 +7254,14 @@ <message name="IDS_BOCA_SPOTLIGHT_PERSISTENT_NOTIFICATION_MESSAGE" desc="Message of the notiification telling users their screen is currently being viewed."> <ph name="TEACHER_NAME">$1<ex>John Doe</ex></ph> is viewing your screen </message> + + <!-- Strings for Class Tools caption bubble --> + <message name="IDS_BOCA_CAPTIONS_TRANSLATION_AVAILABLE_BUTTON_TEXT" desc="Text for the button to start captions translation."> + Translation available + </message> + <message name="IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT" desc="Text for the button to stop captions translation."> + Stop translating + </message> </messages> </release> </grit>
diff --git a/chromeos/chromeos_strings_grd/IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT.png.sha1 new file mode 100644 index 0000000..ffd948fec --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_BOCA_CAPTIONS_STOP_TRANSLATING_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@ +ed21d67d5a15ed52f349ed7b979ecf4d0d26cab9 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_BOCA_CAPTIONS_TRANSLATION_AVAILABLE_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_BOCA_CAPTIONS_TRANSLATION_AVAILABLE_BUTTON_TEXT.png.sha1 new file mode 100644 index 0000000..a250322 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_BOCA_CAPTIONS_TRANSLATION_AVAILABLE_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@ +2d5e58ab12afbddecc87c1ca687fc423d6b67fcb \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_ON_TASK_CANNOT_OPEN_UNSUPPORTED_RESOURCES_IN_LOCKED_MODE_MESSAGE.png.sha1 b/chromeos/chromeos_strings_grd/IDS_ON_TASK_CANNOT_OPEN_UNSUPPORTED_RESOURCES_IN_LOCKED_MODE_MESSAGE.png.sha1 new file mode 100644 index 0000000..35c795d8 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_ON_TASK_CANNOT_OPEN_UNSUPPORTED_RESOURCES_IN_LOCKED_MODE_MESSAGE.png.sha1
@@ -0,0 +1 @@ +f9ca83a13f24277305ec02dde54e142587812171 \ No newline at end of file
diff --git a/clank b/clank index 180ea8e..cb55e66 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 180ea8ed2b2e73fb52d4201a021d0acd2801c05b +Subproject commit cb55e66137f2601c1670d7fbd8f98d4c252d12e2
diff --git a/components/browser_ui/widget/android/java/res/values/dimens.xml b/components/browser_ui/widget/android/java/res/values/dimens.xml index 00be49f..f93a132 100644 --- a/components/browser_ui/widget/android/java/res/values/dimens.xml +++ b/components/browser_ui/widget/android/java/res/values/dimens.xml
@@ -20,6 +20,7 @@ <dimen name="focused_icon_background_stroke_width">2dp</dimen> <dimen name="cpa_button_background_radius_is_checked">12dp</dimen> <dimen name="toolbar_progress_bar_height">2dp</dimen> + <dimen name="toolbar_progress_bar_increased_height">4dp</dimen> <!-- DualControlLayout --> <dimen name="dual_control_margin_between_items">8dp</dimen>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ClipDrawableProgressBar.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ClipDrawableProgressBar.java index 54d2a75..771bc25 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ClipDrawableProgressBar.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ClipDrawableProgressBar.java
@@ -58,7 +58,7 @@ @Nullable private GradientDrawable mEndCapCircleDrawable; private int mForegroundColor; private int mBackgroundColor; - protected int mProgressBarHeight; + protected final int mProgressBarHeight; private float mProgress; private int mDesiredVisibility; @@ -78,8 +78,13 @@ mForegroundColor = SemanticColorUtils.getProgressBarForeground(getContext()); mBackgroundColor = getContext().getColor(R.color.progress_bar_bg_color_list); - mProgressBarHeight = getResources().getDimensionPixelSize( - R.dimen.toolbar_progress_bar_height); + if (useGradientDrawable()) { + mProgressBarHeight = getResources().getDimensionPixelSize( + R.dimen.toolbar_progress_bar_increased_height); + } else { + mProgressBarHeight = getResources().getDimensionPixelSize( + R.dimen.toolbar_progress_bar_height); + } initializeDrawables(); setBackgroundColor(mBackgroundColor); }
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc index 3611db0..a34f386 100644 --- a/components/lens/lens_features.cc +++ b/components/lens/lens_features.cc
@@ -481,6 +481,11 @@ constexpr base::FeatureParam<bool> kLensOverlayVisualSelectionUpdatesEnableGradientRegionStroke{ &kLensOverlayVisualSelectionUpdates, "enable-gradient-region-stroke", + false}; + +constexpr base::FeatureParam<bool> + kLensOverlayVisualSelectionUpdatesEnableWhiteRegionStroke{ + &kLensOverlayVisualSelectionUpdates, "enable-white-region-stroke", true}; constexpr base::FeatureParam<bool> @@ -1046,6 +1051,11 @@ kLensOverlayVisualSelectionUpdatesEnableGradientRegionStroke.Get(); } +bool GetVisualSelectionUpdatesEnableWhiteRegionStroke() { + return base::FeatureList::IsEnabled(kLensOverlayVisualSelectionUpdates) && + kLensOverlayVisualSelectionUpdatesEnableWhiteRegionStroke.Get(); +} + bool GetVisualSelectionUpdatesEnableRegionSelectedGlow() { return base::FeatureList::IsEnabled(kLensOverlayVisualSelectionUpdates) && kLensOverlayVisualSelectionUpdatesEnableRegionSelectedGlow.Get();
diff --git a/components/lens/lens_features.h b/components/lens/lens_features.h index ba53b96..8c2b891 100644 --- a/components/lens/lens_features.h +++ b/components/lens/lens_features.h
@@ -773,6 +773,13 @@ COMPONENT_EXPORT(LENS_FEATURES) extern bool GetVisualSelectionUpdatesEnableGradientRegionStroke(); +// Whether to enable the white region stroke for the visual selection updates. +// Note: `GetVisualSelectionUpdatesEnableGradientRegionStroke` takes precedence +// over this flag. This flag will have no effect if the gradient region stroke +// is enabled. +COMPONENT_EXPORT(LENS_FEATURES) +extern bool GetVisualSelectionUpdatesEnableWhiteRegionStroke(); + // Whether to enable the region selected glow for the visual selection updates. COMPONENT_EXPORT(LENS_FEATURES) extern bool GetVisualSelectionUpdatesEnableRegionSelectedGlow();
diff --git a/components/live_caption/views/caption_bubble.cc b/components/live_caption/views/caption_bubble.cc index 18331587..306d8b4 100644 --- a/components/live_caption/views/caption_bubble.cc +++ b/components/live_caption/views/caption_bubble.cc
@@ -65,6 +65,7 @@ #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/controls/menu/menu_runner.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/styled_label.h" #include "ui/views/event_monitor.h" #include "ui/views/layout/box_layout.h" @@ -136,8 +137,9 @@ SkColor* sk_color, const ui::ColorProvider* color_provider) { std::string rgba = MaybeRemoveCSSImportant(css_string); - if (rgba.empty()) + if (rgba.empty()) { return false; + } uint16_t r, g, b; double a; bool match = RE2::FullMatch( @@ -145,8 +147,9 @@ &b, &a); // If the opacity is set to 0 (fully transparent), we ignore the user's // preferred style and use our default color. - if (!match || a == 0) + if (!match || a == 0) { return false; + } uint16_t a_int = base::ClampRound<uint16_t>(a * 255); #if BUILDFLAG(IS_MAC) // On Mac, any opacity lower than 90% leaves rendering artifacts which make @@ -166,8 +169,8 @@ // Helper class for observing mouse and key events from native window. class CaptionBubbleEventObserver : public ui::EventObserver { public: - explicit CaptionBubbleEventObserver(captions::CaptionBubble* caption_bubble, - views::Widget* widget) + CaptionBubbleEventObserver(captions::CaptionBubble* caption_bubble, + views::Widget* widget) : caption_bubble_(caption_bubble) { CHECK(widget); event_monitor_ = views::EventMonitor::CreateWindowMonitor( @@ -249,10 +252,12 @@ METADATA_HEADER(CaptionBubbleFrameView, views::BubbleFrameView) public: - explicit CaptionBubbleFrameView( - std::vector<raw_ptr<views::View, VectorExperimental>> buttons) + CaptionBubbleFrameView( + std::vector<raw_ptr<views::View, VectorExperimental>> buttons, + raw_ptr<views::View> scrollable) : views::BubbleFrameView(gfx::Insets(), gfx::Insets()), - buttons_(buttons) { + buttons_(buttons), + scrollable_(scrollable) { auto border = std::make_unique<views::BubbleBorder>( views::BubbleBorder::FLOAT, views::BubbleBorder::DIALOG_SHADOW); border->set_rounded_corners(gfx::RoundedCornersF(kCornerRadiusDip)); @@ -268,8 +273,9 @@ // for more about why it doesn't work. int NonClientHitTest(const gfx::Point& point) override { // Outside of the window bounds, do nothing. - if (!bounds().Contains(point)) + if (!bounds().Contains(point)) { return HTNOWHERE; + } // |point| is in coordinates relative to CaptionBubbleFrameView, i.e. // (0,0) is the upper left corner of this view. Convert it to screen @@ -279,8 +285,14 @@ gfx::Point point_in_screen = GetBoundsInScreen().origin() + gfx::Vector2d(point.x(), point.y()); for (views::View* button : buttons_) { - if (button->GetBoundsInScreen().Contains(point_in_screen)) + if (button->GetBoundsInScreen().Contains(point_in_screen)) { return HTCLIENT; + } + } + + if (scrollable_ && + scrollable_->GetBoundsInScreen().Contains(point_in_screen)) { + return HTCLIENT; } // Ensure it's within the BubbleFrameView. This takes into account the @@ -296,7 +308,8 @@ } private: - std::vector<raw_ptr<views::View, VectorExperimental>> buttons_; + const std::vector<raw_ptr<views::View, VectorExperimental>> buttons_; + const raw_ptr<views::View> scrollable_; }; BEGIN_METADATA(CaptionBubbleFrameView) @@ -428,6 +441,71 @@ BEGIN_METADATA(CaptionBubbleLabel) END_METADATA +class CaptionBubbleScrollView : public views::ScrollView { + METADATA_HEADER(CaptionBubbleScrollView, views::ScrollView) + + public: + CaptionBubbleScrollView() { + ClipHeightTo(kMinScrollViewHeight, kMaxScrollViewHeightExpanded); + SetHorizontalScrollBarMode(views::ScrollView::ScrollBarMode::kDisabled); + SetVerticalScrollBarMode(views::ScrollView::ScrollBarMode::kEnabled); + } + + ~CaptionBubbleScrollView() override = default; + + CaptionBubbleScrollView(const CaptionBubbleScrollView&) = delete; + CaptionBubbleScrollView& operator=(const CaptionBubbleScrollView&) = delete; +}; + +BEGIN_METADATA(CaptionBubbleScrollView) +END_METADATA + +class ScrollLockButton : public views::MdTextButton { + METADATA_HEADER(ScrollLockButton, views::MdTextButton) + + public: + explicit ScrollLockButton(views::MdTextButton::PressedCallback callback) + : views::MdTextButton( + std::move(callback), + l10n_util::GetStringUTF16( + IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_SCROLLING)) { + SetCustomPadding(kScrollLockButtonInsets); + label()->SetMultiLine(false); + SetImageLabelSpacing(kScrollLockButtonImageLabelSpacing); + SetBgColorIdOverride(ui::kColorLiveCaptionBubbleButtonBackground); + SetPaintToLayer(); + } + + ScrollLockButton(const ScrollLockButton&) = delete; + ScrollLockButton& operator=(const ScrollLockButton&) = delete; + ~ScrollLockButton() override = default; + + ui::Cursor GetCursor(const ui::MouseEvent& event) override { + return ui::mojom::CursorType::kHand; + } + void SetTextScaleFactor(double text_scale_factor) { + SetFocusRingCornerRadius(text_scale_factor * kLineHeightDip / 2); + } + + bool IsLocked() const { return locked_; } + + void FlipLock() { + locked_ = !locked_; + SetText(l10n_util::GetStringUTF16( + locked_ ? IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_LOCKED + : IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_SCROLLING)); + SchedulePaint(); + } + + views::Label* GetLabel() { return label(); } + + private: + bool locked_ = false; // Initially scrolling is allowed. +}; + +BEGIN_METADATA(ScrollLockButton) +END_METADATA + #if defined(NEED_FOCUS_FOR_ACCESSIBILITY) // A helper class to the CaptionBubbleLabel which observes AXMode changes and // updates the CaptionBubbleLabel focus behavior in response. @@ -489,8 +567,9 @@ } CaptionBubble::~CaptionBubble() { - if (model_) + if (model_) { model_->RemoveObserver(); + } } gfx::Rect CaptionBubble::GetBubbleBounds() { @@ -637,7 +716,14 @@ close_button_ = right_header_container->AddChildView(std::move(close_button)); title_ = content_container->AddChildView(std::move(title)); - label_ = content_container->AddChildView(std::move(label)); + + if (IsScrollabilityEnabled()) { + scrollable_ = content_container->AddChildView( + std::make_unique<CaptionBubbleScrollView>()); + label_ = scrollable_->SetContents(std::move(label)); + } else { + label_ = content_container->AddChildView(std::move(label)); + } auto download_progress_label = std::make_unique<views::Label>(); download_progress_label->SetBackgroundColor(SK_ColorTRANSPARENT); @@ -704,16 +790,33 @@ std::move(translate_header_container_layout)); translate_header_container_ = left_header_container->AddChildViewRaw( std::move(translate_header_container)); + std::unique_ptr<views::BoxLayout> left_header_container_layout = std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets::TLBR( 0, close_button_->GetBorder()->GetInsets().width() / 2, 0, 0)); + left_header_container_layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); + left_header_container_layout->set_between_child_spacing( + kLeftContainerSpacingDip); left_header_container->SetLayoutManager( std::move(left_header_container_layout)); + if (IsScrollabilityEnabled()) { + scroll_lock_button_ = left_header_container->AddChildView( + std::make_unique<ScrollLockButton>(base::BindRepeating( + &CaptionBubble::ScrollLockButtonPressed, + base::Unretained( // Safe, since the button is owned by `this` + this)))); + scroll_lock_button_->GetViewAccessibility().SetIsIgnored(true); + scroll_lock_button_->SetVisible(is_expanded_); + scroll_lock_button_->SetPaintToLayer(); + scroll_lock_button_->layer()->SetFillsBoundsOpaquely(false); + scroll_lock_button_->layer()->SetOpacity(0); + } + left_header_container_ = header_container->AddChildViewRaw(std::move(left_header_container)); header_container->AddChildViewRaw(std::move(right_header_container)); @@ -744,6 +847,13 @@ &CaptionBubble::OnTitleTextChanged, weak_ptr_factory_.GetWeakPtr())); } +void CaptionBubble::ResetScrollIfLocked(gfx::PointF current_offset, + views::ScrollView* scrollable) { + if (scroll_lock_button_->IsLocked()) { + scrollable->ScrollToOffset(current_offset); + } +} + void CaptionBubble::OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const { params->type = views::Widget::InitParams::TYPE_WINDOW; @@ -769,7 +879,10 @@ std::make_unique<CaptionBubbleEventObserver>(this, widget); } - auto frame = std::make_unique<CaptionBubbleFrameView>(buttons); + if (IsScrollabilityEnabled()) { + buttons.emplace_back(scroll_lock_button_.get()); + } + auto frame = std::make_unique<CaptionBubbleFrameView>(buttons, scrollable_); frame_ = frame.get(); return frame; } @@ -810,8 +923,9 @@ void CaptionBubble::CloseButtonPressed() { LogSessionEvent(SessionEvent::kCloseButtonClicked); - if (model_) + if (model_) { model_->CloseButtonPressed(); + } #if BUILDFLAG(IS_CHROMEOS) caption_bubble_settings_->SetLiveCaptionEnabled(false); @@ -826,6 +940,15 @@ SwapButtons(collapse_button_, expand_button_, is_expanded_); + if (IsScrollabilityEnabled()) { + scroll_lock_button_->SetVisible(is_expanded_); + + // Adjust scrollable view size. + scrollable_->ClipHeightTo(kMinScrollViewHeight, + is_expanded_ ? kMaxScrollViewHeightExpanded + : kMaxScrollViewHeightCollapsed); + } + // The change of expanded state may cause the title to change visibility, and // it surely causes the content height to change, so redraw the bubble. Redraw(); @@ -840,20 +963,40 @@ void CaptionBubble::SwapButtons(views::Button* first_button, views::Button* second_button, bool show_first_button) { - if (!show_first_button) + if (!show_first_button) { std::swap(first_button, second_button); + } second_button->SetVisible(false); first_button->SetVisible(true); - if (!first_button->HasFocus()) + if (!first_button->HasFocus()) { first_button->RequestFocus(); + } } void CaptionBubble::CaptionSettingsButtonPressed() { model_->GetContext()->GetOpenCaptionSettingsCallback().Run(); } +void CaptionBubble::ScrollLockButtonPressed() { + // Flip scroll lock button state. + scroll_lock_button_->FlipLock(); + // Capture current position if locked. + if (scroll_lock_button_->IsLocked()) { + // Layout will reset the scroll offset to 0, therefore, record offset + // if scrolling is locked and restore it on layout completion. + const auto current_offset = scrollable_->CurrentOffset(); + scrollable_->RegisterPostLayoutCallback(base::BindRepeating( + &CaptionBubble::ResetScrollIfLocked, + base::Unretained( // Safe, since `scrollable_` is owned by `this` + this), + current_offset)); + } else { + scrollable_->RegisterPostLayoutCallback(base::DoNothing()); + } +} + void CaptionBubble::SetModel(CaptionBubbleModel* model) { if (model_) { model_->RemoveObserver(); @@ -871,16 +1014,20 @@ } void CaptionBubble::AnimationProgressed(const gfx::Animation* animation) { - if (!IsTranslateHeaderEnabled()) { - return; + if (IsTranslateHeaderEnabled()) { + std::vector<raw_ptr<views::View, VectorExperimental>> buttons = + GetButtons(); + for (views::View* button : buttons) { + button->layer()->SetOpacity(animation->GetCurrentValue()); + } + translate_header_container_->layer()->SetOpacity( + animation->GetCurrentValue()); + download_progress_label_->layer()->SetOpacity(animation->GetCurrentValue()); } - std::vector<raw_ptr<views::View, VectorExperimental>> buttons = GetButtons(); - for (views::View* button : buttons) { - button->layer()->SetOpacity(animation->GetCurrentValue()); + + if (IsScrollabilityEnabled()) { + scroll_lock_button_->layer()->SetOpacity(animation->GetCurrentValue()); } - translate_header_container_->layer()->SetOpacity( - animation->GetCurrentValue()); - download_progress_label_->layer()->SetOpacity(animation->GetCurrentValue()); } void CaptionBubble::OnContextActivatabilityChanged() { @@ -890,8 +1037,22 @@ void CaptionBubble::OnTextChanged() { DCHECK(model_); - std::string text = model_->GetFullText(); - label_->SetText(base::UTF8ToUTF16(text)); + + if (IsScrollabilityEnabled()) { + if (scroll_lock_button_->IsLocked()) { + // Record offset to be used later and only if scrolling is still locked. + const auto current_offset = scrollable_->CurrentOffset(); + scrollable_->RegisterPostLayoutCallback( + base::BindRepeating(&CaptionBubble::ResetScrollIfLocked, + base::Unretained(this), current_offset)); + } else { + scrollable_->RegisterPostLayoutCallback(base::DoNothing()); + } + } + + auto text = base::UTF8ToUTF16(model_->GetFullText()); + label_->SetText(std::move(text)); + UpdateBubbleAndTitleVisibility(); } @@ -973,6 +1134,9 @@ label_->SetVisible(!has_error); expand_button_->SetVisible(!has_error && !is_expanded_); collapse_button_->SetVisible(!has_error && is_expanded_); + if (IsScrollabilityEnabled()) { + scroll_lock_button_->SetVisible(!has_error && is_expanded_); + } #if BUILDFLAG(IS_WIN) if (error_type == @@ -1082,8 +1246,9 @@ if (caption_style_) { std::string font_family = MaybeRemoveCSSImportant(caption_style_->font_family); - if (!font_family.empty()) + if (!font_family.empty()) { font_names.push_back(font_family); + } } font_names.push_back(kPrimaryFont); font_names.push_back(kSecondaryFont); @@ -1324,6 +1489,7 @@ ? content_height - kLineHeightDip * text_scale_factor : content_height; label_->SetMinimumHeight(label_height); + auto button_size = close_button_->GetPreferredSize({}); // The back-to-tab button is only visible if the context can be activated. The @@ -1363,19 +1529,33 @@ UpdateContentSize(); } +void CaptionBubble::MaybeScrollToBottom() { + if (IsScrollabilityEnabled()) { + if (!scroll_lock_button_->IsLocked()) { + scrollable_->vertical_scroll_bar()->ScrollByAmount( + views::ScrollBar::ScrollAmount::kEnd); + } + } +} + void CaptionBubble::ShowInactive() { DCHECK(model_); - if (GetWidget()->IsVisible()) + if (GetWidget()->IsVisible()) { + MaybeScrollToBottom(); return; + } GetWidget()->ShowInactive(); GetViewAccessibility().AnnounceText(l10n_util::GetStringUTF16( IDS_LIVE_CAPTION_BUBBLE_APPEAR_SCREENREADER_ANNOUNCEMENT)); LogSessionEvent(SessionEvent::kStreamStarted); + MaybeScrollToBottom(); + // If the caption bubble has already been shown, do not reposition it. - if (has_been_shown_) + if (has_been_shown_) { return; + } has_been_shown_ = true; // The first time that the caption bubble is shown, reposition it to the @@ -1386,8 +1566,9 @@ } void CaptionBubble::Hide() { - if (!GetWidget()->IsVisible()) + if (!GetWidget()->IsVisible()) { return; + } GetWidget()->Hide(); LogSessionEvent(SessionEvent::kStreamEnded); } @@ -1434,10 +1615,18 @@ return views::AsViewClass<views::Label>(label_); } +views::ScrollView* CaptionBubble::GetScrollViewForTesting() { + return views::AsViewClass<views::ScrollView>(scrollable_); +} + views::Label* CaptionBubble::GetDownloadProgressLabelForTesting() { return views::AsViewClass<views::Label>(download_progress_label_); } +views::Label* CaptionBubble::GetScrollLockLabelForTesting() { + return views::AsViewClass<views::Label>(scroll_lock_button_->GetLabel()); +} + bool CaptionBubble::IsGenericErrorMessageVisibleForTesting() const { return generic_error_message_->GetVisible(); } @@ -1459,6 +1648,10 @@ return back_to_tab_button_.get(); } +views::MdTextButton* CaptionBubble::GetScrollLockButtonForTesting() { + return scroll_lock_button_.get(); +} + views::View* CaptionBubble::GetHeaderForTesting() { return header_container_.get(); } @@ -1484,6 +1677,10 @@ base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage); } +bool CaptionBubble::IsScrollabilityEnabled() const { + return base::FeatureList::IsEnabled(captions::kLiveCaptionScrollable); +} + BEGIN_METADATA(CaptionBubble) END_METADATA
diff --git a/components/live_caption/views/caption_bubble.h b/components/live_caption/views/caption_bubble.h index 82cab2b..997d71e 100644 --- a/components/live_caption/views/caption_bubble.h +++ b/components/live_caption/views/caption_bubble.h
@@ -23,6 +23,7 @@ #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/md_text_button.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/styled_label.h" #include "ui/views/metadata/view_factory.h" @@ -38,6 +39,8 @@ class CaptionBubbleEventObserver; class CaptionBubbleFrameView; class CaptionBubbleLabel; +class CaptionBubbleScrollView; +class ScrollLockButton; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. These should be the same as @@ -101,10 +104,13 @@ void UpdateCaptionStyle(std::optional<ui::CaptionStyle> caption_style); views::Label* GetLabelForTesting(); + views::ScrollView* GetScrollViewForTesting(); views::Label* GetDownloadProgressLabelForTesting(); + views::Label* GetScrollLockLabelForTesting(); bool IsGenericErrorMessageVisibleForTesting() const; views::Button* GetCloseButtonForTesting(); views::Button* GetBackToTabButtonForTesting(); + views::MdTextButton* GetScrollLockButtonForTesting(); views::View* GetHeaderForTesting(); TranslationViewWrapperBase* GetTranslationViewWrapperForTesting(); @@ -148,6 +154,7 @@ bool show_first_button); // TranslationViewWrapperBase::Delegate: void CaptionSettingsButtonPressed() override; + void ScrollLockButtonPressed(); // Called by CaptionBubbleModel to notify this object that the model's text // has changed. Sets the text of the caption bubble to the model's text. @@ -191,6 +198,9 @@ // Returns the number of lines in the caption bubble label that are rendered. size_t GetNumLinesInLabel() const; int GetNumLinesVisible(); + + // Internal service methods. + void MaybeScrollToBottom(); void UpdateContentSize(); void Redraw(); void ShowInactive(); @@ -236,11 +246,17 @@ bool IsTranslateHeaderEnabled() const; + bool IsScrollabilityEnabled() const; + void ResetScrollIfLocked(gfx::PointF current_offset, + views::ScrollView* scrollable); + // Unowned. Owned by views hierarchy. raw_ptr<CaptionBubbleLabel> label_; + raw_ptr<CaptionBubbleScrollView> scrollable_; raw_ptr<views::Label> title_; raw_ptr<views::Label> generic_error_text_; raw_ptr<views::Label> download_progress_label_; + raw_ptr<ScrollLockButton> scroll_lock_button_; raw_ptr<views::View> header_container_; raw_ptr<views::View> left_header_container_; raw_ptr<views::View> translate_header_container_;
diff --git a/components/live_caption/views/caption_bubble_browsertest.cc b/components/live_caption/views/caption_bubble_browsertest.cc index 0d2400c..f07c67a 100644 --- a/components/live_caption/views/caption_bubble_browsertest.cc +++ b/components/live_caption/views/caption_bubble_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/cfi_buildflags.h" #include "base/functional/callback.h" #include "base/functional/callback_forward.h" +#include "base/run_loop.h" #include "base/scoped_observation.h" #include "base/strings/strcat.h" #include "base/strings/stringprintf.h" @@ -52,7 +53,10 @@ class CaptionBubbleBrowserTest : public UiBrowserTest { protected: - CaptionBubbleBrowserTest() = default; + CaptionBubbleBrowserTest() { + scoped_feature_list_.InitWithFeatures({captions::kLiveCaptionScrollable}, + {}); + } void SetUpOnMainThread() override { pref_service_.registry()->RegisterBooleanPref( @@ -92,8 +96,13 @@ bubble_ = bubble.get(); views::BubbleDialogDelegateView::CreateBubble(std::move(bubble))->Show(); bubble_->SetModel(model_.get()); - model_->SetPartialText("ABCDEF"); - model_->CommitPartialText(); + + // Prepare RunLoop, + run_loop_ = std::make_unique<base::RunLoop>(); + // Increase to 1024u for a manual run to observe scrolling on screen. + SingleStep(128u); + // The test will wait until all steps are completed. + run_loop_->Run(); } // These next two are not necessary if subclassing DialogBrowserTest. @@ -128,7 +137,60 @@ } private: - views::Widget* GetWidgetForScreenshot() { return bubble_->GetWidget(); } + views::Widget* GetWidgetForScreenshot() const { return bubble_->GetWidget(); } + + // This method adds one more piece of text to the bubble and then + // performs scroll to the start and scroll to the end (for testing only). + // It schedules asynchronous call to itself for the next piece of text, + // in order to yield the the UI thread and let scrolls repaint the view. + void SingleStep(uint64_t i) { + if (!bubble_) { + return; + } + model_->SetPartialText(base::StringPrintf("ABCDEF %ul ", i)); + model_->CommitPartialText(); + auto* const scroll_bar = + bubble_->GetScrollViewForTesting()->vertical_scroll_bar(); + ASSERT_EQ(scroll_bar->GetOrientation(), + views::ScrollBar::Orientation::kVertical); + + // Next iteration needs to be reschedued on UI thread, so that views can + // be repainted. + auto next_step = + (i > 1) ? base::BindPostTask( + base::SingleThreadTaskRunner::GetCurrentDefault(), + base::BindOnce(&CaptionBubbleBrowserTest::SingleStep, + base::Unretained(this), i - 1)) + : base::BindOnce(&base::RunLoop::Quit, + base::Unretained(run_loop_.get())); + + if (scroll_bar->GetVisible()) { + // If the scrollbar is already visible, reschedule simulated scroll to the + // beginning, then scroll to the end, and then do the next step. + // The scrolled view should be repainted after ~every action. + next_step = + base::BindPostTask(base::SingleThreadTaskRunner::GetCurrentDefault(), + base::BindOnce( + [](views::ScrollBar* scroll_bar) { + ASSERT_TRUE(scroll_bar->ScrollByAmount( + views::ScrollBar::ScrollAmount::kStart)); + }, + base::Unretained(scroll_bar))) + .Then(base::BindPostTask( + base::SingleThreadTaskRunner::GetCurrentDefault(), + base::BindOnce( + [](views::ScrollBar* scroll_bar) { + ASSERT_TRUE(scroll_bar->ScrollByAmount( + views::ScrollBar::ScrollAmount::kEnd)); + }, + base::Unretained(scroll_bar)))) + .Then(std::move(next_step)); + } + + std::move(next_step).Run(); + } + + base::test::ScopedFeatureList scoped_feature_list_; TestingPrefServiceSimple pref_service_; @@ -136,6 +198,8 @@ std::unique_ptr<CaptionBubbleModel> model_; std::unique_ptr<LiveCaptionBubbleSettings> settings_; raw_ptr<CaptionBubble> bubble_; + + std::unique_ptr<base::RunLoop> run_loop_; }; // Test that calls ShowUi("default").
diff --git a/components/live_caption/views/caption_bubble_model.cc b/components/live_caption/views/caption_bubble_model.cc index a89b96b..d938ed7 100644 --- a/components/live_caption/views/caption_bubble_model.cc +++ b/components/live_caption/views/caption_bubble_model.cc
@@ -6,19 +6,24 @@ #include "base/feature_list.h" #include "base/functional/callback_forward.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" #include "components/live_caption/caption_bubble_context.h" #include "components/live_caption/views/caption_bubble.h" #include "media/base/media_switches.h" namespace { -// The caption bubble contains 2 lines of text in its normal size and 8 lines -// in its expanded size, so the maximum number of lines before truncating is 9. + +// Non-scrollable caption bubble contains 2 lines of text in its normal size and +// 8 lines in its expanded size, so the maximum number of lines before +// truncating is 9. +// For scrollable caption bubble the number of lines in text is limited by +// `kLiveCaptionScrollableMaxLines` feature parameter (see below). constexpr int kMaxLines = 9; // Returns the length of the longest common prefix between two strings. int GetLongestCommonPrefixLength(const std::string& str1, - const std::string& str2) { + const std::string& str2) { int length = 0; for (unsigned long i = 0, j = 0; i < str1.length() && j < str2.length(); i++, j++, length++) { @@ -34,6 +39,16 @@ namespace captions { +BASE_FEATURE(kLiveCaptionScrollable, + "LiveCaptionScrollable", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE_PARAM(size_t, + kLiveCaptionScrollableMaxLines, + &kLiveCaptionScrollable, + "live_caption_scrollable_max_lines", + 250); + CaptionBubbleModel::CaptionBubbleModel(CaptionBubbleContext* context, OnCaptionBubbleClosedCallback callback) : unique_id_(GetNextId()), @@ -78,8 +93,9 @@ } void CaptionBubbleModel::OnTextChanged() { - if (observer_) + if (observer_) { observer_->OnTextChanged(); + } } void CaptionBubbleModel::OnAutoDetectedLanguageChanged() { @@ -169,12 +185,16 @@ if (!observer_) return; - // Truncate the final text to kMaxLines lines long. This time, alert the + const size_t max_lines = base::FeatureList::IsEnabled(kLiveCaptionScrollable) + ? kLiveCaptionScrollableMaxLines.Get() + : kMaxLines; + + // Truncate the final text to max_lines lines long. This time, alert the // observer that the text has changed. const size_t num_lines = observer_->GetNumLinesInLabel(); - if (num_lines > kMaxLines) { + if (num_lines > max_lines) { const size_t truncate_index = - observer_->GetTextIndexOfLineInLabel(num_lines - kMaxLines); + observer_->GetTextIndexOfLineInLabel(num_lines - max_lines); final_text_.erase(0, truncate_index); OnTextChanged(); }
diff --git a/components/live_caption/views/caption_bubble_model.h b/components/live_caption/views/caption_bubble_model.h index a274529..4375b1f 100644 --- a/components/live_caption/views/caption_bubble_model.h +++ b/components/live_caption/views/caption_bubble_model.h
@@ -7,12 +7,21 @@ #include <string> +#include "base/feature_list.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" +#include "base/metrics/field_trial_params.h" #include "base/types/id_type.h" namespace captions { +// This feature enables scrollability in Live Caption. +BASE_DECLARE_FEATURE(kLiveCaptionScrollable); + +// This parameter sets maximum number of lines in the text, +// if scrollability is enabled. +BASE_DECLARE_FEATURE_PARAM(size_t, kLiveCaptionScrollableMaxLines); + class CaptionBubble; class CaptionBubbleContext; @@ -67,28 +76,27 @@ void SetObserver(CaptionBubble* observer); void RemoveObserver(); - // Set the partial text and alert the observer. + // Sets the partial text and alerts the observer. void SetPartialText(const std::string& partial_text); - // Set the download progress label and alert the observer. + // Sets the download progress label and alerts the observer. void SetDownloadProgressText(const std::u16string& download_progress_text); - // Notify the observer that a language pack was installed. + // Notifies the observer that a language pack was installed. void OnLanguagePackInstalled(); // Commits the partial text as final text. void CommitPartialText(); - // Set that the bubble has an error and alert the observer. + // Sets that the bubble has an error and alert the observer. void OnError(CaptionBubbleErrorType error_type, OnErrorClickedCallback error_clicked_callback, OnDoNotShowAgainClickedCallback error_silenced_callback); - // Mark the bubble as closed. + // Marks the bubble as closed. void CloseButtonPressed(); - // Clear the partial and final text, and alert the - // observer. + // Clears the partial and final text and alerts the observer. void Close(); // Clears the partial and final text and alerts the observer.
diff --git a/components/live_caption/views/format_constants.h b/components/live_caption/views/format_constants.h index 1067d4d..2df51b94 100644 --- a/components/live_caption/views/format_constants.h +++ b/components/live_caption/views/format_constants.h
@@ -14,8 +14,14 @@ inline constexpr int kLiveTranslateImageWidthDip = 16; inline constexpr int kLanguageButtonImageLabelSpacing = 4; inline constexpr auto kLanguageButtonInsets = gfx::Insets::TLBR(2, 8, 2, 6); +inline constexpr int kScrollLockButtonImageLabelSpacing = 4; +inline constexpr auto kScrollLockButtonInsets = gfx::Insets::TLBR(2, 8, 2, 6); inline constexpr int kNumLinesCollapsed = 2; inline constexpr int kNumLinesExpanded = 8; +inline constexpr int kMinScrollViewHeight = 0; +inline constexpr int kMaxScrollViewHeightCollapsed = 48; +inline constexpr int kMaxScrollViewHeightExpanded = 192; +inline constexpr int kLeftContainerSpacingDip = 10; inline constexpr int kCornerRadiusDip = 4; inline constexpr int kSidePaddingDip = 18; inline constexpr int kButtonDip = 16;
diff --git a/components/live_caption_strings.grdp b/components/live_caption_strings.grdp index 29859cd..a5ac16e 100644 --- a/components/live_caption_strings.grdp +++ b/components/live_caption_strings.grdp
@@ -49,6 +49,12 @@ <message name="IDS_LIVE_CAPTION_BUBBLE_CAPTION_SETTINGS" desc="Tooltip for the caption settings button"> Caption settings </message> + <message name="IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_SCROLLING" desc="Label for the scroll button in Scrolling state"> + Scrolling + </message> + <message name="IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_LOCKED" desc="Label for the scroll button in Locked state"> + Locked + </message> <message name="IDS_LIVE_CAPTION_DOWNLOAD_PROGRESS" desc="Download progress indicator after Live Caption is enabled. The user needs to download certain files for the feature to work."> Downloading <ph name="LANGUAGE">$1<ex>Spanish</ex></ph> language pack... <ph name="PERCENT">$2<ex>17</ex></ph>% </message>
diff --git a/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_LOCKED.png.sha1 b/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_LOCKED.png.sha1 new file mode 100644 index 0000000..a11f0e77 --- /dev/null +++ b/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_LOCKED.png.sha1
@@ -0,0 +1 @@ +81becf129e11635a0b4a7dada22809ae040dabae \ No newline at end of file
diff --git a/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_SCROLLING.png.sha1 b/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_SCROLLING.png.sha1 new file mode 100644 index 0000000..994d2c1 --- /dev/null +++ b/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_SCROLL_BUTTON_SCROLLING.png.sha1
@@ -0,0 +1 @@ +edf30f1cdffa908e1a3cb06caa33438e450f6282 \ No newline at end of file
diff --git a/components/management_strings.grdp b/components/management_strings.grdp index 7af0323a..091943c 100644 --- a/components/management_strings.grdp +++ b/components/management_strings.grdp
@@ -350,19 +350,19 @@ <message name="IDS_MANAGEMENT_PROFILE_REPORTING_EXPLANATION" desc="Message explaining browser reporting" formatter_data="android_java"> Managed profile, browser, and some device information is accessible to your administrator. They can see information such as the following: </message> - <message name="IDS_MANAGEMENT_PROFILE_REPORTING_OVERVIEW" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can view the user's work profile overview." formatter_data="android_java"> + <message name="IDS_MANAGEMENT_PROFILE_REPORTING_OVERVIEW" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can view the user's work profile overview. A work profile is a managed profile in an enterprise environment, such as a business, government organization, or other workplace." formatter_data="android_java"> Work profile overview </message> <message name="IDS_MANAGEMENT_PROFILE_REPORTING_USERNAME" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can view the user's work profile username." formatter_data="android_java"> - Work profile information (such as your work profile username) + Work profile information (such as your username) </message> <message name="IDS_MANAGEMENT_PROFILE_REPORTING_BROWSER" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can view the device information that user's work profile belong to" formatter_data="android_java"> Browser and device OS information (such as the browser & OS versions) </message> - <message name="IDS_MANAGEMENT_PROFILE_REPORTING_EXTENSION" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can view user's work profile extensions"> + <message name="IDS_MANAGEMENT_PROFILE_REPORTING_EXTENSION" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can view user's work profile extensions. A work profile is a managed profile in an enterprise environment, such as a business, government organization, or other workplace."> Installed apps & extensions in your work profile </message> - <message name="IDS_MANAGEMENT_PROFILE_REPORTING_POLICY" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can viewuser's work profile policies" formatter_data="android_java"> + <message name="IDS_MANAGEMENT_PROFILE_REPORTING_POLICY" desc="Item in a list of information viewable by the enterprise admin, indicating that the admin can view the user's work profile policies. A work profile is a managed profile in an enterprise environment, such as a business, government organization, or other workplace." formatter_data="android_java"> Applied browser policies in your work profile </message> <message name="IDS_MANAGEMENT_PROFILE_REPORTING_LEARN_MORE" desc="Learn more link for profile reporting management information to provide additional informaiton">
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_PROFILE_REPORTING_USERNAME.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_PROFILE_REPORTING_USERNAME.png.sha1 index a50355c3..bd9f076 100644 --- a/components/management_strings_grdp/IDS_MANAGEMENT_PROFILE_REPORTING_USERNAME.png.sha1 +++ b/components/management_strings_grdp/IDS_MANAGEMENT_PROFILE_REPORTING_USERNAME.png.sha1
@@ -1 +1 @@ -8394488b80db3c7498de2247695e860f1a8bf731 \ No newline at end of file +1a8a2ff2545e3e18e0ad236918f16137907b29b9 \ No newline at end of file
diff --git a/components/metrics/demographics/demographic_metrics_provider.cc b/components/metrics/demographics/demographic_metrics_provider.cc index e79ca19..b097d0e5 100644 --- a/components/metrics/demographics/demographic_metrics_provider.cc +++ b/components/metrics/demographics/demographic_metrics_provider.cc
@@ -9,7 +9,6 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/notreached.h" -#include "components/sync/base/features.h" #include "components/sync/base/user_selectable_type.h" #include "components/sync/service/sync_service.h" #include "components/sync/service/sync_service_utils.h" @@ -35,40 +34,17 @@ bool CanUploadDemographicsToGoogle(syncer::SyncService* sync_service) { CHECK(sync_service); - // PRIORITY_PREFERENCES is the sync datatype used to propagate demographics // information to the client. In its absence, demographics info is unavailable // thus cannot be uploaded. - if (!IsValidUploadState(syncer::GetUploadToGoogleState( - sync_service, syncer::PRIORITY_PREFERENCES)) || - // With `kSyncSupportAlwaysSyncingPriorityPreferences` feature enabled, - // PRIORITY_PREFERENCES will always be active (decoupled from sync user - // toggle). Thus, the preferences user toggle should be checked - // separately. - !sync_service->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kPreferences)) { - return false; - } - - // Even if GetUploadToGoogleState() reports to be active, the user may be in - // transport mode or full-sync (aka sync-the-feature enabled) mode. - // If `kReplaceSyncPromosWithSignInPromos` is enabled, then - // PRIORITY_PREFERENCES being enabled (which implies the user is signed in) is - // enough, and the sync mode doesn't matter. - if (base::FeatureList::IsEnabled( - syncer::kReplaceSyncPromosWithSignInPromos)) { - return true; - } - - // If `kReplaceSyncPromosWithSignInPromos` is NOT enabled, then demographics - // may only be uploaded for users who have opted in to Sync. - // TODO(crbug.com/40066949): Simplify once IsSyncFeatureEnabled() is deleted - // from the codebase. - if (sync_service->IsSyncFeatureEnabled()) { - return true; - } - - return false; + return IsValidUploadState(syncer::GetUploadToGoogleState( + sync_service, syncer::PRIORITY_PREFERENCES)) && + // With `kSyncSupportAlwaysSyncingPriorityPreferences` feature enabled, + // PRIORITY_PREFERENCES will always be active (decoupled from sync user + // toggle). Thus, the preferences user toggle should be checked + // separately. + sync_service->GetUserSettings()->GetSelectedTypes().Has( + syncer::UserSelectableType::kPreferences); } } // namespace
diff --git a/components/metrics/demographics/demographic_metrics_provider_unittest.cc b/components/metrics/demographics/demographic_metrics_provider_unittest.cc index 6bc6711..ae5ab84 100644 --- a/components/metrics/demographics/demographic_metrics_provider_unittest.cc +++ b/components/metrics/demographics/demographic_metrics_provider_unittest.cc
@@ -231,10 +231,13 @@ TEST( DemographicMetricsProviderTest, - ProvideSyncedUserNoisedBirthYearAndGender_SyncFeatureDisabledButPreferencesEnabled_WithSyncToSignin) { - base::test::ScopedFeatureList sync_to_signin_enabled; - sync_to_signin_enabled.InitAndEnableFeature( - syncer::kReplaceSyncPromosWithSignInPromos); + ProvideSyncedUserNoisedBirthYearAndGender_SyncFeatureDisabledButPreferencesEnabled) { + // Disable `kSyncSupportAlwaysSyncingPriorityPreferences` since it decouples + // the PRIORITY_PREFERENCES type from the sync toggle, and makes the test + // redundant. + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + syncer::kSyncSupportAlwaysSyncingPriorityPreferences); base::HistogramTester histogram; @@ -263,39 +266,6 @@ UserDemographicsStatus::kSuccess, 1); } -TEST( - DemographicMetricsProviderTest, - ProvideSyncedUserNoisedBirthYearAndGender_SyncFeatureDisabledButPreferencesEnabled_WithoutSyncToSignin) { - base::test::ScopedFeatureList sync_to_signin_disabled; - sync_to_signin_disabled.InitAndDisableFeature( - syncer::kReplaceSyncPromosWithSignInPromos); - - base::HistogramTester histogram; - - auto client = std::make_unique<TestProfileClient>( - /*number_of_profiles=*/1, SYNC_FEATURE_DISABLED_BUT_PREFERENCES_ENABLED); - client->SetDemographicsInPrefs(kTestBirthYear, kTestGender); - - // Set birth year noise offset to not have it randomized. - const int kBirthYearOffset = 3; - client->GetLocalState()->SetInteger(kUserDemographicsBirthYearOffsetPrefName, - kBirthYearOffset); - - // Run demographics provider. - DemographicMetricsProvider provider( - std::move(client), MetricsLogUploader::MetricServiceType::UMA); - ChromeUserMetricsExtension uma_proto; - provider.ProvideSyncedUserNoisedBirthYearAndGender(&uma_proto); - - // Expect the proto fields to be not set and left to default. - EXPECT_FALSE(uma_proto.user_demographics().has_birth_year()); - EXPECT_FALSE(uma_proto.user_demographics().has_gender()); - - // Verify histograms: Demographics should NOT be provided. - histogram.ExpectUniqueSample("UMA.UserDemographics.Status", - UserDemographicsStatus::kSyncNotEnabled, 1); -} - #if BUILDFLAG(IS_CHROMEOS) TEST( DemographicMetricsProviderTest, @@ -456,13 +426,17 @@ EXPECT_EQ(kTestGender, report.user_demographics().gender()); } -TEST(DemographicMetricsProviderTest, - ProvideSyncedUserNoisedBirthYearAndGender_PreferencesSyncNotSelected) { +TEST( + DemographicMetricsProviderTest, + ProvideSyncedUserNoisedBirthYearAndGender_PreferencesSyncNotSelected_WithAlwaysSyncingFeature) { + base::test::ScopedFeatureList feature_list( + syncer::kSyncSupportAlwaysSyncingPriorityPreferences); base::HistogramTester histogram; auto client = std::make_unique<TestProfileClient>( /*number_of_profiles=*/1, SYNC_FEATURE_ENABLED_BUT_PREFERENCES_NOT_SELECTED); + client->SetDemographicsInPrefs(kTestBirthYear, kTestGender); // Run demographics provider. DemographicMetricsProvider provider(
diff --git a/components/omnibox/browser/autocomplete_grouper_sections.cc b/components/omnibox/browser/autocomplete_grouper_sections.cc index 36109b90..8d3742b3 100644 --- a/components/omnibox/browser/autocomplete_grouper_sections.cc +++ b/components/omnibox/browser/autocomplete_grouper_sections.cc
@@ -576,6 +576,26 @@ }, group_configs) {} +DesktopWebSearchZpsContextualOnlySection:: + DesktopWebSearchZpsContextualOnlySection( + omnibox::GroupConfigMap& group_configs, + size_t contextual_action_limit, + size_t contextual_search_limit) + : Section(contextual_action_limit + contextual_search_limit, + { + Group(contextual_action_limit, + { + {omnibox::GROUP_CONTEXTUAL_SEARCH_ACTION, + contextual_action_limit}, + }), + Group(contextual_search_limit, + { + {omnibox::GROUP_CONTEXTUAL_SEARCH, + contextual_search_limit}, + }), + }, + group_configs) {} + DesktopLensContextualZpsSection::DesktopLensContextualZpsSection( omnibox::GroupConfigMap& group_configs) : ZpsSection(5,
diff --git a/components/omnibox/browser/autocomplete_grouper_sections.h b/components/omnibox/browser/autocomplete_grouper_sections.h index aff07a5..3909d304d 100644 --- a/components/omnibox/browser/autocomplete_grouper_sections.h +++ b/components/omnibox/browser/autocomplete_grouper_sections.h
@@ -243,6 +243,21 @@ size_t contextual_search_limit); }; +// An experimental alternative for `DesktopWebSearchZpsSection` that excludes +// all but contextual matches. It's intended as a full replacement instead +// of modifying that section, for simplicity and ease of removal after +// experimentation. +// - up to `contextual_action_limit` + `contextual_search_limit` total. +// - up to `contextual_action_limit` contextual search action suggestions. +// - up to `contextual_search_limit` contextual search suggestions. +class DesktopWebSearchZpsContextualOnlySection : public Section { + public: + explicit DesktopWebSearchZpsContextualOnlySection( + omnibox::GroupConfigMap& group_configs, + size_t contextual_action_limit, + size_t contextual_search_limit); +}; + // Section expressing the Desktop ZPS limits and grouping for the Lens // contextual searchbox. // - up to 8 suggestions total.
diff --git a/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc b/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc index 3fa02d28..d159a90 100644 --- a/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc +++ b/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc
@@ -2067,6 +2067,34 @@ {99, 98, 97, 96}); } } + +TEST(AutocompleteGrouperSectionsTest, DesktopWebZpsContextualSuggestionsOnly) { + auto test = [](ACMatches matches, std::vector<int> expected_relevances) { + PSections sections; + omnibox::GroupConfigMap group_configs; + sections.push_back( + std::make_unique<DesktopWebSearchZpsContextualOnlySection>( + group_configs, /*contextual_action_limit=*/1u, + /*contextual_search_limit=*/3u)); + auto out_matches = Section::GroupMatches(std::move(sections), matches); + VerifyMatches(out_matches, expected_relevances); + }; + { + SCOPED_TRACE("ZPS contextual search matches only"); + test( + { + CreateMatch(99, omnibox::GROUP_MOST_VISITED), + CreateMatch(98, omnibox::GROUP_VISITED_DOC_RELATED), + CreateMatch(97, omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST), + CreateMatch(96, omnibox::GROUP_CONTEXTUAL_SEARCH_ACTION), + CreateMatch(95, omnibox::GROUP_CONTEXTUAL_SEARCH), + CreateMatch(94, omnibox::GROUP_CONTEXTUAL_SEARCH_ACTION), + CreateMatch(93, omnibox::GROUP_CONTEXTUAL_SEARCH), + }, + // Nothing but contextual action and contextual search matches. + {96, 95, 93}); + } +} #endif // !(BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)) // Test that (on Android) sections are grouped by Search vs URL.
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index a70ee8b..ca62687 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -543,12 +543,24 @@ } #endif } else { - sections.push_back(std::make_unique<DesktopWebURLZpsSection>( - suggestion_groups_map_, max_url_suggestions)); - sections.push_back(std::make_unique<DesktopWebSearchZpsSection>( - suggestion_groups_map_, - max_search_suggestions + contextual_action_limit, - contextual_action_limit, contextual_zps_limit)); + if (contextual_zps_limit > 0u && + omnibox_feature_configs::ContextualSearch::Get() + .contextual_suggestions_ablate_others_when_present && + std::ranges::any_of(matches_, [](const auto& match) { + return match.IsContextualSearchSuggestion(); + })) { + sections.push_back( + std::make_unique<DesktopWebSearchZpsContextualOnlySection>( + suggestion_groups_map_, contextual_action_limit, + contextual_zps_limit)); + } else { + sections.push_back(std::make_unique<DesktopWebURLZpsSection>( + suggestion_groups_map_, max_url_suggestions)); + sections.push_back(std::make_unique<DesktopWebSearchZpsSection>( + suggestion_groups_map_, + max_search_suggestions + contextual_action_limit, + contextual_action_limit, contextual_zps_limit)); + } #if BUILDFLAG(ENABLE_EXTENSIONS) if (base::FeatureList::IsEnabled( extensions_features::kExperimentalOmniboxLabs)) {
diff --git a/components/omnibox/browser/contextual_search_provider.cc b/components/omnibox/browser/contextual_search_provider.cc index 3b06a10e..58184ee 100644 --- a/components/omnibox/browser/contextual_search_provider.cc +++ b/components/omnibox/browser/contextual_search_provider.cc
@@ -318,7 +318,8 @@ // Lens invocation action with secondary text that shows URL host. match.takeover_action = base::MakeRefCounted<ContextualSearchOpenLensAction>(); - match.contents = base::UTF8ToUTF16(input.current_url().host()); + match.contents = + base::UTF8ToUTF16(url_formatter::StripWWW(input.current_url().host())); if (!match.contents.empty()) { match.contents_class = {{0, ACMatchClassification::DIM}}; } @@ -326,6 +327,7 @@ if (!match.description.empty()) { match.description_class = {{0, ACMatchClassification::NONE}}; } + match.fill_into_edit = match.description; matches_.push_back(match); }
diff --git a/components/omnibox/browser/contextual_search_provider_unittest.cc b/components/omnibox/browser/contextual_search_provider_unittest.cc index 4a64d2b..2887f0c 100644 --- a/components/omnibox/browser/contextual_search_provider_unittest.cc +++ b/components/omnibox/browser/contextual_search_provider_unittest.cc
@@ -118,3 +118,40 @@ EXPECT_FALSE(has_actions()); } } + +TEST_F(ContextualSearchProviderTest, LensAdActionFillsEditAndElidesWwwOnly) { + EXPECT_CALL(*client_, IsLensEnabled()).WillRepeatedly(testing::Return(true)); + { + AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER, + TestSchemeClassifier()); + input.set_current_url(GURL("https://something.example.com")); + input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS); + provider_->Start(input, false); + EXPECT_TRUE(provider_->done()); + const AutocompleteMatch& match = provider_->matches()[0]; + EXPECT_FALSE(match.fill_into_edit.empty()); + EXPECT_EQ(match.contents, u"something.example.com"); + } + { + AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER, + TestSchemeClassifier()); + input.set_current_url(GURL("https://www.example.com")); + input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS); + provider_->Start(input, false); + EXPECT_TRUE(provider_->done()); + const AutocompleteMatch& match = provider_->matches()[0]; + EXPECT_FALSE(match.fill_into_edit.empty()); + EXPECT_EQ(match.contents, u"example.com"); + } + { + AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER, + TestSchemeClassifier()); + input.set_current_url(GURL("file:///home/personal/file.pdf")); + input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS); + provider_->Start(input, false); + EXPECT_TRUE(provider_->done()); + const AutocompleteMatch& match = provider_->matches()[0]; + EXPECT_FALSE(match.fill_into_edit.empty()); + EXPECT_EQ(match.contents, u""); + } +}
diff --git a/components/omnibox/common/omnibox_feature_configs.cc b/components/omnibox/common/omnibox_feature_configs.cc index a4144fc2..cd877af 100644 --- a/components/omnibox/common/omnibox_feature_configs.cc +++ b/components/omnibox/common/omnibox_feature_configs.cc
@@ -48,6 +48,10 @@ .Get(); } +BASE_FEATURE(ContextualSearch::kContextualSuggestionsAblateOthersWhenPresent, + "ContextualSuggestionsAblateOthersWhenPresent", + base::FEATURE_DISABLED_BY_DEFAULT); + // Meta-feature that enables/disables the other related features if set. // When not overridden, each feature is enabled/disabled separately. BASE_FEATURE(ContextualSearch::kOmniboxContextualSuggestions, @@ -111,6 +115,9 @@ return meta_state.value_or(base::FeatureList::IsEnabled(feature)); }; + contextual_suggestions_ablate_others_when_present = + base::FeatureList::IsEnabled( + kContextualSuggestionsAblateOthersWhenPresent); starter_pack_page = feature_enabled(kStarterPackPage); contextual_zero_suggest_lens_fulfillment = feature_enabled(kContextualZeroSuggestLensFulfillment);
diff --git a/components/omnibox/common/omnibox_feature_configs.h b/components/omnibox/common/omnibox_feature_configs.h index 1315e286..431dd15 100644 --- a/components/omnibox/common/omnibox_feature_configs.h +++ b/components/omnibox/common/omnibox_feature_configs.h
@@ -133,6 +133,7 @@ ContextualSearch& operator=(const ContextualSearch&); ~ContextualSearch(); + DECLARE_FEATURE(kContextualSuggestionsAblateOthersWhenPresent); DECLARE_FEATURE(kOmniboxContextualSuggestions); DECLARE_FEATURE(kStarterPackPage); DECLARE_FEATURE(kContextualZeroSuggestLensFulfillment); @@ -152,6 +153,11 @@ // match production requirement. bool IsEnabledWithPrefetch() const; + // Whether to make contextual suggestions exclusive; that is, remove + // other kinds of zero suggest matches when there are any contextual + // search matches. + bool contextual_suggestions_ablate_others_when_present; + // Whether the starter pack page scope is enabled. bool starter_pack_page;
diff --git a/components/policy/core/common/cloud/test/policy_builder.cc b/components/policy/core/common/cloud/test/policy_builder.cc index 63ee0069..79e1e86 100644 --- a/components/policy/core/common/cloud/test/policy_builder.cc +++ b/components/policy/core/common/cloud/test/policy_builder.cc
@@ -402,6 +402,8 @@ policy_data_->set_device_id(kFakeDeviceId); policy_data_->set_state(em::PolicyData::ACTIVE); policy_data_->set_service_account_identity(kFakeServiceAccountIdentity); + policy_data_->set_cec_enabled(true); + policy_data_->set_command_invalidation_topic("fake-topic"); policy_data_->add_user_affiliation_ids(user_affiliation_id1); policy_data_->add_user_affiliation_ids(user_affiliation_id2); }
diff --git a/components/policy/core/common/features.cc b/components/policy/core/common/features.cc index 3d22f424..a2ce05a 100644 --- a/components/policy/core/common/features.cc +++ b/components/policy/core/common/features.cc
@@ -18,4 +18,8 @@ "EnhancedSecurityEventFields", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kUseCECFlagInPolicyData, + "UseCECFlagInPolicyData", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace policy::features
diff --git a/components/policy/core/common/features.h b/components/policy/core/common/features.h index 969677d2..f39f089 100644 --- a/components/policy/core/common/features.h +++ b/components/policy/core/common/features.h
@@ -23,6 +23,9 @@ // Enables the addition of new security fields for SecOps. POLICY_EXPORT BASE_DECLARE_FEATURE(kEnhancedSecurityEventFields); +// Controls if we can use the cec flag in PolicyData. +POLICY_EXPORT BASE_DECLARE_FEATURE(kUseCECFlagInPolicyData); + } // namespace policy::features #endif // COMPONENTS_POLICY_CORE_COMMON_FEATURES_H_
diff --git a/components/policy/core/common/remote_commands/remote_commands_service.cc b/components/policy/core/common/remote_commands/remote_commands_service.cc index 55be4abe..e3075bd 100644 --- a/components/policy/core/common/remote_commands/remote_commands_service.cc +++ b/components/policy/core/common/remote_commands/remote_commands_service.cc
@@ -11,15 +11,19 @@ #include "base/check_is_test.h" #include "base/containers/contains.h" +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/metrics/histogram_functions.h" #include "base/strings/stringprintf.h" +#include "build/build_config.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/cloud/cloud_policy_validator.h" #include "components/policy/core/common/cloud/enterprise_metrics.h" +#include "components/policy/core/common/cloud/policy_invalidation_util.h" +#include "components/policy/core/common/features.h" #include "components/policy/core/common/policy_logger.h" #include "components/policy/core/common/remote_commands/remote_commands_factory.h" #include "components/policy/core/common/remote_commands/remote_commands_fetch_reason.h" @@ -214,13 +218,7 @@ bool RemoteCommandsService::FetchRemoteCommands( RemoteCommandsFetchReason reason) { - if (!client_->is_registered()) { - LOG_POLICY(WARNING, REMOTE_COMMANDS) << "Client is not registered."; - return false; - } - - if (command_fetch_in_progress_) { - has_enqueued_fetch_request_ = true; + if (!CanFetchRemoteCommands()) { return false; } @@ -370,6 +368,43 @@ queue_.AddJob(std::move(job)); } +bool RemoteCommandsService::CanFetchRemoteCommands() { + if (!client_->is_registered()) { + LOG_POLICY(WARNING, REMOTE_COMMANDS) << "Client is not registered."; + return false; + } + +#if !BUILDFLAG(IS_CHROMEOS) + // We need to check if CEC is enabled. + if (scope_ == PolicyInvalidationScope::kUser) { + const em::PolicyData* policy = store_->policy(); + if (!policy) { + LOG_POLICY(WARNING, REMOTE_COMMANDS) << "Policy is not available."; + return false; + } + + if (base::FeatureList::IsEnabled(features::kUseCECFlagInPolicyData)) { + if (!policy->cec_enabled()) { + LOG_POLICY(WARNING, REMOTE_COMMANDS) << "CEC is not enabled."; + return false; + } + } else { + invalidation::Topic topic; + if (!GetRemoteCommandTopicFromPolicy(*policy, &topic)) { + LOG_POLICY(WARNING, REMOTE_COMMANDS) << "CEC is not enabled."; + return false; + } + } + } +#endif // !BUILDFLAG(IS_CHROMEOS) + + if (command_fetch_in_progress_) { + has_enqueued_fetch_request_ = true; + return false; + } + return true; +} + void RemoteCommandsService::OnJobStarted(RemoteCommandJob* command) {} void RemoteCommandsService::OnJobFinished(RemoteCommandJob* command) {
diff --git a/components/policy/core/common/remote_commands/remote_commands_service.h b/components/policy/core/common/remote_commands/remote_commands_service.h index a16a3a3..b73e203 100644 --- a/components/policy/core/common/remote_commands/remote_commands_service.h +++ b/components/policy/core/common/remote_commands/remote_commands_service.h
@@ -136,6 +136,13 @@ void EnqueueCommand(const enterprise_management::RemoteCommand& command, const enterprise_management::SignedData& signed_command); + // Returns true if we can fetch remote commands. + // We can't fetch remote command for many reasons, such as + // - the client is not registered. + // - there is a command fetch on going. + // - CEC is not enabled. + bool CanFetchRemoteCommands(); + // RemoteCommandsQueue::Observer: void OnJobStarted(RemoteCommandJob* command) override; void OnJobFinished(RemoteCommandJob* command) override;
diff --git a/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc b/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc index 2102826a..37e65ff 100644 --- a/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc +++ b/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc
@@ -18,12 +18,15 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/repeating_test_future.h" +#include "base/test/scoped_feature_list.h" #include "base/test/test_future.h" #include "base/test/test_mock_time_task_runner.h" +#include "build/build_config.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" #include "components/policy/core/common/cloud/test/policy_builder.h" +#include "components/policy/core/common/features.h" #include "components/policy/core/common/remote_commands/remote_command_job.h" #include "components/policy/core/common/remote_commands/remote_commands_factory.h" #include "components/policy/core/common/remote_commands/remote_commands_fetch_reason.h" @@ -250,6 +253,8 @@ public_key.end()); auto policy_data = std::make_unique<em::PolicyData>(); policy_data->set_device_id("acme-device"); + policy_data->set_cec_enabled(true); + policy_data->set_command_invalidation_topic("test_topic"); store_.set_policy_data_for_testing(std::move(policy_data)); } @@ -563,6 +568,41 @@ em::RemoteCommandResult_ResultType_RESULT_IGNORED); } +#if !BUILDFLAG(IS_CHROMEOS) +TEST_P(RemoteCommandsServiceTest, ShouldRejectCommandWithCecDisabled) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kUseCECFlagInPolicyData); + StartServiceWith<MockJobFactory>(); + + auto policy_data = std::make_unique<em::PolicyData>(); + policy_data->set_device_id("acme-device"); + policy_data->set_cec_enabled(false); + store_.set_policy_data_for_testing(std::move(policy_data)); + + if (GetScope() == PolicyInvalidationScope::kUser) { + EXPECT_FALSE(FetchRemoteCommands()); + } else { + EXPECT_TRUE(FetchRemoteCommands()); + } +} + +TEST_P(RemoteCommandsServiceTest, ShouldRejectCommandWithoutTopic) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(features::kUseCECFlagInPolicyData); + StartServiceWith<MockJobFactory>(); + + auto policy_data = std::make_unique<em::PolicyData>(); + policy_data->set_device_id("acme-device"); + store_.set_policy_data_for_testing(std::move(policy_data)); + + if (GetScope() == PolicyInvalidationScope::kUser) { + EXPECT_FALSE(FetchRemoteCommands()); + } else { + EXPECT_TRUE(FetchRemoteCommands()); + } +} +#endif // !BUILDFLAG(IS_CHROMEOS) + class RemoteCommandsServiceHistogramTest : public RemoteCommandsServiceTest { protected: using MetricReceivedRemoteCommand = @@ -676,7 +716,6 @@ EXPECT_TRUE(FetchRemoteCommands()); FlushAllTasks(); - ExpectReceivedCommandsMetrics({MetricReceivedRemoteCommand::kInvalid}); ExpectExecutedCommandsMetrics({}); }
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index 70c43a0..965609de 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -929,6 +929,9 @@ // set for User Policy response. optional K12AgeClassificationMetricsLogSegment k12_age_classification_metrics_log_segment = 39; + + // Indicates whether the domains has CEC enabled. + optional bool cec_enabled = 40; } message ClientActionRequired {
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/EnterpriseRealTimeUrlCheckMode.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/EnterpriseRealTimeUrlCheckMode.yaml index 82a7774..12c8674 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/EnterpriseRealTimeUrlCheckMode.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/EnterpriseRealTimeUrlCheckMode.yaml
@@ -30,11 +30,10 @@ - 0 - 1 type: integer -future_on: -- ios supported_on: - chrome.*:86- - chrome_os:86- - android:136- +- ios:138- tags: [] type: int-enum
diff --git a/components/safe_browsing/core/browser/db/v4_store.cc b/components/safe_browsing/core/browser/db/v4_store.cc index 07c225d..6e631fe 100644 --- a/components/safe_browsing/core/browser/db/v4_store.cc +++ b/components/safe_browsing/core/browser/db/v4_store.cc
@@ -28,8 +28,7 @@ #include "components/safe_browsing/core/browser/db/v4_store.pb.h" #include "components/safe_browsing/core/common/features.h" #include "components/safe_browsing/core/common/proto/webui.pb.h" -#include "crypto/secure_hash.h" -#include "crypto/sha2.h" +#include "crypto/hash.h" #include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" @@ -697,7 +696,7 @@ bool calculate_checksum = !expected_checksum.empty(); if (calculate_checksum && - (expected_checksum.size() != crypto::kSHA256Length)) { + (expected_checksum.size() != crypto::hash::kSha256Size)) { return CHECKSUM_MISMATCH_FAILURE; } @@ -720,8 +719,7 @@ // At least one of the maps still has elements that need to be merged into the // new store. - std::unique_ptr<crypto::SecureHash> checksum_ctx( - crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + crypto::hash::Hasher checksum_ctx(crypto::hash::HashKind::kSha256); // Keep track of the number of elements picked from the old map. This is used // to determine which elements to drop based on the raw_removals. Note that @@ -760,8 +758,7 @@ next_smallest_prefix_old); if (calculate_checksum) { - checksum_ctx->Update(next_smallest_prefix_old.data(), - next_smallest_prefix_size); + checksum_ctx.Update(next_smallest_prefix_old); } } else { // Element not added to new map. Move the removals iterator forward. @@ -781,8 +778,7 @@ next_smallest_prefix_additions); if (calculate_checksum) { - checksum_ctx->Update(next_smallest_prefix_additions.data(), - next_smallest_prefix_size); + checksum_ctx.Update(next_smallest_prefix_additions); } // Update the iterator map, which means that we have merged one hash @@ -802,21 +798,17 @@ } if (calculate_checksum) { - std::array<char, crypto::kSHA256Length> checksum; - checksum_ctx->Finish(checksum.data(), checksum.size()); - for (size_t i = 0; i < crypto::kSHA256Length; i++) { - if (checksum[i] != expected_checksum[i]) { + std::array<uint8_t, crypto::hash::kSha256Size> checksum; + checksum_ctx.Finish(checksum); + auto expected = base::as_byte_span(expected_checksum); + if (expected != checksum) { #if DCHECK_IS_ON() - std::string checksum_b64 = - base::Base64Encode(base::as_byte_span(checksum)); - std::string expected_checksum_b64 = - base::Base64Encode(expected_checksum); - DVLOG(1) << "Failure: Checksum mismatch: calculated: " << checksum_b64 - << "; expected: " << expected_checksum_b64 - << "; store: " << *this; + std::string checksum_b64 = base::Base64Encode(checksum); + std::string expected_b64 = base::Base64Encode(expected); + DVLOG(1) << "Failure: Checksum mismatch: calculated: " << checksum_b64 + << "; expected: " << expected_b64 << "; store: " << *this; #endif - return CHECKSUM_MISMATCH_FAILURE; - } + return CHECKSUM_MISMATCH_FAILURE; } } @@ -988,8 +980,7 @@ bool has_unmerged = GetNextSmallestUnmergedPrefix(map_view, iterator_map, &next_smallest_prefix); - std::unique_ptr<crypto::SecureHash> checksum_ctx( - crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + crypto::hash::Hasher checksum_ctx(crypto::hash::HashKind::kSha256); while (has_unmerged) { #if DCHECK_IS_ON() // This is expensive (see https://crbug.com/373928217), but it's @@ -1027,33 +1018,28 @@ // prefix of size |next_smallest_prefix_size| from hash_prefix_map_. iterator_map[next_smallest_prefix_size] += next_smallest_prefix_size; - checksum_ctx->Update(next_smallest_prefix.data(), - next_smallest_prefix_size); + checksum_ctx.Update(next_smallest_prefix); // Find the next smallest unmerged element in the map. has_unmerged = GetNextSmallestUnmergedPrefix(map_view, iterator_map, &next_smallest_prefix); } - std::array<char, crypto::kSHA256Length> checksum; - checksum_ctx->Finish(checksum.data(), checksum.size()); - for (size_t i = 0; i < crypto::kSHA256Length; i++) { - if (checksum[i] != expected_checksum_[i]) { - RecordApplyUpdateResult(kReadFromDisk, CHECKSUM_MISMATCH_FAILURE, - store_path_); + std::array<uint8_t, crypto::hash::kSha256Size> checksum; + checksum_ctx.Finish(checksum); + auto expected = base::as_byte_span(expected_checksum_); + if (expected != checksum) { + RecordApplyUpdateResult(kReadFromDisk, CHECKSUM_MISMATCH_FAILURE, + store_path_); #if DCHECK_IS_ON() - std::string checksum_b64 = - base::Base64Encode(base::as_byte_span(checksum)); - std::string expected_checksum_b64 = - base::Base64Encode(expected_checksum_); - DVLOG(1) << "Failure: Checksum mismatch: calculated: " << checksum_b64 - << "; expected: " << expected_checksum_b64 - << "; store: " << *this; + std::string checksum_b64 = base::Base64Encode(base::as_byte_span(checksum)); + std::string expected_checksum_b64 = base::Base64Encode(expected_checksum_); + DVLOG(1) << "Failure: Checksum mismatch: calculated: " << checksum_b64 + << "; expected: " << expected_checksum_b64 << "; store: " << *this; #endif - RecordVerifyChecksumDuration(kReadFromDisk, thread_timer.Elapsed(), - store_path_); - return false; - } + RecordVerifyChecksumDuration(kReadFromDisk, thread_timer.Elapsed(), + store_path_); + return false; } RecordVerifyChecksumDuration(kReadFromDisk, thread_timer.Elapsed(),
diff --git a/components/services/on_device_translation/test/mock_translate_kit_lib.cc b/components/services/on_device_translation/test/mock_translate_kit_lib.cc index f11fd07f..d744254 100644 --- a/components/services/on_device_translation/test/mock_translate_kit_lib.cc +++ b/components/services/on_device_translation/test/mock_translate_kit_lib.cc
@@ -247,7 +247,7 @@ TranslateKitLanguage target_lang) { CHECK(kit_ptr); if (std::string_view(source_lang.language_code, - source_lang.language_code_size) == "cause_crash") { + source_lang.language_code_size) == "crash") { LOG(ERROR) << "Intentionally terminating current process to simulate" " the on device translation service crash for testing."; // Use `TerminateCurrentProcessImmediately()` instead of `CHECK()` to avoid
diff --git a/components/user_data_importer/DEPS b/components/user_data_importer/DEPS new file mode 100644 index 0000000..2da443e --- /dev/null +++ b/components/user_data_importer/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+components/password_manager/core/browser", +] +
diff --git a/components/user_data_importer/utility/BUILD.gn b/components/user_data_importer/utility/BUILD.gn new file mode 100644 index 0000000..4209eea --- /dev/null +++ b/components/user_data_importer/utility/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/rust/rust_static_library.gni") + +source_set("safari_data_importer") { + sources = [ + "safari_data_importer.cc", + "safari_data_importer.h", + ] + + deps = [ "//components/password_manager/core/browser/import:importer" ] +}
diff --git a/components/user_data_importer/utility/safari_data_importer.cc b/components/user_data_importer/utility/safari_data_importer.cc new file mode 100644 index 0000000..e2d8a6d --- /dev/null +++ b/components/user_data_importer/utility/safari_data_importer.cc
@@ -0,0 +1,82 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/user_data_importer/utility/safari_data_importer.h" + +namespace user_data_importer { + +SafariDataImporter::SafariDataImporter( + password_manager::SavedPasswordsPresenter* presenter) + : password_importer_( + std::make_unique<password_manager::PasswordImporter>(presenter)) {} + +SafariDataImporter::~SafariDataImporter() = default; + +void SafariDataImporter::Import( + const base::FilePath& path, + password_manager::PasswordImporter::ImportResultsCallback + passwords_callback, + ImportCallback bookmarks_callback, + ImportCallback history_callback, + ImportCallback payment_cards_callback) { + std::string zip_filename = path.MaybeAsASCII(); + if (zip_filename.empty()) { + password_manager::ImportResults results; + std::move(passwords_callback).Run(std::move(results)); + std::move(bookmarks_callback).Run(0); + std::move(history_callback).Run(0); + std::move(payment_cards_callback).Run(0); + return; + } + + // Passwords import may require conflict resolution, so it is done first. + ImportPasswords(zip_filename, std::move(passwords_callback)); + + // Launch payment cards and bookmarks import processes. + ImportPaymentCards(zip_filename, std::move(payment_cards_callback)); + ImportBookmarks(zip_filename, std::move(bookmarks_callback)); + + // History import may require synchronously reading from the file, so it is + // done last. + ImportHistory(zip_filename, std::move(history_callback)); +} + +void SafariDataImporter::ImportPasswords( + const std::string& zip_filename, + password_manager::PasswordImporter::ImportResultsCallback + passwords_callback) { + // TODO(crbug.com/407587751): Import passwords. + password_manager::ImportResults results; + std::move(passwords_callback).Run(std::move(results)); +} + +void SafariDataImporter::ImportPaymentCards( + const std::string& zip_filename, + ImportCallback payment_cards_callback) { + // TODO(crbug.com/407587751): Import payment cards. + std::move(payment_cards_callback).Run(0); +} + +void SafariDataImporter::ImportBookmarks(const std::string& zip_filename, + ImportCallback bookmarks_callback) { + // TODO(crbug.com/407587751): Import bookmarks. + std::move(bookmarks_callback).Run(0); +} + +void SafariDataImporter::ImportHistory(const std::string& zip_filename, + ImportCallback history_callback) { + // TODO(crbug.com/407587751): Import history. + std::move(history_callback).Run(0); +} + +void SafariDataImporter::ResolvePasswordConflicts( + const std::vector<int>& selected_ids, + password_manager::PasswordImporter::ImportResultsCallback + passwords_callback) { + // TODO(crbug.com/407587751): Resolve conflicts. + password_manager::ImportResults results; + std::move(passwords_callback).Run(std::move(results)); +} + +} // namespace user_data_importer
diff --git a/components/user_data_importer/utility/safari_data_importer.h b/components/user_data_importer/utility/safari_data_importer.h new file mode 100644 index 0000000..c1fa159 --- /dev/null +++ b/components/user_data_importer/utility/safari_data_importer.h
@@ -0,0 +1,70 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_USER_DATA_IMPORTER_UTILITY_SAFARI_DATA_IMPORTER_H_ +#define COMPONENTS_USER_DATA_IMPORTER_UTILITY_SAFARI_DATA_IMPORTER_H_ + +#include "components/password_manager/core/browser/import/password_importer.h" + +namespace user_data_importer { + +class SafariDataImporter { + public: + // A callback used to obtain the number of successfully imported bookmarks, + // urls (for history import) or payment cards. + using ImportCallback = base::OnceCallback<void(int)>; + + SafariDataImporter(password_manager::SavedPasswordsPresenter* presenter); + ~SafariDataImporter(); + + // Attempts to import various data types (passwords, payment cards, bookmarks + // and history) from the file provided in "path". Each data type is optional + // may or may not be present in the file. "passwords_callback" is called at + // the end of the password import process and will be provided a list of + // successful imports as well as conflicts and errors. + // "bookmarks_callback", "history_callback" and "payment_cards_callback" will + // be called at the end of the import processes of each type of data to return + // the number of successful imports. + void Import(const base::FilePath& path, + password_manager::PasswordImporter::ImportResultsCallback + passwords_callback, + ImportCallback bookmarks_callback, + ImportCallback history_callback, + ImportCallback payment_cards_callback); + + // Can be called after calling "Import" in order to import passwords which + // were originally not imported due to conflicts. "selected_ids" provides the + // list of passwords to import. + void ResolvePasswordConflicts( + const std::vector<int>& selected_ids, + password_manager::PasswordImporter::ImportResultsCallback + passwords_callback); + + private: + friend class SafariDataImporterTest; + + // Attempts to import bookmarks from the file provided by "zip_filename". + void ImportBookmarks(const std::string& zip_filename, + ImportCallback bookmarks_callback); + + // Attempts to import history from the file provided by "zip_filename". + void ImportHistory(const std::string& zip_filename, + ImportCallback history_callback); + + // Attempts to import passwords from the file provided by "zip_filename". + void ImportPasswords(const std::string& zip_filename, + password_manager::PasswordImporter::ImportResultsCallback + results_callback); + + // Attempts to import payment cards from the file provided by "zip_filename". + void ImportPaymentCards(const std::string& zip_filename, + ImportCallback payment_cards_callback); + + // The password importer used to import passwords and resolve conflicts. + std::unique_ptr<password_manager::PasswordImporter> password_importer_; +}; + +} // namespace user_data_importer + +#endif // COMPONENTS_USER_DATA_IMPORTER_UTILITY_SAFARI_DATA_IMPORTER_H_
diff --git a/components/visited_url_ranking/internal/session_url_visit_data_fetcher.cc b/components/visited_url_ranking/internal/session_url_visit_data_fetcher.cc index 8a887777..dc91ef61 100644 --- a/components/visited_url_ranking/internal/session_url_visit_data_fetcher.cc +++ b/components/visited_url_ranking/internal/session_url_visit_data_fetcher.cc
@@ -114,23 +114,27 @@ } std::map<URLMergeKey, URLVisitAggregate::TabData> url_visit_tab_data_map; - if (base::Contains(fetcher_sources, Source::kForeign)) { - std::vector<raw_ptr<const sync_sessions::SyncedSession, VectorExperimental>> - sessions; - open_tabs_ui_delegate->GetAllForeignSessions(&sessions); - for (const sync_sessions::SyncedSession* session : sessions) { - AddAggregateVisitDataFromSession( - session, Source::kForeign, options.begin_time, url_visit_tab_data_map, - config.deduplication_helper); - } + const sync_sessions::SyncedSession* local_session = nullptr; + open_tabs_ui_delegate->GetLocalSession(&local_session); + std::vector<raw_ptr<const sync_sessions::SyncedSession, VectorExperimental>> + sessions; + open_tabs_ui_delegate->GetAllForeignSessions(&sessions); + if (local_session) { + sessions.push_back(local_session); } - if (base::Contains(fetcher_sources, Source::kLocal)) { - const sync_sessions::SyncedSession* local_session = nullptr; - open_tabs_ui_delegate->GetLocalSession(&local_session); - if (local_session) { + for (const sync_sessions::SyncedSession* session : sessions) { + if (local_session && + local_session->GetSessionName() == session->GetSessionName()) { + if (!base::Contains(fetcher_sources, Source::kLocal)) { + continue; + } AddAggregateVisitDataFromSession( local_session, Source::kLocal, options.begin_time, url_visit_tab_data_map, config.deduplication_helper); + } else if (base::Contains(fetcher_sources, Source::kForeign)) { + AddAggregateVisitDataFromSession( + session, Source::kForeign, options.begin_time, url_visit_tab_data_map, + config.deduplication_helper); } }
diff --git a/components/visited_url_ranking/internal/session_url_visit_data_fetcher_unittest.cc b/components/visited_url_ranking/internal/session_url_visit_data_fetcher_unittest.cc index 6725424..772cbcd 100644 --- a/components/visited_url_ranking/internal/session_url_visit_data_fetcher_unittest.cc +++ b/components/visited_url_ranking/internal/session_url_visit_data_fetcher_unittest.cc
@@ -209,22 +209,27 @@ } TEST_F(SessionURLVisitDataFetcherTest, FetchURLVisitDataDefaultSources) { - std::vector<std::unique_ptr<sync_sessions::SyncedSession>> sample_sessions; - sample_sessions.push_back(GetSampleSession()); + std::vector<std::unique_ptr<sync_sessions::SyncedSession>> + local_sample_sessions; + std::vector<std::unique_ptr<sync_sessions::SyncedSession>> + foreign_sample_sessions; + local_sample_sessions.push_back(GetSampleSession()); + foreign_sample_sessions.push_back(GetSampleSession()); SetSessionSyncServiceExpectations(); EXPECT_CALL(open_tabs_ui_delegate_, GetLocalSession(testing::_)) .WillOnce(testing::Invoke( - [&sample_sessions](const sync_sessions::SyncedSession** local) { - *local = sample_sessions[0].get(); + [&local_sample_sessions](const sync_sessions::SyncedSession** local) { + local_sample_sessions[0]->SetSessionName("Local Session"); + *local = local_sample_sessions[0].get(); return true; })); EXPECT_CALL(open_tabs_ui_delegate_, GetAllForeignSessions(testing::_)) .WillOnce(testing::Invoke( - [&sample_sessions]( + [&foreign_sample_sessions]( std::vector<raw_ptr<const sync_sessions::SyncedSession, VectorExperimental>>* sessions) { - for (auto& sample_session : sample_sessions) { + for (auto& sample_session : foreign_sample_sessions) { sessions->push_back(sample_session.get()); } return true; @@ -305,4 +310,40 @@ false); } +TEST_F(SessionURLVisitDataFetcherTest, + FetchURLVisitDataDefaultSourcesSameSession) { + std::vector<std::unique_ptr<sync_sessions::SyncedSession>> sample_sessions; + sample_sessions.push_back(GetSampleSession()); + + SetSessionSyncServiceExpectations(); + EXPECT_CALL(open_tabs_ui_delegate_, GetLocalSession(testing::_)) + .WillOnce(testing::Invoke( + [&sample_sessions](const sync_sessions::SyncedSession** local) { + *local = sample_sessions[0].get(); + return true; + })); + EXPECT_CALL(open_tabs_ui_delegate_, GetAllForeignSessions(testing::_)) + .WillOnce(testing::Invoke( + [&sample_sessions]( + std::vector<raw_ptr<const sync_sessions::SyncedSession, + VectorExperimental>>* sessions) { + for (auto& sample_session : sample_sessions) { + sessions->push_back(sample_session.get()); + } + return true; + })); + + base::Time yesterday = base::Time::Now() - base::Days(1); + auto result = FetchAndGetResult(FetchOptions( + { + {URLType::kActiveRemoteTab, {.age_limit = base::Days(1)}}, + }, + { + {Fetcher::kSession, {Source::kForeign}}, + }, + yesterday)); + EXPECT_EQ(result.status, FetchResult::Status::kSuccess); + EXPECT_EQ(result.data.size(), 0u); +} + } // namespace visited_url_ranking
diff --git a/content/browser/ai/echo_ai_manager_impl.cc b/content/browser/ai/echo_ai_manager_impl.cc index 6abbbd8..47d34f7a 100644 --- a/content/browser/ai/echo_ai_manager_impl.cc +++ b/content/browser/ai/echo_ai_manager_impl.cc
@@ -53,6 +53,47 @@ is_language_supported(output); } +// Returns whether optional LanguageModel expected_inputs or expected_outputs +// vectors contain only supported languages. Returns true for absent languages. +bool AreExpectedLanguagesSupported( + const std::optional<std::vector<blink::mojom::AILanguageModelExpectedPtr>>& + expected_vector) { + if (!expected_vector) { + return true; + } + for (const auto& expected_entry : expected_vector.value()) { + if (expected_entry->languages.has_value() && + !IsLanguagesSupported(expected_entry->languages.value())) { + return false; + } + } + return true; +} + +// Returns whether `options` contains any unsupported AILanguageModelPromptType. +bool HasUnsupportedType( + const blink::mojom::AILanguageModelCreateOptionsPtr& options) { + bool has_unsupported_type = false; + if (options) { + if (options->expected_inputs.has_value()) { + for (const auto& expected_input : options->expected_inputs.value()) { + has_unsupported_type |= + expected_input->type != + blink::mojom::AILanguageModelPromptType::kText && + !base::FeatureList::IsEnabled( + blink::features::kAIPromptAPIMultimodalInput); + } + } + if (options->expected_outputs.has_value()) { + for (const auto& expected_output : options->expected_outputs.value()) { + has_unsupported_type |= expected_output->type != + blink::mojom::AILanguageModelPromptType::kText; + } + } + } + return has_unsupported_type; +} + } // namespace EchoAIManagerImpl::EchoAIManagerImpl() = default; @@ -69,23 +110,16 @@ void EchoAIManagerImpl::CanCreateLanguageModel( blink::mojom::AILanguageModelCreateOptionsPtr options, CanCreateLanguageModelCallback callback) { - if (options->expected_inputs.has_value()) { - for (const auto& expected_input : options->expected_inputs.value()) { - if (expected_input->type != - blink::mojom::AILanguageModelPromptType::kText && - !base::FeatureList::IsEnabled( - blink::features::kAIPromptAPIMultimodalInput)) { - std::move(callback).Run(blink::mojom::ModelAvailabilityCheckResult:: - kUnavailableModelAdaptationNotAvailable); - return; - } - if (expected_input->languages.has_value() && - !IsLanguagesSupported(expected_input->languages.value())) { - std::move(callback).Run(blink::mojom::ModelAvailabilityCheckResult:: - kUnavailableUnsupportedLanguage); - return; - } - } + if (HasUnsupportedType(options)) { + std::move(callback).Run(blink::mojom::ModelAvailabilityCheckResult:: + kUnavailableModelAdaptationNotAvailable); + return; + } + if (options && (!AreExpectedLanguagesSupported(options->expected_inputs) || + !AreExpectedLanguagesSupported(options->expected_outputs))) { + std::move(callback).Run(blink::mojom::ModelAvailabilityCheckResult:: + kUnavailableUnsupportedLanguage); + return; } std::move(callback).Run( @@ -115,6 +149,17 @@ } } + if (HasUnsupportedType(options)) { + client_remote->OnError( + blink::mojom::AIManagerCreateClientError::kUnableToCreateSession); + return; + } + if (options && (!AreExpectedLanguagesSupported(options->expected_inputs) || + !AreExpectedLanguagesSupported(options->expected_outputs))) { + client_remote->OnError( + blink::mojom::AIManagerCreateClientError::kUnsupportedLanguage); + return; + } base::flat_set<blink::mojom::AILanguageModelPromptType> enabled_input_types; if (options->expected_inputs.has_value()) { for (const auto& expected_input : options->expected_inputs.value()) {
diff --git a/content/browser/compute_pressure/pressure_service_base.cc b/content/browser/compute_pressure/pressure_service_base.cc index dc9e979..0fbbdb74 100644 --- a/content/browser/compute_pressure/pressure_service_base.cc +++ b/content/browser/compute_pressure/pressure_service_base.cc
@@ -17,6 +17,10 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "services/device/public/cpp/device_features.h" +#if BUILDFLAG(IS_CHROMEOS) +#include "base/check.h" +#endif + namespace { constexpr char kVirtualPressureSourceStartConsoleMessage[] = @@ -66,6 +70,13 @@ // static // https://www.w3.org/TR/compute-pressure/#dfn-document-has-implicit-focus bool PressureServiceBase::HasImplicitFocus(RenderFrameHost* render_frame_host) { +#if BUILDFLAG(IS_CHROMEOS) + // TODO: http://crbug.com/407801065 + // On ChromeOS, in rare occasions render_frame_host may be nullptr. The + // following DUMP_WILL_BE_CHECK() is used to provide additional information + // for diagnosis. + DUMP_WILL_BE_CHECK(render_frame_host); +#endif if (!render_frame_host) { return false; }
diff --git a/gpu/vulkan/skia_vk_memory_allocator_impl.cc b/gpu/vulkan/skia_vk_memory_allocator_impl.cc index 3573ad6..65a8cc10 100644 --- a/gpu/vulkan/skia_vk_memory_allocator_impl.cc +++ b/gpu/vulkan/skia_vk_memory_allocator_impl.cc
@@ -11,227 +11,214 @@ #include "base/feature_list.h" #include "base/trace_event/trace_event.h" -#include "gpu/vulkan/vma_wrapper.h" #include "gpu/vulkan/vulkan_device_queue.h" #include "gpu/vulkan/vulkan_function_pointers.h" -#include "third_party/skia/include/gpu/vk/VulkanMemoryAllocator.h" -#include "third_party/skia/include/gpu/vk/VulkanTypes.h" namespace gpu { -namespace { +SkiaVulkanMemoryAllocator::SkiaVulkanMemoryAllocator(VmaAllocator allocator) + : allocator_(allocator) {} -class SkiaVulkanMemoryAllocator : public skgpu::VulkanMemoryAllocator { - public: - explicit SkiaVulkanMemoryAllocator(VmaAllocator allocator) - : allocator_(allocator) {} - ~SkiaVulkanMemoryAllocator() override = default; +VkResult SkiaVulkanMemoryAllocator::allocateImageMemory( + VkImage image, + uint32_t flags, + skgpu::VulkanBackendMemory* backend_memory) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::allocateMemoryForImage"); + VmaAllocationCreateInfo info = { + .flags = 0, + .usage = VMA_MEMORY_USAGE_UNKNOWN, + .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .preferredFlags = 0, + .memoryTypeBits = 0, + .pool = VK_NULL_HANDLE, + .pUserData = nullptr, + }; - SkiaVulkanMemoryAllocator(const SkiaVulkanMemoryAllocator&) = delete; - SkiaVulkanMemoryAllocator& operator=(const SkiaVulkanMemoryAllocator&) = - delete; - - private: - VkResult allocateImageMemory( - VkImage image, - uint32_t flags, - skgpu::VulkanBackendMemory* backend_memory) override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::allocateMemoryForImage"); - VmaAllocationCreateInfo info = { - .flags = 0, - .usage = VMA_MEMORY_USAGE_UNKNOWN, - .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .preferredFlags = 0, - .memoryTypeBits = 0, - .pool = VK_NULL_HANDLE, - .pUserData = nullptr, - }; - - if (kDedicatedAllocation_AllocationPropertyFlag & flags) { - info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - } - - if (kLazyAllocation_AllocationPropertyFlag & flags) { - // If the caller asked for lazy allocation then they already set up the - // VkImage for it so we must require the lazy property. - info.requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; - // Make the transient allocation a dedicated allocation for tracking - // memory separately. - info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - } - - if (kProtected_AllocationPropertyFlag & flags) { - info.requiredFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT; - } - - VmaAllocation allocation; - VkResult result = vma::AllocateMemoryForImage(allocator_, image, &info, - &allocation, nullptr); - if (VK_SUCCESS == result) { - *backend_memory = - reinterpret_cast<skgpu::VulkanBackendMemory>(allocation); - } - - return result; + if (kDedicatedAllocation_AllocationPropertyFlag & flags) { + info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } - VkResult allocateBufferMemory( - VkBuffer buffer, - BufferUsage usage, - uint32_t flags, - skgpu::VulkanBackendMemory* backend_memory) override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::allocateMemoryForBuffer"); - VmaAllocationCreateInfo info = { - .flags = 0, - .usage = VMA_MEMORY_USAGE_UNKNOWN, - .memoryTypeBits = 0, - .pool = VK_NULL_HANDLE, - .pUserData = nullptr, - }; - - switch (usage) { - case BufferUsage::kGpuOnly: - info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - info.preferredFlags = 0; - break; - case BufferUsage::kCpuWritesGpuReads: - info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - break; - case BufferUsage::kTransfersFromCpuToGpu: - info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - info.preferredFlags = 0; - break; - case BufferUsage::kTransfersFromGpuToCpu: - info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT; - break; - } - - if (kDedicatedAllocation_AllocationPropertyFlag & flags) { - info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - } - - if ((kLazyAllocation_AllocationPropertyFlag & flags) && - BufferUsage::kGpuOnly == usage) { - info.preferredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; - // Make the transient allocation a dedicated allocation for tracking - // memory separately. - info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - } - - if (kPersistentlyMapped_AllocationPropertyFlag & flags) { - SkASSERT(BufferUsage::kGpuOnly != usage); - info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT; - } - - VmaAllocation allocation; - VkResult result = vma::AllocateMemoryForBuffer(allocator_, buffer, &info, - &allocation, nullptr); - if (VK_SUCCESS == result) { - *backend_memory = - reinterpret_cast<skgpu::VulkanBackendMemory>(allocation); - } - - return result; + if (kLazyAllocation_AllocationPropertyFlag & flags) { + // If the caller asked for lazy allocation then they already set up the + // VkImage for it so we must require the lazy property. + info.requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; + // Make the transient allocation a dedicated allocation for tracking + // memory separately. + info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } - void freeMemory(const skgpu::VulkanBackendMemory& memory) override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::freeMemory"); - vma::FreeMemory(allocator_, reinterpret_cast<const VmaAllocation>(memory)); + if (kProtected_AllocationPropertyFlag & flags) { + info.requiredFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT; } - void getAllocInfo(const skgpu::VulkanBackendMemory& memory, - skgpu::VulkanAlloc* alloc) const override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::getAllocInfo"); - const VmaAllocation allocation = - reinterpret_cast<const VmaAllocation>(memory); - VmaAllocationInfo vma_info; - vma::GetAllocationInfo(allocator_, allocation, &vma_info); - - VkMemoryPropertyFlags mem_flags; - vma::GetMemoryTypeProperties(allocator_, vma_info.memoryType, &mem_flags); - - uint32_t flags = 0; - if (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT & mem_flags) { - flags |= skgpu::VulkanAlloc::kMappable_Flag; - } - if (!(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & mem_flags)) { - flags |= skgpu::VulkanAlloc::kNoncoherent_Flag; - } - if (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT & mem_flags) { - flags |= skgpu::VulkanAlloc::kLazilyAllocated_Flag; - } - - alloc->fMemory = vma_info.deviceMemory; - alloc->fOffset = vma_info.offset; - alloc->fSize = vma_info.size; - alloc->fFlags = flags; - alloc->fBackendMemory = memory; + VmaAllocation allocation; + VkResult result = vma::AllocateMemoryForImage(allocator_, image, &info, + &allocation, nullptr); + if (VK_SUCCESS == result) { + *backend_memory = reinterpret_cast<skgpu::VulkanBackendMemory>(allocation); } - VkResult mapMemory(const skgpu::VulkanBackendMemory& memory, - void** data) override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::mapMemory"); - const VmaAllocation allocation = - reinterpret_cast<const VmaAllocation>(memory); - return vma::MapMemory(allocator_, allocation, data); + return result; +} + +VkResult SkiaVulkanMemoryAllocator::allocateBufferMemory( + VkBuffer buffer, + BufferUsage usage, + uint32_t flags, + skgpu::VulkanBackendMemory* backend_memory) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::allocateMemoryForBuffer"); + VmaAllocationCreateInfo info = { + .flags = 0, + .usage = VMA_MEMORY_USAGE_UNKNOWN, + .memoryTypeBits = 0, + .pool = VK_NULL_HANDLE, + .pUserData = nullptr, + }; + + switch (usage) { + case BufferUsage::kGpuOnly: + info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + info.preferredFlags = 0; + break; + case BufferUsage::kCpuWritesGpuReads: + info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + case BufferUsage::kTransfersFromCpuToGpu: + info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + info.preferredFlags = 0; + break; + case BufferUsage::kTransfersFromGpuToCpu: + info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + break; } - void unmapMemory(const skgpu::VulkanBackendMemory& memory) override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::unmapMemory"); - const VmaAllocation allocation = - reinterpret_cast<const VmaAllocation>(memory); - vma::UnmapMemory(allocator_, allocation); + if (kDedicatedAllocation_AllocationPropertyFlag & flags) { + info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } - VkResult flushMemory(const skgpu::VulkanBackendMemory& memory, - VkDeviceSize offset, - VkDeviceSize size) override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::flushMappedMemory"); - const VmaAllocation allocation = - reinterpret_cast<const VmaAllocation>(memory); - return vma::FlushAllocation(allocator_, allocation, offset, size); + if ((kLazyAllocation_AllocationPropertyFlag & flags) && + BufferUsage::kGpuOnly == usage) { + info.preferredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; + // Make the transient allocation a dedicated allocation for tracking + // memory separately. + info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } - VkResult invalidateMemory(const skgpu::VulkanBackendMemory& memory, - VkDeviceSize offset, - VkDeviceSize size) override { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), - "SkiaVulkanMemoryAllocator::invalidateMappedMemory"); - const VmaAllocation allocation = - reinterpret_cast<const VmaAllocation>(memory); - return vma::InvalidateAllocation(allocator_, allocation, offset, size); + if (kPersistentlyMapped_AllocationPropertyFlag & flags) { + SkASSERT(BufferUsage::kGpuOnly != usage); + info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT; } - std::pair<uint64_t, uint64_t> totalAllocatedAndUsedMemory() const override { - uint64_t total_allocated_memory = 0, total_used_memory = 0; - std::array<VmaBudget, VK_MAX_MEMORY_HEAPS> budget; - vma::GetBudget(allocator_, budget.data()); - const VkPhysicalDeviceMemoryProperties* physical_device_memory_properties; - vmaGetMemoryProperties(allocator_, &physical_device_memory_properties); - for (uint32_t i = 0; i < physical_device_memory_properties->memoryHeapCount; - ++i) { - total_allocated_memory += budget[i].statistics.blockBytes; - total_used_memory += budget[i].statistics.allocationBytes; - } - DCHECK_LE(total_used_memory, total_allocated_memory); - return {total_allocated_memory, total_used_memory}; + VmaAllocation allocation; + VkResult result = vma::AllocateMemoryForBuffer(allocator_, buffer, &info, + &allocation, nullptr); + if (VK_SUCCESS == result) { + *backend_memory = reinterpret_cast<skgpu::VulkanBackendMemory>(allocation); } - const VmaAllocator allocator_; -}; + return result; +} -} // namespace +void SkiaVulkanMemoryAllocator::freeMemory( + const skgpu::VulkanBackendMemory& memory) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::freeMemory"); + vma::FreeMemory(allocator_, reinterpret_cast<const VmaAllocation>(memory)); +} + +void SkiaVulkanMemoryAllocator::getAllocInfo( + const skgpu::VulkanBackendMemory& memory, + skgpu::VulkanAlloc* alloc) const { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::getAllocInfo"); + const VmaAllocation allocation = + reinterpret_cast<const VmaAllocation>(memory); + VmaAllocationInfo vma_info; + vma::GetAllocationInfo(allocator_, allocation, &vma_info); + + VkMemoryPropertyFlags mem_flags; + vma::GetMemoryTypeProperties(allocator_, vma_info.memoryType, &mem_flags); + + uint32_t flags = 0; + if (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT & mem_flags) { + flags |= skgpu::VulkanAlloc::kMappable_Flag; + } + if (!(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & mem_flags)) { + flags |= skgpu::VulkanAlloc::kNoncoherent_Flag; + } + if (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT & mem_flags) { + flags |= skgpu::VulkanAlloc::kLazilyAllocated_Flag; + } + + alloc->fMemory = vma_info.deviceMemory; + alloc->fOffset = vma_info.offset; + alloc->fSize = vma_info.size; + alloc->fFlags = flags; + alloc->fBackendMemory = memory; +} + +VkResult SkiaVulkanMemoryAllocator::mapMemory( + const skgpu::VulkanBackendMemory& memory, + void** data) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::mapMemory"); + const VmaAllocation allocation = + reinterpret_cast<const VmaAllocation>(memory); + return vma::MapMemory(allocator_, allocation, data); +} + +void SkiaVulkanMemoryAllocator::unmapMemory( + const skgpu::VulkanBackendMemory& memory) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::unmapMemory"); + const VmaAllocation allocation = + reinterpret_cast<const VmaAllocation>(memory); + vma::UnmapMemory(allocator_, allocation); +} + +VkResult SkiaVulkanMemoryAllocator::flushMemory( + const skgpu::VulkanBackendMemory& memory, + VkDeviceSize offset, + VkDeviceSize size) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::flushMappedMemory"); + const VmaAllocation allocation = + reinterpret_cast<const VmaAllocation>(memory); + return vma::FlushAllocation(allocator_, allocation, offset, size); +} + +VkResult SkiaVulkanMemoryAllocator::invalidateMemory( + const skgpu::VulkanBackendMemory& memory, + VkDeviceSize offset, + VkDeviceSize size) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma"), + "SkiaVulkanMemoryAllocator::invalidateMappedMemory"); + const VmaAllocation allocation = + reinterpret_cast<const VmaAllocation>(memory); + return vma::InvalidateAllocation(allocator_, allocation, offset, size); +} + +std::pair<uint64_t, uint64_t> +SkiaVulkanMemoryAllocator::totalAllocatedAndUsedMemory() const { + uint64_t total_allocated_memory = 0, total_used_memory = 0; + std::array<VmaBudget, VK_MAX_MEMORY_HEAPS> budget; + vma::GetBudget(allocator_, budget.data()); + const VkPhysicalDeviceMemoryProperties* physical_device_memory_properties; + vmaGetMemoryProperties(allocator_, &physical_device_memory_properties); + for (uint32_t i = 0; i < physical_device_memory_properties->memoryHeapCount; + ++i) { + total_allocated_memory += budget[i].statistics.blockBytes; + total_used_memory += budget[i].statistics.allocationBytes; + } + DCHECK_LE(total_used_memory, total_allocated_memory); + return {total_allocated_memory, total_used_memory}; +} sk_sp<skgpu::VulkanMemoryAllocator> CreateSkiaVulkanMemoryAllocator( VulkanDeviceQueue* device_queue) {
diff --git a/gpu/vulkan/skia_vk_memory_allocator_impl.h b/gpu/vulkan/skia_vk_memory_allocator_impl.h index fb87959..af74c646 100644 --- a/gpu/vulkan/skia_vk_memory_allocator_impl.h +++ b/gpu/vulkan/skia_vk_memory_allocator_impl.h
@@ -6,12 +6,55 @@ #define GPU_VULKAN_SKIA_VK_MEMORY_ALLOCATOR_IMPL_H_ #include "base/component_export.h" +#include "gpu/vulkan/vma_wrapper.h" #include "third_party/skia/include/gpu/vk/VulkanMemoryAllocator.h" +#include "third_party/skia/include/gpu/vk/VulkanTypes.h" namespace gpu { class VulkanDeviceQueue; +class SkiaVulkanMemoryAllocator : public skgpu::VulkanMemoryAllocator { + public: + explicit SkiaVulkanMemoryAllocator(VmaAllocator allocator); + ~SkiaVulkanMemoryAllocator() override = default; + + SkiaVulkanMemoryAllocator(const SkiaVulkanMemoryAllocator&) = delete; + SkiaVulkanMemoryAllocator& operator=(const SkiaVulkanMemoryAllocator&) = + delete; + + private: + // skgpu::VulkanMemoryAllocator: + VkResult allocateImageMemory( + VkImage image, + uint32_t flags, + skgpu::VulkanBackendMemory* backend_memory) override; + VkResult allocateBufferMemory( + VkBuffer buffer, + BufferUsage usage, + uint32_t flags, + skgpu::VulkanBackendMemory* backend_memory) override; + void freeMemory(const skgpu::VulkanBackendMemory& memory) override; + + void getAllocInfo(const skgpu::VulkanBackendMemory& memory, + skgpu::VulkanAlloc* alloc) const override; + + VkResult mapMemory(const skgpu::VulkanBackendMemory& memory, + void** data) override; + void unmapMemory(const skgpu::VulkanBackendMemory& memory) override; + + VkResult flushMemory(const skgpu::VulkanBackendMemory& memory, + VkDeviceSize offset, + VkDeviceSize size) override; + VkResult invalidateMemory(const skgpu::VulkanBackendMemory& memory, + VkDeviceSize offset, + VkDeviceSize size) override; + + std::pair<uint64_t, uint64_t> totalAllocatedAndUsedMemory() const override; + + const VmaAllocator allocator_; +}; + COMPONENT_EXPORT(VULKAN) sk_sp<skgpu::VulkanMemoryAllocator> CreateSkiaVulkanMemoryAllocator( VulkanDeviceQueue* device_queue);
diff --git "a/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/properties.json" "b/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/properties.json" index 27c875d0..aa6253e 100644 --- "a/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/properties.json" +++ "b/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/properties.json"
@@ -95,8 +95,7 @@ "bucket": "ci", "builder": "Linux Builder (Wayland)", "project": "chromium" - }, - "run_tests_serially": true + } } } ]
diff --git "a/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/targets/chromium.linux.json" "b/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/targets/chromium.linux.json" index e23e0401..81da044 100644 --- "a/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/targets/chromium.linux.json" +++ "b/infra/config/generated/builders/ci/Linux Builder \050Wayland\051/targets/chromium.linux.json"
@@ -1759,6 +1759,8 @@ "dimensions": { "os": "Ubuntu-24.04" }, + "expiration": 18000, + "hard_timeout": 14400, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 5 },
diff --git a/infra/config/generated/builders/ci/ios-blink-dbg-fyi/targets/chromium.fyi.json b/infra/config/generated/builders/ci/ios-blink-dbg-fyi/targets/chromium.fyi.json index 9aef766..77dc9e91 100644 --- a/infra/config/generated/builders/ci/ios-blink-dbg-fyi/targets/chromium.fyi.json +++ b/infra/config/generated/builders/ci/ios-blink-dbg-fyi/targets/chromium.fyi.json
@@ -789,7 +789,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 + "shards": 10 }, "test": "content_browsertests", "test_id_prefix": "ninja://content/test:content_browsertests/",
diff --git a/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/properties.json b/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/properties.json index 6996a9d..4d69678 100644 --- a/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/properties.json +++ b/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/properties.json
@@ -60,8 +60,7 @@ "bucket": "ci", "builder": "Linux Builder (Wayland)", "project": "chromium" - }, - "run_tests_serially": true + } } } ]
diff --git a/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/targets/chromium.linux.json b/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/targets/chromium.linux.json index f832034..df40371 100644 --- a/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/targets/chromium.linux.json +++ b/infra/config/generated/builders/ci/linux-wayland-mutter-rel-tests/targets/chromium.linux.json
@@ -67,6 +67,8 @@ "dimensions": { "os": "Ubuntu-24.04" }, + "expiration": 18000, + "hard_timeout": 14400, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 5 },
diff --git a/infra/config/generated/builders/try/ios-blink-dbg-fyi/targets/chromium.fyi.json b/infra/config/generated/builders/try/ios-blink-dbg-fyi/targets/chromium.fyi.json index 9aef766..77dc9e91 100644 --- a/infra/config/generated/builders/try/ios-blink-dbg-fyi/targets/chromium.fyi.json +++ b/infra/config/generated/builders/try/ios-blink-dbg-fyi/targets/chromium.fyi.json
@@ -789,7 +789,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 + "shards": 10 }, "test": "content_browsertests", "test_id_prefix": "ninja://content/test:content_browsertests/",
diff --git a/infra/config/generated/builders/try/linux-wayland-mutter-rel/properties.json b/infra/config/generated/builders/try/linux-wayland-mutter-rel/properties.json index 5b0cb6f..7cd1b249c 100644 --- a/infra/config/generated/builders/try/linux-wayland-mutter-rel/properties.json +++ b/infra/config/generated/builders/try/linux-wayland-mutter-rel/properties.json
@@ -63,8 +63,7 @@ "bucket": "ci", "builder": "Linux Builder (Wayland)", "project": "chromium" - }, - "run_tests_serially": true + } } } ]
diff --git a/infra/config/generated/builders/try/linux-wayland-mutter-rel/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-wayland-mutter-rel/targets/chromium.linux.json index 5e00d2c..87dee6d 100644 --- a/infra/config/generated/builders/try/linux-wayland-mutter-rel/targets/chromium.linux.json +++ b/infra/config/generated/builders/try/linux-wayland-mutter-rel/targets/chromium.linux.json
@@ -72,6 +72,8 @@ "dimensions": { "os": "Ubuntu-24.04" }, + "expiration": 18000, + "hard_timeout": 14400, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 5 },
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 3a6dc876..6998949 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -60440,7 +60440,7 @@ ' "led_builder_is_bootstrapped": true,' ' "recipe": "chromium"' '}' - execution_timeout_secs: 25200 + execution_timeout_secs: 10800 build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { @@ -117180,7 +117180,7 @@ ' "led_builder_is_bootstrapped": true,' ' "recipe": "chromium_trybot"' '}' - execution_timeout_secs: 25200 + execution_timeout_secs: 14400 expiration_secs: 7200 grace_period { seconds: 120
diff --git a/infra/config/subprojects/chromium/ci/chromium.linux.star b/infra/config/subprojects/chromium/ci/chromium.linux.star index e63a4c4..e25d6e6 100644 --- a/infra/config/subprojects/chromium/ci/chromium.linux.star +++ b/infra/config/subprojects/chromium/ci/chromium.linux.star
@@ -757,7 +757,6 @@ ) ci.thin_tester( - # TODO(crbug.com/401284929): Put common config with "Linux Tests (Wayland)" in shared bundle. name = "linux-wayland-mutter-rel-tests", # TODO(crbug.com/401284929): Uncomment when enabling gardener_rotations and tree_closing. # branch_selector = branches.selector.LINUX_BRANCHES, @@ -787,8 +786,6 @@ target_platform = builder_config.target_platform.LINUX, ), build_gs_bucket = "chromium-linux-archive", - # TODO(crbug.com/401284929): Remove this when noble pool is increased - run_tests_serially = True, ), targets = targets.bundle( targets = [ @@ -819,9 +816,6 @@ # crbug.com/1473501 retry_only_failed_tests = True, swarming = targets.swarming( - # TODO(crbug.com/401284929) Bump this up to 20 shards and - # possibly revisit the expiration and timeout when more - # noble bots are available. expiration_sec = 18000, hard_timeout_sec = 14400, shards = 10, @@ -833,9 +827,6 @@ # crbug.com/1473501 retry_only_failed_tests = True, swarming = targets.swarming( - # TODO(crbug.com/401284929) Bump this up to 20 shards and - # possibly revisit the expiration and timeout when more - # noble bots are available. expiration_sec = 18000, hard_timeout_sec = 14400, shards = 10, @@ -847,6 +838,8 @@ "--test-launcher-filter-file=../../testing/buildbot/filters/ozone-linux.interactive_ui_tests_mutter.filter", ], swarming = targets.swarming( + expiration_sec = 18000, + hard_timeout_sec = 14400, shards = 5, ), ), @@ -867,8 +860,6 @@ ############################################################################ cq_mirrors_console_view = "mirrors", contact_team_email = "chrome-linux-engprod@google.com", - # TODO(crbug.com/401284929): Remove this when noble pool is increased. - execution_timeout = 7 * time.hour, ) # For documentation, see //services/network/README.md.
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star index cbc4b99..45765ae 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -596,8 +596,6 @@ # "ui/views/widget/.+test.+", # ], # ), - # TODO(crbug.com/401284929): Remove this when noble pool is increased. - execution_timeout = 7 * time.hour, use_clang_coverage = True, )
diff --git a/infra/config/targets/bundles.star b/infra/config/targets/bundles.star index 2f99868..f2dee6b 100644 --- a/infra/config/targets/bundles.star +++ b/infra/config/targets/bundles.star
@@ -5226,7 +5226,7 @@ "--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter", ], swarming = targets.swarming( - shards = 5, + shards = 10, ), ), "content_unittests": targets.mixin(
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 19dae72..35d8fd4 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -7282,6 +7282,18 @@ <message name="IDS_IOS_WEB_INSPECTOR_TITLE" desc="The title of the screen in which the user can enable Web Inspector support, to allow debugging web pages"> Web Inspector </message> + <message name="IDS_IOS_WELCOME_BACK_KEEP_BROWSING_BUTTON" desc="The text of the Keep browsing button on the Welcome Back promo"> + Keep browsing + </message> + <message name="IDS_IOS_WELCOME_BACK_SUBTITLE" desc="The subtitle of the Welcome Back promo"> + Explore helpful features that you've missed + </message> + <message name="IDS_IOS_WELCOME_BACK_TITLE_DEFAULT" desc="The title of the Welcome Back promo for users who are not signed in"> + Welcome back + </message> + <message name="IDS_IOS_WELCOME_BACK_TITLE_SIGNED_IN" desc="The title of the Welcome Back promo for users who are signed in"> + Welcome back, <ph name="USER_NAME">$1<ex>John</ex></ph> + </message> <message name="IDS_IOS_WHATS_HOW_TO_ENABLE_TITLE" desc="Title of a section in What's New that show users the instructions to enable the feature."> How do I enable this feature? </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_KEEP_BROWSING_BUTTON.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_KEEP_BROWSING_BUTTON.png.sha1 new file mode 100644 index 0000000..0a805a1 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_KEEP_BROWSING_BUTTON.png.sha1
@@ -0,0 +1 @@ +ee33e4e943b0654b1818f6162d958794115d3af5 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_SUBTITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_SUBTITLE.png.sha1 new file mode 100644 index 0000000..0a805a1 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +ee33e4e943b0654b1818f6162d958794115d3af5 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_TITLE_DEFAULT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_TITLE_DEFAULT.png.sha1 new file mode 100644 index 0000000..c838a7b1 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_TITLE_DEFAULT.png.sha1
@@ -0,0 +1 @@ +2da2887a37f5130faaf3b411334cff1533d84f2c \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_TITLE_SIGNED_IN.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_TITLE_SIGNED_IN.png.sha1 new file mode 100644 index 0000000..0a805a1 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_WELCOME_BACK_TITLE_SIGNED_IN.png.sha1
@@ -0,0 +1 @@ +ee33e4e943b0654b1818f6162d958794115d3af5 \ No newline at end of file
diff --git a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm index 4131da89..5bb80e1 100644 --- a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm +++ b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm
@@ -2863,6 +2863,11 @@ [_glicCoordinator start]; } +- (void)dismissGlicFlow { + [_glicCoordinator stop]; + _glicCoordinator = nil; +} + #pragma mark - PromosManagerCommands - (void)showPromo { @@ -3884,6 +3889,11 @@ [overlays addObject:sadTabView]; } + UIView* readerModeView = _readerModeCoordinator.viewForSnapshot; + if (readerModeView) { + [overlays addObject:readerModeView]; + } + BrowserContainerViewController* browserContainerViewController = self.browserContainerCoordinator.viewController; // The overlay container view controller is presenting something if it has
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 0d983729..be9b2ed 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1404,6 +1404,8 @@ {kGLICPromoConsentParams, "1"}}; const FeatureEntry::FeatureParam kDoubleScreenForGLICPromoConsent[] = { {kGLICPromoConsentParams, "2"}}; +const FeatureEntry::FeatureParam kSkipGLICPromoConsent[] = { + {kGLICPromoConsentParams, "3"}}; const FeatureEntry::FeatureVariation kGLICPromoConsentVariations[] = { {"Single screen for GLIC Promo Consent Flow", @@ -1411,7 +1413,9 @@ std::size(kSingleScreenForGLICPromoConsent), nullptr}, {"Double screen for GLIC Promo Consent Flow", kDoubleScreenForGLICPromoConsent, - std::size(kDoubleScreenForGLICPromoConsent), nullptr}}; + std::size(kDoubleScreenForGLICPromoConsent), nullptr}, + {"Skip FRE", kSkipGLICPromoConsent, std::size(kSkipGLICPromoConsent), + nullptr}}; // To add a new entry, add to the end of kFeatureEntries. There are four // distinct types of entries:
diff --git a/ios/chrome/browser/intelligence/features/features.h b/ios/chrome/browser/intelligence/features/features.h index a20dc40..60cbdc1 100644 --- a/ios/chrome/browser/intelligence/features/features.h +++ b/ios/chrome/browser/intelligence/features/features.h
@@ -26,6 +26,7 @@ kDisabled = 0, kSinglePage = 1, kDoublePage = 2, + kSkipConsent = 3, }; // Returns the variation of the GLIC Promo Consent flow.
diff --git a/ios/chrome/browser/intelligence/features/features.mm b/ios/chrome/browser/intelligence/features/features.mm index c5c67d9..7924bd33 100644 --- a/ios/chrome/browser/intelligence/features/features.mm +++ b/ios/chrome/browser/intelligence/features/features.mm
@@ -36,6 +36,9 @@ if (param == 2) { return GLICPromoConsentVariations::kDoublePage; } + if (param == 3) { + return GLICPromoConsentVariations::kSkipConsent; + } return GLICPromoConsentVariations::kDisabled; }
diff --git a/ios/chrome/browser/intelligence/gemini/coordinator/glic_coordinator.mm b/ios/chrome/browser/intelligence/gemini/coordinator/glic_coordinator.mm index 96c55fd..445a1a9 100644 --- a/ios/chrome/browser/intelligence/gemini/coordinator/glic_coordinator.mm +++ b/ios/chrome/browser/intelligence/gemini/coordinator/glic_coordinator.mm
@@ -7,11 +7,12 @@ #import "components/prefs/pref_service.h" #import "ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.h" #import "ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator_delegate.h" -#import "ios/chrome/browser/intelligence/gemini/model/glic_service.h" -#import "ios/chrome/browser/intelligence/gemini/model/glic_service_factory.h" #import "ios/chrome/browser/intelligence/gemini/ui/glic_navigation_controller.h" +#import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/model/profile/profile_ios.h" +#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h" +#import "ios/chrome/browser/shared/public/commands/glic_commands.h" @interface GLICCoordinator () <UISheetPresentationControllerDelegate, GLICMediatorDelegate> @@ -24,6 +25,9 @@ // Navigation view controller owning the promo and the consent UI. GLICNavigationController* _navigationController; + + // Handler for sending GLIC commands. + id<GlicCommands> _handler; } #pragma mark - ChromeCoordinator @@ -32,17 +36,17 @@ PrefService* pref_service = self.profile->GetPrefs(); CHECK(pref_service); - _mediator = [[GLICMediator alloc] initWithPrefService:pref_service - browser:self.browser]; + _handler = + HandlerForProtocol(self.browser->GetCommandDispatcher(), GlicCommands); + + _mediator = + [[GLICMediator alloc] initWithPrefService:pref_service + browser:self.browser + baseViewController:self.baseViewController]; _mediator.delegate = self; - _navigationController = [[GLICNavigationController alloc] init]; - _navigationController.sheetPresentationController.delegate = self; - _navigationController.mutator = _mediator; + [_mediator presentGlicFlow]; - [self.baseViewController presentViewController:_navigationController - animated:YES - completion:nil]; [super start]; } @@ -52,9 +56,30 @@ #pragma mark - GLICConsentMediatorDelegate +- (void)presentGlicFRE { + _navigationController = [[GLICNavigationController alloc] init]; + _navigationController.sheetPresentationController.delegate = self; + _navigationController.mutator = _mediator; + + [self.baseViewController presentViewController:_navigationController + animated:YES + completion:nil]; +} + +#pragma mark - UISheetPresentationControllerDelegate + +// Handles the dismissal of the UI. +- (void)presentationControllerDidDismiss: + (UIPresentationController*)presentationController { + // TODO(crbug.com/419064727): Add metric for dismissing coordinator. + [_handler dismissGlicFlow]; +} + +#pragma mark - GLICConsentMediatorDelegate + // Dismisses the UI by stopping the coordinator. - (void)dismissGLICConsentUI { - [self stop]; + [_handler dismissGlicFlow]; } #pragma mark - Private @@ -66,14 +91,4 @@ return !prefService->GetBoolean(prefs::kIOSGLICConsent); } -// Opens the GLIC overlay with a given page context. -- (void)openGLICOverlayForPage: - (std::unique_ptr<optimization_guide::proto::PageContext>)pageContext { - GlicService* glicService = GlicServiceFactory::GetForProfile(self.profile); - glicService->PresentOverlayOnViewController(self.baseViewController, - std::move(pageContext)); - - // TODO(crbug.com/419064727): Dismiss glic promo/consent. -} - @end
diff --git a/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.h b/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.h index fde2ec4e..ea2d221 100644 --- a/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.h +++ b/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_INTELLIGENCE_GEMINI_COORDINATOR_GLIC_MEDIATOR_H_ #define IOS_CHROME_BROWSER_INTELLIGENCE_GEMINI_COORDINATOR_GLIC_MEDIATOR_H_ -#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> #import "ios/chrome/browser/intelligence/gemini/ui/glic_consent_mutator.h" @@ -18,11 +18,15 @@ @interface GLICMediator : NSObject <GLICConsentMutator> - (instancetype)initWithPrefService:(PrefService*)prefService - browser:(Browser*)browser; + browser:(Browser*)browser + baseViewController:(UIViewController*)baseViewController; // The delegate for this mediator. @property(nonatomic, weak) id<GLICMediatorDelegate> delegate; +// Presents the Glic flow, which can either show the FRE or Glic directly. +- (void)presentGlicFlow; + @end #endif // IOS_CHROME_BROWSER_INTELLIGENCE_GEMINI_COORDINATOR_GLIC_MEDIATOR_H_
diff --git a/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.mm b/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.mm index bb26bebe8..764f136 100644 --- a/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.mm +++ b/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator.mm
@@ -8,32 +8,57 @@ #import "base/metrics/histogram_functions.h" #import "components/prefs/pref_service.h" +#import "ios/chrome/browser/intelligence/features/features.h" #import "ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator_delegate.h" #import "ios/chrome/browser/intelligence/gemini/metrics/glic_metrics.h" +#import "ios/chrome/browser/intelligence/gemini/model/glic_service.h" +#import "ios/chrome/browser/intelligence/gemini/model/glic_service_factory.h" #import "ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" +@interface GLICMediator () + +// The base view controller to present UI. +@property(nonatomic, weak) UIViewController* baseViewController; + +@end + @implementation GLICMediator { // Browser instance. raw_ptr<Browser> _browser; + // Pref service to check if user flows were previously triggered. raw_ptr<PrefService> _prefService; + // The PageContext wrapper used to provide context about a page. PageContextWrapper* _pageContextWrapper; } - (instancetype)initWithPrefService:(PrefService*)prefService - browser:(Browser*)browser { + browser:(Browser*)browser + baseViewController:(UIViewController*)baseViewController { self = [super init]; if (self) { _browser = browser; _prefService = prefService; + _baseViewController = baseViewController; } return self; } +- (void)presentGlicFlow { + if (GLICPromoConsentVariationsParam() == + GLICPromoConsentVariations::kSkipConsent) { + [self prepareGLICOverlay]; + return; + } + + // TODO(crbug.com/419064727): Determine what flow should be shown. + [self.delegate presentGlicFRE]; +} + #pragma mark - GLICConsentMutator // Did consent to GLIC. @@ -74,7 +99,7 @@ std::unique_ptr<optimization_guide::proto::PageContext> page_context) { GLICMediator* strongSelf = weakSelf; - [strongSelf.delegate openGLICOverlayForPage:std::move(page_context)]; + [strongSelf openGLICOverlayForPage:std::move(page_context)]; strongSelf->_pageContextWrapper = nil; }); @@ -87,4 +112,15 @@ [_pageContextWrapper populatePageContextFieldsAsync]; } +// Opens the GLIC overlay with a given page context. +- (void)openGLICOverlayForPage: + (std::unique_ptr<optimization_guide::proto::PageContext>)pageContext { + GlicService* glicService = + GlicServiceFactory::GetForProfile(_browser->GetProfile()); + glicService->PresentOverlayOnViewController(self.baseViewController, + std::move(pageContext)); + + // TODO(crbug.com/419064727): Dismiss glic promo/consent. +} + @end
diff --git a/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator_delegate.h b/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator_delegate.h index 344cad10..d3139ea 100644 --- a/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator_delegate.h +++ b/ios/chrome/browser/intelligence/gemini/coordinator/glic_mediator_delegate.h
@@ -5,24 +5,17 @@ #ifndef IOS_CHROME_BROWSER_INTELLIGENCE_GEMINI_COORDINATOR_GLIC_MEDIATOR_DELEGATE_H_ #define IOS_CHROME_BROWSER_INTELLIGENCE_GEMINI_COORDINATOR_GLIC_MEDIATOR_DELEGATE_H_ -namespace optimization_guide { -namespace proto { -class PageContext; -} // namespace proto -} // namespace optimization_guide - @class GLICConsentMediator; // Delegate for the GLICMediator. @protocol GLICMediatorDelegate +// Presents the Glic first run experience. +- (void)presentGlicFRE; + // Dismisses the GLIC consent UI. - (void)dismissGLICConsentUI; -// Opens GLIC Overlay. -- (void)openGLICOverlayForPage: - (std::unique_ptr<optimization_guide::proto::PageContext>)pageContext; - @end #endif // IOS_CHROME_BROWSER_INTELLIGENCE_GEMINI_COORDINATOR_GLIC_MEDIATOR_DELEGATE_H_
diff --git a/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.h b/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.h index d16c57a2..bb725d6a 100644 --- a/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.h +++ b/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.h
@@ -10,6 +10,9 @@ // Coordinator for the Reader mode UI. @interface ReaderModeCoordinator : ChromeCoordinator +// UIView used for snapshot overlay. +@property(nonatomic, readonly) UIView* viewForSnapshot; + @end #endif // IOS_CHROME_BROWSER_READER_MODE_COORDINATOR_READER_MODE_COORDINATOR_H_
diff --git a/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm b/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm index a939dd4..03c6867 100644 --- a/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm +++ b/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm
@@ -21,6 +21,10 @@ ReaderModeOptionsCoordinator* _optionsCoordinator; } +- (UIView*)viewForSnapshot { + return _viewController.view; +} + #pragma mark - ChromeCoordinator - (void)start {
diff --git a/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm b/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm index 02c4957..ebedd8d 100644 --- a/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm +++ b/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm
@@ -61,4 +61,53 @@ grey_accessibilityID(kReaderModeViewAccessibilityIdentifier)]; } +// Tests that swiping between a Reader Mode web state and a normal web +// state shows the expected view. +- (void)testSideSwipeReaderMode { + const GURL readerModeURL = self.testServer->GetURL("/article.html"); + [ChromeEarlGrey loadURL:readerModeURL]; + [ChromeEarlGrey waitForPageToFinishLoading]; + + // Open Reader Mode UI. + [ChromeEarlGreyUI openToolsMenu]; + [ChromeEarlGreyUI + tapToolsMenuAction:grey_accessibilityID(kToolsMenuReaderMode)]; + [ChromeEarlGrey + waitForSufficientlyVisibleElementWithMatcher: + grey_accessibilityID(kReaderModeViewAccessibilityIdentifier)]; + + // Open a new Tab with an article to have a tab to switch to. + [ChromeEarlGreyUI openNewTab]; + const GURL nonReaderModeURL = self.testServer->GetURL("/pony.html"); + [ChromeEarlGrey loadURL:nonReaderModeURL]; + [ChromeEarlGrey waitForPageToFinishLoading]; + + // Side swipe on the toolbar. + [[EarlGrey + selectElementWithMatcher:grey_kindOfClassName(@"PrimaryToolbarView")] + performAction:grey_swipeSlowInDirection(kGREYDirectionRight)]; + + // Reader Mode view is visible. + [ChromeEarlGrey + waitForSufficientlyVisibleElementWithMatcher: + grey_accessibilityID(kReaderModeViewAccessibilityIdentifier)]; + // Verifies that the navigation to the destination page happened. + GREYAssertEqual(readerModeURL, [ChromeEarlGrey webStateVisibleURL], + @"Did not navigate to Reader Mode url."); + + // Side swipe back to the non-Reader mode page on the toolbar. + [[EarlGrey + selectElementWithMatcher:grey_kindOfClassName(@"PrimaryToolbarView")] + performAction:grey_swipeSlowInDirection(kGREYDirectionLeft)]; + + // Non-Reader Mode view is visible. + [[EarlGrey + selectElementWithMatcher:grey_accessibilityID( + kReaderModeViewAccessibilityIdentifier)] + assertWithMatcher:grey_nil()]; + // Verifies that the navigation to the destination page happened. + GREYAssertEqual(nonReaderModeURL, [ChromeEarlGrey webStateVisibleURL], + @"Did not navigate to non-Reader Mode url."); +} + @end
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_coordinator.mm index 888ff11..73f1a31 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_coordinator.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_coordinator.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_coordinator.h" +#import "base/metrics/user_metrics.h" #import "ios/chrome/browser/net/model/crurl.h" #import "ios/chrome/browser/passwords/model/ios_chrome_password_check_manager.h" #import "ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.h" @@ -79,6 +80,9 @@ // An observer that tracks whether push notification permission settings have // been modified. NotificationsSettingsObserver* _notificationsSettingsObserver; + + // The service responsible for running the password checks. + scoped_refptr<IOSChromePasswordCheckManager> _passwordCheckManager; } @synthesize baseNavigationController = _baseNavigationController; @@ -117,9 +121,11 @@ _viewController = [[PasswordCheckupViewController alloc] initWithStyle:ChromeTableViewStyle()]; _viewController.handler = self; + + _passwordCheckManager = + IOSChromePasswordCheckManagerFactory::GetForProfile(self.profile); _mediator = [[PasswordCheckupMediator alloc] - initWithPasswordCheckManager:IOSChromePasswordCheckManagerFactory:: - GetForProfile(self.profile)]; + initWithPasswordCheckManager:_passwordCheckManager]; _viewController.delegate = _mediator; _mediator.consumer = _viewController; _mediator.delegate = self; @@ -173,6 +179,7 @@ // credentials for `warningType`. - (void)showPasswordIssuesWithWarningType: (password_manager::WarningType)warningType { + [self logPasswordCheckState]; DUMP_WILL_BE_CHECK(!_passwordIssuesCoordinator); [self stopReauthCoordinatorBeforeStartingChildCoordinator]; @@ -396,6 +403,9 @@ // Local authentication is required every time the current // scene is backgrounded and foregrounded until reauthCoordinator is stopped. - (void)startReauthCoordinatorWithAuthOnStart:(BOOL)authOnStart { + base::RecordAction( + base::UserMetricsAction("MobilePasswordCheckupCoordinatorShowReauth")); + DCHECK(!_reauthCoordinator); _reauthCoordinator = [[ReauthenticationCoordinator alloc] @@ -451,4 +461,42 @@ } } +// TODO(crbug.com/409680593): Remove when done with the investigation. +- (void)logPasswordCheckState { + switch (_passwordCheckManager->GetPasswordCheckState()) { + case PasswordCheckState::kCanceled: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateCanceled")); + return; + case PasswordCheckState::kIdle: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateIdle")); + return; + case PasswordCheckState::kNoPasswords: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateNoPasswords")); + return; + case PasswordCheckState::kOffline: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateOffline")); + return; + case PasswordCheckState::kOther: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateOther")); + return; + case PasswordCheckState::kQuotaLimit: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateQuotaLimit")); + return; + case PasswordCheckState::kRunning: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateRunning")); + return; + case PasswordCheckState::kSignedOut: + base::RecordAction(base::UserMetricsAction( + "MobilePasswordCheckupCoordinatorCheckStateSignedOut")); + return; + } +} + @end
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_coordinator.mm index 8559dd19..d08dbcd0 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_coordinator.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_coordinator.mm
@@ -8,6 +8,7 @@ #import "base/debug/dump_without_crashing.h" #import "base/memory/raw_ptr.h" #import "base/memory/scoped_refptr.h" +#import "base/metrics/user_metrics.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/passwords/model/ios_chrome_password_check_manager.h" @@ -118,6 +119,8 @@ } - (void)start { + base::RecordAction( + base::UserMetricsAction("MobilePasswordIssuesCoordinatorStart")); [super start]; ProfileIOS* profile = self.profile;
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_table_view_controller.mm index e78c9845..4d012b6 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_table_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_issues/password_issues_table_view_controller.mm
@@ -89,12 +89,20 @@ #pragma mark - UIViewController - (void)viewDidLoad { + base::RecordAction( + base::UserMetricsAction("MobilePasswordIssuesViewDidLoad")); [super viewDidLoad]; self.tableView.accessibilityIdentifier = kPasswordIssuesTableViewID; [self loadModel]; } +- (void)viewDidAppear:(BOOL)animated { + base::RecordAction( + base::UserMetricsAction("MobilePasswordIssuesViewDidAppear")); + [super viewDidAppear:animated]; +} + - (void)didMoveToParentViewController:(UIViewController*)parent { [super didMoveToParentViewController:parent]; if (!parent) {
diff --git a/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm index 21e6e54..d62b9d4b 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm
@@ -6,6 +6,7 @@ #import "base/check.h" #import "base/metrics/histogram_macros.h" +#import "base/metrics/user_metrics.h" #import "ios/chrome/browser/settings/ui_bundled/password/create_password_manager_title_view.h" #import "ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_constants.h" #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" @@ -123,6 +124,9 @@ - (void)recordAuthenticationEvent:(ReauthenticationEvent)event { UMA_HISTOGRAM_ENUMERATION(password_manager::kReauthenticationUIEventHistogram, event); + base::RecordAction(base::UserMetricsAction( + event == ReauthenticationEvent::kSuccess ? "MobileReauthSuccessful" + : "MobileReauthFailed")); } // Starts the native UI for Local Authentication.
diff --git a/ios/chrome/browser/shared/public/commands/glic_commands.h b/ios/chrome/browser/shared/public/commands/glic_commands.h index 35ff24e4..a190ad7 100644 --- a/ios/chrome/browser/shared/public/commands/glic_commands.h +++ b/ios/chrome/browser/shared/public/commands/glic_commands.h
@@ -11,6 +11,9 @@ // Starts the Glic flow. - (void)startGlicFlow; +// Dismiss the Glic flow. +- (void)dismissGlicFlow; + @end #endif // IOS_CHROME_BROWSER_SHARED_PUBLIC_COMMANDS_GLIC_COMMANDS_H_
diff --git a/ios/chrome/browser/tips_notifications/eg_test/tips_notifications_egtest.mm b/ios/chrome/browser/tips_notifications/eg_test/tips_notifications_egtest.mm index 6a915b6..d6faf59 100644 --- a/ios/chrome/browser/tips_notifications/eg_test/tips_notifications_egtest.mm +++ b/ios/chrome/browser/tips_notifications/eg_test/tips_notifications_egtest.mm
@@ -142,9 +142,6 @@ // Opt in to Tips Notications via the SetUpList long-press menu. Mark all // Tips Notifications as "sent", except for the ones included in `types`. - (void)optInToTipsNotifications:(std::vector<TipsNotificationType>)types { - // Ensure that the SetUpList reloads. - [ChromeEarlGrey closeCurrentTab]; - [ChromeEarlGrey openNewTab]; // Long press the SetUpList module. id<GREYMatcher> setUpList = grey_accessibilityID(set_up_list::kSetUpListContainerID); @@ -404,4 +401,22 @@ @"Reactivation notification request was not added."); } +// Tests that the CPE Promo appears when tapping on the CPE tip notification. +- (void)testCPENotification { + MaybeDismissNotification(); + [ChromeEarlGreyUI waitForAppToIdle]; + [self optInToTipsNotifications:{}]; + + // Request the notification and tap it. + [ChromeEarlGrey requestTipsNotification:TipsNotificationType::kCPE]; + TapNotification(); + [ChromeEarlGrey + waitForUIElementToAppearWithMatcher: + grey_accessibilityID(@"kCredentialProviderPromoAccessibilityId")]; + // Close the promo. + id<GREYMatcher> noThanksButton = grey_accessibilityID( + kConfirmationAlertSecondaryActionAccessibilityIdentifier); + [ChromeEarlGrey waitForAndTapButton:noThanksButton]; +} + @end
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm index bf66f91..3387bae 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm
@@ -181,12 +181,16 @@ // Decide whether safe browsing database can be checked. // If url_lookup_service_ is null, safe browsing database should be checked by // default. - bool can_check_db = - url_lookup_service ? url_lookup_service->CanCheckSafeBrowsingDb() : true; + bool can_check_db = can_perform_full_url_lookup + ? url_lookup_service->CanCheckSafeBrowsingDb() + : true; bool can_check_high_confidence_allowlist = - url_lookup_service + can_perform_full_url_lookup ? url_lookup_service->CanCheckSafeBrowsingHighConfidenceAllowlist() : true; + std::string url_lookup_service_metric_suffix = + can_perform_full_url_lookup ? url_lookup_service->GetMetricSuffix() + : safe_browsing::kNoRealTimeURLLookupService; return std::make_unique<safe_browsing::SafeBrowsingUrlCheckerImpl>( /*headers=*/net::HttpRequestHeaders(), /*load_flags=*/0, @@ -200,8 +204,8 @@ /*frame_tree_node_id=*/ security_interstitials::UnsafeResource::kNoFrameTreeNodeId, /*navigation_id=*/std::nullopt, can_perform_full_url_lookup, can_check_db, - can_check_high_confidence_allowlist, - /*url_lookup_service_metric_suffix=*/"", web::GetUIThreadTaskRunner({}), + can_check_high_confidence_allowlist, url_lookup_service_metric_suffix, + web::GetUIThreadTaskRunner({}), url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr, hash_real_time_service ? hash_real_time_service->GetWeakPtr() : nullptr, hash_real_time_selection, @@ -237,12 +241,16 @@ // Decide whether safe browsing database can be checked. // If url_lookup_service_ is null, safe browsing database should be checked by // default. - bool can_check_db = - url_lookup_service ? url_lookup_service->CanCheckSafeBrowsingDb() : true; + bool can_check_db = can_perform_full_url_lookup + ? url_lookup_service->CanCheckSafeBrowsingDb() + : true; bool can_check_high_confidence_allowlist = - url_lookup_service + can_perform_full_url_lookup ? url_lookup_service->CanCheckSafeBrowsingHighConfidenceAllowlist() : true; + std::string url_lookup_service_metric_suffix = + can_perform_full_url_lookup ? url_lookup_service->GetMetricSuffix() + : safe_browsing::kNoRealTimeURLLookupService; return std::make_unique<safe_browsing::SafeBrowsingUrlCheckerImpl>( /*headers=*/net::HttpRequestHeaders(), /*load_flags=*/0, @@ -256,8 +264,8 @@ /*frame_tree_node_id=*/ security_interstitials::UnsafeResource::kNoFrameTreeNodeId, /*navigation_id=*/std::nullopt, can_perform_full_url_lookup, can_check_db, - can_check_high_confidence_allowlist, - /*url_lookup_service_metric_suffix=*/"", web::GetUIThreadTaskRunner({}), + can_check_high_confidence_allowlist, url_lookup_service_metric_suffix, + web::GetUIThreadTaskRunner({}), url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr, hash_real_time_service ? hash_real_time_service->GetWeakPtr() : nullptr, hash_real_time_selection,
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm index 13d868d..25f151d 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm
@@ -461,12 +461,20 @@ pref_service_.SetBoolean( unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, true); + base::HistogramTester histogram_tester; MarkUrlAsRealTimeSafe(safe_url); client.CheckUrl(safe_url); EXPECT_TRUE(client.result_pending()); client.WaitForResult(); EXPECT_FALSE(client.result_pending()); EXPECT_FALSE(client.url_is_unsafe()); + histogram_tester.ExpectUniqueSample("SafeBrowsing.RT.LocalMatch.Result", + /*sample=*/true, + /*expected_bucket_count=*/1); + histogram_tester.ExpectBucketCount( + "SafeBrowsing.RT.LocalMatch.Result.Consumer", + /*sample=*/true, + /*expected_bucket_count=*/1); GURL unsafe_url(kMalwarePage); MarkUrlAsRealTimeUnsafe(unsafe_url); @@ -537,6 +545,20 @@ client.WaitForResult(); EXPECT_FALSE(client.result_pending()); EXPECT_TRUE(client.url_is_unsafe()); + + // Checking the allow list should be allowed if real time checks are disabled. + pref_service_.SetBoolean( + unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, false); + lookup_service_->set_can_check_safe_browsing_db(false); + lookup_service_->set_can_check_high_confidence_allow_list(false); + + // Checking the url should return a safe result coming from the high + // confidence allow list. + client.CheckUrl(safe_url); + EXPECT_TRUE(client.result_pending()); + client.WaitForResult(); + EXPECT_FALSE(client.result_pending()); + EXPECT_FALSE(client.url_is_unsafe()); } // Verifies that safe and unsafe URLs are identified correctly for when a sync @@ -603,12 +625,20 @@ pref_service_.SetBoolean( unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, true); + base::HistogramTester histogram_tester; MarkUrlAsRealTimeSafe(safe_url); client.CheckUrlWithAsyncChecker(safe_url); EXPECT_TRUE(client.result_pending()); client.WaitForResult(); EXPECT_FALSE(client.result_pending()); EXPECT_FALSE(client.url_is_unsafe()); + histogram_tester.ExpectBucketCount("SafeBrowsing.RT.LocalMatch.Result", + /*sample=*/true, + /*expected_bucket_count=*/1); + histogram_tester.ExpectBucketCount( + "SafeBrowsing.RT.LocalMatch.Result.Consumer", + /*sample=*/true, + /*expected_bucket_count=*/1); GURL unsafe_url(kMalwarePage); MarkUrlAsRealTimeUnsafe(unsafe_url);
diff --git a/ios_internal b/ios_internal index 6d08270..76f095c 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 6d082702c7c77c8dc97cdf1a572a852b53e569df +Subproject commit 76f095ce054370cefa6ea76ff83685a554e45873
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc index 53f13dd..123a527 100644 --- a/media/audio/win/audio_low_latency_input_win.cc +++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -1346,7 +1346,6 @@ fifo_->PushSilence(num_frames_to_read); } else { const int bytes_per_sample = input_format_.Format.wBitsPerSample / 8; - peak_detector_.FindPeak(data_ptr, num_frames_to_read, bytes_per_sample); fifo_->Push(data_ptr, num_frames_to_read, bytes_per_sample); } @@ -1819,7 +1818,7 @@ hr_dbg = audio_client_->GetStreamLatency(&latency); if (SUCCEEDED(hr_dbg)) { // The 5000 addition is to round end result to closest integer. - const int latency_ms = (device_period_shared_mode + 5000) / 10000; + const int latency_ms = (latency + 5000) / 10000; DVLOG(1) << "Stream latency: " << latency_ms << " ms"; } #endif
diff --git a/media/audio/win/test_support/fake_iaudio_client.cc b/media/audio/win/test_support/fake_iaudio_client.cc index 5b3849c..d258312 100644 --- a/media/audio/win/test_support/fake_iaudio_client.cc +++ b/media/audio/win/test_support/fake_iaudio_client.cc
@@ -10,17 +10,19 @@ #include <wrl.h> #include "base/functional/bind.h" +#include "base/logging.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "base/time/time.h" +#include "media/audio/win/core_audio_util_win.h" #include "media/audio/win/test_support/fake_iaudio_capture_client.h" namespace { -// TOOD(crbug.com/418678875): make this configurable. -constexpr UINT32 kBufferSizeFrames = 256; -constexpr REFERENCE_TIME kSamplingPeriodMs = 1; -constexpr REFERENCE_TIME kStreamLatencyMs = 1; +// The audio engine typically processes events at a rate of 100Hz. +constexpr base::TimeDelta kSamplingPeriodMs = base::Milliseconds(10); +// Maximum latency for the current stream. +constexpr base::TimeDelta kStreamLatencyMs = 10 * kSamplingPeriodMs; } // namespace @@ -31,7 +33,7 @@ // Stream once immediately. StreamData(); // And again every kSamplingPeriodMs milliseconds. - timer_.Start(FROM_HERE, base::Milliseconds(kSamplingPeriodMs), + timer_.Start(FROM_HERE, kSamplingPeriodMs, base::BindRepeating(&FakeIAudioClient::DataStreamer::StreamData, base::Unretained(this))); } @@ -55,10 +57,7 @@ FakeIAudioClient::~FakeIAudioClient() = default; IFACEMETHODIMP FakeIAudioClient::GetBufferSize(UINT32* buffer_size) { - // TOOD(crbug.com/418678875): Real devices often have a buffer size that is a - // multiple of 10ms and depends on the sample rate. Consider making this - // configurable and dependent on the sample rate. - *buffer_size = kBufferSizeFrames; + *buffer_size = buffer_size_frames_; return S_OK; } @@ -69,8 +68,10 @@ IFACEMETHODIMP FakeIAudioClient::GetDevicePeriod( REFERENCE_TIME* default_device_period, REFERENCE_TIME* minimum_device_period) { - // Convert to 100ns units. - *default_device_period = kSamplingPeriodMs * 10000; + const REFERENCE_TIME period_in_100ns_units = + kSamplingPeriodMs.InMicroseconds() * 10; + *default_device_period = period_in_100ns_units; + *minimum_device_period = period_in_100ns_units; return S_OK; } @@ -85,7 +86,7 @@ if (riid == __uuidof(IAudioCaptureClient)) { audio_capture_client_ = Microsoft::WRL::Make<FakeIAudioCaptureClient>( - client_type_, kBufferSizeFrames, frame_size_bytes_); + client_type_, buffer_size_frames_, frame_size_bytes_); audio_capture_client_.CopyTo( reinterpret_cast<IAudioCaptureClient**>(service)); return S_OK; @@ -95,8 +96,9 @@ } IFACEMETHODIMP FakeIAudioClient::GetStreamLatency(REFERENCE_TIME* latency) { - // Convert to 100ns units. - *latency = kStreamLatencyMs * 10000; + const REFERENCE_TIME latency_in_100ns_units = + kStreamLatencyMs.InMicroseconds() * 10; + *latency = latency_in_100ns_units; return S_OK; } @@ -106,7 +108,11 @@ REFERENCE_TIME periodicity, const WAVEFORMATEX* format, LPCGUID audio_session_guid) { - // TOOD(crbug.com/418678875): validate the format. + VLOG(1) << CoreAudioUtil::WaveFormatToString( + const_cast<WAVEFORMATEX*>(format)); + buffer_size_frames_ = static_cast<UINT32>( + (format->nSamplesPerSec * kSamplingPeriodMs.InMicroseconds()) / + base::Time::kMicrosecondsPerSecond); frame_size_bytes_ = (format->wBitsPerSample / 8) * format->nChannels; return S_OK; }
diff --git a/media/audio/win/test_support/fake_iaudio_client.h b/media/audio/win/test_support/fake_iaudio_client.h index 40255be..d969174 100644 --- a/media/audio/win/test_support/fake_iaudio_client.h +++ b/media/audio/win/test_support/fake_iaudio_client.h
@@ -79,6 +79,9 @@ base::SequenceBound<DataStreamer> streamer_; HANDLE buffer_ready_event_handle_ = nullptr; Microsoft::WRL::ComPtr<IAudioCaptureClient> audio_capture_client_ = nullptr; + // Size of each audio buffer in audio frames. + // Example: 10ms between samples and 48kHz sample rate => 480 audio frames. + UINT32 buffer_size_frames_ = 0; // The size of an audio frame in bytes. WORD frame_size_bytes_ = 0; };
diff --git a/media/base/cdm_capability.cc b/media/base/cdm_capability.cc index 9a899f2..a2372a6 100644 --- a/media/base/cdm_capability.cc +++ b/media/base/cdm_capability.cc
@@ -90,6 +90,9 @@ case CdmCapabilityQueryStatus::kNoMediaDrmSupport: return "MediaDrm not available for the key system and robustness " "specified."; + case CdmCapabilityQueryStatus:: + kMediaFoundationGetExtendedDRMTypeSupportFailed: + return "kMediaFoundationGetExtendedDRMTypeSupportFailed"; } NOTREACHED();
diff --git a/media/base/cdm_capability.h b/media/base/cdm_capability.h index 90b9332d..6aa87d1c 100644 --- a/media/base/cdm_capability.h +++ b/media/base/cdm_capability.h
@@ -115,7 +115,9 @@ kUnexpectedEmptyCapability = 10, // MediaDrm not available for the key system and robustness specified. kNoMediaDrmSupport = 11, - kMaxValue = kNoMediaDrmSupport, + // Creation of IMFExtendedDRMTypeSupport failed. + kMediaFoundationGetExtendedDRMTypeSupportFailed = 12, + kMaxValue = kMediaFoundationGetExtendedDRMTypeSupportFailed, }; // Returns a string version of the status.
diff --git a/media/mojo/mojom/cdm_capability_mojom_traits.cc b/media/mojo/mojom/cdm_capability_mojom_traits.cc index 52d4fe5f..0290416 100644 --- a/media/mojo/mojom/cdm_capability_mojom_traits.cc +++ b/media/mojo/mojom/cdm_capability_mojom_traits.cc
@@ -104,6 +104,10 @@ return media::mojom::CdmCapabilityQueryStatus::kUnexpectedEmptyCapability; case media::CdmCapabilityQueryStatus::kNoMediaDrmSupport: return media::mojom::CdmCapabilityQueryStatus::kNoMediaDrmSupport; + case media::CdmCapabilityQueryStatus:: + kMediaFoundationGetExtendedDRMTypeSupportFailed: + return media::mojom::CdmCapabilityQueryStatus:: + kMediaFoundationGetExtendedDRMTypeSupportFailed; } NOTREACHED(); @@ -159,6 +163,11 @@ case media::mojom::CdmCapabilityQueryStatus::kNoMediaDrmSupport: *output = media::CdmCapabilityQueryStatus::kNoMediaDrmSupport; return true; + case media::mojom::CdmCapabilityQueryStatus:: + kMediaFoundationGetExtendedDRMTypeSupportFailed: + *output = media::CdmCapabilityQueryStatus:: + kMediaFoundationGetExtendedDRMTypeSupportFailed; + return true; } NOTREACHED();
diff --git a/media/mojo/mojom/key_system_support.mojom b/media/mojo/mojom/key_system_support.mojom index cb9d48a2..be32a38b 100644 --- a/media/mojo/mojom/key_system_support.mojom +++ b/media/mojo/mojom/key_system_support.mojom
@@ -50,6 +50,7 @@ kCreateDummyMediaFoundationCdmFailed = 9, kUnexpectedEmptyCapability = 10, kNoMediaDrmSupport = 11, + kMediaFoundationGetExtendedDRMTypeSupportFailed = 12, }; // TODO(crbug.com/40841428): Ideally, this should be replaced by a
diff --git a/media/mojo/services/media_foundation_service.cc b/media/mojo/services/media_foundation_service.cc index c5f42840..df74d54e 100644 --- a/media/mojo/services/media_foundation_service.cc +++ b/media/mojo/services/media_foundation_service.cc
@@ -395,6 +395,12 @@ } #endif + // Remove VP9 from the OS CDM capabilities check + // since it does not support clearlead. + if (is_os_cdm && is_hw_secure && (video_codec == VideoCodec::kVP9)) { + continue; + } + if (is_type_supported_cb.Run( is_hw_secure, GetTypeString(video_codec, /*audio_codec=*/std::nullopt, @@ -546,9 +552,12 @@ << hr; std::move(callback).Run( false, KeySystemCapability( - // TODO(crbug.com/384962301): need better error codes here. - base::unexpected(CdmCapabilityQueryStatus::kUnknown), - base::unexpected(CdmCapabilityQueryStatus::kUnknown))); + base::unexpected( + CdmCapabilityQueryStatus:: + kMediaFoundationGetExtendedDRMTypeSupportFailed), + base::unexpected( + CdmCapabilityQueryStatus:: + kMediaFoundationGetExtendedDRMTypeSupportFailed))); return; }
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index a8833b5..19f5c95 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -3573,96 +3573,76 @@ return rects; } -void PDFiumEngine::ChangeInvalidator::Invalidate(const gfx::Rect& rect) { - gfx::Rect expanded_rect = rect; - expanded_rect.Inset(-1); - engine_->client_->Invalidate(expanded_rect); +bool PDFiumEngine::ChangeInvalidator::Invalidate( + base::span<const gfx::Rect> screen_rects) { + bool invalidated = false; + for (const auto& rect : screen_rects) { + if (rect.IsEmpty()) { + continue; + } + + gfx::Rect expanded_rect = rect; + expanded_rect.Outset(1); + engine_->client_->Invalidate(expanded_rect); + invalidated = true; + } + return invalidated; } -PDFiumEngine::SelectionChangeInvalidator::SelectionChangeInvalidator( - PDFiumEngine* engine) - : ChangeInvalidator(engine), old_selections_(GetVisibleSelections()) {} - -PDFiumEngine::SelectionChangeInvalidator::~SelectionChangeInvalidator() { +bool PDFiumEngine::ChangeInvalidator::InvalidateChangesOnDestruct() { // Offset the old selections if the document scrolled since we recorded them. gfx::Vector2d offset = previous_origin_ - engine_->GetVisibleRect().origin(); - for (auto& old_selection : old_selections_) - old_selection.Offset(offset); + for (auto& previous_rect : previous_rects_) { + previous_rect.Offset(offset); + } - std::vector<gfx::Rect> new_selections = GetVisibleSelections(); - for (auto& new_selection : new_selections) { - for (auto& old_selection : old_selections_) { - if (!old_selection.IsEmpty() && new_selection == old_selection) { + std::vector<gfx::Rect> new_rects = GetVisibleChangeRects(); + for (auto& new_rect : new_rects) { + for (auto& previous_rect : previous_rects_) { + if (!previous_rect.IsEmpty() && new_rect == previous_rect) { // Rectangle was selected before and after, so no need to invalidate it. // Mark the rectangles by setting them to empty. - new_selection = old_selection = gfx::Rect(); + new_rect = previous_rect = gfx::Rect(); break; } } } - bool selection_changed = false; - for (const auto& old_selection : old_selections_) { - if (!old_selection.IsEmpty()) { - Invalidate(old_selection); - selection_changed = true; - } - } - for (const auto& new_selection : new_selections) { - if (!new_selection.IsEmpty()) { - Invalidate(new_selection); - selection_changed = true; - } - } + bool invalidated = Invalidate(previous_rects_); + invalidated |= Invalidate(new_rects); + return invalidated; +} - if (selection_changed) { +PDFiumEngine::SelectionChangeInvalidator::SelectionChangeInvalidator( + PDFiumEngine* engine) + : ChangeInvalidator(engine) { + previous_rects_ = GetVisibleChangeRects(); +} + +PDFiumEngine::SelectionChangeInvalidator::~SelectionChangeInvalidator() { + if (InvalidateChangesOnDestruct()) { engine_->OnSelectionTextChanged(); engine_->OnSelectionPositionChanged(); } } std::vector<gfx::Rect> -PDFiumEngine::SelectionChangeInvalidator::GetVisibleSelections() const { +PDFiumEngine::SelectionChangeInvalidator::GetVisibleChangeRects() const { return GetVisibleScreenRectsFromRanges(engine_->selection_); } PDFiumEngine::HighlightChangeInvalidator::HighlightChangeInvalidator( PDFiumEngine* engine) - : ChangeInvalidator(engine), old_highlights_(GetVisibleHighlights()) {} + : ChangeInvalidator(engine) { + previous_rects_ = GetVisibleChangeRects(); +} PDFiumEngine::HighlightChangeInvalidator::~HighlightChangeInvalidator() { - // Offset the old selections if the document scrolled since we recorded them. - gfx::Vector2d offset = previous_origin_ - engine_->GetVisibleRect().origin(); - for (auto& old_highlight : old_highlights_) { - old_highlight.Offset(offset); - } - - std::vector<gfx::Rect> new_highlights = GetVisibleHighlights(); - for (auto& new_highlight : new_highlights) { - for (auto& old_highlight : old_highlights_) { - if (!old_highlight.IsEmpty() && new_highlight == old_highlight) { - // Rectangle was selected before and after, so no need to invalidate it. - // Mark the rectangles by setting them to empty. - new_highlight = old_highlight = gfx::Rect(); - break; - } - } - } - - for (const auto& old_highlight : old_highlights_) { - if (!old_highlight.IsEmpty()) { - Invalidate(old_highlight); - } - } - for (const auto& new_highlight : new_highlights) { - if (!new_highlight.IsEmpty()) { - Invalidate(new_highlight); - } - } + InvalidateChangesOnDestruct(); } std::vector<gfx::Rect> -PDFiumEngine::HighlightChangeInvalidator::GetVisibleHighlights() const { +PDFiumEngine::HighlightChangeInvalidator::GetVisibleChangeRects() const { return GetVisibleScreenRectsFromRanges(engine_->text_fragment_highlights_); }
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index b9e2adf..f25b66f9 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -566,62 +566,58 @@ AddSearchResultCallback add_result_callback); private: - // This is a base class for shared functions and data needed between change - // invalidators for selection and text fragment highlights. + // This is a base class for shared functions and data needed for change + // invalidators. Subclasses are used to detect the difference in change rects + // between construction and destruction. At destruction, it invalidates all + // the tracked rects that changed. class ChangeInvalidator { protected: explicit ChangeInvalidator(PDFiumEngine* engine); - ~ChangeInvalidator(); + virtual ~ChangeInvalidator(); + + // Gets all visible rects for the tracked changes. + virtual std::vector<gfx::Rect> GetVisibleChangeRects() const = 0; // Gets all of the visible screen rects from a list of `ranges`. std::vector<gfx::Rect> GetVisibleScreenRectsFromRanges( base::span<const PDFiumRange> ranges) const; - // Invalidates `rect`, but with `rect` slightly expanded to - // compensate for any rounding errors. - void Invalidate(const gfx::Rect& rect); + // Invalidates all `screen_rects`, but with each rect slightly expanded to + // compensate for any rounding errors. Skips any empty rects. Returns + // whether any rect invalidation occurred. + bool Invalidate(base::span<const gfx::Rect> screen_rects); + // Invalidates all rects added or removed between construction and + // destruction. Returns whether any invalidation occurred. + bool InvalidateChangesOnDestruct(); + + // Must be non-nullptr. const raw_ptr<PDFiumEngine> engine_; // The origin at the time this object was constructed. const gfx::Point previous_origin_; + + // Screen rectangles that were highlighted on construction. + std::vector<gfx::Rect> previous_rects_; }; - // This helper class is used to detect the difference in selection between - // construction and destruction. At destruction, it invalidates all the - // parts that are newly selected, along with all the parts that used to be - // selected but are not anymore. + // Tracks and invalidates text selection changes. class SelectionChangeInvalidator : public ChangeInvalidator { public: explicit SelectionChangeInvalidator(PDFiumEngine* engine); - ~SelectionChangeInvalidator(); + ~SelectionChangeInvalidator() override; private: - // Returns all the currently visible selection rectangles, in screen - // coordinates. - std::vector<gfx::Rect> GetVisibleSelections() const; - - // Screen rectangles that were selected on construction. - std::vector<gfx::Rect> old_selections_; + std::vector<gfx::Rect> GetVisibleChangeRects() const override; }; - // This helper class is used to detect the difference in highlights between - // construction and destruction. At destruction, it invalidates all the - // parts that are newly highlighted, along with all the parts that used to be - // highlighted but are not anymore. Almost exactly the same as - // `SelectionChangeInvalidator` except this class only invalidates text - // fragment highlights rather than selections. + // Tracks and invalidates text fragment highlight changes. class HighlightChangeInvalidator : public ChangeInvalidator { public: explicit HighlightChangeInvalidator(PDFiumEngine* engine); - ~HighlightChangeInvalidator(); + ~HighlightChangeInvalidator() override; private: - // Returns all the currently visible highlighted rectangles, in screen - // coordinates. - std::vector<gfx::Rect> GetVisibleHighlights() const; - - // Screen rectangles that were highlighted on construction. - std::vector<gfx::Rect> old_highlights_; + std::vector<gfx::Rect> GetVisibleChangeRects() const override; }; // Used to store mouse down state to handle it in other mouse event handlers.
diff --git a/pdf/pdfium/pdfium_font_win.cc b/pdf/pdfium/pdfium_font_win.cc index 71b34cd..128687d 100644 --- a/pdf/pdfium/pdfium_font_win.cc +++ b/pdf/pdfium/pdfium_font_win.cc
@@ -13,7 +13,6 @@ #include "base/containers/contains.h" #include "base/containers/fixed_flat_map.h" #include "base/containers/flat_map.h" -#include "base/feature_list.h" #include "base/logging.h" #include "base/no_destructor.h" #include "base/sequence_checker.h" @@ -60,13 +59,6 @@ return face; } -// Kill switch in case this goes horribly wrong. -// TODO(crbug.com/381126164): Remove after this lands safely in a Stable -// release. -BASE_FEATURE(kPdfEnumFontsWin, - "PdfEnumFontsWin", - base::FEATURE_ENABLED_BY_DEFAULT); - // Maps font description and charset to `FontId` as requested by PDFium, with // `FontId` as an opaque type that PDFium works with. Based on the `FontId`, // PDFium can read from the font files using GetFontData(). Properly frees the @@ -82,10 +74,6 @@ ~SkiaFontMapper() = delete; void EnumFonts(FPDF_SYSFONTINFO* sysfontinfo, void* mapper) { - if (!base::FeatureList::IsEnabled(kPdfEnumFontsWin)) { - return; - } - const int count = manager_->countFamilies(); for (int i = 0; i < count; ++i) { SkString family;
diff --git a/remoting/client/common/remoting_client.cc b/remoting/client/common/remoting_client.cc index 02404d9..77af81d 100644 --- a/remoting/client/common/remoting_client.cc +++ b/remoting/client/common/remoting_client.cc
@@ -4,6 +4,7 @@ #include "remoting/client/common/remoting_client.h" +#include <cstdint> #include <memory> #include <string> #include <string_view> @@ -21,6 +22,7 @@ #include "remoting/base/passthrough_oauth_token_getter.h" #include "remoting/client/common/frame_consumer_wrapper.h" #include "remoting/client/common/logging.h" +#include "remoting/proto/control.pb.h" #include "remoting/proto/remoting/v1/host_info.pb.h" #include "remoting/proto/remoting/v1/remote_support_host_messages.pb.h" #include "remoting/protocol/chromium_port_allocator_factory.h" @@ -28,6 +30,7 @@ #include "remoting/protocol/client_authentication_config.h" #include "remoting/protocol/connection_to_host.h" #include "remoting/protocol/errors.h" +#include "remoting/protocol/host_stub.h" #include "remoting/protocol/ice_config_fetcher_default.h" #include "remoting/protocol/jingle_session.h" #include "remoting/protocol/jingle_session_manager.h" @@ -46,6 +49,10 @@ namespace remoting { +namespace { +constexpr std::int32_t kMinBitrateBps = 10485760; +} + RemotingClient::RemotingClient( base::OnceClosure quit_closure, protocol::FrameConsumer* frame_consumer, @@ -240,6 +247,15 @@ protocol::ErrorCode error) { CLIENT_LOG << "OnConnectionState change: " << protocol::ConnectionToHost::StateToString(state); + if (state == protocol::ConnectionToHost::State::CONNECTED && + connection_->host_stub()) { + protocol::PeerConnectionParameters peer_connection_params; + peer_connection_params.set_preferred_min_bitrate_bps(kMinBitrateBps); + connection_->host_stub()->ControlPeerConnection(peer_connection_params); + } else if (state == protocol::ConnectionToHost::State::CLOSED || + state == protocol::ConnectionToHost::State::FAILED) { + StopSession(); + } } void RemotingClient::OnConnectionReady(bool ready) {
diff --git a/testing/buildbot/filters/ios.content_browsertests.filter b/testing/buildbot/filters/ios.content_browsertests.filter index 2fee7ac..236b3f2 100644 --- a/testing/buildbot/filters/ios.content_browsertests.filter +++ b/testing/buildbot/filters/ios.content_browsertests.filter
@@ -251,40 +251,15 @@ -All/DumpAccessibilityTreeTest.AccessibilityInputWeek/blink -All/DumpAccessibilityTreeTest.AccessibilityInteractiveControlsWithLabels/blink -All/DumpAccessibilityTreeTest.ReloadSelectionCrash/blink --All/RenderFrameHostManagerUnloadBrowserTest.PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes/0 --All/RenderFrameHostManagerUnloadBrowserTest.PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes/1 --All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDAllFrames_BFCacheDisabled --All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDAllFrames_BFCacheEnabled --All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDCrashedFrame_BFCacheDisabled --All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDCrashedFrame_BFCacheEnabled --All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/arraybuffer --All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/form --All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/string --All/SendBeaconBrowserTest.CrossOriginAndCORSSafelistedRedirectRequest/arraybuffer --All/SendBeaconBrowserTest.CrossOriginAndCORSSafelistedRedirectRequest/string --All/SendBeaconBrowserTest.CrossOriginAndCORSSafelistedRedirectRequest/form --All/SendBeaconBrowserTest.MultipleRedirectsRequestWithDelayedIframeRemoval/arraybuffer --All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/blob --All/SendBeaconBrowserTest.MultipleRedirectsRequestWithDelayedIframeRemoval/blob --All/SendBeaconBrowserTest.MultipleRedirectsRequestWithDelayedIframeRemoval/string --All/ServiceWorkerBrowserTestWithStoragePartitioning.StorageKeyWithHostPermissionsWithSharedWorkers/0 -All/YieldingParserDumpAccessibilityTreeTest.AccessibilityInputDateWithPopupOpenMultiple/blink -All/YieldingParserDumpAccessibilityTreeTest.AccessibilityInputTimeWithPopupOpen/blink -AttributionInternalsWebUiBrowserTest.ClearButton_ClearsSourceTable -AttributionInternalsWebUiBrowserTest.WebUIShownWithActiveImpression_ImpressionsDisplayed -AttributionInternalsWebUiBrowserTest.WebUIShownWithPendingAggregatableReports_ReportsDisplayed -AttributionInternalsWebUiBrowserTest.WebUIShownWithPendingReports_ReportsDisplayed --BackForwardCacheBrowserTest.BackNavigationFromCrashedPage --BackForwardCacheBrowserTest.EvictsFromCacheIfRendererProcessCrashes -BackForwardCacheBrowserTestWithJavaScriptDetails.StickyFeaturesWithDetails --BrowserChildProcessObserverBrowserTest.LaunchAndCrash -BrowserChildProcessObserverBrowserTest.LaunchAndDisconnect -BrowserChildProcessObserverBrowserTest.LaunchAndForceShutdown --CaptureStreamRenderProcessHostTest.KillProcessZerosAudioCaptureStreams --CaptureStreamRenderProcessHostTest.KillProcessZerosVideoCaptureStreams --ChildProcessSecurityPolicyInProcessBrowserTest.NoLeak --CommitNavigationRaceBrowserTest.CrashedInPendingCommit/NavigationQueueing --CommitNavigationRaceBrowserTest.CrashedInPendingCommit/UndoCommitNavigation -CorsOriginPatternSetterBrowserTest.BlockDifferentPort -CrossPlatformAccessibilityBrowserTest.ControlsIdsForColorPopup -CrossPlatformAccessibilityBrowserTest.ControlsIdsForDateTimePopup @@ -292,10 +267,7 @@ -DataDecoderBrowserTest.NoCallbackAfterDestruction_Gzip -DataDecoderBrowserTest.NoCallbackAfterDestruction_Json -DataDecoderBrowserTest.NoCallbackAfterDestruction_Xml --DatabaseTest.ModificationsPersistAfterRendererCrash --DevToolsProtocolDeviceEmulationTest.RenderKillDoesNotCrashBrowser -FencedFrameSecurityExploitBrowserTestWithTrustTokensEnabled.BrowserForbidsTrustTokenParamsOnFencedFrameNav --FrameTreeBrowserTest.FrameTreeAfterCrash -IndexedDBBrowserTest.DoesntHangTest -IndexedDBBrowserTest.NegativeDBDataVersion -IndexedDBBrowserTest.NegativeDBSchemaVersion @@ -303,51 +275,20 @@ -InterestGroupBiddingAndAuctionServerBrowserTest.ChecksPermissionPolicyWarning -InterestGroupBiddingAndAuctionServerBrowserTest.TestEmpty -InterestGroupBrowserTest.JoinInterestGroupNonObjectJSONFields --IsolatedOriginTest.LocalStorageOriginEnforcement_IsolatedAccessingNonIsolated --IsolatedOriginTest.LocalStorageOriginEnforcement_OpaqueOrigin --IsolatedOriginTest.LocalStorage_EmptyLocalFrameToken --IsolatedOriginTest.LocalStorage_WrongLocalFrameToken --IsolatedOriginTest.SessionStorage_EmptyLocalFrameToken --IsolatedOriginTest.SessionStorage_WrongLocalFrameToken --IsolatedOriginTest.SessionStorage_WrongOrigin -LoaderBrowserTest.DynamicTitle1 -LoaderBrowserTest.DynamicTitle2 -LocalCompileHintsBrowserTest.LocalCompileHints --MessagePortCloseEventBrowserTest.CloseEventHappensIfProcessCrashes -MediaSessionPictureInPictureContentBrowserTest.ActionAvailableAfterEndOfStreamAndSrcUpdate -MediaSessionServiceImplBrowserTest.ResetServiceWhenNavigatingAway -NavigationBrowserTest.PostUploadIllegalFilePath -NavigationBrowserTest.ProcessShutdownDuringDeferredNavigationThrottle --NavigationCookiesBrowserTest.CookiesInheritedAboutBlank --NavigationCookiesBrowserTest.CookiesInheritedSrcDoc --NavigationRequestBrowserTest.CancelNavigationInWillStartRequest --NavigationRequestBrowserTest.EarlySwapMetrics_CrashNoCommit --NavigationRequestBrowserTest.EarlySwapMetrics_CrashedSubframe --NavigationRequestBrowserTest.NoLeakFromStartingSiteInstance --NavigationRequestBrowserTest.RendererCrashedBeforeCommitErrorPage -NetworkServiceBrowserTest.WebUIBindingsNoHttp -NetworkServiceNetLogBrowserTest.LogCreated --PageImplTest.NewPageObjectCreatedOnFrameCrash --PageImplTest.SameSiteNavigationAfterFrameCrash --PointerLockBrowserTest.PointerLockInnerContentsCrashes --PointerLockBrowserTest.PointerLockOopifCrashes --PolicyContainerHostBrowserTest.CheckRendererPolicyContainerAccessesAfterCrash -PowerMonitorTest.TestRendererProcess --PrerenderBrowserTest.AbandonIfPrimaryMainFrameRendererProcessIsKilled --PrerenderBrowserTest.AbandonIfRendererProcessCrashes --PrerenderBrowserTest.AbandonIfRendererProcessIsKilled -PrivateAggregationInternalsWebUiBrowserTest.WebUIClearStorage_ReportsRemoved -PrivateAggregationInternalsWebUiBrowserTest.WebUIShownWithReports_ReportsDisplayed -PrivateNetworkAccessBrowserTestRespectPreflightResultsForWorkers.FetchSharedWorkerFromSecureTreatAsPublicToLocal -RenderFrameDevToolsAgentHostFencedFrameBrowserTest.PageCrashInFencedFrame --RenderFrameHostImplBrowserTest.CheckRFHLifecycleStateWhenRendererCrashes --RenderFrameHostImplBrowserTest.DevToolsNavigationToken_EarlyCommitAfterCrash --RenderFrameHostImplBrowserTest.FileReloadAfterCrash --RenderFrameHostImplBrowserTest.GetCanonicalUrlAfterRendererCrash --RenderFrameHostImplBrowserTest.NotifiesProcessHostOfAudibleAudio --RenderFrameHostImplBrowserTest.RequestSnapshotAXTreeAfterRenderProcessHostDeath --RenderFrameHostImplBrowserTest.TerminationDisablersClearedOnRendererCrash --RenderFrameHostImplBrowserTest.WebUiReloadAfterCrash -RenderAccessibilityImplTest.TestHitTestPopupDoesNotCrash -RenderFrameDevToolsAgentHostBrowserTest.CancelCrossOriginNavigationAfterReadyToCommit -RenderWidgetHostDelegatedInkMetadataTest.FlagGetsSetFromRenderFrameMetadata @@ -383,9 +324,6 @@ -WebContentsImplBrowserTest.PopupsOfPopupsFromJavaScriptEndFullscreen -WebContentsImplBrowserTest.ReinitializeMainFrameForCrashedTab -WebUIImplBrowserTest.NavigateFromCrashedAboutBlank --WebContentsObserverBrowserTest.CookieCallbacks_MainFrame --WebContentsObserverBrowserTest.CookieCallbacks_Subframe --WebContentsObserverBrowserTest.CookieCallbacks_Subresource # TODO(crbug.com/41471694): The below tests related to the touchpad and gesture_detection # have been failing since https://crrev.com/c/5468600.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 5bee75d..2036f81 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -844,6 +844,21 @@ ] } ], + "AndroidTabDeclutterAutoDeletePromo": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AndroidTabDeclutterAutoDelete" + ] + } + ] + } + ], "AndroidTabDeclutterPerformanceImprovements": [ { "platforms": [ @@ -9175,24 +9190,6 @@ ] } ], - "ExtensionsCollapseMainMenu": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "ExtensionsCollapseMainMenu" - ] - } - ] - } - ], "ExtensionsToolbarAndMenuRedesign": [ { "platforms": [ @@ -9211,6 +9208,28 @@ ] } ], + "ExtensionsZeroStatePromo": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Variant1", + "params": { + "x_iph-variant": "custom-action-iph" + }, + "enable_features": [ + "ExtensionsCollapseMainMenu", + "IPH_ExtensionsZeroStatePromo" + ] + } + ] + } + ], "ExternalBeginFrameSourceWinUsesRunOrPostTask": [ { "platforms": [ @@ -14940,6 +14959,21 @@ ] } ], + "NewTabPageCustomization": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "NewTabPageCustomization" + ] + } + ] + } + ], "NimbleCollisionAvoidanceV1": [ { "platforms": [ @@ -24282,6 +24316,35 @@ ] } ], + "UnimportantFramePolicy": [ + { + "platforms": [ + "android_webview", + "android", + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "UnimportantFrame_LowerPriority", + "enable_features": [ + "UnimportantFramesPriority", + "UserVisibleProcessPriority" + ] + }, + { + "name": "UnimportantFrame_LowerPriorityAndFrameRate", + "enable_features": [ + "ThrottleUnimportantFrameRate", + "UnimportantFramesPriority", + "UserVisibleProcessPriority" + ] + } + ] + } + ], "UnlockDatabaseOnClose": [ { "platforms": [
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle index b5d2b90f..7e53a76 100644 --- a/third_party/androidx/build.gradle +++ b/third_party/androidx/build.gradle
@@ -305,7 +305,7 @@ google() maven { // This URL is generated by the fetch_all_androidx.py script. - url 'https://androidx.dev/snapshots/builds/13543585/artifacts/repository' + url 'https://androidx.dev/snapshots/builds/13545927/artifacts/repository' } mavenCentral() }
diff --git a/third_party/angle b/third_party/angle index 275745f..4b375fe 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 275745ff8b294d025f3dac0eb431998442f600b8 +Subproject commit 4b375fe5f51f3503dd4a88a5a13596db3dbf78e3
diff --git a/third_party/blink/public/mojom/ai/ai_language_model.mojom b/third_party/blink/public/mojom/ai/ai_language_model.mojom index 5501363d..5d81c81 100644 --- a/third_party/blink/public/mojom/ai/ai_language_model.mojom +++ b/third_party/blink/public/mojom/ai/ai_language_model.mojom
@@ -64,8 +64,8 @@ }; // The expected data type and languages specified with session creation. -// See LanguageModelExpectedInput in IDL. -struct AILanguageModelExpectedInput { +// See LanguageModelExpected in IDL. +struct AILanguageModelExpected { AILanguageModelPromptType type; array<AILanguageCode>? languages; }; @@ -93,7 +93,8 @@ struct AILanguageModelCreateOptions { AILanguageModelSamplingParams? sampling_params; array<AILanguageModelPrompt> initial_prompts; - array<AILanguageModelExpectedInput>? expected_inputs; + array<AILanguageModelExpected>? expected_inputs; + array<AILanguageModelExpected>? expected_outputs; }; // The client interface that receives an AILanguageModel or errors from an
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index a35797b3..5e89373f 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -698,8 +698,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_create_core_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_create_options.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_create_options.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected_input.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected_input.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_message.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_message.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_message_content.h",
diff --git a/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc index 0cb466e..235205e 100644 --- a/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc
@@ -7,6 +7,7 @@ #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/core/animation/interpolable_dynamic_range_limit.h" #include "third_party/blink/renderer/core/animation/length_units_checker.h" +#include "third_party/blink/renderer/core/css/css_dynamic_range_limit_mix_value.h" #include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h" #include "third_party/blink/renderer/core/style/computed_style.h" @@ -63,12 +64,15 @@ const StyleResolverState& state, ConversionCheckers& conversion_checkers) const { // TODO(crbug.com/415626999): Create a TreeCountingChecker for sibling-index() - if (auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value)) { + if (auto* mix_value = + DynamicTo<cssvalue::CSSDynamicRangeLimitMixValue>(value)) { CSSPrimitiveValue::LengthTypeFlags types; - primitive_value->AccumulateLengthUnitTypes(types); - if (InterpolationType::ConversionChecker* length_units_checker = - LengthUnitsChecker::MaybeCreate(types, state)) { - conversion_checkers.push_back(length_units_checker); + for (const CSSPrimitiveValue* primitive_value : mix_value->Percentages()) { + primitive_value->AccumulateLengthUnitTypes(types); + if (InterpolationType::ConversionChecker* length_units_checker = + LengthUnitsChecker::MaybeCreate(types, state)) { + conversion_checkers.push_back(length_units_checker); + } } } return ConvertDynamicRangeLimit(
diff --git a/third_party/blink/renderer/core/css/container_query_evaluator.cc b/third_party/blink/renderer/core/css/container_query_evaluator.cc index 7a0f72d..6befe5c 100644 --- a/third_party/blink/renderer/core/css/container_query_evaluator.cc +++ b/third_party/blink/renderer/core/css/container_query_evaluator.cc
@@ -352,15 +352,6 @@ MakeGarbageCollected<ScrollStateQuerySnapshot>(*container_element); } } - if ((unit_flags_ & MediaQueryExpValue::UnitFlags::kTreeCounting) == 0 && - (result.unit_flags & MediaQueryExpValue::UnitFlags::kTreeCounting) != 0) { - Element* container = ContainerElement(); - if (ContainerNode* parent = container->ParentElementOrDocumentFragment()) { - parent->SetChildrenAffectedByForwardPositionalRules(); - parent->SetChildrenAffectedByBackwardPositionalRules(); - container->GetDocument().GetStyleEngine().SetUsesTreeCountingFunctions(); - } - } unit_flags_ |= result.unit_flags; return result.value; @@ -950,10 +941,7 @@ break; } - if (!style_changed && !DependsOnTreeCounting()) { - // If some query depends on a tree-counting function (e.g. sibling-index()), - // we must re-evaluate the queries even if the style didn't change. This is - // because the sibling-index/count isn't stored on ComputedStyle. + if (!style_changed) { return recalc_change; } @@ -973,15 +961,13 @@ MayDependOnWritingDirection() && old_style.GetWritingDirection() != new_style.GetWritingDirection(); - if (invalidate_for_writing_direction || invalidate_for_font || - DependsOnTreeCounting()) { + if (invalidate_for_writing_direction || invalidate_for_font) { // Writing direction and font sizing are cached on CSSContainerValues. Need // to recreate the values based on the current ComputedStyle. UpdateContainerValues(); } - if (invalidate_for_writing_direction || invalidate_for_font || - DependsOnTreeCounting()) { + if (invalidate_for_writing_direction || invalidate_for_font) { switch (StyleAffectingSizeChanged()) { case ContainerQueryEvaluator::Change::kNone: break; @@ -1009,8 +995,7 @@ if (!base::ValuesEquivalent(old_style.InheritedVariables(), new_style.InheritedVariables()) || !base::ValuesEquivalent(old_style.NonInheritedVariables(), - new_style.NonInheritedVariables()) || - DependsOnTreeCounting()) { + new_style.NonInheritedVariables())) { switch (StyleContainerChanged()) { case ContainerQueryEvaluator::Change::kNone: break;
diff --git a/third_party/blink/renderer/core/css/container_query_evaluator.h b/third_party/blink/renderer/core/css/container_query_evaluator.h index 4f91d64..9fcca655 100644 --- a/third_party/blink/renderer/core/css/container_query_evaluator.h +++ b/third_party/blink/renderer/core/css/container_query_evaluator.h
@@ -59,9 +59,6 @@ std::optional<double> Width() const; std::optional<double> Height() const; void SetReferencedByUnit() { referenced_by_unit_ = true; } - bool DependsOnTreeCounting() { - return (unit_flags_ & MediaQueryExpValue::UnitFlags::kTreeCounting) != 0; - } bool DependsOnStyle() const { return depends_on_style_; } bool DependsOnStuck() const { return depends_on_stuck_; } bool DependsOnSnapped() const { return depends_on_snapped_; }
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 2ca04e6..f5728d9 100644 --- a/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc +++ b/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc
@@ -34,7 +34,6 @@ #include <utility> #include "base/memory/values_equivalent.h" -#include "third_party/blink/renderer/core/css/container_query_evaluator.h" #include "third_party/blink/renderer/core/css/invalidation/invalidation_tracing_flag.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/dom/element.h" @@ -166,12 +165,6 @@ g_empty_atom); return true; } - if (ContainerQueryEvaluator* evaluator = - element.GetContainerQueryEvaluator()) { - if (evaluator->DependsOnTreeCounting()) { - return true; - } - } } } return false;
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator.cc b/third_party/blink/renderer/core/css/media_query_evaluator.cc index 03cefe4..89479b30 100644 --- a/third_party/blink/renderer/core/css/media_query_evaluator.cc +++ b/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -1772,42 +1772,6 @@ return result ? KleeneValue::kTrue : KleeneValue::kFalse; } -namespace { - -unsigned ConversionFlagsToUnitFlags( - CSSToLengthConversionData::Flags conversion_flags) { - unsigned unit_flags = 0; - - using Flags = CSSToLengthConversionData::Flags; - using Flag = CSSToLengthConversionData::Flag; - using UnitFlags = MediaQueryExpValue::UnitFlags; - - if (conversion_flags & (static_cast<Flags>(Flag::kEm) | - static_cast<Flags>(Flag::kGlyphRelative))) { - unit_flags |= UnitFlags::kFontRelative; - } - if (conversion_flags & (static_cast<Flags>(Flag::kRootFontRelative))) { - unit_flags |= UnitFlags::kRootFontRelative; - } - if (conversion_flags & static_cast<Flags>(Flag::kDynamicViewport)) { - unit_flags |= UnitFlags::kDynamicViewport; - } - if (conversion_flags & (static_cast<Flags>(Flag::kViewport) | - static_cast<Flags>(Flag::kSmallLargeViewport))) { - unit_flags |= UnitFlags::kStaticViewport; - } - if (conversion_flags & static_cast<Flags>(Flag::kContainerRelative)) { - unit_flags |= UnitFlags::kContainer; - } - if (conversion_flags & static_cast<Flags>(Flag::kSiblingRelative)) { - unit_flags |= UnitFlags::kTreeCounting; - } - - return unit_flags; -} - -} // namespace - KleeneValue MediaQueryEvaluator::EvalStyleFeature( const MediaQueryFeatureExpNode& feature, MediaQueryResultFlags* result_flags) const { @@ -1839,10 +1803,8 @@ return KleeneValue::kFalse; } - CSSToLengthConversionData::Flags conversion_flags; - const CSSValue* query_value = - StyleResolver::ComputeValue(container, CSSPropertyName(property_name), - query_specified, conversion_flags); + const CSSValue* query_value = StyleResolver::ComputeValue( + container, CSSPropertyName(property_name), query_specified); if (const auto* decl_value = DynamicTo<CSSUnparsedDeclarationValue>(query_value)) { @@ -1859,10 +1821,6 @@ return KleeneValue::kFalse; } - if (result_flags && conversion_flags != 0) { - result_flags->unit_flags |= ConversionFlagsToUnitFlags(conversion_flags); - } - const CSSValue* computed_value = CustomProperty(property_name, *media_values_->GetDocument()) .CSSValueFromComputedStyle(
diff --git a/third_party/blink/renderer/core/css/media_query_exp.cc b/third_party/blink/renderer/core/css/media_query_exp.cc index 9e0e410e..8f92412 100644 --- a/third_party/blink/renderer/core/css/media_query_exp.cc +++ b/third_party/blink/renderer/core/css/media_query_exp.cc
@@ -701,17 +701,14 @@ unsigned MediaQueryExpValue::GetUnitFlags() const { CSSPrimitiveValue::LengthTypeFlags length_type_flags; - unsigned unit_flags = 0; - if (IsValue()) { if (auto* primitive = DynamicTo<CSSPrimitiveValue>(GetCSSValue())) { primitive->AccumulateLengthUnitTypes(length_type_flags); - if (primitive->IsElementDependent()) { - unit_flags |= UnitFlags::kTreeCounting; - } } } + unsigned unit_flags = 0; + if (length_type_flags.test(CSSPrimitiveValue::kUnitTypeFontSize) || length_type_flags.test(CSSPrimitiveValue::kUnitTypeFontXSize) || length_type_flags.test(CSSPrimitiveValue::kUnitTypeZeroCharacterWidth) ||
diff --git a/third_party/blink/renderer/core/css/media_query_exp.h b/third_party/blink/renderer/core/css/media_query_exp.h index b9326c3..51f8fb4b 100644 --- a/third_party/blink/renderer/core/css/media_query_exp.h +++ b/third_party/blink/renderer/core/css/media_query_exp.h
@@ -149,10 +149,9 @@ kDynamicViewport = 1 << 2, kStaticViewport = 1 << 3, kContainer = 1 << 4, - kTreeCounting = 1 << 5, }; - static const int kUnitFlagsBits = 6; + static const int kUnitFlagsBits = 5; unsigned GetUnitFlags() const;
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc index 41946d7..a57562df 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc
@@ -1263,7 +1263,7 @@ } // So that we don't introduce more, or break the entire test inadvertently. - EXPECT_EQ(broken_properties, 16); + EXPECT_EQ(broken_properties, 15); } TEST(CSSParserImplTest, ParseSupportsBlinkFeature) {
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc index 66ea681d..6cc2d00 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -393,6 +393,41 @@ } } +// Returns a list for a <gap-rule>. A <gap-rule> is defined as: +// [ <line-width> || <line-style> || <color> ]. The computed value serialization +// should follow the shortest serialization principle, making it consistent with +// the specified serialization. +CSSValueList* GetValueListForGapRule(const CSSValue& width_value, + const CSSValue& style_value, + const CSSValue& color_value) { + CSSValueList* result_list = CSSValueList::CreateSpaceSeparated(); + + if (const auto* ident_value = DynamicTo<CSSIdentifierValue>(width_value); + !(ident_value && ident_value->GetValueID() == CSSValueID::kMedium) && + !width_value.IsInitialValue()) { + result_list->Append(width_value); + } + + if (const auto* ident_value = DynamicTo<CSSIdentifierValue>(style_value); + !(ident_value && ident_value->GetValueID() == CSSValueID::kNone) && + !style_value.IsInitialValue()) { + result_list->Append(style_value); + } + if (const auto* ident_value = DynamicTo<CSSIdentifierValue>(color_value); + !(ident_value && + ident_value->GetValueID() == CSSValueID::kCurrentcolor) && + !color_value.IsInitialValue()) { + result_list->Append(color_value); + } + + if (result_list->length() == 0) { + const CSSValue* default_width = + CSSIdentifierValue::Create(CSSValueID::kMedium); + result_list->Append(*default_width); + } + return result_list; +} + } // namespace const CSSValueList* ComputedStyleUtils::ValuesForMaskShorthand( @@ -3880,8 +3915,17 @@ // behavior of handling the shorthand since values are stored as single // values and not lists. if (!RuntimeEnabledFeatures::CSSGapDecorationEnabled()) { - return ValuesForShorthandProperty(shorthand, style, layout_object, - allow_visited_style, value_phase); + const CSSValue* width_value = + shorthand.properties()[0]->CSSValueFromComputedStyle( + style, layout_object, allow_visited_style, value_phase); + const CSSValue* style_value = + shorthand.properties()[1]->CSSValueFromComputedStyle( + style, layout_object, allow_visited_style, value_phase); + const CSSValue* color_value = + shorthand.properties()[2]->CSSValueFromComputedStyle( + style, layout_object, allow_visited_style, value_phase); + + return GetValueListForGapRule(*width_value, *style_value, *color_value); } CHECK_EQ(shorthand.length(), 3u); @@ -3982,10 +4026,10 @@ } for (size_t j = 0; j < rules_count; ++j) { - CSSValueList* gap_rule = CSSValueList::CreateSpaceSeparated(); - gap_rule->Append(width_repeat_value->Values().Item(j)); - gap_rule->Append(style_repeat_value->Values().Item(j)); - gap_rule->Append(color_repeat_value->Values().Item(j)); + CSSValueList* gap_rule = + GetValueListForGapRule(width_repeat_value->Values().Item(j), + style_repeat_value->Values().Item(j), + color_repeat_value->Values().Item(j)); repeated_gap_rules->Append(*gap_rule); } @@ -4005,10 +4049,8 @@ return nullptr; } - CSSValueList* gap_rule = CSSValueList::CreateSpaceSeparated(); - gap_rule->Append(width_values->Item(i)); - gap_rule->Append(style_values->Item(i)); - gap_rule->Append(color_values->Item(i)); + CSSValueList* gap_rule = GetValueListForGapRule( + width_values->Item(i), style_values->Item(i), color_values->Item(i)); result->Append(*gap_rule); } }
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 96d89c2..0e383eb 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -2863,15 +2863,6 @@ Element* element, const CSSPropertyName& property_name, const CSSValue& value) { - CSSToLengthConversionData::Flags flags; - return ComputeValue(element, property_name, value, flags); -} - -const CSSValue* StyleResolver::ComputeValue( - Element* element, - const CSSPropertyName& property_name, - const CSSValue& value, - CSSToLengthConversionData::Flags& flags) { Document& document = element->GetDocument(); document.GetStyleEngine().UpdateViewportSize(); const ComputedStyle* base_style = element->GetComputedStyle(); @@ -2898,7 +2889,6 @@ return nullptr; } CSSPropertyRef property_ref(property_name, document); - flags = state.TakeLengthConversionFlags(); const ComputedStyle* style = state.TakeStyle(); return ComputedStyleUtils::ComputedPropertyValue(property_ref.GetProperty(), *style);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.h b/third_party/blink/renderer/core/css/resolver/style_resolver.h index 905e6914..f0dfb75 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.h
@@ -32,7 +32,6 @@ #include "third_party/blink/renderer/core/css/element_rule_collector.h" #include "third_party/blink/renderer/core/css/resolver/matched_properties_cache.h" #include "third_party/blink/renderer/core/css/resolver/style_builder.h" -#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/css/selector_checker.h" #include "third_party/blink/renderer/core/css/selector_filter.h" #include "third_party/blink/renderer/core/css/style_request.h" @@ -223,13 +222,7 @@ // Return a computed value for the passed-in property:value pair in the // context of the current ComputedStyle of the 'element'. // Returns nullptr for custom property values that are IACVT. - static const CSSValue* ComputeValue(Element*, - const CSSPropertyName&, - const CSSValue&, - CSSToLengthConversionData::Flags&); - // A wrapper for the function above when not interested in the conversion - // flags. - static const CSSValue* ComputeValue(Element*, + static const CSSValue* ComputeValue(Element* element, const CSSPropertyName&, const CSSValue&); // Resolves a single CSSValue in the context of some element's computed style.
diff --git a/third_party/blink/renderer/core/frame/history.cc b/third_party/blink/renderer/core/frame/history.cc index dd55dee0..145a254 100644 --- a/third_party/blink/renderer/core/frame/history.cc +++ b/third_party/blink/renderer/core/frame/history.cc
@@ -60,8 +60,7 @@ namespace { -void MaybeRecordUkm(LocalDOMWindow* window, - bool is_history_modifying_operation) { +void MaybeRecordHistoryAdvanceMethodUkm(LocalDOMWindow* window) { if (!window || !window->GetFrame()) { return; } @@ -71,8 +70,7 @@ bool from_ad = window->GetFrame()->IsAdScriptInStack() || window->GetFrame()->IsAdFrame(); - ukm::builders::HistoryApi(window->UkmSourceID()) - .SetIsHistoryModifyingOperation(is_history_modifying_operation) + ukm::builders::HistoryApi_AdvanceMethod(window->UkmSourceID()) .SetHasStickyUserActivation(has_sticky_user_activation) .SetFromAd(from_ad) .Record(window->UkmRecorder()); @@ -89,8 +87,6 @@ } unsigned History::length(ExceptionState& exception_state) const { - MaybeRecordUkm(DomWindow(), /*is_history_modifying_operation=*/false); - if (!DomWindow()) { exception_state.ThrowSecurityError( "May not use a History object associated with a Document that is not " @@ -103,8 +99,6 @@ ScriptValue History::state(ScriptState* script_state, ExceptionState& exception_state) { - MaybeRecordUkm(DomWindow(), /*is_history_modifying_operation=*/false); - return StateHelper(script_state, exception_state); } @@ -116,8 +110,6 @@ void History::setScrollRestoration(const V8ScrollRestoration& value, ExceptionState& exception_state) { - MaybeRecordUkm(DomWindow(), /*is_history_modifying_operation=*/false); - HistoryItem* item = GetHistoryItem(); if (!item) { exception_state.ThrowSecurityError( @@ -139,8 +131,6 @@ V8ScrollRestoration History::scrollRestoration( ExceptionState& exception_state) { - MaybeRecordUkm(DomWindow(), /*is_history_modifying_operation=*/false); - if (!DomWindow()) { exception_state.ThrowSecurityError( "May not use a History object associated with a Document that is not " @@ -222,7 +212,9 @@ void History::go(ScriptState* script_state, int delta, ExceptionState& exception_state) { - MaybeRecordUkm(DomWindow(), /*is_history_modifying_operation=*/true); + if (delta > 0) { + MaybeRecordHistoryAdvanceMethodUkm(DomWindow()); + } LocalDOMWindow* window = DomWindow(); if (!window) { @@ -275,7 +267,7 @@ const String& title, const String& url, ExceptionState& exception_state) { - MaybeRecordUkm(DomWindow(), /*is_history_modifying_operation=*/true); + MaybeRecordHistoryAdvanceMethodUkm(DomWindow()); v8::Isolate* isolate = script_state->GetIsolate(); WebFrameLoadType load_type = WebFrameLoadType::kStandard; @@ -311,8 +303,6 @@ const String& title, const String& url, ExceptionState& exception_state) { - MaybeRecordUkm(DomWindow(), /*is_history_modifying_operation=*/true); - v8::Isolate* isolate = script_state->GetIsolate(); scoped_refptr<SerializedScriptValue> serialized_data = SerializedScriptValue::Serialize(isolate, data.V8Value(),
diff --git a/third_party/blink/renderer/core/paint/box_fragment_painter.cc b/third_party/blink/renderer/core/paint/box_fragment_painter.cc index 481f100..1e43569c 100644 --- a/third_party/blink/renderer/core/paint/box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/box_fragment_painter.cc
@@ -184,8 +184,10 @@ const bool has_sibling = current->PreviousSibling() || current->NextSibling(); if (has_sibling && previous_sibling && - previous_sibling.GetLayoutObject()->IsDescendantOf(parent)) + !previous_sibling.Item()->IsFloating() && + previous_sibling.GetLayoutObject()->IsDescendantOf(parent)) { break; + } if (auto* parent_layout_inline = DynamicTo<LayoutInline>(parent)) { if (parent_layout_inline->HitTestCulledInline(result, hit_test_location,
diff --git a/third_party/blink/renderer/modules/ai/ai_utils.cc b/third_party/blink/renderer/modules/ai/ai_utils.cc index 37688213..983dc31 100644 --- a/third_party/blink/renderer/modules/ai/ai_utils.cc +++ b/third_party/blink/renderer/modules/ai/ai_utils.cc
@@ -188,14 +188,14 @@ return result; } -Vector<mojom::blink::AILanguageModelExpectedInputPtr> ToMojoExpectedInputs( - const HeapVector<Member<LanguageModelExpectedInput>>& expected_inputs) { - Vector<mojom::blink::AILanguageModelExpectedInputPtr> result; +Vector<mojom::blink::AILanguageModelExpectedPtr> ToMojoExpectations( + const HeapVector<Member<LanguageModelExpected>>& expected_inputs) { + Vector<mojom::blink::AILanguageModelExpectedPtr> result; result.reserve(expected_inputs.size()); std::ranges::transform( expected_inputs, std::back_inserter(result), - [](const Member<LanguageModelExpectedInput>& expected_input) { - auto value = mojom::blink::AILanguageModelExpectedInput::New(); + [](const Member<LanguageModelExpected>& expected_input) { + auto value = mojom::blink::AILanguageModelExpected::New(); value->type = ToMojoInputType(expected_input->type()); if (expected_input->hasLanguages()) { value->languages = ToMojoLanguageCodes(expected_input->languages());
diff --git a/third_party/blink/renderer/modules/ai/ai_utils.h b/third_party/blink/renderer/modules/ai/ai_utils.h index ee744c1..96acf3e 100644 --- a/third_party/blink/renderer/modules/ai/ai_utils.h +++ b/third_party/blink/renderer/modules/ai/ai_utils.h
@@ -12,7 +12,7 @@ #include "third_party/blink/public/mojom/ai/ai_rewriter.mojom-blink.h" #include "third_party/blink/public/mojom/ai/ai_summarizer.mojom-blink.h" #include "third_party/blink/public/mojom/ai/ai_writer.mojom-blink.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected_input.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_proofreader_create_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rewriter_create_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_summarizer_create_options.h" @@ -59,9 +59,9 @@ mojom::blink::AIProofreaderCreateOptionsPtr ToMojoProofreaderCreateOptions( const ProofreaderCreateCoreOptions* core_options); -// Convert language model expected inputs to the corresponding mojo type. -Vector<mojom::blink::AILanguageModelExpectedInputPtr> ToMojoExpectedInputs( - const HeapVector<Member<LanguageModelExpectedInput>>& expected_inputs); +// Convert language model expected inputs or outputs to the matching mojo type. +Vector<mojom::blink::AILanguageModelExpectedPtr> ToMojoExpectations( + const HeapVector<Member<LanguageModelExpected>>& expected); // Implementation of LookupMatchingLocaleByBestFit // (https://tc39.es/ecma402/#sec-lookupmatchinglocalebybestfit) as
diff --git a/third_party/blink/renderer/modules/ai/language_model.cc b/third_party/blink/renderer/modules/ai/language_model.cc index 2d3ef5ec..db9bd08 100644 --- a/third_party/blink/renderer/modules/ai/language_model.cc +++ b/third_party/blink/renderer/modules/ai/language_model.cc
@@ -371,13 +371,6 @@ AIMetrics::AISessionType::kLanguageModel), AIMetrics::AIAPI::kCanCreateSession); mojom::blink::AILanguageModelSamplingParamsPtr sampling_params; - Vector<mojom::blink::AILanguageModelExpectedInputPtr> expected_inputs; - String system_prompt; - Vector<mojom::blink::AILanguageModelPromptPtr> initial_prompts; - if (options && options->hasExpectedInputs()) { - expected_inputs = ToMojoExpectedInputs(options->expectedInputs()); - } - auto sampling_params_or_exception = ResolveSamplingParamsOption(options); if (!sampling_params_or_exception.has_value()) { resolver->Resolve(AvailabilityToV8(Availability::kUnavailable)); @@ -385,13 +378,22 @@ } sampling_params = std::move(sampling_params_or_exception.value()); + Vector<mojom::blink::AILanguageModelExpectedPtr> expected_in, expected_out; + if (options && options->hasExpectedInputs()) { + expected_in = ToMojoExpectations(options->expectedInputs()); + } + if (options && options->hasExpectedOutputs()) { + expected_out = ToMojoExpectations(options->expectedOutputs()); + } + + Vector<mojom::blink::AILanguageModelPromptPtr> initial_prompts; HeapMojoRemote<mojom::blink::AIManager>& ai_manager_remote = AIInterfaceProxy::GetAIManagerRemote( ExecutionContext::From(script_state)); ai_manager_remote->CanCreateLanguageModel( mojom::blink::AILanguageModelCreateOptions::New( std::move(sampling_params), std::move(initial_prompts), - std::move(expected_inputs)), + std::move(expected_in), std::move(expected_out)), WTF::BindOnce( [](ScriptPromiseResolver<V8Availability>* resolver, mojom::blink::ModelAvailabilityCheckResult check_result) {
diff --git a/third_party/blink/renderer/modules/ai/language_model.h b/third_party/blink/renderer/modules/ai/language_model.h index 04d4c61..cd2c16b 100644 --- a/third_party/blink/renderer/modules/ai/language_model.h +++ b/third_party/blink/renderer/modules/ai/language_model.h
@@ -14,7 +14,6 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_append_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_clone_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_create_options.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected_input.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_message_role.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_prompt_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
diff --git a/third_party/blink/renderer/modules/ai/language_model_create_client.cc b/third_party/blink/renderer/modules/ai/language_model_create_client.cc index 352952c..54666b3 100644 --- a/third_party/blink/renderer/modules/ai/language_model_create_client.cc +++ b/third_party/blink/renderer/modules/ai/language_model_create_client.cc
@@ -56,9 +56,6 @@ void LanguageModelCreateClient::Create() { mojom::blink::AILanguageModelSamplingParamsPtr sampling_params; - Vector<mojom::blink::AILanguageModelExpectedInputPtr> expected_inputs; - Vector<mojom::blink::AILanguageModelPromptPtr> initial_prompts; - auto sampling_params_or_exception = ResolveSamplingParamsOption(options_); if (!sampling_params_or_exception.has_value()) { switch (sampling_params_or_exception.error()) { @@ -79,8 +76,12 @@ } sampling_params = std::move(sampling_params_or_exception.value()); + Vector<mojom::blink::AILanguageModelExpectedPtr> expected_in, expected_out; if (options_->hasExpectedInputs()) { - expected_inputs = ToMojoExpectedInputs(options_->expectedInputs()); + expected_in = ToMojoExpectations(options_->expectedInputs()); + } + if (options_->hasExpectedOutputs()) { + expected_out = ToMojoExpectations(options_->expectedOutputs()); } // TODO(crbug.com/381974893): Remove this warning after a couple milestones. @@ -91,7 +92,9 @@ "`systemPrompt` is no longer supported. Use " "`initialPrompts: [{role: 'system', content: ... }, ...]` instead."); } - // TODO(crbug.com/419583879): Add better test coverage for this. + + // TODO(crbug.com/419583879): Add better test coverage for initialPrompts. + Vector<mojom::blink::AILanguageModelPromptPtr> initial_prompts; if (options_->hasInitialPrompts()) { for (const auto& message : options_->initialPrompts()) { if (message->role() == V8LanguageModelMessageRole::Enum::kSystem && @@ -138,7 +141,7 @@ std::move(client_remote), mojom::blink::AILanguageModelCreateOptions::New( std::move(sampling_params), std::move(initial_prompts), - std::move(expected_inputs))); + std::move(expected_in), std::move(expected_out))); } void LanguageModelCreateClient::OnResult(
diff --git a/third_party/blink/renderer/modules/ai/language_model_create_options.idl b/third_party/blink/renderer/modules/ai/language_model_create_options.idl index a5a1d4d..462f0b3 100644 --- a/third_party/blink/renderer/modules/ai/language_model_create_options.idl +++ b/third_party/blink/renderer/modules/ai/language_model_create_options.idl
@@ -41,8 +41,9 @@ unrestricted double topK; unrestricted double temperature; - // The expected input types and languages for the session. - sequence<LanguageModelExpectedInput> expectedInputs; + // The expected types and languages for the session. + sequence<LanguageModelExpected> expectedInputs; + sequence<LanguageModelExpected> expectedOutputs; }; dictionary LanguageModelCreateOptions : LanguageModelCreateCoreOptions { @@ -56,7 +57,7 @@ DOMString systemPrompt; }; -dictionary LanguageModelExpectedInput { +dictionary LanguageModelExpected { required LanguageModelMessageType type; sequence<DOMString> languages; };
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc b/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc index 154cc79..ab6604d 100644 --- a/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc +++ b/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc
@@ -444,6 +444,24 @@ double last_score = 1; double cumulative_confidence = 0; + // TODO(crbug.com/419881396): `LanguageDetectionModel::PredictWithScan` should + // be updated to provide consistent results. Currently it only ever reports + // the "und" language tag for the empty string. Otherwise it will report + // unknown. + if (predictions.size() == 1) { + auto und = predictions.at(0); + CHECK_EQ(und.language, "und"); + HeapVector<Member<LanguageDetectionResult>> results; + // Append "und" to end. Set it's confidence so that the total confidences + // add up to 1. + auto* und_result = MakeGarbageCollected<LanguageDetectionResult>(); + results.push_back(und_result); + und_result->setDetectedLanguage(String("und")); + und_result->setConfidence(1); + + return results; + } + const WTF::UncheckedIterator<LanguageDetectionModel::LanguagePrediction>& unknown_iter = std::find_if( predictions.begin(), predictions.end(),
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/translator.cc b/third_party/blink/renderer/modules/ai/on_device_translation/translator.cc index 0271fd0..1bc1bbe 100644 --- a/third_party/blink/renderer/modules/ai/on_device_translation/translator.cc +++ b/third_party/blink/renderer/modules/ai/on_device_translation/translator.cc
@@ -28,6 +28,32 @@ namespace blink { namespace { using mojom::blink::CanCreateTranslatorResult; + +bool ValidateAndCanonicalizeSourceAndTargetLanguages( + v8::Isolate* isolate, + TranslatorCreateCoreOptions* options) { + CHECK(options->hasSourceLanguage()); + CHECK(options->hasTargetLanguage()); + + v8::Maybe<std::string> canonicalized_source_language = + isolate->ValidateAndCanonicalizeUnicodeLocaleId( + options->sourceLanguage().Ascii()); + if (canonicalized_source_language.IsNothing()) { + return false; + } + + v8::Maybe<std::string> canonicalized_target_language = + isolate->ValidateAndCanonicalizeUnicodeLocaleId( + options->targetLanguage().Ascii()); + if (canonicalized_target_language.IsNothing()) { + return false; + } + + options->setSourceLanguage(String(canonicalized_source_language.FromJust())); + options->setTargetLanguage(String(canonicalized_target_language.FromJust())); + return true; +} + } // namespace Translator::Translator( @@ -79,6 +105,11 @@ return ScriptPromise<V8Availability>(); } + if (!ValidateAndCanonicalizeSourceAndTargetLanguages( + script_state->GetIsolate(), options)) { + return EmptyPromise(); + } + ScriptPromiseResolver<V8Availability>* resolver = MakeGarbageCollected<ScriptPromiseResolver<V8Availability>>(script_state); ScriptPromise<V8Availability> promise = resolver->Promise(); @@ -123,6 +154,11 @@ return EmptyPromise(); } + if (!ValidateAndCanonicalizeSourceAndTargetLanguages( + script_state->GetIsolate(), options)) { + return EmptyPromise(); + } + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver<Translator>>(script_state);
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index f968686..f60cb9a 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1476,7 +1476,8 @@ # Failing on Intel Mac11 crbug.com/379233396 [ Mac11 ] external/wpt/ai/translator/* [ Failure ] -### sheriff 2019-07-16 +# Failing (PRECONDITION_FAILED) without blink::features::kAIPromptAPIMultimodalInput flag +crbug.com/419853199 wpt_internal/ai/language-model-api-prompt-multimodal.https.window.html [ Failure Pass ] ### sheriff 2018-05-28
diff --git a/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.optional.https.window.js b/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.optional.https.window.js index 1dd248a9..ee8765adf 100644 --- a/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.optional.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.optional.https.window.js
@@ -52,3 +52,15 @@ assert_array_equals(detector.expectedInputLanguages, expectedInputLanguages); assert_true(Object.isFrozen(detector.expectedInputLanguages)); }, 'Creating LanguageDetector with expectedInputLanguages'); + + +promise_test(async () => { + const detector = await createLanguageDetector(); + + const results = await detector.detect(''); + assert_equals(results.length, 1); + + const [result] = results; + assert_equals(result.detectedLanguage, 'und'); + assert_equals(result.confidence, 1); +}, 'LanguageDetector.detect() detects empty string');
diff --git a/third_party/blink/web_tests/external/wpt/ai/translator/translator-locale.https.window.js b/third_party/blink/web_tests/external/wpt/ai/translator/translator-locale.https.window.js new file mode 100644 index 0000000..73e7eff2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/ai/translator/translator-locale.https.window.js
@@ -0,0 +1,50 @@ +// META: title=Detect english +// META: global=window +// META: timeout=long +// META: script=resources/util.js +// META: script=/resources/testdriver.js +// META: script=../resources/util.js +// META: script=../resources/locale-util.js + +'use strict'; + +function assert_rejects_invalid_expected_input_languages( + t, method, sourceLanguage, targetLanguage) { + return promise_rejects_js( + t, RangeError, method({sourceLanguage, targetLanguage})); +} + +function testInvalidLanguagePairs(t, method) { + const allValidLanguageTags = Object.values(valid_language_tags).flat(); + // Invalid source language. + for (const sourceLanguage of invalid_language_tags) { + for (const targetLanguage of allValidLanguageTags) { + assert_rejects_invalid_expected_input_languages( + t, method, sourceLanguage, targetLanguage); + } + } + // Invalid target language. + for (const sourceLanguage of allValidLanguageTags) { + for (const targetLanguage of invalid_language_tags) { + assert_rejects_invalid_expected_input_languages( + t, method, sourceLanguage, targetLanguage); + } + } + // Invalid source and target language + for (const sourceLanguage of invalid_language_tags) { + for (const targetLanguage of invalid_language_tags) { + assert_rejects_invalid_expected_input_languages( + t, method, sourceLanguage, targetLanguage); + } + } +} + +promise_test(async t => { + // We don't need to consume user activation since it should throw a RangeError + // before it even can check if it needs to consume user activation. + testInvalidLanguagePairs(t, Translator.create); +}, 'LanguageDetector.create() throws RangeError for invalid language tags'); + +promise_test(async t => { + testInvalidLanguagePairs(t, Translator.availability); +}, 'LanguageDetector.availability() throws RangeError for invalid language tags');
diff --git a/third_party/blink/web_tests/external/wpt/cookie-store/resources/cookie-test-helpers.js b/third_party/blink/web_tests/external/wpt/cookie-store/resources/cookie-test-helpers.js index 178947a..8e23ff2c 100644 --- a/third_party/blink/web_tests/external/wpt/cookie-store/resources/cookie-test-helpers.js +++ b/third_party/blink/web_tests/external/wpt/cookie-store/resources/cookie-test-helpers.js
@@ -210,9 +210,10 @@ // Wipe cookies used by tests before and after the test. async function deleteAllCookies() { - (await cookieStore.getAll()).forEach(({name, value}) => { - cookieStore.delete(name); - }); + await Promise.all((await cookieStore.getAll()).map(async ({name, value}) => { + await cookieStore.delete(name); + await cookieStore.delete({name: name, partitioned: true}); + })); } return promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-conditional/container-queries/style-query-registered-custom-rem-change.html b/third_party/blink/web_tests/external/wpt/css/css-conditional/container-queries/style-query-registered-custom-rem-change.html deleted file mode 100644 index 33808fb..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-conditional/container-queries/style-query-registered-custom-rem-change.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!DOCTYPE html> -<title>CSS Container Queries Test: style() query with rem unit for registered custom property</title> -<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#style-container"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="support/cq-testcommon.js"></script> -<style> - @property --length { - syntax: "<length>"; - initial-value: 0px; - inherits: false; - } - - :root, body { font-size: 16px; } - #container { --length: 100px; } - - #target { color: red; } - @container style(--length: calc(1rem * 10)) { - #target { color: green; } - } -</style> -<div id="container"> - <div id="target">Should be green</div> -</div> -<script> - test(() => { - assert_equals(getComputedStyle(target).color, "rgb(255, 0, 0)"); - }, "Initially, 1rem * 10 evaluates to 160px"); - - test(() => { - document.documentElement.style.fontSize = "10px"; - assert_equals(getComputedStyle(target).color, "rgb(0, 128, 0)"); - }, "Changing the :root font-size to 10px makes 1rem * 10 evaluate to 100px"); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/parsing/gap-decorations-rule-shorthand-roundtrip.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/parsing/gap-decorations-rule-shorthand-roundtrip.tentative.html new file mode 100644 index 0000000..5955af8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/parsing/gap-decorations-rule-shorthand-roundtrip.tentative.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>CSS Gap Decorations: *rule properties round trips properly</title> + <link rel="help" href="https://drafts.csswg.org/css-multicol/#propdef-column-rule"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <div id="target"></div> +<script> +const rule_properties = ['column-rule', 'row-rule', 'rule'] +for(let rule_property of rule_properties) { + let div = document.querySelector('#target'); + const computed_rule_serialization = window.getComputedStyle(div)[rule_property]; + div.style[rule_property] = computed_rule_serialization; + + test(() => { + assert_equals(computed_rule_serialization, div.style[rule_property]); + }, `${rule_property} round trips properly.`); +} +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-computed.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-computed.html index 96ba734d8..22ed11c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-computed.html
@@ -25,9 +25,9 @@ const currentColor = 'rgb(0, 255, 0)'; const mediumWidth = getComputedStyle(document.getElementById('reference')).columnRuleWidth; // e.g. 3px -test_computed_value("column-rule", "10px", "0px none " + currentColor); +test_computed_value("column-rule", "10px", "0px " + currentColor); test_computed_value("column-rule", "dotted", mediumWidth + " dotted " + currentColor); -test_computed_value("column-rule", "0px none rgb(255, 0, 255)"); +test_computed_value("column-rule", "0px none rgb(255, 0, 255)", "0px rgb(255, 0, 255)"); test_computed_value("column-rule", "10px dotted rgb(255, 0, 255)"); test_computed_value("column-rule", "medium hidden currentcolor", "0px hidden " + currentColor);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/tree-counting/sibling-function-container-query-invalidation.html b/third_party/blink/web_tests/external/wpt/css/css-values/tree-counting/sibling-function-container-query-invalidation.html deleted file mode 100644 index c0d6d91..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-values/tree-counting/sibling-function-container-query-invalidation.html +++ /dev/null
@@ -1,92 +0,0 @@ -<!DOCTYPE html> -<title>CSS Values and Units Test: sibling-index() and sibling-count() changes in container queries</title> -<link rel="help" href="https://drafts.csswg.org/css-values-5/#tree-counting"> -<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-features"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<style> - @property --length { - syntax: "<length>"; - initial-value: 0px; - inherits: false; - } - .container { container-type: inline-size; } - #c1 { - width: 100px; - --length: 100px; - } - #c2 { - width: 400px; - --length: 600px; - } - span { - --match-100: no; - --match-600: no; - } - @container (width = calc(100px * sibling-index())) { - span { background-color: green; } - } - @container (width = calc(200px * sibling-count())) { - span { color: lime; } - } - @container style(--length: calc(100px * sibling-index())) { - span { --match-100: yes; } - } - @container style(--length: calc(300px * sibling-count())) { - span { --match-600: yes; } - } -</style> -<div style="color:black"> - <div id="rm1"></div> - <div id="rm2"></div> - <div id="c1" class="container"> - <span id="t1"></span> - </div> - <div id="c2" class="container"> - <span id="t2"></span> - </div> -</div> -<script> - test(() => { - assert_equals(getComputedStyle(t1).backgroundColor, "rgba(0, 0, 0, 0)"); - assert_equals(getComputedStyle(t1).color, "rgb(0, 0, 0)"); - }, "sibling-index() in @container width query initially not matching"); - - test(() => { - assert_equals(getComputedStyle(t1).backgroundColor, "rgba(0, 0, 0, 0)"); - assert_equals(getComputedStyle(t1).color, "rgb(0, 0, 0)"); - }, "sibling-count() in @container width query initially not matching"); - - test(() => { - assert_equals(getComputedStyle(t1).getPropertyValue("--match-100"), "no"); - assert_equals(getComputedStyle(t1).getPropertyValue("--match-600"), "no"); - }, "sibling-index() in @container style() query initially not matching"); - - test(() => { - assert_equals(getComputedStyle(t2).getPropertyValue("--match-100"), "no"); - assert_equals(getComputedStyle(t2).getPropertyValue("--match-600"), "no"); - }, "sibling-count() in @container style() query initially not matching"); - - rm1.remove(); - rm2.remove(); - - test(() => { - assert_equals(getComputedStyle(t1).backgroundColor, "rgb(0, 128, 0)"); - assert_equals(getComputedStyle(t1).color, "rgb(0, 0, 0)"); - }, "sibling-index() in @container width query matching after removal"); - - test(() => { - assert_equals(getComputedStyle(t2).backgroundColor, "rgba(0, 0, 0, 0)"); - assert_equals(getComputedStyle(t2).color, "rgb(0, 255, 0)"); - }, "sibling-count() in @container width query matching after removal"); - - test(() => { - assert_equals(getComputedStyle(t1).getPropertyValue("--match-100"), "yes"); - assert_equals(getComputedStyle(t1).getPropertyValue("--match-600"), "no"); - }, "sibling-index() in @container style() query matching after removal"); - - test(() => { - assert_equals(getComputedStyle(t2).getPropertyValue("--match-100"), "no"); - assert_equals(getComputedStyle(t2).getPropertyValue("--match-600"), "yes"); - }, "sibling-count() in @container style() query matching after removal"); -</script>
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule-expected.txt index 94cea83d..4339029 100644 --- a/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule-expected.txt +++ b/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule-expected.txt
@@ -3,9 +3,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". PASS computedStyle.getPropertyValue('-webkit-column-rule') is "1px dotted rgb(0, 0, 0)" -PASS computedStyle.getPropertyValue('-webkit-column-rule') is "0px none rgb(255, 0, 0)" +PASS computedStyle.getPropertyValue('-webkit-column-rule') is "0px rgb(255, 0, 0)" PASS computedStyle.getPropertyValue('-webkit-column-rule') is "3px dashed rgb(255, 0, 0)" -PASS computedStyle.getPropertyValue('-webkit-column-rule') is "0px none rgb(0, 0, 255)" +PASS computedStyle.getPropertyValue('-webkit-column-rule') is "0px rgb(0, 0, 255)" PASS computedStyle.getPropertyValue('-webkit-column-rule') is "0px hidden rgb(0, 0, 255)" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule.html b/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule.html index 85ee6f9..97f69575 100644 --- a/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule.html +++ b/third_party/blink/web_tests/fast/css/getComputedStyle/getComputedStyle-column-rule.html
@@ -21,7 +21,7 @@ shouldBeEqualToString("computedStyle.getPropertyValue('-webkit-column-rule')", '1px dotted rgb(0, 0, 0)'); e.style.webkitColumnRule="10px red"; -shouldBeEqualToString("computedStyle.getPropertyValue('-webkit-column-rule')", '0px none rgb(255, 0, 0)'); +shouldBeEqualToString("computedStyle.getPropertyValue('-webkit-column-rule')", '0px rgb(255, 0, 0)'); e.style.webkitColumnRuleWidth="medium" e.style.webkitColumnRuleStyle="dashed" @@ -29,7 +29,7 @@ e.style.webkitColumnRule="10px dotted blue" e.style.webkitColumnRuleStyle="none"; -shouldBeEqualToString("computedStyle.getPropertyValue('-webkit-column-rule')", '0px none rgb(0, 0, 255)'); +shouldBeEqualToString("computedStyle.getPropertyValue('-webkit-column-rule')", '0px rgb(0, 0, 255)'); e.style.webkitColumnRuleStyle="hidden"; shouldBeEqualToString("computedStyle.getPropertyValue('-webkit-column-rule')", '0px hidden rgb(0, 0, 255)');
diff --git a/third_party/blink/web_tests/fast/dom/elementsFromPoint/elementsFromPoint-inline-with-floating-sibling.html b/third_party/blink/web_tests/fast/dom/elementsFromPoint/elementsFromPoint-inline-with-floating-sibling.html new file mode 100644 index 0000000..077c14f --- /dev/null +++ b/third_party/blink/web_tests/fast/dom/elementsFromPoint/elementsFromPoint-inline-with-floating-sibling.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<span id=outer> + <a id=anchor href='https://www.google.com'> + <div style='position: relative; float: left;'>text in div</div> + <span id=target>text</span> + </a> +</span> +<script> +test(function(t) +{ + var position = target.getBoundingClientRect(); + + var elements = document.elementsFromPoint(position.x, position.y); + assert_true(elements.includes(anchor)); +}, "elementsFromPoint should return all elements under a point"); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability-available.https.window.js b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability-available.https.window.js index 0e79d98..a872981c 100644 --- a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability-available.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability-available.https.window.js
@@ -15,10 +15,11 @@ {topK: [1, 1.5, 2, 3, 99]}, // Nominally int 1-10+. {temperature: [0, 0.5, 1, 2]}, // Nominally float 0-1. {expectedInputs: [undefined, [], [{type: 'text'}], [{type: 'text', languages: ['en']}], ]}, + {expectedOutputs: [undefined, [], [{type: 'text'}], [{type: 'text', languages: ['en']}], ]}, ]; for (const options of generateOptionCombinations(kCreateOptionsSpec)) { const availability = await LanguageModel.availability(options); - assert_in_array(availability, kValidAvailabilities, options); + assert_in_array(availability, kValidAvailabilities, JSON.stringify(options)); } }, 'LanguageModel.availability() returns available with supported options'); @@ -27,6 +28,9 @@ // An array of unsupported test options. const kUnsupportedCreateOptions = [ { expectedInputs: [{type: 'text', languages: ['unk']}] }, // Language not supported. + { expectedOutputs: [{type: 'text', languages: ['unk']}] }, // Language not supported. + { expectedOutputs: [{type: 'image' }] }, // Type not supported. + { expectedOutputs: [{type: 'audio' }] }, // Type not supported. { topK: 0, temperature: 0.5 }, // zero topK not supported. { topK: -3, temperature: 0.5 }, // negative topK not supported. { topK: 3, temperature: -0.5 }, // negative temperature not supported. @@ -34,7 +38,7 @@ { temperature: 0.5 }, // temperature without topK not supported. ]; for (const options of kUnsupportedCreateOptions) { - assert_equals(await LanguageModel.availability(options), 'unavailable', options); + assert_equals(await LanguageModel.availability(options), 'unavailable', JSON.stringify(options)); } }, 'LanguageModel.availability() returns unavailable with unsupported options');
diff --git a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability.https.window.js b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability.https.window.js index 4a1c79e..dae8c9bc 100644 --- a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-availability.https.window.js
@@ -24,6 +24,11 @@ [{type: 'text', languages: ['en', 'ja', 'ko']}], [{type: 'audio', languages: ['es']}, {type: 'image', languages: ['fr']}], ]}, + {expectedOutputs: [undefined, [], [{type: 'text'}], + [{type: 'text'}, {type: 'audio'}, {type: 'image'}], + [{type: 'text', languages: ['en', 'ja', 'ko']}], + [{type: 'audio', languages: ['es']}, {type: 'image', languages: ['fr']}], + ]}, {initialPrompts: [undefined, [], [{role: 'system', content: 'have fun'}], [{role: 'system', content: 'have fun'}, {role: 'user', content: 'be good'}], [{role: 'system', content: 'be good'}, {role: 'system', content: 'be bad'}], @@ -32,6 +37,6 @@ ]; for (const options of generateOptionCombinations(kCreateOptionsSpec)) { const availability = await LanguageModel.availability(options); - assert_in_array(availability, kValidAvailabilities, options); + assert_in_array(availability, kValidAvailabilities, JSON.stringify(options)); } }, 'LanguageModel.availability() returns a valid value with plausible options');
diff --git a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-prompt-multimodal.https.window.js b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-prompt-multimodal.https.window.js index 7a45793..04cf98242 100644 --- a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-prompt-multimodal.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-prompt-multimodal.https.window.js
@@ -10,6 +10,9 @@ const kValidSVGImagePath = 'resources/media/wikipedia-logo.svg'; const kValidVideoPath = 'resources/media/video.mp4'; +const kImageOptions = {expectedInputs: [{type: 'image'}]}; +const kAudioOptions = {expectedInputs: [{type: 'audio'}]}; + function messageWithContent(prompt, type, value) { return [{ role: 'user', @@ -22,15 +25,11 @@ *****************************************/ promise_test(async t => { - await ensureLanguageModel(); - + await ensureLanguageModel(kImageOptions); const newImage = new Image(); newImage.src = kValidImagePath; - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - - // TODO(crbug.com/409615288): This should throw a TypeError according to the - // spec. + const session = await LanguageModel.create(kImageOptions); + // TODO(crbug.com/409615288): Expect a TypeError according to the spec. promise_rejects_dom( t, 'SyntaxError', session.prompt(messageWithContent(kPrompt, 'text', newImage))); @@ -45,44 +44,36 @@ const newImage = new Image(); newImage.src = kValidImagePath; const session = await LanguageModel.create(); - promise_rejects_dom( t, 'NotSupportedError', session.prompt(messageWithContent(kPrompt, 'image', newImage))); }, 'Prompt image without `image` expectedInput'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const blob = await (await fetch(kValidImagePath)).blob(); - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent(kPrompt, 'image', blob)); - assert_regexp_match(result, /<image>/); }, 'Prompt with Blob image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const blob = await (await fetch(kValidImagePath)).blob(); const bitmap = await createImageBitmap(blob); - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent(kPrompt, 'image', bitmap)); assert_regexp_match(result, /<image>/); }, 'Prompt with ImageBitmap image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const blob = await (await fetch(kValidImagePath)).blob(); const bitmap = await createImageBitmap(blob); const frame = new VideoFrame(bitmap, {timestamp: 1}); - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent(kPrompt, 'image', frame)); frame.close(); // Avoid JS garbage collection warning. @@ -90,83 +81,69 @@ }, 'Prompt with VideoFrame image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const canvas = new OffscreenCanvas(512, 512); // Requires a context to convert to a bitmap. var context = canvas.getContext('2d'); context.fillRect(10, 10, 200, 200); - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent(kPrompt, 'image', canvas)); assert_regexp_match(result, /<image>/); }, 'Prompt with OffscreenCanvas image content'); promise_test(async () => { - await ensureLanguageModel(); - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + await ensureLanguageModel(kImageOptions); + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt( messageWithContent(kPrompt, 'image', new ImageData(256, 256))); assert_regexp_match(result, /<image>/); }, 'Prompt with ImageData image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const newImage = new Image(); newImage.src = kValidImagePath; - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent(kPrompt, 'image', newImage)); assert_regexp_match(result, /<image>/); }, 'Prompt with HTMLImageElement image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); var canvas = document.createElement('canvas'); canvas.width = 1224; canvas.height = 768; - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent(kPrompt, 'image', canvas)); assert_regexp_match(result, /<image>/); }, 'Prompt with HTMLCanvasElement image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const image_data = await fetch(kValidImagePath); - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt( messageWithContent(kPrompt, 'image', await image_data.arrayBuffer())); assert_regexp_match(result, /<image>/); }, 'Prompt with ArrayBuffer image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const image_data = await fetch(kValidImagePath); - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent( kPrompt, 'image', new DataView(await image_data.arrayBuffer()))); assert_regexp_match(result, /<image>/); }, 'Prompt with ArrayBufferView image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const newImage = new Image(); newImage.src = kValidSVGImagePath; - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent( kPrompt, 'image', newImage)); @@ -175,7 +152,7 @@ promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('width', '100'); svg.setAttribute('height', '100'); @@ -191,9 +168,7 @@ const {promise, resolve} = Promise.withResolvers(); svgImage.addEventListener('load', resolve); await promise; - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent( kPrompt, 'image', svgImage)); @@ -201,17 +176,14 @@ }, 'Prompt with SVGImageElement image content'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kImageOptions); var video = document.createElement('video'); video.src = kValidVideoPath; video.width = 1224; video.height = 768; // Video must have frames fetched. See crbug.com/417249941#comment3 await video.play(); - - const session = - await LanguageModel.create({expectedInputs: [{type: 'image'}]}); - + const session = await LanguageModel.create(kImageOptions); const result = await session.prompt(messageWithContent( kPrompt, 'image', video)); @@ -226,55 +198,45 @@ await ensureLanguageModel(); const blob = await (await fetch(kValidAudioPath)).blob(); const session = await LanguageModel.create(); - promise_rejects_dom( t, 'NotSupportedError', session.prompt(messageWithContent(kPrompt, 'audio', blob))); }, 'Prompt audio without `audio` expectedInput'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kAudioOptions); const blob = await (await fetch(kValidAudioPath)).blob(); - const session = - await LanguageModel.create({expectedInputs: [{type: 'audio'}]}); - + const session = await LanguageModel.create(kAudioOptions); const result = await session.prompt(messageWithContent(kPrompt, 'audio', blob)); assert_regexp_match(result, /<audio>/); }, 'Prompt with Blob audio content'); promise_test(async (t) => { - await ensureLanguageModel(); + await ensureLanguageModel(kAudioOptions); const blob = await (await fetch(kValidImagePath)).blob(); - const session = - await LanguageModel.create({expectedInputs: [{type: 'audio'}]}); - - // TODO(crbug.com/409615288): This should throw a TypeError according to the - // spec. + const session = await LanguageModel.create(kAudioOptions); + // TODO(crbug.com/409615288): Expect a TypeError according to the spec. promise_rejects_dom( t, 'DataError', session.prompt(messageWithContent(kPrompt, 'audio', blob))); }, 'Prompt audio with blob containing invalid audio data.'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kAudioOptions); const audio_data = await fetch(kValidAudioPath); const audioCtx = new AudioContext(); const buffer = await audioCtx.decodeAudioData(await audio_data.arrayBuffer()); - const session = - await LanguageModel.create({expectedInputs: [{type: 'audio'}]}); - + const session = await LanguageModel.create(kAudioOptions); const result = await session.prompt(messageWithContent(kPrompt, 'audio', buffer)); assert_regexp_match(result, /<audio>/); }, 'Prompt with AudioBuffer'); promise_test(async () => { - await ensureLanguageModel(); + await ensureLanguageModel(kAudioOptions); const audio_data = await fetch(kValidAudioPath); - const session = - await LanguageModel.create({expectedInputs: [{type: 'audio'}]}); - + const session = await LanguageModel.create(kAudioOptions); const result = await session.prompt( messageWithContent(kPrompt, 'audio', await audio_data.arrayBuffer())); assert_regexp_match(result, /<audio>/);
diff --git a/third_party/chromite b/third_party/chromite index d36e7e1..4659653 160000 --- a/third_party/chromite +++ b/third_party/chromite
@@ -1 +1 @@ -Subproject commit d36e7e10909f4da15efe9683d0d531ad21b0b430 +Subproject commit 465965353f053ebc8f1a7219dd70e923f384c08d
diff --git a/third_party/dawn b/third_party/dawn index b3eb2e0..0ab79c2 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit b3eb2e09c68723b23dda602602cf3ef5f48a196d +Subproject commit 0ab79c2accfe342465aeda872b3aabd1d140d8c9
diff --git a/third_party/skia b/third_party/skia index f42bb59..0834eea 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit f42bb59753feff1eb831991ad29075150bbec626 +Subproject commit 0834eea9de33f68c8c8129d3be21e539dde490e7
diff --git a/third_party/swiftshader b/third_party/swiftshader index f70c119..a8133cb 160000 --- a/third_party/swiftshader +++ b/third_party/swiftshader
@@ -1 +1 @@ -Subproject commit f70c1194c1730893f7848cff07ca4ec196269709 +Subproject commit a8133cbb3c8969e3c1e6b3cea2c02ec8312ef9ca
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index fa392b2..a0de53f 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit fa392b2f49641c1cf3921d147f2974a75c177800 +Subproject commit a0de53f5f078733c45d9cf84500e92b908c62d15
diff --git a/tools/determinism/deterministic_build_ignorelist.pyl b/tools/determinism/deterministic_build_ignorelist.pyl index f8b293a..68ce3d4 100644 --- a/tools/determinism/deterministic_build_ignorelist.pyl +++ b/tools/determinism/deterministic_build_ignorelist.pyl
@@ -92,5 +92,10 @@ 'test_control_flow_guard.exe.pdb', 'cloud_authenticator_test_service.exe', 'cloud_authenticator_test_service.exe.pdb', + + # TODO(crbug.com/419882718): TestSystemMsiInstallerStandaloneSetup.exe is + # produced by signing files using `signtool.exe` on each build, so the + # builds of this file are non-deterministic. + 'TestSystemMsiInstallerStandaloneSetup.exe', ], }
diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py index cb7b8f46..a0df36c 100755 --- a/tools/json_schema_compiler/idl_schema.py +++ b/tools/json_schema_compiler/idl_schema.py
@@ -447,7 +447,7 @@ self.manifest_keys = None self.types = [] self.callbacks = OrderedDict() - self.description = description + self.description = description.strip().replace('\n', '') self.deprecated = deprecated def process(self):
diff --git a/tools/json_schema_compiler/idl_schema_test.py b/tools/json_schema_compiler/idl_schema_test.py index 71857ca..3d2bb2f 100755 --- a/tools/json_schema_compiler/idl_schema_test.py +++ b/tools/json_schema_compiler/idl_schema_test.py
@@ -46,6 +46,16 @@ self.idl_basics = loaded[0] self.maxDiff = None + def testNamespaceDescription(self): + # Tests the top level namespace description is cleaned up and joined + # together as expected. + schema = self.idl_basics + self.assertEqual( + 'Tests a variety of basic API definition features, ensuring things are' + ' parsed and processed as expected.', + schema['description'], + ) + def testSimpleCallbacks(self): schema = self.idl_basics expected = {'name': 'cb', 'parameters': []}
diff --git a/tools/json_schema_compiler/test/idl_basics.idl b/tools/json_schema_compiler/test/idl_basics.idl index f65d6d52..fbae1e2 100644 --- a/tools/json_schema_compiler/test/idl_basics.idl +++ b/tools/json_schema_compiler/test/idl_basics.idl
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Tests a variety of basic API definition features. +// Tests a variety of basic API definition features, ensuring things are parsed +// and processed as expected. namespace idl_basics { // Enum description
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 0fce9a8..3d4d781 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -25371,6 +25371,104 @@ </description> </action> +<action name="MobilePasswordCheckupCoordinatorCheckStateCanceled" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the canceled state of the password check upon opening + Password Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorCheckStateIdle" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the idle state of the password check upon opening Password + Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorCheckStateNoPasswords" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the no passwords state of the password check upon opening + Password Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorCheckStateOffline" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the offline state of the password check upon opening + Password Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorCheckStateOther" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the other state of the password check upon opening + Password Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorCheckStateQuotaLimit" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the quota limit state of the password check upon opening + Password Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorCheckStateRunning" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the running state of the password check upon opening + Password Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorCheckStateSignedOut" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported to track the signed out state of the password check upon opening + Password Issues from the Password Checkup homepage. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordCheckupCoordinatorShowReauth" + not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported when reauth is requested as a result of entering the Password + Checkup homepage. iOS only. TODO(crbug.com/409680593): This user action was + added to investigate a crash. Remove when done with the investigation. + </description> +</action> + <action name="MobilePasswordCheckupSettingsBack"> <owner>noemies@google.com</owner> <description> @@ -25432,6 +25530,15 @@ </description> </action> +<action name="MobilePasswordIssuesCoordinatorStart" not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported when the PasswordIssuesCoordinator is started. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + <action name="MobilePasswordIssuesOpenPasswordDetails"> <owner>noemies@google.com</owner> <description> @@ -25462,6 +25569,24 @@ </description> </action> +<action name="MobilePasswordIssuesViewDidAppear" not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported when the PasswordIssuesTableViewController view has appeared. iOS + only. TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + +<action name="MobilePasswordIssuesViewDidLoad" not_user_triggered="true"> + <owner>noemies@google.com</owner> + <description> + Reported when the PasswordIssuesTableViewController view has loaded. iOS + only. TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + <action name="MobilePasswordIssuesWeakOpen"> <owner>noemies@google.com</owner> <description> @@ -25760,6 +25885,24 @@ </description> </action> +<action name="MobileReauthFailed"> + <owner>noemies@google.com</owner> + <description> + Reported when reauthentication failed. iOS only. TODO(crbug.com/409680593): + This user action was added to investigate a crash. Remove when done with the + investigation. + </description> +</action> + +<action name="MobileReauthSuccessful"> + <owner>noemies@google.com</owner> + <description> + Reported when reauthentication succeeded. iOS only. + TODO(crbug.com/409680593): This user action was added to investigate a + crash. Remove when done with the investigation. + </description> +</action> + <action name="MobileReceivedExternalIntent"> <obsolete> Deprecated as of 06/2021. Replaced by MobileTabbedModeViewIntentFromApp and @@ -44805,6 +44948,14 @@ </description> </action> +<action name="Tabs.ArchivedTabAutoDeletePromo"> + <owner>hitarthkothari@google.com</owner> + <owner>clank-tab-dev@google.com</owner> + <description> + Recorded when the user opts in/out of auto delete through the promo. + </description> +</action> + <action name="Tabs.ArchivedTabRescued"> <owner>wylieb@google.com</owner> <owner>clank-tab-dev@google.com</owner> @@ -49909,4 +50060,12 @@ <affected-action name="TabSwitcher.ContextMenu"/> </action-suffix> +<action-suffix separator="." ordering="suffix"> + <suffix name="No" + label="Recorded when user opts out of auto delete through the promo."/> + <suffix name="Yes" + label="Recorded when user opts into auto delete through the promo."/> + <affected-action name="Tabs.ArchivedTabAutoDeletePromo"/> +</action-suffix> + </actions>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a0140a1..b894b5e 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -8700,6 +8700,7 @@ <int value="-1964725496" label="AutofillEnableCvcStorageAndFilling:disabled"/> <int value="-1964343476" label="FullscreenInsetsApiMigration:disabled"/> <int value="-1964261747" label="WebVrVsyncAlign:disabled"/> + <int value="-1964008670" label="AndroidUseCorrectDisplayWorkArea:disabled"/> <int value="-1963995131" label="DesktopPWAsKeepAlive:disabled"/> <int value="-1963838301" label="ShowSyncPausedReasonCookiesClearedOnExit:enabled"/> @@ -11585,6 +11586,8 @@ <int value="-873334439" label="PersistShareHubOnAppSwitch:disabled"/> <int value="-872764392" label="ContextualSuggestionsBottomSheet:disabled"/> <int value="-872630301" label="ProjectorGm3:enabled"/> + <int value="-871980975" + label="ContextualSuggestionsAblateOthersWhenPresent:disabled"/> <int value="-871784177" label="DeprecateMenagerieAPI:enabled"/> <int value="-871520682" label="AccessibilityInternalsPageImprovements:enabled"/> @@ -12570,6 +12573,7 @@ <int value="-503430431" label="XRSandbox:enabled"/> <int value="-502828934" label="CrOSLateBootArcSwitchToKeyMintDaemon:enabled"/> <int value="-502813092" label="SmdsSupport:enabled"/> + <int value="-502027435" label="AndroidUseCorrectDisplayWorkArea:enabled"/> <int value="-502004335" label="OobeHidDetectionRevamp:enabled"/> <int value="-501853726" label="MultiZoneRgbKeyboard:enabled"/> <int value="-500367371" label="CCTPageInsightsHubBetterScroll:enabled"/> @@ -12609,6 +12613,8 @@ <int value="-489672760" label="ImeFstDecoderParamsUpdate:disabled"/> <int value="-488779992" label="blink-settings"/> <int value="-488744544" label="PromoBrowserCommands:disabled"/> + <int value="-488228498" + label="ContextualSuggestionsAblateOthersWhenPresent:enabled"/> <int value="-487324278" label="TpcdSupportSettings:enabled"/> <int value="-487294731" label="EnablePerfettoSystemTracing:disabled"/> <int value="-486491020" label="ReadAnythingWithScreen2x:enabled"/>
diff --git a/tools/metrics/histograms/metadata/ash/enums.xml b/tools/metrics/histograms/metadata/ash/enums.xml index 5478d69..789210d 100644 --- a/tools/metrics/histograms/metadata/ash/enums.xml +++ b/tools/metrics/histograms/metadata/ash/enums.xml
@@ -1242,23 +1242,24 @@ <!-- LINT.ThenChange(//ash/system/extended_updates/extended_updates_metrics.h:ExtendedUpdatesEntryPointEvent) --> -<enum name="FloatingWorkspaceV1RestoredSessionType"> - <int value="0" label="Unknown browser session type"/> - <int value="1" label="Local browser session"/> - <int value="2" label="Remote browser session"/> +<!-- LINT.IfChange(FloatingWorkspaceStartupUiClosureReason) --> + +<enum name="FloatingWorkspaceStartupUiClosureReason"> + <int value="0" label="Closed manually"/> + <int value="1" label="Closed automatically"/> </enum> +<!-- LINT.ThenChange(//chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.h:StartupUiClosureReason) --> + +<!-- LINT.IfChange(FloatingWorkspaceV2LaunchTemplateFailureType) --> + <enum name="FloatingWorkspaceV2LaunchTemplateFailureType"> <int value="0" label="Unknown failure type"/> <int value="1" label="Storage error"/> <int value="2" label="The desk count requirement not met"/> </enum> -<enum name="FloatingWorkspaceV2LaunchTemplateTimeoutType"> - <int value="0" label="Unknown timeout type"/> - <int value="1" label="Passed wait period timeout"/> - <int value="2" label="No floating workspace template"/> -</enum> +<!-- LINT.ThenChange(//chrome/browser/ash/floating_workspace/floating_workspace_metrics_util.h:LaunchTemplateFailureType) --> <enum name="FloatingWorkspaceV2UploadTemplateStatusType"> <int value="0" label="Unknown upload status"/>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index a300d47..db1fe3c 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -3038,38 +3038,52 @@ </histogram> <histogram name="Ash.DeskTemplate.FloatingWorkspaceTabCount" units="tabs" - expires_after="2024-09-27"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> <summary> Records the number of tabs in a Floating Workspace desk when it is saved. + + Warning: this histogram was expired from 2024-09-27 to 2025-05-23; data may + be missing. </summary> </histogram> <histogram name="Ash.DeskTemplate.FloatingWorkspaceWindowAndTabCount" - units="windows and tabs" expires_after="2024-09-27"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> + units="windows and tabs" expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> <summary> Records the number of windows and tabs in a Floating Workspace desk when it is saved. + + Warning: this histogram was expired from 2024-09-27 to 2025-05-23; data may + be missing. </summary> </histogram> <histogram name="Ash.DeskTemplate.FloatingWorkspaceWindowCount" units="windows" - expires_after="2024-09-27"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> <summary> Records the number of windows in a Floating Workspace desk when it is saved. + + Warning: this histogram was expired from 2024-09-27 to 2025-05-23; data may + be missing. </summary> </histogram> <histogram name="Ash.DeskTemplate.LaunchFloatingWorkspace" enum="BooleanHit" - expires_after="2024-09-27"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> - <summary>Emitted when a Floating Workspace desk is launched.</summary> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> + <summary> + Emitted when a Floating Workspace desk is launched. + + Warning: this histogram was expired from 2024-09-27 to 2025-05-23; data may + be missing. + </summary> </histogram> <histogram name="Ash.DeskTemplate.LaunchFromTemplate" enum="BooleanHit" @@ -3649,92 +3663,90 @@ </summary> </histogram> -<histogram name="Ash.FloatingWorkspace.FloatingWorkspaceV1Initialized" - enum="BooleanHit" expires_after="2024-01-28"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> - <summary> - Recorded when floating workspace service is launched. The false bucket is - unused here. - </summary> -</histogram> - -<histogram name="Ash.FloatingWorkspace.FloatingWorkspaceV1RestoredSessionType" - enum="FloatingWorkspaceV1RestoredSessionType" expires_after="2024-01-28"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> - <summary> - Recorded the browser session type (local or remote) restored by floating - workspace service on current device. - </summary> -</histogram> - <histogram name="Ash.FloatingWorkspace.FloatingWorkspaceV2Initialized" - enum="BooleanHit" expires_after="2024-08-23"> - <owner>zhumatthew@google.com</owner> - <owner>marcuskoehler@google.com</owner> + enum="BooleanHit" expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> <summary> Recorded when floating workspace service V2 is launched. The false bucket is unused here. + + Warning: this histogram was expired from 2024-08-23 to 2025-05-23; data may + be missing. + </summary> +</histogram> + +<histogram name="Ash.FloatingWorkspace.StartupUiClosureReason" + enum="FloatingWorkspaceStartupUiClosureReason" expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> + <summary> + Record if Floating Workspace startup UI was closed manually or automatically + (once the template was restored). </summary> </histogram> <histogram name="Ash.FloatingWorkspace.TemplateLaunchFailureStatus" enum="FloatingWorkspaceV2LaunchTemplateFailureType" - expires_after="2024-02-08"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> - <summary>Recorded the reason for template launch failures.</summary> -</histogram> - -<histogram name="Ash.FloatingWorkspace.TemplateLaunchTimeOut" - enum="FloatingWorkspaceV2LaunchTemplateTimeoutType" - expires_after="2024-02-08"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> <summary> - Recorded the reason for template launch timeouts either when we pass the - threshold for waiting for a floating workspace to be downloaded or when - there's no floating workspace template to be downloaded after waiting for - the set timeout. + Recorded the reason for template launch failures. + + Warning: this histogram was expired from 2024-02-08 to 2025-05-23; data may + be missing. </summary> </histogram> <histogram name="Ash.FloatingWorkspace.TemplateLoadTime" units="seconds" - expires_after="2024-02-08"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> <summary> - Indicate the time to download a floating workspace template. If after set - timeout is reached and there is no floating workspace template downloaded, a - record of the timeout will be recorded in - "Ash.FloatingWorkspace.TemplateLaunchTimeOut". + Indicate the time to download and launch a floating workspace template. + + Warning: this histogram was expired from 2024-02-08 to 2025-05-23; data may + be missing. </summary> </histogram> <histogram name="Ash.FloatingWorkspace.TemplateNotFound" enum="BooleanHit" - expires_after="2024-08-23"> - <owner>zhumatthew@google.com</owner> - <owner>marcuskoehler@google.com</owner> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> <summary> Recorded when floating workspace service V2 is initialized, but no floating workspace template was found. The false bucket is unused here. + + Warning: this histogram was expired from 2024-08-23 to 2025-05-23; data may + be missing. </summary> </histogram> <histogram name="Ash.FloatingWorkspace.TemplateSize" units="B" - expires_after="2024-02-08"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> - <summary>Record the size of an uploaded floating workspace template.</summary> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> + <summary> + Record the size of an uploaded floating workspace template. + + Warning: this histogram was expired from 2024-02-08 to 2025-05-23; data may + be missing. + </summary> </histogram> <histogram name="Ash.FloatingWorkspace.TemplateUploadStatus" enum="FloatingWorkspaceV2UploadTemplateStatusType" - expires_after="2024-02-08"> - <owner>ligeng@google.com</owner> - <owner>marcuskoehler@google.com</owner> - <summary>Record the floating workspace template upload status.</summary> + expires_after="2026-05-23"> + <owner>andreydav@google.com</owner> + <owner>slutskii@google.com</owner> + <summary> + Record the floating workspace template upload status. + + Warning: this histogram was expired from 2024-02-08 to 2025-05-23; data may + be missing. + </summary> </histogram> <histogram name="Ash.FocusMode.Api.{Method}.Latency" units="ms"
diff --git a/tools/metrics/histograms/metadata/chromeos/enums.xml b/tools/metrics/histograms/metadata/chromeos/enums.xml index a1ac4da6bc..cef0143 100644 --- a/tools/metrics/histograms/metadata/chromeos/enums.xml +++ b/tools/metrics/histograms/metadata/chromeos/enums.xml
@@ -454,6 +454,7 @@ <int value="3" label="Region in VPD is too short for country code"/> <int value="4" label="Region in VPD is too long for country code"/> <int value="5" label="Valid country code parsed from VPD"/> + <int value="6" label="Removed subkey from country information"/> </enum> <!-- LINT.ThenChange(//chrome/browser/regional_capabilities/regional_capabilities_service_client.h:ChromeOSFallbackCountry) -->
diff --git a/tools/metrics/histograms/metadata/custom_tabs/enums.xml b/tools/metrics/histograms/metadata/custom_tabs/enums.xml index f2168d4..ae95a71 100644 --- a/tools/metrics/histograms/metadata/custom_tabs/enums.xml +++ b/tools/metrics/histograms/metadata/custom_tabs/enums.xml
@@ -53,6 +53,8 @@ <int value="3" label="Connected to service with KeepAlive connection"/> </enum> +<!--LINT.IfChange(CustomTabsFeatureUsed) --> + <enum name="CustomTabsFeatureUsed"> <int value="0" label="Sessions - counter for all sessions"/> <int value="1" label="Action button EXTRA_ACTION_BUTTON_BUNDLE"/> @@ -136,8 +138,12 @@ <int value="63" label="Open in Browser button in the toolbar state EXTRA_OPEN_IN_BROWSER_STATE"/> + <int value="64" label="Launch Handler API usage EXTRA_LAUNCH_HANDLER"/> + <int value="65" label="File Handlers API usage EXTRA_FILE_HANDLERS"/> </enum> +<!--LINT.ThenChange(//chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java:CustomTabsFeature) --> + <enum name="CustomTabsMinimizedEvents"> <int value="0" label="Minimized into PiP"/> <int value="1" label="Maximized from PiP"/>
diff --git a/tools/metrics/histograms/metadata/media/enums.xml b/tools/metrics/histograms/metadata/media/enums.xml index af0766b8..538d419 100644 --- a/tools/metrics/histograms/metadata/media/enums.xml +++ b/tools/metrics/histograms/metadata/media/enums.xml
@@ -340,6 +340,8 @@ <int value="8" label="MediaFoundationGetCdmFactoryFailed"/> <int value="9" label="CreateDummyMediaFoundationCdmFailed"/> <int value="10" label="UnexpectedEmptyCapability"/> + <int value="11" label="NoMediaDrmSupport"/> + <int value="12" label="MediaFoundationGetExtendedDRMTypeSupportFailed"/> </enum> <enum name="CdmHostVerificationStatus">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index a8e1e6c9..b4f18511 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -11569,13 +11569,14 @@ </metric> </event> -<event name="HistoryApi"> +<event name="HistoryApi.AdvanceMethod"> <owner>yaoxia@chromium.org</owner> <owner>shivanisha@chromium.org</owner> <summary> - Records usage of the window.history API, capturing details about the - operation type, user activation, and ad-related information. Recorded when - window.history API is used. + Records usage of `window.history` methods that advance the history position + (`pushState()`, `forward()`, and `go()` with positive values), capturing + details about user activation and ad-related information. Recorded when + these specific methods are invoked. </summary> <metric name="FromAd" enum="Boolean"> <summary> @@ -11591,12 +11592,6 @@ (https://mustaqahmed.github.io/user-activation-v2) </summary> </metric> - <metric name="IsHistoryModifyingOperation" enum="Boolean"> - <summary> - Whether the operation modifies the history state (i.e., back(), forward(), - go(), pushState(), replaceState()). - </summary> - </metric> </event> <event name="HistoryClusters" singular="True">
diff --git a/tools/perf/cbb_ref_info/OWNERS b/tools/perf/cbb_ref_info/OWNERS new file mode 100644 index 0000000..6f143fe2 --- /dev/null +++ b/tools/perf/cbb_ref_info/OWNERS
@@ -0,0 +1,5 @@ +johnchen@chromium.org +jeffyoon@google.com +faridzad@google.com +cbruni@chromium.org +
diff --git a/tools/perf/cbb_ref_info/README.md b/tools/perf/cbb_ref_info/README.md new file mode 100644 index 0000000..2bbc1a5 --- /dev/null +++ b/tools/perf/cbb_ref_info/README.md
@@ -0,0 +1,12 @@ +<!-- Copyright 2025 The Chromium Authors + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +# CBB: Information on Browsers Being Tested + +JSON files in this directory contain browser information, such as their +versions. This data is utilized by CBB to generate metadata for performance +test results, which are then uploaded to Cloud Storage. These JSON files are +automatically generated by the CBB autoroller tool. **Please do not update them +manually.**
diff --git a/tools/perf/cbb_ref_info/chrome_android_dev.json b/tools/perf/cbb_ref_info/chrome_android_dev.json new file mode 100644 index 0000000..56e97b8 --- /dev/null +++ b/tools/perf/cbb_ref_info/chrome_android_dev.json
@@ -0,0 +1,9 @@ +{ + "browser": "Chrome", + "channel": "Dev", + "platform": "Android", + "version": "138.0.7178.0", + "chromium_main_branch_position": 1463168, + "skia_hash": "db50a61378fddb9a29efa40e0058cec56de88c1b", + "v8_hash": "770751e8c5989e59409a67716cceb8085f3d23ed" +}
diff --git a/tools/perf/cbb_ref_info/chrome_android_stabe.json b/tools/perf/cbb_ref_info/chrome_android_stabe.json new file mode 100644 index 0000000..3a9d39d --- /dev/null +++ b/tools/perf/cbb_ref_info/chrome_android_stabe.json
@@ -0,0 +1,9 @@ +{ + "browser": "Chrome", + "channel": "Stable", + "platform": "Android", + "version": "136.0.7103.126", + "chromium_main_branch_position": 1453031, + "skia_hash": "5b8860c391f7c3d5b09b62e0d58c45cb6fa814f0", + "v8_hash": "003b9d837532294cb2c7e297619584843155024d" +}
diff --git a/tools/perf/cbb_ref_info/chrome_mac_dev.json b/tools/perf/cbb_ref_info/chrome_mac_dev.json new file mode 100644 index 0000000..d471614 --- /dev/null +++ b/tools/perf/cbb_ref_info/chrome_mac_dev.json
@@ -0,0 +1,9 @@ +{ + "browser": "Chrome", + "channel": "Dev", + "platform": "Mac", + "version": "138.0.7191.0", + "chromium_main_branch_position": 1462727, + "skia_hash": "3ead037d837c32c819d77607e01f208e91caca07", + "v8_hash": "746106c4a66d561ed6443d7298be8f2e59dc2273" +}
diff --git a/tools/perf/cbb_ref_info/chrome_mac_stable.json b/tools/perf/cbb_ref_info/chrome_mac_stable.json new file mode 100644 index 0000000..0757b50 --- /dev/null +++ b/tools/perf/cbb_ref_info/chrome_mac_stable.json
@@ -0,0 +1,9 @@ +{ + "browser": "Chrome", + "channel": "Stable", + "platform": "Mac", + "version": "137.0.7151.41", + "chromium_main_branch_position": 1453031, + "skia_hash": "5b8860c391f7c3d5b09b62e0d58c45cb6fa814f0", + "v8_hash": "003b9d837532294cb2c7e297619584843155024d" +}
diff --git a/tools/perf/cbb_ref_info/chrome_win_dev.json b/tools/perf/cbb_ref_info/chrome_win_dev.json new file mode 100644 index 0000000..e1bb573 --- /dev/null +++ b/tools/perf/cbb_ref_info/chrome_win_dev.json
@@ -0,0 +1,9 @@ +{ + "browser": "Chrome", + "channel": "Dev", + "platform": "Windows", + "version": "138.0.7191.0", + "chromium_main_branch_position": 1462727, + "skia_hash": "3ead037d837c32c819d77607e01f208e91caca07", + "v8_hash": "746106c4a66d561ed6443d7298be8f2e59dc2273" +}
diff --git a/tools/perf/cbb_ref_info/chrome_win_stable.json b/tools/perf/cbb_ref_info/chrome_win_stable.json new file mode 100644 index 0000000..b01e9f5 --- /dev/null +++ b/tools/perf/cbb_ref_info/chrome_win_stable.json
@@ -0,0 +1,9 @@ +{ + "browser": "Chrome", + "channel": "Stable", + "platform": "Windows", + "version": "137.0.7151.41", + "chromium_main_branch_position": 1453031, + "skia_hash": "5b8860c391f7c3d5b09b62e0d58c45cb6fa814f0", + "v8_hash": "003b9d837532294cb2c7e297619584843155024d" +}
diff --git a/tools/perf/cbb_ref_info/edge_dev.json b/tools/perf/cbb_ref_info/edge_dev.json new file mode 100644 index 0000000..8bd0d5b --- /dev/null +++ b/tools/perf/cbb_ref_info/edge_dev.json
@@ -0,0 +1,6 @@ +{ + "browser": "Edge", + "channel": "Dev", + "platform": "Windows", + "version": "138.0.3324.1" +}
diff --git a/tools/perf/cbb_ref_info/edge_stable.json b/tools/perf/cbb_ref_info/edge_stable.json new file mode 100644 index 0000000..66a6fef --- /dev/null +++ b/tools/perf/cbb_ref_info/edge_stable.json
@@ -0,0 +1,6 @@ +{ + "browser": "Edge", + "channel": "Stable", + "platform": "Windows", + "version": "136.0.3240.76" +}
diff --git a/tools/perf/cbb_ref_info/safari_stable.json b/tools/perf/cbb_ref_info/safari_stable.json new file mode 100644 index 0000000..cbd4fef --- /dev/null +++ b/tools/perf/cbb_ref_info/safari_stable.json
@@ -0,0 +1,6 @@ +{ + "browser": "Safari", + "channel": "Stable", + "platform": "Mac", + "version": "18.4 (20621.1.15.11.10)" +}
diff --git a/tools/perf/cbb_ref_info/safari_tech.json b/tools/perf/cbb_ref_info/safari_tech.json new file mode 100644 index 0000000..270831b --- /dev/null +++ b/tools/perf/cbb_ref_info/safari_tech.json
@@ -0,0 +1,6 @@ +{ + "browser": "Safari", + "channel": "Preview", + "platform": "Mac", + "version": "18.4 (Release 219, 20622.1.12)" +}
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 60985fb1..aa45f671 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/v50.1/linux-arm64/trace_processor_shell" }, "win": { - "hash": "51a7438fd3099888e9543e8b1360318c556c3573", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/7e5757999c0e9f06b12c33bf4d861cc0ff10ed8c/trace_processor_shell.exe" + "hash": "17e710ea7ce4088032ab247282b5883ef763bec5", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/dd35b295cd359ba094404218414955f961a0d6ae/trace_processor_shell.exe" }, "linux_arm": { "hash": "99f971ca131f6d11c73f4b918099d434bdd8093c", @@ -22,7 +22,7 @@ }, "linux": { "hash": "48b1a4909b4df12760653f09a084984e1a97c166", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6281f236ce89284e6c468dfd78d0eb0c595531fe/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/dd35b295cd359ba094404218414955f961a0d6ae/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/accessibility/ax_bitset.h b/ui/accessibility/ax_bitset.h index f1c7f03..ca51648 100644 --- a/ui/accessibility/ax_bitset.h +++ b/ui/accessibility/ax_bitset.h
@@ -20,6 +20,9 @@ AXBitset() = default; ~AXBitset() = default; + uint64_t GetSetBits() const { return set_bits_; } + uint64_t GetValues() const { return values_; } + // Returns whether enum T at |value| is set to true, false or unset. std::optional<bool> Has(T enum_value) const { uint64_t index = static_cast<uint64_t>(enum_value);
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index abf0483..c92f3907 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc
@@ -31,6 +31,7 @@ #include "base/timer/elapsed_timer.h" #include "components/crash/core/common/crash_key.h" #include "third_party/abseil-cpp/absl/cleanup/cleanup.h" +#include "ui/accessibility/ax_bitset.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_event.h" #include "ui/accessibility/ax_language_detection.h" @@ -197,6 +198,48 @@ } } +template <typename EnumType, typename CallbackType> +void CallIfAttributeValuesChanged(const ui::AXBitset<EnumType>& old_attributes, + const ui::AXBitset<EnumType>& new_attributes, + bool value_if_unset, + CallbackType callback) { + // `old_values` and `new_values` will contain: + // - The actual T/F value for explicitly set attributes. + // - '0' for attributes that were not set. + uint64_t old_values = + old_attributes.GetValues() & old_attributes.GetSetBits(); + uint64_t new_values = + new_attributes.GetValues() & new_attributes.GetSetBits(); + + // If `value_if_unset` is true, it means any attribute *not* in `set_bits_` + // should be treated as having the value 'true'. + if (value_if_unset) { + old_values |= ~old_attributes.GetSetBits(); + new_values |= ~new_attributes.GetSetBits(); + } + + // `changes` will have a '1' at each bit position where the old and new values + // differ. + uint64_t changes = old_values ^ new_values; + while (changes) { + // Get the index of the least significant '1' bit in `changes`. + // This is an attribute that has changed its effective value. + uint64_t index = std::countr_zero(changes); + uint64_t mask = 1ULL << index; + + // Extract the effective old and new value for this specific attribute. + bool effective_old_value = static_cast<bool>(old_values & mask); + bool effective_new_value = static_cast<bool>(new_values & mask); + + DCHECK_NE(effective_old_value, effective_new_value); + EnumType attr = static_cast<EnumType>(index); + callback(attr, effective_old_value, effective_new_value); + + // Clear the processed differing bit from `changes` to find the next one. + changes &= changes - 1; + } +} + bool IsCollapsed(const AXNode* node) { return node && node->HasState(ax::mojom::State::kCollapsed); }
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index 13452416..75314724 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -1429,6 +1429,85 @@ EXPECT_EQ("scrollXMax changed from 0 to 10", change_log2[10]); } +TEST(AXTreeTest, BoolAttributeChangeCallbacks) { + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(1); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kBusy, + false); + initial_state.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kModal, + true); + AXTree tree(initial_state); + + // Scenario 1: Unset -> Explicitly False (should NOT trigger callback). + TestAXTreeObserver test_observer(&tree); + AXTreeUpdate update1; + update1.nodes.resize(1); + update1.nodes[0].id = 1; + // kLiveAtomic was unset, now set to false. + update1.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, + false); + // Keep others same for now. + update1.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kBusy, false); + update1.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true); + EXPECT_TRUE(tree.Unserialize(update1)); + + // kLiveAtomic: Unset (effective F) -> Explicit F. No change in effective + // value. Expect no change log entries. + EXPECT_EQ(0U, test_observer.attribute_change_log().size()); + + // Scenario 2: Explicitly False -> Unset (should NOT trigger callback). + // Current state: kLiveAtomic=F, kBusy=F, kModal=T. + TestAXTreeObserver test_observer2(&tree); + AXTreeUpdate update2; + update2.nodes.resize(1); + update2.nodes[0].id = 1; + // kBusy was F, now remove it (becomes unset, effective F). + // kLiveAtomic remains F, kModal remains T. + update2.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, + false); + update2.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true); + EXPECT_TRUE(tree.Unserialize(update2)); + + // kBusy: Explicit F -> Unset (effective F). No change in effective value. + // Expect no change log entries. + EXPECT_EQ(0U, test_observer2.attribute_change_log().size()); + + // Scenario 3: Unset -> Explicitly True (SHOULD trigger callback). + // Current state: kLiveAtomic=F, kBusy=Unset (effective F), kModal=T. + TestAXTreeObserver test_observer3(&tree); + AXTreeUpdate update3; + update3.nodes.resize(1); + update3.nodes[0].id = 1; + // kBusy was Unset (effective F), now set to True. + update3.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, + false); + update3.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kBusy, true); + update3.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true); + EXPECT_TRUE(tree.Unserialize(update3)); + + // kBusy: Unset (effective F) -> True. Change expected. + EXPECT_EQ(1U, test_observer3.attribute_change_log().size()); + EXPECT_EQ("busy changed to true", test_observer3.attribute_change_log()[0]); + + // Scenario 4: Explicitly True -> Unset (SHOULD trigger callback). + // Current state: kLiveAtomic=F, kBusy=T, kModal=T. + TestAXTreeObserver test_observer4(&tree); + AXTreeUpdate update4; + update4.nodes.resize(1); + update4.nodes[0].id = 1; + // kModal was True, now remove it (becomes Unset, effective F). + update4.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, + false); + update4.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kBusy, true); + EXPECT_TRUE(tree.Unserialize(update4)); + + // kModal: True -> Unset (effective F). Change expected. + EXPECT_EQ(1U, test_observer4.attribute_change_log().size()); + EXPECT_EQ("modal changed to false", test_observer4.attribute_change_log()[0]); +} + TEST(AXTreeTest, IntListChangeCallbacks) { std::vector<int32_t> one; one.push_back(1);
diff --git a/ui/android/display_android_manager.cc b/ui/android/display_android_manager.cc index 0e83768..dc3654e 100644 --- a/ui/android/display_android_manager.cc +++ b/ui/android/display_android_manager.cc
@@ -106,7 +106,7 @@ float hdr_max_luminance_ratio) { display->set_label(label); display->set_bounds(bounds); - if (base::FeatureList::IsEnabled(kUsingCorrectWorkArea)) { + if (base::FeatureList::IsEnabled(kAndroidUseCorrectDisplayWorkArea)) { display->set_work_area(work_area); } else { display->set_work_area(bounds);
diff --git a/ui/android/display_android_manager_unittest.cc b/ui/android/display_android_manager_unittest.cc index 2a8c748..8cab19d 100644 --- a/ui/android/display_android_manager_unittest.cc +++ b/ui/android/display_android_manager_unittest.cc
@@ -90,7 +90,7 @@ EXPECT_EQ(display.device_scale_factor(), display_params.dip_scale); EXPECT_EQ(display.bounds(), display_params.scaled_bounds); - if (base::FeatureList::IsEnabled(kUsingCorrectWorkArea)) { + if (base::FeatureList::IsEnabled(kAndroidUseCorrectDisplayWorkArea)) { EXPECT_EQ(display.work_area(), display_params.scaled_work_area); } else { EXPECT_EQ(display.work_area(), display_params.scaled_bounds); @@ -140,7 +140,7 @@ base::test::ScopedFeatureList scoped_feature_list; if (GetParam()) { - scoped_feature_list.InitAndEnableFeature(kUsingCorrectWorkArea); + scoped_feature_list.InitAndEnableFeature(kAndroidUseCorrectDisplayWorkArea); } // Checking the initial state
diff --git a/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java b/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java index 263b2bf..9a9d253 100644 --- a/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java +++ b/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java
@@ -18,11 +18,11 @@ import android.os.Build.VERSION_CODES; import android.util.DisplayMetrics; import android.view.Display; -import android.view.WindowInsets; import android.view.WindowManager; import androidx.annotation.RequiresApi; import androidx.core.os.BuildCompat; +import androidx.core.view.WindowInsetsCompat; import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; @@ -47,6 +47,10 @@ // The behavior of observing window configuration changes using ComponentCallbacks is new in S. private static final boolean USE_CONFIGURATION = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; + // Insets that define the area where content can't be displayed. + protected static final int WINDOW_INSETS_TYPE = + WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(); + // When this object exists, a positive value means that the forced DIP scale is set and // the zero means it is not. The non existing object (i.e. null reference) means that // the existence and value of the forced DIP scale has not yet been determined. @@ -153,6 +157,7 @@ } private final @Nullable Context mWindowContext; + private final @Nullable WindowManager mWindowManager; private final @Nullable ComponentCallbacks mComponentCallbacks; private final Display mDisplay; private @Nullable Consumer<Display> mHdrSdrRatioCallback; @@ -181,10 +186,12 @@ } }; mWindowContext.registerComponentCallbacks(mComponentCallbacks); + mWindowManager = mWindowContext.getSystemService(WindowManager.class); mDisplay = mWindowContext.getDisplay(); updateFromConfiguration(); } else { mWindowContext = null; + mWindowManager = null; mComponentCallbacks = null; mDisplay = display; } @@ -209,16 +216,20 @@ } @RequiresApi(VERSION_CODES.R) + private Insets getWindowInsets() { + return assumeNonNull(mWindowManager) + .getCurrentWindowMetrics() + .getWindowInsets() + .getInsetsIgnoringVisibility(WINDOW_INSETS_TYPE); + } + + @RequiresApi(VERSION_CODES.R) private void updateFromConfiguration() { assumeNonNull(mWindowContext); - WindowManager windowManager = mWindowContext.getSystemService(WindowManager.class); - Rect bounds = windowManager.getMaximumWindowMetrics().getBounds(); - int windowInsetsType = WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout(); - Insets insets = - windowManager - .getCurrentWindowMetrics() - .getWindowInsets() - .getInsetsIgnoringVisibility(windowInsetsType); + assumeNonNull(mWindowManager); + + Rect bounds = mWindowManager.getMaximumWindowMetrics().getBounds(); + Insets insets = getWindowInsets(); DisplayMetrics displayMetrics = mWindowContext.getResources().getDisplayMetrics(); @@ -264,6 +275,7 @@ updateFromConfiguration(); return; } + Point size = new Point(); DisplayMetrics displayMetrics = new DisplayMetrics(); display.getRealSize(size); @@ -359,6 +371,7 @@ } arrInfo = new AdaptiveRefreshRateInfo(hasArrSupport, suggestedFrameRateHigh); } + super.update( display.getName(), bounds,
diff --git a/ui/android/ui_android_feature_map.cc b/ui/android/ui_android_feature_map.cc index f3e60ee..6897218 100644 --- a/ui/android/ui_android_feature_map.cc +++ b/ui/android/ui_android_feature_map.cc
@@ -17,6 +17,7 @@ // Array of features exposed through the Java UiAndroidFeatureMap API. const base::Feature* const kFeaturesExposedToJava[] = { + &ui::kAndroidUseCorrectDisplayWorkArea, &ui::kAndroidWindowManagementWebApi, &ui::kAndroidWindowOcclusion, &ui::kCheckIntentCallerPermission, @@ -25,7 +26,6 @@ &ui::kMirrorBackForwardGesturesInRTL, &ui::kRequireLeadingInTextViewWithLeading, &ui::kSelectFileOpenDocument, - &ui::kUsingCorrectWorkArea, }; // static
diff --git a/ui/android/ui_android_features.cc b/ui/android/ui_android_features.cc index 4c4ae1c..9752dbbe 100644 --- a/ui/android/ui_android_features.cc +++ b/ui/android/ui_android_features.cc
@@ -9,14 +9,30 @@ BASE_FEATURE(kAndroidHDR, "AndroidHDR", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kAndroidUseCorrectDisplayWorkArea, + "AndroidUseCorrectDisplayWorkArea", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kAndroidWindowManagementWebApi, "AndroidWindowManagementWebApi", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kAndroidWindowOcclusion, + "AndroidWindowOcclusion", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kCheckIntentCallerPermission, + "CheckIntentCallerPermission", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kDeprecatedExternalPickerFunction, "DeprecatedExternalPickerFunction", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kDisablePhotoPickerForVideoCapture, + "DisablePhotoPickerForVideoCapture", + base::FEATURE_ENABLED_BY_DEFAULT); + BASE_FEATURE(kMirrorBackForwardGesturesInRTL, "MirrorBackForwardGesturesInRTL", base::FEATURE_DISABLED_BY_DEFAULT); @@ -37,24 +53,8 @@ "SendTouchMovesToEventForwarderObservers", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kCheckIntentCallerPermission, - "CheckIntentCallerPermission", - base::FEATURE_DISABLED_BY_DEFAULT); - -BASE_FEATURE(kDisablePhotoPickerForVideoCapture, - "DisablePhotoPickerForVideoCapture", - base::FEATURE_ENABLED_BY_DEFAULT); - -BASE_FEATURE(kUsingCorrectWorkArea, - "UsingCorrectWorkArea", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kUseNewEtc1Encoder, "UseNewEtc1Encoder", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kAndroidWindowOcclusion, - "AndroidWindowOcclusion", - base::FEATURE_DISABLED_BY_DEFAULT); - } // namespace ui
diff --git a/ui/android/ui_android_features.h b/ui/android/ui_android_features.h index 0fe5e3a1..1dbe1bd0 100644 --- a/ui/android/ui_android_features.h +++ b/ui/android/ui_android_features.h
@@ -17,13 +17,29 @@ // ships. UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kAndroidHDR); +// Feature controlling how to compute work area on Android. +// TODO(crbug.com/372385871): Cleanup flag after investigating nothing is broken +// after changing the default behavior for +// availWidth/availHeight/availTop/availLeft. +UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kAndroidUseCorrectDisplayWorkArea); + // TODO(crbug.com/401215712): Clean up the flag after making sure tha the Window // Management Web API works well. UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kAndroidWindowManagementWebApi); +// Enables using occlusion information from Android to save CPU and memory. +UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kAndroidWindowOcclusion); + +// When launching an intent, check whether the caller has the permission to +// access a URI before returning the result. +UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kCheckIntentCallerPermission); + // Use the old-style opening of an External Picker when uploading files. UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kDeprecatedExternalPickerFunction); +// Whether photo picker should be disabled for video capture. +UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kDisablePhotoPickerForVideoCapture); + // Flip the back/forward direction of navigation gestures when the UI language // is an RTL language. UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kMirrorBackForwardGesturesInRTL); @@ -44,25 +60,9 @@ UI_ANDROID_EXPORT BASE_DECLARE_FEATURE( kSendTouchMovesToEventForwarderObservers); -// When launching an intent, check whether the caller has the permission to -// access a URI before returning the result. -UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kCheckIntentCallerPermission); - -// Whether photo picker should be disabled for video capture. -UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kDisablePhotoPickerForVideoCapture); - -// Feature controlling how to compute work area on Android. -// TODO(crbug.com/372385871): Cleanup flag after investigating nothing is broken -// after changing the default behavior for -// availWidth/availHeight/availTop/availLeft. -UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kUsingCorrectWorkArea); - // Enables the new ETC1 encoder (used in tab and back/forward thumbnails). UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kUseNewEtc1Encoder); -// Enables using occlusion information from Android to save CPU and memory. -UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kAndroidWindowOcclusion); - } // namespace ui #endif // UI_ANDROID_UI_ANDROID_FEATURES_H_
diff --git a/ui/ozone/platform/wayland/host/zwp_text_input_v3.cc b/ui/ozone/platform/wayland/host/zwp_text_input_v3.cc index bc9e5db..01412226 100644 --- a/ui/ozone/platform/wayland/host/zwp_text_input_v3.cc +++ b/ui/ozone/platform/wayland/host/zwp_text_input_v3.cc
@@ -136,31 +136,26 @@ // Clear last committed values. ResetCommittedImeData(); // There is no explicit reset API in v3. See [1]. - // So use disable+enable to force a reset. + // Disable+enable to force a reset has been discussed as a possible solution. + // But this is not implemented yet in compositors. In fact, it was seen in + // both mutter and kwin that it can cause the IME to enter a grab state + // unexpectedly. So at this point, leave it unimplemented. // - // TODO(crbug.com/352352898) Calling enable below as per text-input-v3 will - // reset all state including surrounding text but chromium expects reset to - // only clear preedit, see WaylandInputMethodContext::Reset(). This needs to - // be addressed on the protocol side and/or chromium side so that they match. // If no reset is implemented at all, it can lead to bad user experience, // e.g. preedit being duplicated if composition is aborted on the chromium // side by clicking in the input field. So the logic below is still needed // until a proper fix is in place. // + // Even though chromium expects only preedit to be reset, the surrounding text + // in fact could change along with reset being called if composition was + // canceled internally. So we shouldn't keep old surrounding text anyway. See + // related crbug.com/353915732 where surrounding text update is not sent after + // reset when composition is canceled. + // // [1] // https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/34 - zwp_text_input_v3_disable(obj_.get()); - Commit(); - // Pending state should be reset on enable as per the protocol. Even though - // chromium expects only preedit to be reset, the surrounding text in fact - // could change along with reset being called if composition was canceled - // internally. So we shouldn't keep old surrounding text anyway. See related - // crbug.com/353915732 where surrounding text update is not sent after reset - // when composition is canceled. ResetPendingImeData(); ResetInputEventsState(); - zwp_text_input_v3_enable(obj_.get()); - Commit(); } void ZwpTextInputV3Impl::SetClient(ZwpTextInputV3Client* context) {
diff --git a/ui/ozone/platform/wayland/host/zwp_text_input_v3_unittest.cc b/ui/ozone/platform/wayland/host/zwp_text_input_v3_unittest.cc index e656970..c3d42e5c 100644 --- a/ui/ozone/platform/wayland/host/zwp_text_input_v3_unittest.cc +++ b/ui/ozone/platform/wayland/host/zwp_text_input_v3_unittest.cc
@@ -74,13 +74,11 @@ PostToServerAndWait([](wl::TestWaylandServerThread* server) { InSequence s; EXPECT_CALL(*server->text_input_manager_v3()->text_input(), Disable()) - .Times(1); - EXPECT_CALL(*server->text_input_manager_v3()->text_input(), Commit()) - .Times(1); + .Times(0); EXPECT_CALL(*server->text_input_manager_v3()->text_input(), Enable()) - .Times(1); + .Times(0); EXPECT_CALL(*server->text_input_manager_v3()->text_input(), Commit()) - .Times(1); + .Times(0); }); text_input_v3_->Reset(); } @@ -546,10 +544,9 @@ PostToServerAndWait([](wl::TestWaylandServerThread* server) { auto* zwp_text_input = server->text_input_manager_v3()->text_input(); InSequence s; - EXPECT_CALL(*zwp_text_input, Disable()).Times(1); - EXPECT_CALL(*zwp_text_input, Commit()).Times(1); - EXPECT_CALL(*zwp_text_input, Enable()); - EXPECT_CALL(*zwp_text_input, Commit()).Times(1); + EXPECT_CALL(*zwp_text_input, Disable()).Times(0); + EXPECT_CALL(*zwp_text_input, Enable()).Times(0); + EXPECT_CALL(*zwp_text_input, Commit()).Times(0); }); text_input_v3_->Reset(); VerifyAndClearExpectations(); @@ -730,10 +727,9 @@ PostToServerAndWait([](wl::TestWaylandServerThread* server) { auto* zwp_text_input = server->text_input_manager_v3()->text_input(); InSequence s; - EXPECT_CALL(*zwp_text_input, Disable()).Times(1); - EXPECT_CALL(*zwp_text_input, Commit()).Times(1); - EXPECT_CALL(*zwp_text_input, Enable()); - EXPECT_CALL(*zwp_text_input, Commit()).Times(1); + EXPECT_CALL(*zwp_text_input, Disable()).Times(0); + EXPECT_CALL(*zwp_text_input, Enable()).Times(0); + EXPECT_CALL(*zwp_text_input, Commit()).Times(0); }); text_input_v3_->Reset(); VerifyAndClearExpectations();
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc index c3980db..2aa9cbc 100644 --- a/ui/views/accessibility/view_accessibility.cc +++ b/ui/views/accessibility/view_accessibility.cc
@@ -1538,6 +1538,34 @@ } } +void ViewAccessibility::OnWidgetUpdatedRecursive(Widget* widget, + Widget* old_widget) { + CHECK(widget); + + // If we have already marked `is_widget_closed_` as true, then there's a + // chance that the view was reparented to a non-closed widget. If so, we must + // update `is_widget_closed_` in case the new widget is not closed. + is_widget_closed_ = widget->IsClosed(); + + // Initialize the AtomicViewAXTreeManager if necessary when the view gets + // added to the widget. We must wait for the widget to become available to + // get valid data our of GetData(). + if (needs_ax_tree_manager()) { + EnsureAtomicViewAXTreeManager(); + } + + if (view_) { + internal::ScopedChildrenLock lock(view_); + for (auto& child : view_->children()) { + child->GetViewAccessibility().OnWidgetUpdatedRecursive(widget, + old_widget); + } + } + for (auto& child : virtual_children()) { + child->OnWidgetUpdatedRecursive(widget, old_widget); + } +} + void ViewAccessibility::OnWidgetClosing(Widget* widget) { // The RootView's ViewAccessibility should be the only registered // WidgetObserver. @@ -1567,10 +1595,7 @@ old_widget->RemoveObserver(this); } - // If we have already marked `is_widget_closed_` as true, then there's a - // chance that the view was reparented to a non-closed widget. If so, we must - // update `is_widget_closed_` in case the new widget is not closed. - SetWidgetClosedRecursive(widget, widget->IsClosed()); + OnWidgetUpdatedRecursive(widget, old_widget); } void ViewAccessibility::CompleteCacheInitialization() {
diff --git a/ui/views/accessibility/view_accessibility.h b/ui/views/accessibility/view_accessibility.h index 776ae77a..40d6ad4f 100644 --- a/ui/views/accessibility/view_accessibility.h +++ b/ui/views/accessibility/view_accessibility.h
@@ -734,6 +734,8 @@ // Fully initialize the cache. void CompleteCacheInitializationRecursive(); + void OnWidgetUpdatedRecursive(Widget* widget, Widget* old_widget); + // Prune/Unprune all descendant views from the accessibility tree. We prune // for two reasons: 1) The view has been explicitly marked as a leaf node, 2) // The view is focusable and lacks focusable descendants (e.g. a button with a
diff --git a/ui/views/accessibility/view_ax_platform_node_delegate.cc b/ui/views/accessibility/view_ax_platform_node_delegate.cc index 0ad4598..987a4a5 100644 --- a/ui/views/accessibility/view_ax_platform_node_delegate.cc +++ b/ui/views/accessibility/view_ax_platform_node_delegate.cc
@@ -224,18 +224,6 @@ return ax_platform_node_->GetNativeViewAccessible(); } -void ViewAXPlatformNodeDelegate::OnWidgetUpdated(Widget* widget, - Widget* old_widget) { - ViewAccessibility::OnWidgetUpdated(widget, old_widget); - - // Initialize the AtomicViewAXTreeManager if necessary when the view gets - // added to the widget. We must wait for the widget to become available to - // get valid data our of GetData(). - if (widget && needs_ax_tree_manager()) { - EnsureAtomicViewAXTreeManager(); - } -} - void ViewAXPlatformNodeDelegate::FireNativeEvent(ax::mojom::Event event_type) { DCHECK(ax_platform_node_); Widget* const widget = view()->GetWidget();
diff --git a/ui/views/accessibility/view_ax_platform_node_delegate.h b/ui/views/accessibility/view_ax_platform_node_delegate.h index 28d0c34..8c47a18 100644 --- a/ui/views/accessibility/view_ax_platform_node_delegate.h +++ b/ui/views/accessibility/view_ax_platform_node_delegate.h
@@ -60,7 +60,6 @@ void EndPopupFocusOverride() override; void FireFocusAfterMenuClose() override; gfx::NativeViewAccessible GetNativeObject() const override; - void OnWidgetUpdated(Widget* widget, Widget* old_widget) override; void FireNativeEvent(ax::mojom::Event event_type) override; #if BUILDFLAG(IS_MAC) void AnnounceTextAs(const std::u16string& text,
diff --git a/ui/views/controls/menu/menu_pre_target_handler_aura.cc b/ui/views/controls/menu/menu_pre_target_handler_aura.cc index 03e45ee..ea8ce147 100644 --- a/ui/views/controls/menu/menu_pre_target_handler_aura.cc +++ b/ui/views/controls/menu/menu_pre_target_handler_aura.cc
@@ -103,14 +103,6 @@ return true; } break; - case ui::VKEY_LEFT: - case ui::VKEY_RIGHT: - // Exit the menu when Left/Right key is pressed and Shift+Command is down - // as it is supposed to move window. - if (event.IsCommandDown() && event.IsShiftDown()) { - return true; - } - break; default: break; }
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 65154f1..dfe785f 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h
@@ -438,9 +438,10 @@ gfx::NativeView parent = gfx::NativeView(); // Specifies the initial bounds of the Widget. Default is empty, which means - // the NativeWidget may specify a default size. If the parent is specified, - // |bounds| is in the parent's coordinate system. If the parent is not - // specified, it's in screen's global coordinate system. + // the NativeWidget may specify a default size. If the parent is specified + // and the widget type is not WINDOW_TYPE_POPUP, `bounds` is in the parent's + // coordinate system. Otherwise, it's in screen coordinates. + // TODO(crbug.com/40287810): can we use screen coordinates universally? gfx::Rect bounds; #if BUILDFLAG(IS_CHROMEOS) @@ -753,7 +754,10 @@ std::string GetWorkspace() const; // Sizes and/or places the widget to the specified bounds, size or position. - // `bounds` is in screen coordinates. + // `bounds` is in screen coordinates for top-level (is_top_level() == true) + // widgets and WINDOW_TYPE_POPUP widgets. Other widgets use its parent + // widget's client area coordinates. + // TODO(crbug.com/40287810): can we use screen coordinates universally? void SetBounds(const gfx::Rect& bounds); void SetSize(const gfx::Size& size);
diff --git a/ui/webui/OWNERS b/ui/webui/OWNERS index a42ad1e..85225da 100644 --- a/ui/webui/OWNERS +++ b/ui/webui/OWNERS
@@ -1 +1,8 @@ +# Note: Unless you want a specific reviewer's expertise, please send CLs to +# chromium-ui-webui-reviews@google.com rather than to specific individuals. +# These CLs will be automatically reassigned to a reviewer within about +# 5 minutes. This approach helps our team to load-balance incoming reviews. +# Googlers can read more about this at go/gwsq-gerrit. +chromium-ui-webui-reviews@google.com + file://ui/webui/PLATFORM_OWNERS
diff --git a/ui/webui/PLATFORM_OWNERS b/ui/webui/PLATFORM_OWNERS index 7d0b81e..50abe0bd 100644 --- a/ui/webui/PLATFORM_OWNERS +++ b/ui/webui/PLATFORM_OWNERS
@@ -1,6 +1,10 @@ -# Please use more specific OWNERS when possible. -dpapad@chromium.org -johntlee@chromium.org -khorimoto@chromium.org # For Chrome OS changes. -rbpotter@chromium.org -temao@chromium.org +# The find-owners plugin does not support groups, so the actual WebUI reviewers +# are listed below but tagged with {LAST_RESORT_SUGGESTION} so that Gerrit will +# preferentially suggest the review alias in //ui/webui/OWNERS. +dpapad@chromium.org #{LAST_RESORT_SUGGESTION} +johntlee@chromium.org #{LAST_RESORT_SUGGESTION} +rbpotter@chromium.org #{LAST_RESORT_SUGGESTION} +temao@chromium.org #{LAST_RESORT_SUGGESTION} + +# For ChromeOS Changes +khorimoto@chromium.org #{LAST_RESORT_SUGGESTION}
diff --git a/v8 b/v8 index 6cd9d55..594d6e12 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 6cd9d55b3be68f3ba3ad48c83f878a156bc0430a +Subproject commit 594d6e12d62cabde031c20471a654b927b46d952