diff --git a/DEPS b/DEPS index 09df101..c3ba0b6 100644 --- a/DEPS +++ b/DEPS
@@ -299,15 +299,15 @@ # 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': '8943ec85c41cc1dd976785f2d29f712952fc2e92', + 'skia_revision': 'b368746d696a72bff291dddf7ab1492f5d72267f', # 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': '2227d8bbb76f71e31edca694815522149547c305', + 'v8_revision': '6eadb14bb7a7908c7c0b86a0381260430b6c81fc', # 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': '2072aea9998c4170bff1811a5013605b99c66547', + 'angle_revision': '0f3aaebf742f0ac16360a1191d75f99843d1b255', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -434,11 +434,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavif # and whatever else without interference from each other. - 'libavif_revision': 'bfb84ad6f9791be5b1d2d68e43bf1c79fc17b06c', + 'libavif_revision': '96b8450ca5e5acf173645aafc5c5e91959dfe0c1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '73c1fba668a86dd003fa2ac6af86ab7d89c09908', + 'nearby_revision': 'b3f85342261db10bbeb2e5a07c7e54b616309b9e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -478,7 +478,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '19ffb9c00636bcabb6c6ce76ccaa4370583d3649', + 'libcxx_revision': '2fc3d704672fbd3e85fad8492d39e02d49412891', # GN CIPD package version. 'gn_version': 'git_revision:5e19d2fb166fbd4f6f32147fbb2f497091a54ad8', @@ -1205,7 +1205,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e1c8efebe0a3cce42ca46d6057b6d4bd909ad203', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '18359bb9a19ee9b31a33fae83aa49ced770a9b81', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1640,7 +1640,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '165c172f3a6e30aa98495eaef67d5042cb4133a8', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'aa7e493dcf9bf77707735b98723b916e08561bbe', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1822,10 +1822,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'b99b81d6c5f615447fbdb469fa720808faf998b1', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '216c8e78167b6643afb2dbb170f1501471971112', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '597a2ba41aaa0b7ce09c8e0db94060cd6af7a52d', + Var('webrtc_git') + '/src.git' + '@' + '919b79b7efc34a059cafef7e0901c467b230d69a', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1895,7 +1895,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5232f9de253ba0a63dfdd8c7965d59fb4cb2b315', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@94562e58e6e22f0f8b5c1dd89ab590f94494bf85', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index 24dee108..fbc78d2cc 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -189,6 +189,9 @@ Flag.baseFeature(AutofillFeatures.AUTOFILL_SERVER_BEHAVIORS, "When enabled, Autofill will request experimental " + "predictions from the Autofill API."), + Flag.baseFeature(AutofillFeatures.AUTOFILL_SUPPORT_POOR_MANS_PLACEHOLDER, + "When enabled, Autofill will infer labels from artificial placeholders, " + + "placed on top of input fields using CSS."), Flag.baseFeature(FeatureConstants.KEYBOARD_ACCESSORY_PAYMENT_VIRTUAL_CARD_FEATURE, "When enabled, merchant bound virtual cards will be offered in the keyboard " + "accessory."),
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java index def3b07..0ad75e76 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java
@@ -4,11 +4,9 @@ package org.chromium.android_webview.test; -import android.os.Build; import android.os.LocaleList; import android.support.test.InstrumentationRegistry; -import androidx.annotation.RequiresApi; import androidx.test.filters.SmallTest; import org.junit.After; @@ -21,7 +19,6 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.util.JSUtils; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.net.test.EmbeddedTestServer; import java.util.Locale; @@ -80,20 +77,12 @@ private boolean isSingleLocale(String lang, String country) { String languageTag = String.format("%s-%s", lang, country); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - // In N+, multiple locales can be set. - return languageTag.equals(LocaleList.getDefault().toLanguageTags()); - } else { - return languageTag.equals(Locale.getDefault().toLanguageTag()); - } + // In N+, multiple locales can be set. + return languageTag.equals(LocaleList.getDefault().toLanguageTags()); } private void setSingleLocale(String lang, String country) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - LocaleList.setDefault(new LocaleList(new Locale(lang, country))); - } else { - Locale.setDefault(new Locale(lang, country)); - } + LocaleList.setDefault(new LocaleList(new Locale(lang, country))); } private void setLocaleForTesting(String lang, String country) { @@ -154,8 +143,6 @@ */ @Test @SmallTest - @MinAndroidSdkLevel(Build.VERSION_CODES.N) - @RequiresApi(Build.VERSION_CODES.N) @Feature({"AndroidWebView"}) public void testAcceptLanguagesWithenUS() throws Throwable { LocaleList.setDefault(new LocaleList(new Locale("ko", "KR")));
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java index 24d7953..0abc802 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java
@@ -34,7 +34,6 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.os.Build; import android.provider.Settings; import android.support.test.InstrumentationRegistry; import android.view.View; @@ -46,7 +45,6 @@ import org.hamcrest.Matcher; import org.junit.After; -import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -178,9 +176,6 @@ @MediumTest @Feature({"AndroidWebView"}) public void testMenuOptions_switchProvider_shownOnNougat() throws Throwable { - Assume.assumeTrue("This test verifies behavior introduced in Nougat and above", - Build.VERSION.SDK_INT >= Build.VERSION_CODES.N); - launchHomeFragment(); openOptionsMenu(); @@ -192,19 +187,6 @@ @Test @MediumTest @Feature({"AndroidWebView"}) - public void testMenuOptions_switchProvider_notShown() throws Throwable { - Assume.assumeTrue("This test verifies pre-Nougat behavior", - Build.VERSION.SDK_INT < Build.VERSION_CODES.N); - - launchHomeFragment(); - - openOptionsMenu(); - onView(withId(R.id.options_menu_switch_provider)).check(doesNotExist()); - } - - @Test - @MediumTest - @Feature({"AndroidWebView"}) public void testMenuOptions_reportBug() throws Throwable { launchHomeFragment();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java index 52c7602..20f740c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java
@@ -40,7 +40,6 @@ import org.junit.After; import org.junit.Assert; -import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -242,9 +241,6 @@ @MediumTest @Feature({"AndroidWebView"}) public void testDifferentWebViewPackageError_bannerMessage_postNougat() throws Throwable { - Assume.assumeTrue("This test verifies behavior introduced in Nougat and above", - Build.VERSION.SDK_INT >= Build.VERSION_CODES.N); - Context context = InstrumentationRegistry.getTargetContext(); // Inject a dummy PackageInfo as the current WebView package to make sure it will always be // different from the test's app package. @@ -271,9 +267,6 @@ @Feature({"AndroidWebView"}) // Test the dialog shown when the WebView package error message is clicked. public void testDifferentWebViewPackageError_dialog_postNougat() throws Throwable { - Assume.assumeTrue("This test verifies behavior introduced in Nougat and above", - Build.VERSION.SDK_INT >= Build.VERSION_CODES.N); - Context context = InstrumentationRegistry.getTargetContext(); // Inject a dummy PackageInfo as the current WebView package to make sure it will always be // different from the test's app package. @@ -298,65 +291,4 @@ .perform(click()); intended(IntentMatchers.hasAction(Settings.ACTION_WEBVIEW_SETTINGS)); } - - @Test - @MediumTest - @Feature({"AndroidWebView"}) - // Test that error message is shown when system's WebView provider package is different from dev - // UI's on a preNougat android versions (where WebView provider can't be changed). - public void testDifferentWebViewPackageError_bannerMessage_preNougat() throws Throwable { - Assume.assumeTrue("This test verifies pre-Nougat behavior", - Build.VERSION.SDK_INT < Build.VERSION_CODES.N); - - Context context = InstrumentationRegistry.getTargetContext(); - // Inject a dummy PackageInfo as the current WebView package to make sure it will always be - // different from the test's app package. - WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE); - launchHomeFragment(); - - String expectedErrorMessage = String.format(Locale.US, - WebViewPackageError.DIFFERENT_WEBVIEW_PROVIDER_ERROR_MESSAGE, - WebViewPackageHelper.loadLabel(context)); - ViewUtils.waitForView(withId(R.id.main_error_view)); - onView(withId(R.id.main_error_view)).check(matches(isDisplayed())); - onView(withId(R.id.error_text)).check(matches(withText(expectedErrorMessage))); - // Since the current provider is set to a fake package not an actual installed WebView - // provider, the UI shouldn't offer opening current WebView provider dev UI. It should not - // offer to change system WebView provider because this is not supported on pre-Nougat - // android versions. - onView(withId(R.id.action_button)).check(matches(not(isDisplayed()))); - } - - @Test - @MediumTest - @Feature({"AndroidWebView"}) - // Test the dialog shown when the WebView package error message is clicked (where WebView - // provider can't be changed). - public void testDifferentWebViewPackageError_dialog_preNougat() throws Throwable { - Assume.assumeTrue("This test verifies pre-Nougat behavior", - Build.VERSION.SDK_INT < Build.VERSION_CODES.N); - - Context context = InstrumentationRegistry.getTargetContext(); - // Inject a dummy PackageInfo as the current WebView package to make sure it will always be - // different from the test's app package. - WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE); - launchHomeFragment(); - - String dialogExpectedMessage = String.format(Locale.US, - WebViewPackageError.DIFFERENT_WEBVIEW_PROVIDER_DIALOG_MESSAGE, - WebViewPackageHelper.loadLabel(context)); - ViewUtils.waitForView(withId(R.id.main_error_view)); - onView(withId(R.id.main_error_view)).perform(click()); - ViewUtils.waitForView(withText(dialogExpectedMessage)); - onView(withText(dialogExpectedMessage)).check(matches(isDisplayed())); - // Since the current provider is set to a fake package not an actual installed WebView - // provider, the UI shouldn't offer opening current WebView provider dev UI. It should not - // offer to change system WebView provider because this is not supported on pre-Nougat - // android versions. - // - // There should be no buttons in the Dialog. - onView(withId(android.R.id.button1)).check(matches(not(isDisplayed()))); - onView(withId(android.R.id.button2)).check(matches(not(isDisplayed()))); - onView(withId(android.R.id.button3)).check(matches(not(isDisplayed()))); - } }
diff --git a/ash/ambient/util/ambient_util.h b/ash/ambient/util/ambient_util.h index 054a171a..9292674 100644 --- a/ash/ambient/util/ambient_util.h +++ b/ash/ambient/util/ambient_util.h
@@ -33,10 +33,12 @@ // Ambient mode uses non-standard colors for some text and the media icon, so // provides a wrapper for |AshColorProvider::GetContentLayerColor|. This is // currently only supported for primary and secondary text and icons. +// TODO(b/262012604) rework to use ui::ColorProvider. ASH_EXPORT SkColor GetContentLayerColor(AshColorProvider::ContentLayerType content_layer_type, bool dark_mode_enable); // Version of the above that uses AshColorProvider::IsDarkModeEnabled(). +// TODO(b/262012604) rework to use ui::ColorProvider. ASH_EXPORT SkColor GetContentLayerColor(AshColorProvider::ContentLayerType content_layer_type);
diff --git a/ash/app_list/views/app_list_view_pixeltest.cc b/ash/app_list/views/app_list_view_pixeltest.cc index 2dec915..103efa2 100644 --- a/ash/app_list/views/app_list_view_pixeltest.cc +++ b/ash/app_list/views/app_list_view_pixeltest.cc
@@ -83,6 +83,8 @@ SetUpAnswerCardResult(results, 1, 1); test_helper->GetProductivityLauncherSearchView() ->OnSearchResultContainerResultsChanged(); + // OnSearchResultContainerResultsChanged will schedule show animations(). + base::RunLoop().RunUntilIdle(); HideCursor(); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
diff --git a/ash/metrics/login_unlock_throughput_recorder.cc b/ash/metrics/login_unlock_throughput_recorder.cc index 9bc43c8..1fa227ace 100644 --- a/ash/metrics/login_unlock_throughput_recorder.cc +++ b/ash/metrics/login_unlock_throughput_recorder.cc
@@ -28,6 +28,7 @@ #include "ui/compositor/layer.h" #include "ui/compositor/total_animation_throughput_reporter.h" #include "ui/views/animation/bounds_animator.h" +#include "ui/views/animation/bounds_animator_observer.h" namespace ash { namespace { @@ -351,6 +352,32 @@ ReportLogin(start, data); } +void LoginUnlockThroughputRecorder::OnArcOptedIn() { + arc_opt_in_time_ = base::TimeTicks::Now(); +} + +void LoginUnlockThroughputRecorder::OnArcAppListReady() { + if (arc_app_list_ready_reported_) + return; + + // |Ash.ArcAppInitialAppsInstallDuration| histogram is only reported for + // the first user session after they opted into the ARC++. + // |arc_opt_in_time_| will only have value if user opted in into the ARC++ + // in this session (in this browser instance). + if (arc_opt_in_time_.has_value()) { + const auto duration = base::TimeTicks::Now() - arc_opt_in_time_.value(); + UmaHistogramCustomTimes("Ash.ArcAppInitialAppsInstallDuration", duration, + base::Seconds(1) /* min */, + base::Hours(1) /* max */, 100 /* buckets */); + } + + arc_app_list_ready_reported_ = true; +} + +bool LoginUnlockThroughputRecorder::NeedReportArcAppListReady() const { + return arc_opt_in_time_.has_value() && !arc_app_list_ready_reported_; +} + void LoginUnlockThroughputRecorder::ScheduleWaitForShelfAnimationEnd() { ShelfView* shelf_view = RootWindowController::ForWindow(
diff --git a/ash/metrics/login_unlock_throughput_recorder.h b/ash/metrics/login_unlock_throughput_recorder.h index 7925dba..46d3fe5 100644 --- a/ash/metrics/login_unlock_throughput_recorder.h +++ b/ash/metrics/login_unlock_throughput_recorder.h
@@ -17,6 +17,7 @@ #include "base/time/time.h" #include "cc/metrics/frame_sequence_metrics.h" #include "chromeos/ash/components/login/login_state/login_state.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/compositor/total_animation_throughput_reporter.h" namespace ui { @@ -70,6 +71,16 @@ // This is called when the list of shelf icons is updated. void UpdateShelfIconList(const ShelfModel* model); + // This is called when ARC++ becomes enabled. + void OnArcOptedIn(); + + // This is called when list of ARC++ apps is updated. + void OnArcAppListReady(); + + // This is true if we need to report Ash.ArcAppInitialAppsInstallDuration + // histogram in this session but it has not been reported yet. + bool NeedReportArcAppListReady() const; + void ResetScopedThroughputReporterBlockerForTesting(); const ui::TotalAnimationThroughputReporter* @@ -137,6 +148,10 @@ bool user_logged_in_ = false; + bool arc_app_list_ready_reported_ = false; + + absl::optional<base::TimeTicks> arc_opt_in_time_; + base::WeakPtr<ui::TotalAnimationThroughputReporter> login_animation_throughput_reporter_;
diff --git a/ash/projector/projector_controller_impl.cc b/ash/projector/projector_controller_impl.cc index 51ef9c4..f670cc7c 100644 --- a/ash/projector/projector_controller_impl.cc +++ b/ash/projector/projector_controller_impl.cc
@@ -507,7 +507,6 @@ DCHECK(client_->GetSpeechRecognitionAvailability().IsAvailable()); client_->StopSpeechRecognition(); - is_speech_recognition_on_ = false; } void ProjectorControllerImpl::OnContainerFolderCreated(
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index e112fbd..8ca459cc 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -342,8 +342,8 @@ "update_types.h", "view_shadow.cc", "view_shadow.h", - "views_text_services_context_menu_impl.cc", - "views_text_services_context_menu_impl.h", + "views_text_services_context_menu_ash.cc", + "views_text_services_context_menu_ash.h", "vm_camera_mic_constants.cc", "vm_camera_mic_constants.h", "wallpaper/google_photos_wallpaper_params.cc",
diff --git a/ash/public/cpp/views_text_services_context_menu_impl.cc b/ash/public/cpp/views_text_services_context_menu_ash.cc similarity index 66% rename from ash/public/cpp/views_text_services_context_menu_impl.cc rename to ash/public/cpp/views_text_services_context_menu_ash.cc index 74e87ca..fb262a8 100644 --- a/ash/public/cpp/views_text_services_context_menu_impl.cc +++ b/ash/public/cpp/views_text_services_context_menu_ash.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/public/cpp/views_text_services_context_menu_impl.h" +#include "ash/public/cpp/views_text_services_context_menu_ash.h" #include "ash/public/cpp/clipboard_history_controller.h" #include "chromeos/crosapi/mojom/clipboard_history.mojom.h" @@ -13,16 +13,25 @@ namespace ash { -ViewsTextServicesContextMenuImpl::ViewsTextServicesContextMenuImpl( +ViewsTextServicesContextMenuAsh::ViewsTextServicesContextMenuAsh( ui::SimpleMenuModel* menu, views::Textfield* client) : views::ViewsTextServicesContextMenuBase(menu, client) { - AddClipboardHistoryMenuOption(menu); + // If the menu has a paste option, add a clipboard history option as well. + const absl::optional<size_t> paste_index = + menu->GetIndexOfCommandId(ui::TouchEditable::kPaste); + + if (!paste_index.has_value()) + return; + + const size_t target_index = paste_index.value() + 1; + menu->InsertItemAt(target_index, IDS_APP_SHOW_CLIPBOARD_HISTORY, + l10n_util::GetStringUTF16(IDS_APP_SHOW_CLIPBOARD_HISTORY)); } -ViewsTextServicesContextMenuImpl::~ViewsTextServicesContextMenuImpl() = default; +ViewsTextServicesContextMenuAsh::~ViewsTextServicesContextMenuAsh() = default; -bool ViewsTextServicesContextMenuImpl::GetAcceleratorForCommandId( +bool ViewsTextServicesContextMenuAsh::GetAcceleratorForCommandId( int command_id, ui::Accelerator* accelerator) const { if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) { @@ -34,35 +43,34 @@ command_id, accelerator); } -bool ViewsTextServicesContextMenuImpl::IsCommandIdChecked( - int command_id) const { +bool ViewsTextServicesContextMenuAsh::IsCommandIdChecked(int command_id) const { if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) return true; return ViewsTextServicesContextMenuBase::IsCommandIdChecked(command_id); } -bool ViewsTextServicesContextMenuImpl::IsCommandIdEnabled( - int command_id) const { +bool ViewsTextServicesContextMenuAsh::IsCommandIdEnabled(int command_id) const { if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) return ClipboardHistoryController::Get()->CanShowMenu(); return ViewsTextServicesContextMenuBase::IsCommandIdEnabled(command_id); } -void ViewsTextServicesContextMenuImpl::ExecuteCommand(int command_id, - int event_flags) { +void ViewsTextServicesContextMenuAsh::ExecuteCommand(int command_id, + int event_flags) { if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) { auto* clipboard_history_controller = ClipboardHistoryController::Get(); // Calculate the menu source type from `event_flags`. ui::MenuSourceType source_type; - if (event_flags & ui::EF_LEFT_MOUSE_BUTTON) + if (event_flags & ui::EF_LEFT_MOUSE_BUTTON) { source_type = ui::MENU_SOURCE_MOUSE; - else if (event_flags & ui::EF_FROM_TOUCH) + } else if (event_flags & ui::EF_FROM_TOUCH) { source_type = ui::MENU_SOURCE_TOUCH; - else + } else { source_type = ui::MENU_SOURCE_KEYBOARD; + } clipboard_history_controller->ShowMenu( client()->GetCaretBounds(), source_type, @@ -74,26 +82,11 @@ ViewsTextServicesContextMenuBase::ExecuteCommand(command_id, event_flags); } -bool ViewsTextServicesContextMenuImpl::SupportsCommand(int command_id) const { +bool ViewsTextServicesContextMenuAsh::SupportsCommand(int command_id) const { if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) return true; return ViewsTextServicesContextMenuBase::SupportsCommand(command_id); } -void ViewsTextServicesContextMenuImpl::AddClipboardHistoryMenuOption( - ui::SimpleMenuModel* menu) { - const absl::optional<size_t> index_of_paste = - menu->GetIndexOfCommandId(ui::TouchEditable::kPaste); - - // Only add the clipboard history menu option when having the menu option - // for paste. - if (!index_of_paste.has_value()) - return; - - const size_t target_index = index_of_paste.value() + 1; - menu->InsertItemAt(target_index, IDS_APP_SHOW_CLIPBOARD_HISTORY, - l10n_util::GetStringUTF16(IDS_APP_SHOW_CLIPBOARD_HISTORY)); -} - } // namespace ash
diff --git a/ash/public/cpp/views_text_services_context_menu_ash.h b/ash/public/cpp/views_text_services_context_menu_ash.h new file mode 100644 index 0000000..b0b243fb --- /dev/null +++ b/ash/public/cpp/views_text_services_context_menu_ash.h
@@ -0,0 +1,42 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_ASH_H_ +#define ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_ASH_H_ + +#include "ash/public/cpp/ash_public_export.h" +#include "ui/views/controls/views_text_services_context_menu_base.h" + +namespace views { +class Textfield; +} + +namespace ash { + +// This class implements support for adding and handling text service items in +// ChromeOS system UI textfields and ash-chrome browser native textfields (i.e., +// the omnibox but not the WebUI embedded in the browser). +class ASH_PUBLIC_EXPORT ViewsTextServicesContextMenuAsh + : public views::ViewsTextServicesContextMenuBase { + public: + ViewsTextServicesContextMenuAsh(ui::SimpleMenuModel* menu, + views::Textfield* client); + ViewsTextServicesContextMenuAsh(const ViewsTextServicesContextMenuAsh&) = + delete; + ViewsTextServicesContextMenuAsh& operator=( + const ViewsTextServicesContextMenuAsh&) = delete; + ~ViewsTextServicesContextMenuAsh() override; + + // ViewsTextServicesContextMenuBase: + bool GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) const override; + bool IsCommandIdChecked(int command_id) const override; + bool IsCommandIdEnabled(int command_id) const override; + void ExecuteCommand(int command_id, int event_flags) override; + bool SupportsCommand(int command_id) const override; +}; + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_ASH_H_
diff --git a/ash/public/cpp/views_text_services_context_menu_impl.h b/ash/public/cpp/views_text_services_context_menu_impl.h deleted file mode 100644 index 8856872..0000000 --- a/ash/public/cpp/views_text_services_context_menu_impl.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_IMPL_H_ -#define ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_IMPL_H_ - -#include "ash/public/cpp/ash_public_export.h" -#include "ui/views/controls/views_text_services_context_menu_base.h" - -namespace views { -class Textfield; -} - -namespace ash { - -// This class supports the text context menu with the exclusive functions under -// the CrOS environment. -class ASH_PUBLIC_EXPORT ViewsTextServicesContextMenuImpl - : public views::ViewsTextServicesContextMenuBase { - public: - ViewsTextServicesContextMenuImpl(ui::SimpleMenuModel* menu, - views::Textfield* client); - ViewsTextServicesContextMenuImpl(const ViewsTextServicesContextMenuImpl&) = - delete; - ViewsTextServicesContextMenuImpl& operator=( - const ViewsTextServicesContextMenuImpl&) = delete; - ~ViewsTextServicesContextMenuImpl() override; - - // ViewsTextServicesContextMenuBase: - bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) const override; - bool IsCommandIdChecked(int command_id) const override; - bool IsCommandIdEnabled(int command_id) const override; - void ExecuteCommand(int command_id, int event_flags) override; - bool SupportsCommand(int command_id) const override; - - private: - // Adds the menu option which shows the clipboard history menu after - // activation. - void AddClipboardHistoryMenuOption(ui::SimpleMenuModel* menu); -}; - -} // namespace ash - -#endif // ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_IMPL_H_
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc index 8670cbcb..6cbe14a 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc
@@ -131,7 +131,9 @@ // If this is a v1 pairing, we pass off the responsibility to the Bluetooth // pairing dialog, and will listen for the // BluetoothAdapter::Observer::DevicePairedChanged event before firing the - // |paired_callback|. + // |paired_callback|. V1 devices only support the "initial pairing" protocol, + // not the "retroactive" or "subsequent" pairing protocols, so only + // "initial pairing" metrics are emitted to here. if (device_->version().value() == DeviceFastPairVersion::kV1) { RecordInitialSuccessFunnelFlow( FastPairInitialSuccessFunnelEvent::kV1DeviceDetected); @@ -479,8 +481,11 @@ // be. if (!ShouldBeEnabledForLoginStatus( Shell::Get()->session_controller()->login_status())) { - RecordInitialSuccessFunnelFlow( - FastPairInitialSuccessFunnelEvent::kGuestModeDetected); + if (device_->protocol == Protocol::kFastPairInitial) { + RecordInitialSuccessFunnelFlow( + FastPairInitialSuccessFunnelEvent::kGuestModeDetected); + } + QP_LOG(VERBOSE) << __func__ << ": No logged in user to save account key to"; std::move(pairing_procedure_complete_).Run(device_); return; @@ -538,8 +543,12 @@ QP_LOG(INFO) << __func__ << ": Device is already saved, skipping write account key. " "Pairing procedure complete."; - RecordInitialSuccessFunnelFlow( - FastPairInitialSuccessFunnelEvent::kDeviceAlreadyAssociatedToAccount); + + if (device_->protocol == Protocol::kFastPairInitial) { + RecordInitialSuccessFunnelFlow( + FastPairInitialSuccessFunnelEvent::kDeviceAlreadyAssociatedToAccount); + } + std::move(pairing_procedure_complete_).Run(device_); return; } @@ -558,8 +567,11 @@ RAND_bytes(account_key.data(), account_key.size()); account_key[0] = 0x04; - RecordInitialSuccessFunnelFlow( - FastPairInitialSuccessFunnelEvent::kPreparingToWriteAccountKey); + if (device_->protocol == Protocol::kFastPairInitial) { + RecordInitialSuccessFunnelFlow( + FastPairInitialSuccessFunnelEvent::kPreparingToWriteAccountKey); + } + fast_pair_gatt_service_client_->WriteAccountKey( account_key, fast_pair_handshake_->fast_pair_data_encryptor(), base::BindOnce(&FastPairPairerImpl::OnWriteAccountKey, @@ -600,8 +612,12 @@ QP_LOG(INFO) << __func__ << ": Account key written to device. Pairing procedure complete."; - RecordInitialSuccessFunnelFlow( - FastPairInitialSuccessFunnelEvent::kAccountKeyWritten); + + if (device_->protocol == Protocol::kFastPairInitial) { + RecordInitialSuccessFunnelFlow( + FastPairInitialSuccessFunnelEvent::kAccountKeyWritten); + } + std::move(pairing_procedure_complete_).Run(device_); }
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc index 52e76b9..1ef93c520 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc
@@ -2494,5 +2494,34 @@ EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); } +TEST_F(FastPairPairerImplTest, RetroactiveNotLoggedToInitial) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + fast_pair_repository_.SetOptInStatus( + nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kFastPairSavedDevices}, + /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairRetroactive); + // When pairing starts, if the classic address can't be resolved to + // a device then we pair via address. + SetGetDeviceNullptr(); + CreatePairer(); + fake_fast_pair_handshake_->InvokeCallback(); + EXPECT_CALL(pairing_procedure_complete_, Run); + RunWriteAccountKeyCallback(); + histogram_tester().ExpectTotalCount( + kWriteAccountKeyCharacteristicResultMetric, 1); + EXPECT_EQ(histogram_tester().GetBucketCount( + kInitialSuccessFunnelMetric, + FastPairInitialSuccessFunnelEvent::kPreparingToWriteAccountKey), + 0); + EXPECT_EQ(histogram_tester().GetBucketCount( + kInitialSuccessFunnelMetric, + FastPairInitialSuccessFunnelEvent::kAccountKeyWritten), + 0); +} + } // namespace quick_pair } // namespace ash
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc index a0813d76..5c53335 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc
@@ -127,20 +127,18 @@ void RetroactivePairingDetectorImpl::OnDevicePaired( scoped_refptr<Device> device) { - // When a device is paired to via Fast Pair, we save the device's classic - // pairing address here so when we get the the BluetoothAdapter's - // |DevicePairedChanged| fired, we can determine if it was the one we already - // have paired to. The classic address is assigned to the Device during the - // initial Fast Pair pairing protocol during the key exchange, and if it - // doesn't exist, then it wasn't properly paired during initial Fast Pair + // The classic address is assigned to the Device during the + // initial Fast Pair pairing protocol and if it doesn't exist, + // then it wasn't properly paired during initial Fast Pair // pairing. if (!device->classic_address()) return; - // Sometimes we might encounter the case where |DevicePairedChanged| fires - // before FastPair's |OnDevicePaired|, and if that is the case and a device - // has been inserted in the |potential_retroactive_addresses_|, we need - // to remove it. + // The Bluetooth Adapter system event `DevicePairedChanged` fires before + // Fast Pair's `OnDevicePaired`, and a Fast Pair pairing is expected to have + // both events. If a device is Fast Paired, it is already inserted in the + // |potential_retroactive_addresses_| in `DevicePairedChanged`; we need to + // remove it to prevent a false positive. if (base::Contains(potential_retroactive_addresses_, device->classic_address().value())) { QP_LOG(VERBOSE) @@ -151,9 +149,6 @@ RemoveDeviceInformation(device->classic_address().value()); return; } - - QP_LOG(INFO) << __func__ << ": Storing Fast Pair device address"; - fast_pair_addresses_.insert(device->classic_address().value()); } void RetroactivePairingDetectorImpl::DevicePairedChanged( @@ -166,17 +161,19 @@ // This event fires whenever a device pairing has changed with the adapter. // If the |new_paired_status| is false, it means a device was unpaired with // the adapter, so we early return since it would not be a device to - // retroactively pair to. If the device that was paired to that fires this - // event is a device we just paired to with Fast Pair, then we early return - // since it also wouldn't be one to retroactively pair to. We want to only - // continue our check here if we have a newly paired device that was paired - // with classic Bluetooth pairing. - const std::string& classic_address = device->GetAddress(); - if (!new_paired_status || - base::Contains(fast_pair_addresses_, classic_address)) { + // retroactively pair to. + if (!new_paired_status) { return; } + // Both classic paired and Fast paired devices call this function, so we + // have to add the device to |potential_retroactive_addresses_|. We expect + // devices paired via Fast Pair to always call `OnDevicePaired` after calling + // this function, which will remove the device from + // |potential_retroactive_addresses_|. + const std::string& classic_address = device->GetAddress(); + potential_retroactive_addresses_.insert(classic_address); + // In order to confirm that this device is a retroactive pairing, we need to // first check if it has already been saved to the user's account. If it has // already been saved, we don't want to prompt the user to save a device @@ -192,18 +189,12 @@ bool is_device_saved_to_account) { if (is_device_saved_to_account) { QP_LOG(INFO) << __func__ << ": device already saved to user's account"; + RemoveDeviceInformation(classic_address); return; } QP_LOG(VERBOSE) << __func__ << ": device = " << classic_address; - // The device pairing just changed, and this means that it was just - // classically paired. Because we have now verified that it not saved to the - // user's account, we can continue verifying this device for the retroactive - // pairing scenario by checking if the Message Stream contains the model id - // and ble address. - potential_retroactive_addresses_.insert(classic_address); - // Attempt to retrieve a MessageStream instance immediately, if it was // already connected. MessageStream* message_stream =
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h index 74212eb..67b038a 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h
@@ -133,10 +133,6 @@ void RemoveDeviceInformation(const std::string& device_address); - // The classic pairing addresses of Fast Pair devices that we have already - // paired to. - base::flat_set<std::string> fast_pair_addresses_; - // The classic pairing addresses of potential Retroactive Pair supported // devices that are found in the adapter. We have to store them and wait for a // MessageStream instance to be created for the device in order to fully
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc index ac04d4f1..2b2ff53 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc
@@ -240,22 +240,6 @@ std::unique_ptr<RetroactivePairingDetector> retroactive_pairing_detector_; }; -TEST_F(RetroactivePairingDetectorTest, DevicedPaired_FastPair) { - Login(user_manager::UserType::USER_TYPE_REGULAR); - fast_pair_repository_.SetOptInStatus( - nearby::fastpair::OptInStatus::STATUS_OPTED_IN); - base::RunLoop().RunUntilIdle(); - CreateRetroactivePairingDetector(); - - EXPECT_FALSE(retroactive_pair_found_); - - PairFastPairDeviceWithFastPair(kTestDeviceAddress); - PairFastPairDeviceWithClassicBluetooth( - /*new_paired_status=*/true, kTestDeviceAddress); - - EXPECT_FALSE(retroactive_pair_found_); -} - TEST_F(RetroactivePairingDetectorTest, DevicedPaired_FastPair_BluetoothEventFiresFirst) { Login(user_manager::UserType::USER_TYPE_REGULAR); @@ -273,6 +257,46 @@ EXPECT_FALSE(retroactive_pair_found_); } +// Regression test for b/261041950 +TEST_F(RetroactivePairingDetectorTest, + FastPairPairingEventCalledDuringBluetoothAdapterPairingEvent) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + fast_pair_repository_.SetOptInStatus( + nearby::fastpair::OptInStatus::STATUS_OPTED_IN); + CreateRetroactivePairingDetector(); + + EXPECT_FALSE(retroactive_pair_found_); + + SetMessageStream(kModelIdBleAddressBytes); + + // Simulate the Bluetooth Adapter event firing, with the callback to + // `IsDeviceSavedToAccount` delayed. + fast_pair_repository_.SetIsDeviceSavedToAccountCallbackDelayed( + /*is_delayed=*/true); + PairFastPairDeviceWithClassicBluetooth( + /*new_paired_status=*/true, kTestDeviceAddress); + + // Simulate the Fast Pair pairing event firing during the Bluetooth Adapter + // pairing event call stack. The Bluetooth Adapter system + // event response has not finished completing because of the delay set in + // `SetIsDeviceSavedToAccountCallbackDelayed`. + PairFastPairDeviceWithFastPair(kTestDeviceAddress); + + // Trigger the callback to check the repository after the Fast Pair pairing + // event fires. This will conclude the BluetoothAdapter pairing event call + // stack. + fast_pair_repository_.TriggerIsDeviceSavedToAccountCallback(); + + // Simulate data being received via Message Stream for the device. It should + // not be detected since the Fast Pair event has been fired, removing it + // as a possible retroactive device. + fake_socket_->TriggerReceiveCallback(); + NotifyMessageStreamConnected(kTestDeviceAddress); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(retroactive_pair_found_); +} + TEST_F(RetroactivePairingDetectorTest, DeviceUnpaired) { Login(user_manager::UserType::USER_TYPE_REGULAR); fast_pair_repository_.SetOptInStatus(
diff --git a/ash/quick_pair/repository/fake_fast_pair_repository.cc b/ash/quick_pair/repository/fake_fast_pair_repository.cc index ca1d6bb..1d5e0e3 100644 --- a/ash/quick_pair/repository/fake_fast_pair_repository.cc +++ b/ash/quick_pair/repository/fake_fast_pair_repository.cc
@@ -178,6 +178,11 @@ void FakeFastPairRepository::IsDeviceSavedToAccount( const std::string& mac_address, IsDeviceSavedToAccountCallback callback) { + if (saved_to_account_callback_is_delayed_) { + saved_to_account_callback_ = std::move(callback); + return; + } + if (base::Contains(saved_mac_addresses_, mac_address)) { std::move(callback).Run(true); return; @@ -186,5 +191,9 @@ std::move(callback).Run(false); } +void FakeFastPairRepository::TriggerIsDeviceSavedToAccountCallback() { + std::move(saved_to_account_callback_).Run(false); +} + } // namespace quick_pair } // namespace ash
diff --git a/ash/quick_pair/repository/fake_fast_pair_repository.h b/ash/quick_pair/repository/fake_fast_pair_repository.h index 8d042e6..e055d23 100644 --- a/ash/quick_pair/repository/fake_fast_pair_repository.h +++ b/ash/quick_pair/repository/fake_fast_pair_repository.h
@@ -89,9 +89,19 @@ void IsDeviceSavedToAccount(const std::string& mac_address, IsDeviceSavedToAccountCallback callback) override; + // `SetIsDeviceSavedToAccountCallbackDelay` and + // `TriggerIsDeviceSavedToAccountCallback` are used together to control when + // the callback is triggered. + void TriggerIsDeviceSavedToAccountCallback(); + void SetIsDeviceSavedToAccountCallbackDelayed(bool is_delayed) { + saved_to_account_callback_is_delayed_ = is_delayed; + } + private: static void SetInstance(FastPairRepository* instance); + IsDeviceSavedToAccountCallback saved_to_account_callback_; + bool saved_to_account_callback_is_delayed_ = false; nearby::fastpair::OptInStatus status_ = nearby::fastpair::OptInStatus::STATUS_UNKNOWN; std::vector<nearby::fastpair::FastPairDevice> devices_;
diff --git a/ash/shelf/swipe_home_to_overview_controller_unittest.cc b/ash/shelf/swipe_home_to_overview_controller_unittest.cc index 668179d..f81f9914 100644 --- a/ash/shelf/swipe_home_to_overview_controller_unittest.cc +++ b/ash/shelf/swipe_home_to_overview_controller_unittest.cc
@@ -24,9 +24,11 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_tick_clock.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/compositor/test/layer_animation_stopped_waiter.h" #include "ui/compositor/test/test_utils.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect_f.h" @@ -106,17 +108,12 @@ } void WaitForHomeLauncherAnimationToFinish() { - auto* compositor = - Shell::GetPrimaryRootWindowController()->GetHost()->compositor(); - // Wait until home launcher animation finishes. - while (GetAppListTestHelper() - ->GetAppListView() - ->GetWidget() - ->GetLayer() - ->GetAnimator() - ->is_animating()) { - EXPECT_TRUE(ui::WaitForNextFrameToBePresented(compositor)); - } + ui::LayerAnimationStoppedWaiter animation_waiter; + ui::Layer* app_list_layer = + GetAppListTestHelper()->GetAppListView()->GetWidget()->GetLayer(); + animation_waiter.Wait(app_list_layer); + + ui::Compositor* compositor = app_list_layer->GetCompositor(); // Ensure there is one more frame presented after animation finishes // to allow animation throughput data is passed from cc to ui.
diff --git a/ash/shell.cc b/ash/shell.cc index dfdabe87..5a3baa3 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -100,7 +100,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/system_sounds_delegate.h" #include "ash/public/cpp/tab_cluster/tab_cluster_ui_controller.h" -#include "ash/public/cpp/views_text_services_context_menu_impl.h" +#include "ash/public/cpp/views_text_services_context_menu_ash.h" #include "ash/quick_pair/keyed_service/quick_pair_mediator.h" #include "ash/rgb_keyboard/rgb_keyboard_manager.h" #include "ash/root_window_controller.h" @@ -1536,8 +1536,8 @@ base::BindRepeating( [](ui::SimpleMenuModel* menu_model, views::Textfield* textfield) -> std::unique_ptr<views::ViewsTextServicesContextMenu> { - return std::make_unique<ViewsTextServicesContextMenuImpl>( - menu_model, textfield); + return std::make_unique<ViewsTextServicesContextMenuAsh>(menu_model, + textfield); })); for (auto& observer : shell_observers_)
diff --git a/ash/style/dark_light_mode_controller_impl.cc b/ash/style/dark_light_mode_controller_impl.cc index 56a15eb..4b2c9b0 100644 --- a/ash/style/dark_light_mode_controller_impl.cc +++ b/ash/style/dark_light_mode_controller_impl.cc
@@ -134,6 +134,7 @@ !IsDarkModeEnabled()); active_user_pref_service_->CommitPendingWrite(); NotifyColorModeChanges(); + SystemNudgeController::RecordNudgeAction(NudgeCatalogName::kDarkLightMode); // Updates showing logic of educational nudge on toggling the entry points of // dark/light mode.
diff --git a/ash/system/camera/autozoom_controller_impl.cc b/ash/system/camera/autozoom_controller_impl.cc index dfdff6b..b3ace6a 100644 --- a/ash/system/camera/autozoom_controller_impl.cc +++ b/ash/system/camera/autozoom_controller_impl.cc
@@ -66,6 +66,7 @@ SetState(state_ == cros::mojom::CameraAutoFramingState::OFF ? cros::mojom::CameraAutoFramingState::ON_SINGLE : cros::mojom::CameraAutoFramingState::OFF); + SystemNudgeController::RecordNudgeAction(NudgeCatalogName::kAutozoom); } void AutozoomControllerImpl::AddObserver(AutozoomObserver* observer) {
diff --git a/ash/system/do_not_disturb_notification_controller.cc b/ash/system/do_not_disturb_notification_controller.cc index fed5bde5..8a40391 100644 --- a/ash/system/do_not_disturb_notification_controller.cc +++ b/ash/system/do_not_disturb_notification_controller.cc
@@ -22,7 +22,6 @@ using message_center::MessageCenter; -const char kDoNotDisturbNotificationId[] = "do_not_disturb"; const char kDoNotDisturbNotifierId[] = "ash.do_not_disturb_notification_controller"; @@ -36,6 +35,10 @@ MessageCenter::Get()->RemoveObserver(this); } +// static +const char DoNotDisturbNotificationController::kDoNotDisturbNotificationId[] = + "do_not_disturb"; + std::unique_ptr<message_center::Notification> DoNotDisturbNotificationController::CreateNotification() { message_center::RichNotificationData optional_fields;
diff --git a/ash/system/do_not_disturb_notification_controller.h b/ash/system/do_not_disturb_notification_controller.h index d4e513f8..a52232a 100644 --- a/ash/system/do_not_disturb_notification_controller.h +++ b/ash/system/do_not_disturb_notification_controller.h
@@ -30,6 +30,8 @@ ~DoNotDisturbNotificationController() override; + static const char kDoNotDisturbNotificationId[]; + // message_center::MessageCenterObserver: void OnQuietModeChanged(bool in_quiet_mode) override;
diff --git a/ash/system/do_not_disturb_notification_controller_unittest.cc b/ash/system/do_not_disturb_notification_controller_unittest.cc index 5a5b207..bb0051a 100644 --- a/ash/system/do_not_disturb_notification_controller_unittest.cc +++ b/ash/system/do_not_disturb_notification_controller_unittest.cc
@@ -15,8 +15,6 @@ using message_center::MessageCenter; -const char kDoNotDisturbNotificationId[] = "do_not_disturb"; - } // namespace class DoNotDisturbNotificationControllerTest @@ -42,7 +40,7 @@ bool IsDoNotDisturbNotificationPresent() { return MessageCenter::Get()->FindNotificationById( - kDoNotDisturbNotificationId); + DoNotDisturbNotificationController::kDoNotDisturbNotificationId); } private: @@ -87,8 +85,8 @@ ASSERT_TRUE(IsDoNotDisturbNotificationPresent()); // Simulate a click on the notification's "Turn off" button. - auto* notification = - message_center->FindNotificationById(kDoNotDisturbNotificationId); + auto* notification = message_center->FindNotificationById( + DoNotDisturbNotificationController::kDoNotDisturbNotificationId); notification->delegate()->Click(0, absl::nullopt); EXPECT_FALSE(IsDoNotDisturbNotificationPresent()); EXPECT_FALSE(message_center->IsQuietMode());
diff --git a/ash/system/message_center/session_state_notification_blocker.cc b/ash/system/message_center/session_state_notification_blocker.cc index 9c5e130..eb87c26 100644 --- a/ash/system/message_center/session_state_notification_blocker.cc +++ b/ash/system/message_center/session_state_notification_blocker.cc
@@ -6,12 +6,11 @@ #include "ash/session/session_controller_impl.h" #include "ash/shell.h" -#include "ash/system/message_center/ash_message_center_lock_screen_controller.h" +#include "ash/system/do_not_disturb_notification_controller.h" #include "ash/system/power/battery_notification.h" #include "base/containers/contains.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" using session_manager::SessionState; @@ -96,6 +95,15 @@ if (Shell::Get()->session_controller()->IsRunningInAppMode()) return false; + // Do not show the "Do not disturb" notification if there is no active + // session. + if (notification.id() == + DoNotDisturbNotificationController::kDoNotDisturbNotificationId && + Shell::Get()->session_controller()->GetSessionState() != + SessionState::ACTIVE) { + return false; + } + if (notification.id() == BatteryNotification::kNotificationId) return true;
diff --git a/ash/system/message_center/session_state_notification_blocker_unittest.cc b/ash/system/message_center/session_state_notification_blocker_unittest.cc index 2c9ab2a..d65199dd 100644 --- a/ash/system/message_center/session_state_notification_blocker_unittest.cc +++ b/ash/system/message_center/session_state_notification_blocker_unittest.cc
@@ -9,9 +9,9 @@ #include "ash/constants/ash_features.h" #include "ash/constants/notifier_catalogs.h" #include "ash/session/test_session_controller_client.h" +#include "ash/system/do_not_disturb_notification_controller.h" #include "ash/system/power/battery_notification.h" #include "ash/test/ash_test_base.h" -#include "base/command_line.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "ui/message_center/message_center.h" @@ -95,6 +95,19 @@ return blocker_->ShouldShowNotificationAsPopup(notification); } + bool ShouldShowDoNotDisturbNotification() { + message_center::Notification notification( + message_center::NOTIFICATION_TYPE_SIMPLE, + DoNotDisturbNotificationController::kDoNotDisturbNotificationId, + u"chromeos-title", u"chromeos-message", ui::ImageModel(), + u"chromeos-source", GURL(), + message_center::NotifierId( + message_center::NotifierType::SYSTEM_COMPONENT, "test-notifier", + NotificationCatalogName::kDoNotDisturb), + message_center::RichNotificationData(), nullptr); + return blocker_->ShouldShowNotification(notification); + } + void SetLockedState(bool locked) { GetSessionControllerClient()->SetSessionState( locked ? SessionState::LOCKED : SessionState::ACTIVE); @@ -261,5 +274,27 @@ SessionStateNotificationBlocker::SetUseLoginNotificationDelayForTest(false); } +TEST_P(SessionStateNotificationBlockerTest, DoNotDisturbNotification) { + // OOBE. + GetSessionControllerClient()->SetSessionState(SessionState::OOBE); + EXPECT_FALSE(ShouldShowDoNotDisturbNotification()); + + // Login screen. + GetSessionControllerClient()->SetSessionState(SessionState::LOGIN_PRIMARY); + EXPECT_FALSE(ShouldShowDoNotDisturbNotification()); + + // Logged in as a normal user. + SimulateUserLogin("user@test.com"); + EXPECT_TRUE(ShouldShowDoNotDisturbNotification()); + + // Lock. + SetLockedState(true); + EXPECT_FALSE(ShouldShowDoNotDisturbNotification()); + + // Unlock. + SetLockedState(false); + EXPECT_TRUE(ShouldShowDoNotDisturbNotification()); +} + } // namespace } // namespace ash
diff --git a/ash/system/microphone_mute/microphone_mute_notification_controller.cc b/ash/system/microphone_mute/microphone_mute_notification_controller.cc index 7a14527..f90baeb 100644 --- a/ash/system/microphone_mute/microphone_mute_notification_controller.cc +++ b/ash/system/microphone_mute/microphone_mute_notification_controller.cc
@@ -9,6 +9,7 @@ #include <vector> #include "ash/constants/notifier_catalogs.h" +#include "ash/public/cpp/new_window_delegate.h" #include "ash/public/cpp/notification_utils.h" #include "ash/public/cpp/sensor_disabled_notification_delegate.h" #include "ash/shell.h" @@ -21,10 +22,14 @@ #include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/message_center/message_center.h" +#include "ui/message_center/public/cpp/notification_delegate.h" namespace ash { namespace { +// TODO(b/244529735): Replace the generic support URL with the final one. +const char kLearnMoreUrl[] = "https://www.support.google.com/chromebook"; + void SetMicrophoneNotificationVisible(const bool visible) { PrivacyHubNotificationController* const privacy_hub_notification_controller = Shell::Get()->system_notification_controller()->privacy_hub(); @@ -132,12 +137,30 @@ notification_data.remove_on_click = true; scoped_refptr<message_center::NotificationDelegate> delegate; - // Don't show a button to unmute device if the microphone was muted by a HW - // mute switch, as in that case unmute action would not work. - if (!mic_muted_by_mute_switch_) { + + if (mic_muted_by_mute_switch_) { + // If microphone is muted by the hardware(HW) switch, show the 'Learn more' + // button, pointing to the instructions how to unmute the system (unmute + // can't be done programmatically). + notification_data.buttons.emplace_back( + l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE)); + delegate = + base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( + base::BindRepeating([](absl::optional<int> button_index) { + if (!button_index) { + return; + } + + NewWindowDelegate::GetPrimary()->OpenUrl( + GURL(kLearnMoreUrl), + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); + })); + } else { + // If microphone is muted by the software(SW) switch, add the unmute + // button to the notification. notification_data.buttons.emplace_back(l10n_util::GetStringUTF16( IDS_MICROPHONE_MUTED_NOTIFICATION_ACTION_BUTTON)); - delegate = base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( base::BindRepeating([](absl::optional<int> button_index) {
diff --git a/ash/system/microphone_mute/microphone_mute_notification_controller_unittest.cc b/ash/system/microphone_mute/microphone_mute_notification_controller_unittest.cc index aff8c4d2..8c96c27 100644 --- a/ash/system/microphone_mute/microphone_mute_notification_controller_unittest.cc +++ b/ash/system/microphone_mute/microphone_mute_notification_controller_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/sensor_disabled_notification_delegate.h" +#include "ash/public/cpp/test/test_new_window_delegate.h" #include "ash/public/cpp/test/test_system_tray_client.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/microphone_mute/microphone_mute_notification_controller.h" @@ -17,8 +18,12 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "chromeos/ash/components/audio/cras_audio_handler.h" +#include "chromeos/ash/components/dbus/audio/cras_audio_client.h" #include "chromeos/ash/components/dbus/audio/fake_cras_audio_client.h" +#include "testing/gmock/include/gmock/gmock.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" #include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/notification.h" @@ -26,6 +31,8 @@ namespace ash { +namespace { + class FakeSensorDisabledNotificationDelegate : public SensorDisabledNotificationDelegate { public: @@ -48,16 +55,32 @@ std::vector<std::u16string> apps_accessing_microphone_; }; +class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> { + public: + // TestNewWindowDelegate: + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); +}; + +} // namespace + class MicrophoneMuteNotificationControllerTest : public AshTestBase { public: MicrophoneMuteNotificationControllerTest() { scoped_feature_list_.InitAndEnableFeature(features::kMicMuteNotifications); + auto delegate = std::make_unique<MockNewWindowDelegate>(); + new_window_delegate_ = delegate.get(); + window_delegate_provider_ = + std::make_unique<TestNewWindowDelegateProvider>(std::move(delegate)); } ~MicrophoneMuteNotificationControllerTest() override = default; // AshTestBase: void SetUp() override { AshTestBase::SetUp(); + controller_ = std::make_unique<MicrophoneMuteNotificationController>(); delegate_ = std::make_unique<FakeSensorDisabledNotificationDelegate>(); } @@ -137,11 +160,15 @@ return histogram_tester_; } + MockNewWindowDelegate& new_window_delegate() { return *new_window_delegate_; } + private: const base::HistogramTester histogram_tester_; base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<MicrophoneMuteNotificationController> controller_; std::unique_ptr<FakeSensorDisabledNotificationDelegate> delegate_; + MockNewWindowDelegate* new_window_delegate_ = nullptr; + std::unique_ptr<TestNewWindowDelegateProvider> window_delegate_provider_; }; TEST_F(MicrophoneMuteNotificationControllerTest, SimpleMuteUnMute) { @@ -269,7 +296,8 @@ EXPECT_FALSE(GetNotification()); } -TEST_F(MicrophoneMuteNotificationControllerTest, MuteNotificationActionButton) { +TEST_F(MicrophoneMuteNotificationControllerTest, + SwMuteNotificationActionButton) { MuteMicrophone(); LaunchApp(u"junior"); SetNumberOfActiveInputStreams(1); @@ -296,7 +324,7 @@ 1); } -TEST_F(MicrophoneMuteNotificationControllerTest, MuteNotificationActionBody) { +TEST_F(MicrophoneMuteNotificationControllerTest, SwMuteNotificationActionBody) { MuteMicrophone(); LaunchApp(u"junior"); SetNumberOfActiveInputStreams(1); @@ -325,23 +353,45 @@ } TEST_F(MicrophoneMuteNotificationControllerTest, - NoNotificationActionButtonIfMutedByHwSwitch) { + HwMuteNotificationActionButton) { SetMicrophoneMuteSwitchState(/*muted=*/true); LaunchApp(u"junior"); SetNumberOfActiveInputStreams(1); - // The mute notification should not have an action button if device is muted - // by a mute switch. + // The mute notification should have a "Learn more" button. message_center::Notification* notification = GetNotification(); ASSERT_TRUE(notification); - EXPECT_EQ(0u, notification->buttons().size()); + EXPECT_EQ(1u, notification->buttons().size()); + + // Clicking the "Learn more" button should open a new Chrome tab with the + // support link. + EXPECT_CALL(new_window_delegate(), OpenUrl).Times(1); + ClickOnNotificationButton(); + + EXPECT_TRUE(chromeos::CrasAudioHandler::Get()->IsInputMuted()); SetMicrophoneMuteSwitchState(/*muted=*/false); ASSERT_FALSE(chromeos::CrasAudioHandler::Get()->IsInputMuted()); EXPECT_FALSE(GetNotification()); } +TEST_F(MicrophoneMuteNotificationControllerTest, HwMuteNotificationActionBody) { + SetMicrophoneMuteSwitchState(/*muted=*/true); + LaunchApp(u"junior"); + SetNumberOfActiveInputStreams(1); + + message_center::Notification* notification = GetNotification(); + ASSERT_TRUE(notification); + EXPECT_EQ(1u, notification->buttons().size()); + + ClickOnNotificationBody(); + + // Check that clicking the body has no effect and notification disappears. + EXPECT_TRUE(chromeos::CrasAudioHandler::Get()->IsInputMuted()); + EXPECT_FALSE(GetNotification()); +} + TEST_F(MicrophoneMuteNotificationControllerTest, TogglingMuteSwitchRemovesNotificationActionButton) { // Mute microphone, and activate an audio input stream. @@ -353,12 +403,18 @@ message_center::Notification* notification = GetNotification(); ASSERT_TRUE(notification); EXPECT_EQ(1u, notification->buttons().size()); + EXPECT_EQ(l10n_util::GetStringUTF16( + IDS_MICROPHONE_MUTED_NOTIFICATION_ACTION_BUTTON), + notification->buttons()[0].title); - // Toggle microphone mute switch and verify the action button disappears. + // Toggle microphone mute switch and verify that new notification appears with + // a "Learn more" button. SetMicrophoneMuteSwitchState(/*muted=*/true); notification = GetNotification(); ASSERT_TRUE(notification); - EXPECT_EQ(0u, notification->buttons().size()); + EXPECT_EQ(1u, notification->buttons().size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE), + notification->buttons()[0].title); SetMicrophoneMuteSwitchState(/*muted=*/false); ASSERT_FALSE(chromeos::CrasAudioHandler::Get()->IsInputMuted());
diff --git a/ash/system/notification_center/notification_center_test_api.cc b/ash/system/notification_center/notification_center_test_api.cc index 07d14d64..5088263b 100644 --- a/ash/system/notification_center/notification_center_test_api.cc +++ b/ash/system/notification_center/notification_center_test_api.cc
@@ -14,6 +14,7 @@ #include "ash/system/notification_center/notification_center_view.h" #include "ash/system/notification_center/notification_list_view.h" #include "ash/system/notification_center/stacked_notification_bar.h" +#include "ash/system/unified/notification_counter_view.h" #include "ash/system/unified/unified_system_tray.h" #include "base/strings/string_number_conversions.h" #include "ui/base/models/image_model.h" @@ -84,6 +85,12 @@ return notification_center_tray_->GetVisible(); } +bool NotificationCenterTestApi::IsDoNotDisturbIconShown() { + return notification_center_tray_->notification_icons_controller_ + ->quiet_mode_view() + ->GetVisible(); +} + views::View* NotificationCenterTestApi::GetNotificationViewForId( const std::string& id) { // Ensure this api is only called when the notification list view exists, i.e.
diff --git a/ash/system/notification_center/notification_center_test_api.h b/ash/system/notification_center/notification_center_test_api.h index b9573d6..9c2fe57 100644 --- a/ash/system/notification_center/notification_center_test_api.h +++ b/ash/system/notification_center/notification_center_test_api.h
@@ -61,10 +61,14 @@ // otherwise. bool IsPopupShown(const std::string& id); - // Returns true if `NotificationCenterTray`` is showing in the shelf, false + // Returns true if `NotificationCenterTray` is showing in the shelf, false // otherwise. bool IsTrayShown(); + // Returns true if `QuietModeView` is showing in the `NotificationCenterTray`, + // false otherwise. + bool IsDoNotDisturbIconShown(); + // Returns the notification view associated with the provided notification id. // Should be only used when the notifications bubble is open. views::View* GetNotificationViewForId(const std::string& id);
diff --git a/ash/system/notification_center/notification_center_tray.h b/ash/system/notification_center/notification_center_tray.h index d5324ec..be8560b 100644 --- a/ash/system/notification_center/notification_center_tray.h +++ b/ash/system/notification_center/notification_center_tray.h
@@ -13,7 +13,6 @@ #include "ash/system/tray/tray_background_view.h" #include "ash/system/unified/notification_icons_controller.h" #include "ui/base/metadata/metadata_header_macros.h" -#include "ui/message_center/message_center.h" #include "ui/message_center/message_center_observer.h" #include "ui/message_center/message_center_types.h"
diff --git a/ash/system/notification_center/notification_center_tray_unittest.cc b/ash/system/notification_center/notification_center_tray_unittest.cc index 4f0ea38..9d4366d2 100644 --- a/ash/system/notification_center/notification_center_tray_unittest.cc +++ b/ash/system/notification_center/notification_center_tray_unittest.cc
@@ -199,6 +199,31 @@ EXPECT_FALSE(test_api()->IsBubbleShown()); } +// Tests that visibility of the Do not disturb icon changes with Do not disturb +// mode. +TEST_F(NotificationCenterTrayTest, DoNotDisturbIconVisibility) { + // Test the case where the tray is not initially visible. + ASSERT_FALSE(test_api()->IsTrayShown()); + EXPECT_FALSE(test_api()->IsDoNotDisturbIconShown()); + message_center::MessageCenter::Get()->SetQuietMode(true); + EXPECT_TRUE(test_api()->IsTrayShown()); + EXPECT_TRUE(test_api()->IsDoNotDisturbIconShown()); + message_center::MessageCenter::Get()->SetQuietMode(false); + EXPECT_FALSE(test_api()->IsTrayShown()); + EXPECT_FALSE(test_api()->IsDoNotDisturbIconShown()); + + // Test the case where the tray is initially visible. + test_api()->AddNotification(); + ASSERT_TRUE(test_api()->IsTrayShown()); + EXPECT_FALSE(test_api()->IsDoNotDisturbIconShown()); + message_center::MessageCenter::Get()->SetQuietMode(true); + EXPECT_TRUE(test_api()->IsTrayShown()); + EXPECT_TRUE(test_api()->IsDoNotDisturbIconShown()); + message_center::MessageCenter::Get()->SetQuietMode(false); + EXPECT_TRUE(test_api()->IsTrayShown()); + EXPECT_FALSE(test_api()->IsDoNotDisturbIconShown()); +} + // TODO(b/252875025): // Add following test cases as we add relevant functionality: // - Focus Change dismissing bubble
diff --git a/ash/system/time/time_tray_item_view.cc b/ash/system/time/time_tray_item_view.cc index fe84631..a070e851 100644 --- a/ash/system/time/time_tray_item_view.cc +++ b/ash/system/time/time_tray_item_view.cc
@@ -22,7 +22,7 @@ : TimeView::ClockLayout::VERTICAL_CLOCK; time_view_ = AddChildView(std::make_unique<TimeView>( clock_layout, Shell::Get()->system_tray_model()->clock(), type)); - time_view_->SetTextColor(kColorAshIconColorPrimary); + time_view_->SetTextColorId(kColorAshIconColorPrimary); } TimeTrayItemView::~TimeTrayItemView() = default;
diff --git a/ash/system/time/time_view.cc b/ash/system/time/time_view.cc index 3d676fb..017702bb 100644 --- a/ash/system/time/time_view.cc +++ b/ash/system/time/time_view.cc
@@ -194,10 +194,28 @@ Layout(); } -void TimeView::SetTextColor(ui::ColorId color_id, +void TimeView::SetTextColorId(ui::ColorId color_id, + bool auto_color_readability_enabled) { + auto set_color_id = [&](views::Label* label) { + label->SetEnabledColorId(color_id); + label->SetAutoColorReadabilityEnabled(auto_color_readability_enabled); + }; + + switch (type_) { + case kTime: + set_color_id(horizontal_label_); + set_color_id(vertical_label_hours_); + set_color_id(vertical_label_minutes_); + return; + case kDate: + set_color_id(horizontal_label_date_); + } +} + +void TimeView::SetTextColor(SkColor color, bool auto_color_readability_enabled) { auto set_color = [&](views::Label* label) { - label->SetEnabledColorId(color_id); + label->SetEnabledColor(color); label->SetAutoColorReadabilityEnabled(auto_color_readability_enabled); };
diff --git a/ash/system/time/time_view.h b/ash/system/time/time_view.h index 898627e..1419fe9 100644 --- a/ash/system/time/time_view.h +++ b/ash/system/time/time_view.h
@@ -76,9 +76,12 @@ // Updates clock layout. void UpdateClockLayout(ClockLayout clock_layout); - // Updates the time text color. - void SetTextColor(ui::ColorId color_id, - bool auto_color_readability_enabled = false); + // Updates the time text color id. + void SetTextColorId(ui::ColorId color_id, + bool auto_color_readability_enabled = false); + + // Updates the text color. + void SetTextColor(SkColor color, bool auto_color_readability_enabled = false); // Updates the time text fontlist. void SetTextFont(const gfx::FontList& font_list);
diff --git a/ash/system/tray/system_nudge.cc b/ash/system/tray/system_nudge.cc index 6e55e7e..32d8b77f 100644 --- a/ash/system/tray/system_nudge.cc +++ b/ash/system/tray/system_nudge.cc
@@ -189,9 +189,6 @@ const std::u16string accessibility_text = GetAccessibilityText(); if (!accessibility_text.empty()) nudge_view_->GetViewAccessibility().AnnounceText(accessibility_text); - - base::UmaHistogramEnumeration("Ash.NotifierFramework.Nudge.ShownCount", - params_.catalog_name); } void SystemNudge::Close() {
diff --git a/ash/system/tray/system_nudge.h b/ash/system/tray/system_nudge.h index e89cefd8..c786cfc 100644 --- a/ash/system/tray/system_nudge.h +++ b/ash/system/tray/system_nudge.h
@@ -66,6 +66,8 @@ views::Widget* widget() { return widget_.get(); } + NudgeCatalogName catalog_name() { return params_.catalog_name; } + protected: // Each SystemNudge subclass must override these methods to customize // their nudge by creating a label and getting an icon specific to the feature
diff --git a/ash/system/tray/system_nudge_controller.cc b/ash/system/tray/system_nudge_controller.cc index 330e33dc..aa54c08 100644 --- a/ash/system/tray/system_nudge_controller.cc +++ b/ash/system/tray/system_nudge_controller.cc
@@ -10,6 +10,8 @@ #include "ash/shell.h" #include "ash/system/tray/system_nudge.h" #include "base/bind.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" #include "base/time/time.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" @@ -27,6 +29,19 @@ gfx::Tween::LINEAR; constexpr gfx::Tween::Type kNudgeFadeScalingAnimationTweenType = gfx::Tween::LINEAR_OUT_SLOW_IN; + +constexpr char NotifierFrameworkNudgeHistogram[] = + "Ash.NotifierFramework.Nudge"; + +// Used in histogram names. +std::string GetNudgeTimeToActionRange(const base::TimeDelta& time) { + if (time <= base::Minutes(1)) + return "Within1m"; + if (time <= base::Hours(1)) + return "Within1h"; + return "WithinSession"; +} + } // namespace // A class for observing the nudge fade out animation. Once the fade @@ -67,6 +82,31 @@ hide_nudge_animation_observer_.reset(); } +// static +void SystemNudgeController::RecordNudgeAction(NudgeCatalogName catalog_name) { + auto& nudge_registry = GetNudgeRegistry(); + auto it = std::find_if( + std::begin(nudge_registry), std::end(nudge_registry), + [catalog_name]( + const std::pair<NudgeCatalogName, base::TimeTicks> registry_entry) { + return catalog_name == registry_entry.first; + }); + + // Don't record "TimeToAction" metric if the nudge hasn't been shown. + if (it == std::end(nudge_registry)) + return; + + const base::TimeDelta delta = base::TimeTicks::Now() - (*it).second; + const std::string time_range = GetNudgeTimeToActionRange(delta); + + base::UmaHistogramEnumeration( + base::StrCat({NotifierFrameworkNudgeHistogram, ".TimeToAction.", + time_range.c_str()}), + catalog_name); + + nudge_registry.erase(it); +} + void SystemNudgeController::ShowNudge() { if (nudge_ && !nudge_->widget()->IsClosed()) { hide_nudge_timer_.AbandonAndStop(); @@ -77,6 +117,7 @@ nudge_ = CreateSystemNudge(); nudge_->Show(); StartFadeAnimation(/*show=*/true); + RecordNudgeShown(nudge_->catalog_name()); // Start a timer to close the nudge after a set amount of time. hide_nudge_timer_.Start(FROM_HERE, kNudgeShowTime, @@ -92,10 +133,22 @@ hide_nudge_timer_.FireNow(); } +void SystemNudgeController::ResetNudgeRegistryForTesting() { + GetNudgeRegistry().clear(); +} + void SystemNudgeController::HideNudge() { StartFadeAnimation(/*show=*/false); } +// static +std::vector<std::pair<NudgeCatalogName, base::TimeTicks>>& +SystemNudgeController::GetNudgeRegistry() { + static auto nudge_registry = + std::vector<std::pair<NudgeCatalogName, base::TimeTicks>>(); + return nudge_registry; +} + void SystemNudgeController::StartFadeAnimation(bool show) { // Clean any pending animation observer. hide_nudge_animation_observer_.reset(); @@ -142,4 +195,23 @@ } } +void SystemNudgeController::RecordNudgeShown(NudgeCatalogName catalog_name) { + base::UmaHistogramEnumeration("Ash.NotifierFramework.Nudge.ShownCount", + catalog_name); + auto& nudge_registry = GetNudgeRegistry(); + + auto it = std::find_if( + std::begin(nudge_registry), std::end(nudge_registry), + [catalog_name]( + const std::pair<NudgeCatalogName, base::TimeTicks> registry_entry) { + return catalog_name == registry_entry.first; + }); + + if (it == std::end(nudge_registry)) { + nudge_registry.emplace_back(catalog_name, base::TimeTicks::Now()); + } else { + (*it).second = base::TimeTicks::Now(); + } +} + } // namespace ash
diff --git a/ash/system/tray/system_nudge_controller.h b/ash/system/tray/system_nudge_controller.h index b07a38c..85223ece 100644 --- a/ash/system/tray/system_nudge_controller.h +++ b/ash/system/tray/system_nudge_controller.h
@@ -8,6 +8,7 @@ #include <memory> #include "ash/ash_export.h" +#include "ash/constants/notifier_catalogs.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "ui/compositor/layer_animation_observer.h" @@ -28,6 +29,10 @@ SystemNudgeController& operator=(const SystemNudgeController&) = delete; virtual ~SystemNudgeController(); + // Records Nudge "TimeToAction" metric, which tracks the time from when a + // nudge was shown to when the action the nudge informs of was performed. + static void RecordNudgeAction(NudgeCatalogName catalog_name); + // Shows the nudge widget. void ShowNudge(); @@ -40,6 +45,10 @@ // Get the system nudge for testing purpose. SystemNudge* GetSystemNudgeForTesting() { return nudge_.get(); } + // Resets the `nudge_registry` object that records the time a nudge was last + // shown. + void ResetNudgeRegistryForTesting(); + protected: // Concrete subclasses must implement this method to return a // SystemNudge that creates a label and specifies an icon specific @@ -50,9 +59,17 @@ void HideNudge(); private: + // Returns the registry which keeps track of when a nudge was last shown. + static std::vector<std::pair<NudgeCatalogName, base::TimeTicks>>& + GetNudgeRegistry(); + // Begins the animation for fading in or fading out the nudge. void StartFadeAnimation(bool show); + // Records the time a nudge was last shown and stores it in the + // `nudge_registry`. + void RecordNudgeShown(NudgeCatalogName catalog_name); + // Contextual nudge which shows a view. std::unique_ptr<SystemNudge> nudge_;
diff --git a/ash/system/tray/system_nudge_unittest.cc b/ash/system/tray/system_nudge_unittest.cc index 5f87de40e..66644ff1 100644 --- a/ash/system/tray/system_nudge_unittest.cc +++ b/ash/system/tray/system_nudge_unittest.cc
@@ -9,9 +9,11 @@ #include "ash/public/cpp/shelf_types.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_layout_manager.h" +#include "ash/system/tray/system_nudge_controller.h" #include "ash/system/tray/system_nudge_label.h" #include "ash/test/ash_test_base.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/task_environment.h" #include "ui/gfx/vector_icon_types.h" namespace ash { @@ -26,12 +28,22 @@ constexpr char kNudgeName[] = "TestSystemNudge"; +constexpr NudgeCatalogName kTestCatalogName = + NudgeCatalogName::kTestCatalogName; + +constexpr char kNudgeShownCount[] = "Ash.NotifierFramework.Nudge.ShownCount"; +constexpr char kNudgeTimeToActionWithin1m[] = + "Ash.NotifierFramework.Nudge.TimeToAction.Within1m"; +constexpr char kNudgeTimeToActionWithin1h[] = + "Ash.NotifierFramework.Nudge.TimeToAction.Within1h"; +constexpr char kNudgeTimeToActionWithinSession[] = + "Ash.NotifierFramework.Nudge.TimeToAction.WithinSession"; + gfx::VectorIcon kEmptyIcon; class TestSystemNudge : public SystemNudge { public: - explicit TestSystemNudge( - NudgeCatalogName catalog_name = NudgeCatalogName::kTestCatalogName) + explicit TestSystemNudge(NudgeCatalogName catalog_name = kTestCatalogName) : SystemNudge(kNudgeName, catalog_name, kIconSize, @@ -54,14 +66,26 @@ } }; -constexpr char kNudgeShownCountHistogramName[] = - "Ash.NotifierFramework.Nudge.ShownCount"; +class TestSystemNudgeController : public SystemNudgeController { + public: + TestSystemNudgeController() = default; + TestSystemNudgeController(const TestSystemNudgeController&) = delete; + TestSystemNudgeController& operator=(const TestSystemNudgeController&) = + delete; + ~TestSystemNudgeController() override = default; + + // SystemNudgeController: + std::unique_ptr<SystemNudge> CreateSystemNudge() override { + return std::make_unique<TestSystemNudge>(kTestCatalogName); + } +}; } // namespace class SystemNudgeTest : public AshTestBase { public: - SystemNudgeTest() = default; + SystemNudgeTest() + : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} SystemNudgeTest(const SystemNudgeTest&) = delete; SystemNudgeTest& operator=(const SystemNudgeTest&) = delete; ~SystemNudgeTest() override = default; @@ -107,20 +131,54 @@ TEST_F(SystemNudgeTest, ShownCountMetric) { base::HistogramTester histogram_tester; + auto nudge_controller = std::make_unique<TestSystemNudgeController>(); - const NudgeCatalogName catalog_name_1 = static_cast<NudgeCatalogName>(1); - const NudgeCatalogName catalog_name_2 = static_cast<NudgeCatalogName>(2); - TestSystemNudge nudge_1(catalog_name_1); - TestSystemNudge nudge_2(catalog_name_2); + histogram_tester.ExpectBucketCount(kNudgeShownCount, kTestCatalogName, 0); - nudge_1.Show(); - histogram_tester.ExpectBucketCount(kNudgeShownCountHistogramName, - catalog_name_1, 1); + nudge_controller->ShowNudge(); + histogram_tester.ExpectBucketCount(kNudgeShownCount, kTestCatalogName, 1); - nudge_2.Show(); - nudge_2.Show(); - histogram_tester.ExpectBucketCount(kNudgeShownCountHistogramName, - catalog_name_2, 2); + nudge_controller->ShowNudge(); + nudge_controller->ShowNudge(); + histogram_tester.ExpectBucketCount(kNudgeShownCount, kTestCatalogName, 3); +} + +TEST_F(SystemNudgeTest, TimeToActionMetric) { + base::HistogramTester histogram_tester; + auto nudge_controller = std::make_unique<TestSystemNudgeController>(); + nudge_controller->ResetNudgeRegistryForTesting(); + + // Metric is not recorded if nudge has not been shown. + SystemNudgeController::RecordNudgeAction(kTestCatalogName); + histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1m, + kTestCatalogName, 0); + + // Metric is recorded after nudge is shown. + nudge_controller->ShowNudge(); + task_environment()->FastForwardBy(base::Seconds(1)); + SystemNudgeController::RecordNudgeAction(kTestCatalogName); + histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1m, + kTestCatalogName, 1); + + // Metric is not recorded if the nudge action is performed again without + // another nudge being shown. + SystemNudgeController::RecordNudgeAction(kTestCatalogName); + histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1m, + kTestCatalogName, 1); + + // Metric is recorded with appropriate time range after showing nudge again + // and waiting the time to fall into the next time bucket. + nudge_controller->ShowNudge(); + task_environment()->FastForwardBy(base::Minutes(2)); + SystemNudgeController::RecordNudgeAction(kTestCatalogName); + histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1h, + kTestCatalogName, 1); + + nudge_controller->ShowNudge(); + task_environment()->FastForwardBy(base::Hours(2)); + SystemNudgeController::RecordNudgeAction(kTestCatalogName); + histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithinSession, + kTestCatalogName, 1); } TEST_F(SystemNudgeTest, NudgePositionChangeWhenShelfAutoHide) {
diff --git a/ash/system/unified/notification_counter_view.cc b/ash/system/unified/notification_counter_view.cc index 75cc1ae..5eae9db7 100644 --- a/ash/system/unified/notification_counter_view.cc +++ b/ash/system/unified/notification_counter_view.cc
@@ -4,19 +4,14 @@ #include "ash/system/unified/notification_counter_view.h" -#include <algorithm> - -#include "ash/public/cpp/vm_camera_mic_constants.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" -#include "ash/style/ash_color_provider.h" #include "ash/system/message_center/ash_message_center_lock_screen_controller.h" #include "ash/system/message_center/message_center_utils.h" #include "ash/system/tray/tray_constants.h" -#include "ash/system/tray/tray_utils.h" #include "ash/system/unified/notification_icons_controller.h" #include "base/i18n/number_formatting.h" #include "ui/base/l10n/l10n_util.h" @@ -25,11 +20,9 @@ #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/gfx/image/canvas_image_source.h" -#include "ui/gfx/vector_icon_utils.h" #include "ui/message_center/message_center.h" #include "ui/views/border.h" #include "ui/views/controls/image_view.h" -#include "ui/views/controls/label.h" #include "ui/views/controls/separator.h" namespace ash { @@ -196,11 +189,9 @@ QuietModeView::~QuietModeView() = default; void QuietModeView::Update() { - // TODO(yamaguchi): Add this check when new style of the system tray is - // implemented, so that icon resizing will not happen here. - // DCHECK_EQ(kTrayIconSize, - // gfx::GetDefaultSizeOfVectorIcon(kSystemTrayDoNotDisturbIcon)); - if (message_center::MessageCenter::Get()->IsQuietMode()) { + if (message_center::MessageCenter::Get()->IsQuietMode() && + Shell::Get()->session_controller()->GetSessionState() == + session_manager::SessionState::ACTIVE) { image_view()->SetImage(ui::ImageModel::FromVectorIcon( kSystemTrayDoNotDisturbIcon, kColorAshIconColorPrimary)); SetVisible(true);
diff --git a/ash/system/unified/notification_counter_view.h b/ash/system/unified/notification_counter_view.h index 40b1063..1d6337a 100644 --- a/ash/system/unified/notification_counter_view.h +++ b/ash/system/unified/notification_counter_view.h
@@ -7,7 +7,6 @@ #include "ash/ash_export.h" #include "ash/system/tray/tray_item_view.h" -#include "base/scoped_observation.h" namespace session_manager { enum class SessionState;
diff --git a/ash/system/unified/notification_counter_view_unittest.cc b/ash/system/unified/notification_counter_view_unittest.cc index 3ee91d09..8fe1b164 100644 --- a/ash/system/unified/notification_counter_view_unittest.cc +++ b/ash/system/unified/notification_counter_view_unittest.cc
@@ -12,8 +12,6 @@ #include "ash/test/ash_test_base.h" #include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/image/image.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" @@ -43,7 +41,8 @@ class NotificationCounterViewTest : public AshTestBase, public testing::WithParamInterface<bool> { public: - NotificationCounterViewTest() = default; + NotificationCounterViewTest() + : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} NotificationCounterViewTest(const NotificationCounterViewTest&) = delete; NotificationCounterViewTest& operator=(const NotificationCounterViewTest&) = delete; @@ -72,6 +71,15 @@ ->notification_counter_view(); } + QuietModeView* GetDoNotDisturbIconView() { + auto* status_area_widget = GetPrimaryShelf()->status_area_widget(); + return IsQsRevampEnabled() + ? status_area_widget->notification_center_tray() + ->notification_icons_controller_->quiet_mode_view() + : status_area_widget->unified_system_tray() + ->notification_icons_controller_->quiet_mode_view(); + } + private: std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; }; @@ -166,4 +174,20 @@ EXPECT_FALSE(GetNotificationCounterView()->GetVisible()); } +TEST_P(NotificationCounterViewTest, DoNotDisturbIconVisibility) { + ASSERT_FALSE(GetDoNotDisturbIconView()->GetVisible()); + + // Turn on Do not disturb mode. + message_center::MessageCenter::Get()->SetQuietMode(true); + EXPECT_TRUE(GetDoNotDisturbIconView()->GetVisible()); + + // Show the lock screen. + BlockUserSession(BLOCKED_BY_LOCK_SCREEN); + EXPECT_FALSE(GetDoNotDisturbIconView()->GetVisible()); + + // Log in. + UnblockUserSession(); + EXPECT_TRUE(GetDoNotDisturbIconView()->GetVisible()); +} + } // namespace ash
diff --git a/ash/system/unified/notification_icons_controller.cc b/ash/system/unified/notification_icons_controller.cc index e783eb5..dad44cf 100644 --- a/ash/system/unified/notification_icons_controller.cc +++ b/ash/system/unified/notification_icons_controller.cc
@@ -175,15 +175,14 @@ notification_counter_view_ = tray_container->AddChildView( std::make_unique<NotificationCounterView>(shelf_, /*controller=*/this)); - // `quiet_mode_view_` and `separator_` are only shown in the - // `UnifiedSystemTray` with the QsRevamp feature disabled. Once kQsRevamp - // launches `quiet_mode_view_` will remain in the `UnifiedSystemTray`. - // The `separator_` will not be needed because the icons related to this - // controller will have their own dedicated tray button. - if (!features::IsQsRevampEnabled()) { - quiet_mode_view_ = - tray_container->AddChildView(std::make_unique<QuietModeView>(shelf_)); + quiet_mode_view_ = + tray_container->AddChildView(std::make_unique<QuietModeView>(shelf_)); + // `separator_` is only shown in the `UnifiedSystemTray` with the QsRevamp + // feature disabled. The `separator_` will not be needed once kQsRevamp + // launches because the icons related to this controller will have their own + // dedicated tray button. + if (!features::IsQsRevampEnabled()) { separator_ = tray_container->AddChildView( std::make_unique<SeparatorTrayItemView>(shelf_)); } @@ -222,8 +221,7 @@ void NotificationIconsController::UpdateNotificationIndicators() { notification_counter_view_->Update(); - if (!features::IsQsRevampEnabled()) - quiet_mode_view_->Update(); + quiet_mode_view_->Update(); } void NotificationIconsController::OnSystemTrayButtonSizeChanged(
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index a4a7a6c..d41f53d 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -36,7 +36,6 @@ #include "ash/system/tray/tray_background_view.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_container.h" -#include "ash/system/tray/tray_event_filter.h" #include "ash/system/unified/camera_mic_tray_item_view.h" #include "ash/system/unified/current_locale_view.h" #include "ash/system/unified/date_tray.h" @@ -49,7 +48,6 @@ #include "ash/system/unified/unified_system_tray_bubble.h" #include "ash/system/unified/unified_system_tray_model.h" #include "ash/system/unified/unified_system_tray_view.h" -#include "base/debug/stack_trace.h" #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -63,8 +61,6 @@ #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/gfx/geometry/point.h" -#include "ui/message_center/message_center.h" -#include "ui/message_center/notification_view_controller.h" #include "ui/views/controls/image_view.h" namespace ash { @@ -214,12 +210,6 @@ AddTrayItemToContainer(std::make_unique<ScreenCaptureTrayItemView>(shelf)); - if (features::IsQsRevampEnabled()) { - quiet_mode_view_ = - tray_container()->AddChildView(std::make_unique<QuietModeView>(shelf)); - tray_items_.push_back(quiet_mode_view_); - } - if (!features::IsQsRevampEnabled()) { tray_items_.push_back( notification_icons_controller_->notification_counter_view()); @@ -275,11 +265,13 @@ ShelfConfig::Get()->AddObserver(this); Shell::Get()->tablet_mode_controller()->AddObserver(this); + message_center::MessageCenter::Get()->AddObserver(this); } UnifiedSystemTray::~UnifiedSystemTray() { Shell::Get()->tablet_mode_controller()->RemoveObserver(this); ShelfConfig::Get()->RemoveObserver(this); + message_center::MessageCenter::Get()->RemoveObserver(this); DestroyBubbles(); @@ -513,6 +505,12 @@ UpdateLayout(); } +void UnifiedSystemTray::OnQuietModeChanged(bool in_quiet_mode) { + if (!features::IsQsRevampEnabled()) { + notification_icons_controller_->UpdateNotificationIndicators(); + } +} + void UnifiedSystemTray::OnDateTrayActionPerformed(const ui::Event& event) { if (!bubble_) ShowBubble(); @@ -720,9 +718,6 @@ } void UnifiedSystemTray::UpdateNotificationInternal() { - if (features::IsQsRevampEnabled()) - quiet_mode_view_->Update(); - // Limit update frequency in order to avoid flashing when 2 updates are // incoming in a very short period of time. It happens when ARC++ apps // creating bundled notifications.
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h index 67040800..0840971 100644 --- a/ash/system/unified/unified_system_tray.h +++ b/ash/system/unified/unified_system_tray.h
@@ -13,8 +13,6 @@ #include "ash/public/cpp/accelerators.h" #include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/tablet_mode_observer.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/time/time_view.h" #include "ash/system/tray/tray_background_view.h" #include "ash/system/unified/unified_system_tray_controller.h" #include "ash/system/unified/unified_system_tray_model.h" @@ -49,7 +47,6 @@ class NotificationIconsController; class PrivacyIndicatorsTrayItemView; class PrivacyScreenToastController; -class QuietModeView; class Shelf; class TrayBubbleView; class TrayItemView; @@ -74,7 +71,8 @@ : public TrayBackgroundView, public ShelfConfig::Observer, public UnifiedSystemTrayController::Observer, - public TabletModeObserver { + public TabletModeObserver, + public message_center::MessageCenterObserver { public: class Observer : public base::CheckedObserver { public: @@ -216,6 +214,9 @@ void OnTabletModeStarted() override; void OnTabletModeEnded() override; + // message_center::MessageCenterObserver: + void OnQuietModeChanged(bool in_quiet_mode) override; + // Gets called when an action is performed on the `DateTray`. void OnDateTrayActionPerformed(const ui::Event& event); @@ -309,7 +310,6 @@ NetworkTrayView* network_tray_view_ = nullptr; ChannelIndicatorView* channel_indicator_view_ = nullptr; - QuietModeView* quiet_mode_view_ = nullptr; // Contains all tray items views added to tray_container(). std::list<TrayItemView*> tray_items_;
diff --git a/ash/system/unified/unified_system_tray_unittest.cc b/ash/system/unified/unified_system_tray_unittest.cc index 1f1a6d9..d5f266bc 100644 --- a/ash/system/unified/unified_system_tray_unittest.cc +++ b/ash/system/unified/unified_system_tray_unittest.cc
@@ -6,7 +6,6 @@ #include "ash/accessibility/accessibility_controller_impl.h" #include "ash/constants/ash_features.h" -#include "ash/ime/ime_controller_impl.h" #include "ash/public/cpp/test/shell_test_api.h" #include "ash/root_window_controller.h" #include "ash/shelf/shelf.h" @@ -21,10 +20,8 @@ #include "ash/system/time/time_tray_item_view.h" #include "ash/system/time/time_view.h" #include "ash/system/unified/ime_mode_view.h" -#include "ash/system/unified/notification_counter_view.h" #include "ash/system/unified/unified_slider_bubble_controller.h" #include "ash/system/unified/unified_system_tray_bubble.h" -#include "ash/system/unified/unified_system_tray_controller.h" #include "ash/system/unified/unified_system_tray_view.h" #include "ash/test/ash_test_base.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" @@ -37,7 +34,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/display/display.h" #include "ui/display/screen.h" -#include "ui/events/event.h" #include "ui/events/event_constants.h" #include "ui/message_center/message_center.h" @@ -149,10 +145,6 @@ return GetPrimaryUnifiedSystemTray()->ime_mode_view_; } - QuietModeView* quiet_mode_view() { - return GetPrimaryUnifiedSystemTray()->quiet_mode_view_; - } - private: int id_ = 0; base::test::ScopedFeatureList feature_list_; @@ -685,23 +677,6 @@ ShelfConfig::Get()->GetShelfControlButtonColor(widget)); } -// Tests that the `quiet_mode_view_` is visible based on the system's quiet mode -// setting. -TEST_P(UnifiedSystemTrayTest, QuietModeViewVisibility) { - // `quiet_mode_view_` does not exist in `unified_system_tray_` if QsRevamp is - // not enabled. It is owned by `notification_icons_controller` in that case. - if (!IsQsRevampEnabled()) - return; - - auto* message_center = message_center::MessageCenter::Get(); - - message_center->SetQuietMode(false); - EXPECT_FALSE(quiet_mode_view()->GetVisible()); - - message_center->SetQuietMode(true); - EXPECT_TRUE(quiet_mode_view()->GetVisible()); -} - // Tests that the bubble automatically hides if it is visible when another // bubble becomes visible, and otherwise does not automatically show or hide. TEST_P(UnifiedSystemTrayTest, BubbleHideBehavior) {
diff --git a/ash/webui/diagnostics_ui/resources/keyboard_tester.html b/ash/webui/diagnostics_ui/resources/keyboard_tester.html index 9f3baef..7717a3b 100644 --- a/ash/webui/diagnostics_ui/resources/keyboard_tester.html +++ b/ash/webui/diagnostics_ui/resources/keyboard_tester.html
@@ -1,13 +1,13 @@ <style include="diagnostics-shared"> @media (min-width: 600px) { :host { - --cr-dialog-width: 416px; + --cr-dialog-width: 504px; } } @media (min-width: 768px) { :host { - --cr-dialog-width: 512px; + --cr-dialog-width: 636px; } }
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc index 8551a4c..84ca5aa6 100644 --- a/ash/webui/personalization_app/personalization_app_ui.cc +++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -307,7 +307,7 @@ "script-src chrome://resources chrome://test chrome://webui-test " "'self';"); - // TODO(crbug.com/1098690): Trusted Type Polymer + // TODO(crbug.com/1400799): Enable TrustedTypes. source->DisableTrustedTypesCSP(); AddResources(source);
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn index 0a6bb25..d8e0a94 100644 --- a/base/allocator/partition_allocator/BUILD.gn +++ b/base/allocator/partition_allocator/BUILD.gn
@@ -393,6 +393,7 @@ "BACKUP_REF_PTR_POISON_OOB_PTR=$backup_ref_ptr_poison_oob_ptr", "PUT_REF_COUNT_IN_PREVIOUS_SLOT=$put_ref_count_in_previous_slot", "USE_ASAN_BACKUP_REF_PTR=$use_asan_backup_ref_ptr", + "USE_ASAN_UNOWNED_PTR=$use_asan_unowned_ptr", "ENABLE_GWP_ASAN_SUPPORT=$_enable_gwp_asan_support", # Not to be used directly - instead use
diff --git a/base/allocator/partition_allocator/partition_alloc.gni b/base/allocator/partition_allocator/partition_alloc.gni index cf598e18..88915bd5 100644 --- a/base/allocator/partition_allocator/partition_alloc.gni +++ b/base/allocator/partition_allocator/partition_alloc.gni
@@ -83,6 +83,9 @@ # research. ASAN BRP is not supported in Chromium-external builds. use_asan_backup_ref_ptr = build_with_chromium && is_asan && (is_win || is_android || is_linux) + + # Use probe-on-destruct unowned ptr detection with ASAN. + use_asan_unowned_ptr = false } # AsanBackupRefPtr is not supported outside Chromium. The implementation is @@ -96,6 +99,11 @@ !enable_backup_ref_ptr_support || !use_asan_backup_ref_ptr, "Both BackupRefPtr and AsanBackupRefPtr can't be enabled at the same time") +# AsanBackupRefPtr and AsanUnownedPtr are mutually exclusive variants of raw_ptr. +assert( + !use_asan_unowned_ptr || !use_asan_backup_ref_ptr, + "Both AsanUnownedPtr and AsanBackupRefPtr can't be enabled at the same time") + assert(!use_asan_backup_ref_ptr || is_asan, "AsanBackupRefPtr requires AddressSanitizer") @@ -151,6 +159,7 @@ enable_backup_ref_ptr_support = false enable_mte_checked_ptr_support = false use_asan_backup_ref_ptr = false + use_asan_unowned_ptr = false put_ref_count_in_previous_slot = false enable_backup_ref_ptr_slow_checks = false enable_dangling_raw_ptr_checks = false @@ -187,6 +196,9 @@ enable_backup_ref_ptr_support || !backup_ref_ptr_poison_oob_ptr, "Can't enable poisoning for OOB pointers if BackupRefPtr isn't enabled at all") +assert(!use_asan_unowned_ptr || is_asan, + "AsanUnownedPtr requires AddressSanitizer") + declare_args() { enable_pkeys = is_linux && target_cpu == "x64" }
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h index f2273362..4191f0e4 100644 --- a/base/memory/raw_ptr.h +++ b/base/memory/raw_ptr.h
@@ -817,6 +817,90 @@ }; #endif // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) +#if BUILDFLAG(USE_ASAN_UNOWNED_PTR) + +struct AsanUnownedPtrImpl { + // Wraps a pointer. + template <typename T> + static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) { + return ptr; + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + template <typename T> + static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) { + ProbeForLowSeverityLifetimeIssue(wrapped_ptr); + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function is allowed to crash on nullptr. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { + // ASAN will catch use of dereferenced ptr without additional probing. + return wrapped_ptr; + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function must handle nullptr gracefully. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { + ProbeForLowSeverityLifetimeIssue(wrapped_ptr); + return wrapped_ptr; + } + + // Unwraps the pointer, without making an assertion on whether memory was + // freed or not. + template <typename T> + static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { + return wrapped_ptr; + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + // Note, this cast may change the address if upcasting to base that lies in + // the middle of the derived object. + return wrapped_ptr; + } + + // Advance the wrapped pointer by `delta_elems`. + template <typename T, + typename Z, + typename = std::enable_if_t<offset_type<Z>, void>> + static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) { + return wrapped_ptr + delta_elems; + } + + template <typename T> + static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1, + T* wrapped_ptr2) { + return wrapped_ptr1 - wrapped_ptr2; + } + + // Returns a copy of a wrapped pointer, without making an assertion on whether + // memory was freed or not. + template <typename T> + static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { + return wrapped_ptr; + } + + template <typename T> + static void ProbeForLowSeverityLifetimeIssue(T* wrapped_ptr) { + if (wrapped_ptr) { + reinterpret_cast<const volatile uint8_t*>(wrapped_ptr)[0]; + } + } + + // This is for accounting only, used by unit tests. + static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {} + static PA_ALWAYS_INLINE void IncrementLessCountForTest() {} + static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} +}; + +#endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR) + template <class Super> struct RawPtrCountingImplWrapperForTest : public raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl { @@ -985,6 +1069,10 @@ using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/true>; #elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) using Impl = internal::AsanBackupRefPtrImpl; +#elif BUILDFLAG(USE_ASAN_UNOWNED_PTR) + // No special bookkeeping required for this case, just treat these + // as ordinary pointers. + using Impl = internal::RawPtrNoOpImpl; #elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) using Impl = internal::MTECheckedPtrImpl< internal::MTECheckedPtrImplPartitionAllocSupport>; @@ -999,6 +1087,8 @@ using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/false>; #elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) using Impl = internal::AsanBackupRefPtrImpl; +#elif BUILDFLAG(USE_ASAN_UNOWNED_PTR) + using Impl = internal::AsanUnownedPtrImpl; #elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) using Impl = internal::MTECheckedPtrImpl< internal::MTECheckedPtrImplPartitionAllocSupport>; @@ -1060,7 +1150,7 @@ static_assert(raw_ptr_traits::IsSupportedType<T>::value, "raw_ptr<T> doesn't work with this kind of pointee type T"); -#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) +#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || BUILDFLAG(USE_ASAN_UNOWNED_PTR) // BackupRefPtr requires a non-trivial default constructor, destructor, etc. constexpr PA_ALWAYS_INLINE raw_ptr() noexcept : wrapped_ptr_(nullptr) {} @@ -1103,7 +1193,8 @@ wrapped_ptr_ = nullptr; } -#else // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) +#else // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || + // BUILDFLAG(USE_ASAN_UNOWNED_PTR) // raw_ptr can be trivially default constructed (leaving |wrapped_ptr_| // uninitialized). This is needed for compatibility with raw pointers. @@ -1124,7 +1215,8 @@ PA_ALWAYS_INLINE ~raw_ptr() noexcept = default; -#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) +#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || + // BUILDFLAG(USE_ASAN_UNOWNED_PTR) // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr. // NOLINTNEXTLINE(google-explicit-constructor)
diff --git a/base/memory/raw_ptr_unittest.cc b/base/memory/raw_ptr_unittest.cc index 034232ca..9ce62e1 100644 --- a/base/memory/raw_ptr_unittest.cc +++ b/base/memory/raw_ptr_unittest.cc
@@ -56,7 +56,8 @@ static_assert(sizeof(raw_ptr<std::string>) == sizeof(std::string*), "raw_ptr shouldn't add memory overhead"); -#if !BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) +#if !BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && \ + !BUILDFLAG(USE_ASAN_UNOWNED_PTR) // |is_trivially_copyable| assertion means that arrays/vectors of raw_ptr can // be copied by memcpy. static_assert(std::is_trivially_copyable<raw_ptr<void>>::value,
diff --git a/base/memory/raw_ref.h b/base/memory/raw_ref.h index 71eb6b0..669acee 100644 --- a/base/memory/raw_ref.h +++ b/base/memory/raw_ref.h
@@ -83,6 +83,9 @@ #if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) std::is_same_v<Impl, internal::AsanBackupRefPtrImpl> || #endif // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) +#if BUILDFLAG(USE_ASAN_UNOWNED_PTR) + std::is_same_v<Impl, internal::AsanUnownedPtrImpl> || +#endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR) std::is_same_v<Impl, internal::RawPtrNoOpImpl>; public:
diff --git a/base/win/sid.cc b/base/win/sid.cc index 4e48268c..f0904ac3 100644 --- a/base/win/sid.cc +++ b/base/win/sid.cc
@@ -7,25 +7,56 @@ #include <windows.h> #include <sddl.h> +#include <stdint.h> #include <stdlib.h> +#include <algorithm> #include <iterator> +#include <map> #include <utility> #include "base/check.h" -#include "base/notreached.h" +#include "base/no_destructor.h" #include "base/rand_util.h" +#include "base/strings/string_util_win.h" #include "base/win/scoped_handle.h" #include "base/win/scoped_localalloc.h" #include "base/win/windows_version.h" +#include "third_party/boringssl/src/include/openssl/crypto.h" +#include "third_party/boringssl/src/include/openssl/sha.h" -namespace base { -namespace win { +namespace base::win { namespace { -absl::optional<long> // NOLINT(runtime/int) -WellKnownCapabilityToRid(WellKnownCapability capability) { +template <typename Iterator> +Sid FromSubAuthorities(const SID_IDENTIFIER_AUTHORITY& identifier_authority, + size_t sub_authority_count, + Iterator sub_authorities) { + DCHECK(sub_authority_count <= SID_MAX_SUB_AUTHORITIES); + BYTE sid_buffer[SECURITY_MAX_SID_SIZE]; + SID* sid = reinterpret_cast<SID*>(sid_buffer); + sid->Revision = SID_REVISION; + sid->SubAuthorityCount = static_cast<UCHAR>(sub_authority_count); + sid->IdentifierAuthority = identifier_authority; + for (size_t index = 0; index < sub_authority_count; ++index) { + sid->SubAuthority[index] = static_cast<DWORD>(*sub_authorities++); + } + DCHECK(::IsValidSid(sid)); + return *Sid::FromPSID(sid); +} + +Sid FromSubAuthorities(const SID_IDENTIFIER_AUTHORITY& identifier_authority, + std::initializer_list<int32_t> sub_authorities) { + return FromSubAuthorities(identifier_authority, sub_authorities.size(), + sub_authorities.begin()); +} + +Sid FromNtAuthority(std::initializer_list<int32_t> sub_authorities) { + return FromSubAuthorities(SECURITY_NT_AUTHORITY, sub_authorities); +} + +int32_t WellKnownCapabilityToRid(WellKnownCapability capability) { switch (capability) { case WellKnownCapability::kInternetClient: return SECURITY_CAPABILITY_INTERNET_CLIENT; @@ -52,97 +83,6 @@ case WellKnownCapability::kContacts: return SECURITY_CAPABILITY_CONTACTS; } - return absl::nullopt; -} - -absl::optional<WELL_KNOWN_SID_TYPE> WellKnownSidToEnum(WellKnownSid sid) { - switch (sid) { - case WellKnownSid::kNull: - return WinNullSid; - case WellKnownSid::kWorld: - return WinWorldSid; - case WellKnownSid::kCreatorOwner: - return WinCreatorOwnerSid; - case WellKnownSid::kNetwork: - return WinNetworkSid; - case WellKnownSid::kBatch: - return WinBatchSid; - case WellKnownSid::kInteractive: - return WinInteractiveSid; - case WellKnownSid::kService: - return WinServiceSid; - case WellKnownSid::kAnonymous: - return WinAnonymousSid; - case WellKnownSid::kSelf: - return WinSelfSid; - case WellKnownSid::kAuthenticatedUser: - return WinAuthenticatedUserSid; - case WellKnownSid::kRestricted: - return WinRestrictedCodeSid; - case WellKnownSid::kLocalSystem: - return WinLocalSystemSid; - case WellKnownSid::kLocalService: - return WinLocalServiceSid; - case WellKnownSid::kNetworkService: - return WinNetworkServiceSid; - case WellKnownSid::kBuiltinAdministrators: - return WinBuiltinAdministratorsSid; - case WellKnownSid::kBuiltinUsers: - return WinBuiltinUsersSid; - case WellKnownSid::kBuiltinGuests: - return WinBuiltinGuestsSid; - case WellKnownSid::kUntrustedLabel: - return WinUntrustedLabelSid; - case WellKnownSid::kLowLabel: - return WinLowLabelSid; - case WellKnownSid::kMediumLabel: - return WinMediumLabelSid; - case WellKnownSid::kHighLabel: - return WinHighLabelSid; - case WellKnownSid::kSystemLabel: - return WinSystemLabelSid; - case WellKnownSid::kWriteRestricted: - return WinWriteRestrictedCodeSid; - case WellKnownSid::kCreatorOwnerRights: - return WinCreatorOwnerRightsSid; - case WellKnownSid::kAllApplicationPackages: - return WinBuiltinAnyPackageSid; - case WellKnownSid::kAllRestrictedApplicationPackages: - // This should be handled by FromKnownSid. - NOTREACHED(); - break; - } - return absl::nullopt; -} - -absl::optional<Sid> FromSubAuthorities( - PSID_IDENTIFIER_AUTHORITY identifier_authority, - BYTE sub_authority_count, - PDWORD sub_authorities) { - BYTE sid[SECURITY_MAX_SID_SIZE]; - if (!::InitializeSid(sid, identifier_authority, sub_authority_count)) - return absl::nullopt; - - for (DWORD index = 0; index < sub_authority_count; ++index) { - PDWORD sub_authority = ::GetSidSubAuthority(sid, index); - *sub_authority = sub_authorities[index]; - } - return Sid::FromPSID(sid); -} - -template <typename T> -absl::optional<std::vector<Sid>> FromVector( - const std::vector<T>& values, - absl::optional<Sid> (*create_sid)(T)) { - std::vector<Sid> converted_sids; - converted_sids.reserve(values.size()); - for (T value : values) { - auto sid = create_sid(value); - if (!sid) - return absl::nullopt; - converted_sids.push_back(std::move(*sid)); - } - return converted_sids; } } // namespace @@ -154,94 +94,128 @@ } absl::optional<Sid> Sid::FromKnownCapability(WellKnownCapability capability) { - absl::optional<long> capability_rid = // NOLINT(runtime/int) - WellKnownCapabilityToRid(capability); - if (!capability_rid) - return absl::nullopt; - SID_IDENTIFIER_AUTHORITY capability_authority = { - SECURITY_APP_PACKAGE_AUTHORITY}; - DWORD sub_authorities[] = {SECURITY_CAPABILITY_BASE_RID, - static_cast<DWORD>(*capability_rid)}; - return FromSubAuthorities(&capability_authority, std::size(sub_authorities), - sub_authorities); + int32_t capability_rid = WellKnownCapabilityToRid(capability); + return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY, + {SECURITY_CAPABILITY_BASE_RID, capability_rid}); } absl::optional<Sid> Sid::FromNamedCapability(const wchar_t* capability_name) { - DCHECK_GE(GetVersion(), Version::WIN10); - - if (!capability_name || !*capability_name) - return absl::nullopt; - - typedef decltype( - ::DeriveCapabilitySidsFromName)* DeriveCapabilitySidsFromNameFunc; - static const DeriveCapabilitySidsFromNameFunc derive_capability_sids = - []() -> DeriveCapabilitySidsFromNameFunc { - HMODULE module = GetModuleHandle(L"api-ms-win-security-base-l1-2-2.dll"); - if (!module) - return nullptr; - - return reinterpret_cast<DeriveCapabilitySidsFromNameFunc>( - ::GetProcAddress(module, "DeriveCapabilitySidsFromName")); - }(); - if (!derive_capability_sids) - return absl::nullopt; - - // Pre-reserve some space for SID deleters. - std::vector<ScopedLocalAlloc> deleter_list; - deleter_list.reserve(16); - - PSID* capability_groups = nullptr; - DWORD capability_group_count = 0; - PSID* capability_sids = nullptr; - DWORD capability_sid_count = 0; - - if (!derive_capability_sids(capability_name, &capability_groups, - &capability_group_count, &capability_sids, - &capability_sid_count)) { + if (!capability_name || !*capability_name) { return absl::nullopt; } + static const base::NoDestructor<std::map<std::wstring, WellKnownCapability>> + known_capabilities( + {{L"INTERNETCLIENT", WellKnownCapability::kInternetClient}, + {L"INTERNETCLIENTSERVER", + WellKnownCapability::kInternetClientServer}, + {L"PRIVATENETWORKCLIENTSERVER", + WellKnownCapability::kPrivateNetworkClientServer}, + {L"PICTURESLIBRARY", WellKnownCapability::kPicturesLibrary}, + {L"VIDEOSLIBRARY", WellKnownCapability::kVideosLibrary}, + {L"MUSICLIBRARY", WellKnownCapability::kMusicLibrary}, + {L"DOCUMENTSLIBRARY", WellKnownCapability::kDocumentsLibrary}, + {L"ENTERPRISEAUTHENTICATION", + WellKnownCapability::kEnterpriseAuthentication}, + {L"SHAREDUSERCERTIFICATES", + WellKnownCapability::kSharedUserCertificates}, + {L"REMOVABLESTORAGE", WellKnownCapability::kRemovableStorage}, + {L"APPOINTMENTS", WellKnownCapability::kAppointments}, + {L"CONTACTS", WellKnownCapability::kContacts}}); - deleter_list.emplace_back(capability_groups); - deleter_list.emplace_back(capability_sids); - - for (DWORD i = 0; i < capability_group_count; ++i) { - deleter_list.emplace_back(capability_groups[i]); + std::wstring cap_upper = base::ToUpperASCII(capability_name); + auto known_cap = known_capabilities->find(cap_upper); + if (known_cap != known_capabilities->end()) { + return FromKnownCapability(known_cap->second); } - for (DWORD i = 0; i < capability_sid_count; ++i) { - deleter_list.emplace_back(capability_sids[i]); - } + CRYPTO_library_init(); + static_assert((SHA256_DIGEST_LENGTH / sizeof(DWORD)) == + SECURITY_APP_PACKAGE_RID_COUNT); + DWORD rids[(SHA256_DIGEST_LENGTH / sizeof(DWORD)) + 2]; + rids[0] = SECURITY_CAPABILITY_BASE_RID; + rids[1] = SECURITY_CAPABILITY_APP_RID; - if (capability_sid_count < 1) - return absl::nullopt; - - return FromPSID(capability_sids[0]); + SHA256(reinterpret_cast<const uint8_t*>(cap_upper.c_str()), + cap_upper.size() * sizeof(wchar_t), + reinterpret_cast<uint8_t*>(&rids[2])); + return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY, std::size(rids), + rids); } absl::optional<Sid> Sid::FromKnownSid(WellKnownSid type) { - if (type == WellKnownSid::kAllRestrictedApplicationPackages) { - SID_IDENTIFIER_AUTHORITY package_authority = { - SECURITY_APP_PACKAGE_AUTHORITY}; - DWORD sub_authorities[] = {SECURITY_APP_PACKAGE_BASE_RID, - SECURITY_BUILTIN_PACKAGE_ANY_RESTRICTED_PACKAGE}; - return FromSubAuthorities(&package_authority, 2, sub_authorities); + switch (type) { + case WellKnownSid::kNull: + return FromSubAuthorities(SECURITY_NULL_SID_AUTHORITY, + {SECURITY_NULL_RID}); + case WellKnownSid::kWorld: + return FromSubAuthorities(SECURITY_WORLD_SID_AUTHORITY, + {SECURITY_WORLD_RID}); + case WellKnownSid::kCreatorOwner: + return FromSubAuthorities(SECURITY_CREATOR_SID_AUTHORITY, + {SECURITY_CREATOR_OWNER_RID}); + case WellKnownSid::kCreatorOwnerRights: + return FromSubAuthorities(SECURITY_CREATOR_SID_AUTHORITY, + {SECURITY_CREATOR_OWNER_RIGHTS_RID}); + case WellKnownSid::kNetwork: + return FromNtAuthority({SECURITY_NETWORK_RID}); + case WellKnownSid::kBatch: + return FromNtAuthority({SECURITY_BATCH_RID}); + case WellKnownSid::kInteractive: + return FromNtAuthority({SECURITY_INTERACTIVE_RID}); + case WellKnownSid::kService: + return FromNtAuthority({SECURITY_SERVICE_RID}); + case WellKnownSid::kAnonymous: + return FromNtAuthority({SECURITY_ANONYMOUS_LOGON_RID}); + case WellKnownSid::kSelf: + return FromNtAuthority({SECURITY_PRINCIPAL_SELF_RID}); + case WellKnownSid::kAuthenticatedUser: + return FromNtAuthority({SECURITY_AUTHENTICATED_USER_RID}); + case WellKnownSid::kRestricted: + return FromNtAuthority({SECURITY_RESTRICTED_CODE_RID}); + case WellKnownSid::kWriteRestricted: + return FromNtAuthority({SECURITY_WRITE_RESTRICTED_CODE_RID}); + case WellKnownSid::kLocalSystem: + return FromNtAuthority({SECURITY_LOCAL_SYSTEM_RID}); + case WellKnownSid::kLocalService: + return FromNtAuthority({SECURITY_LOCAL_SERVICE_RID}); + case WellKnownSid::kNetworkService: + return FromNtAuthority({SECURITY_NETWORK_SERVICE_RID}); + case WellKnownSid::kBuiltinAdministrators: + return FromNtAuthority( + {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS}); + case WellKnownSid::kBuiltinUsers: + return FromNtAuthority( + {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS}); + case WellKnownSid::kBuiltinGuests: + return FromNtAuthority( + {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS}); + case WellKnownSid::kUntrustedLabel: + return FromIntegrityLevel(SECURITY_MANDATORY_UNTRUSTED_RID); + case WellKnownSid::kLowLabel: + return FromIntegrityLevel(SECURITY_MANDATORY_LOW_RID); + case WellKnownSid::kMediumLabel: + return FromIntegrityLevel(SECURITY_MANDATORY_MEDIUM_RID); + case WellKnownSid::kHighLabel: + return FromIntegrityLevel(SECURITY_MANDATORY_HIGH_RID); + case WellKnownSid::kSystemLabel: + return FromIntegrityLevel(SECURITY_MANDATORY_SYSTEM_RID); + case WellKnownSid::kAllApplicationPackages: + return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY, + {SECURITY_APP_PACKAGE_BASE_RID, + SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE}); + case WellKnownSid::kAllRestrictedApplicationPackages: + return FromSubAuthorities( + SECURITY_APP_PACKAGE_AUTHORITY, + {SECURITY_APP_PACKAGE_BASE_RID, + SECURITY_BUILTIN_PACKAGE_ANY_RESTRICTED_PACKAGE}); } - - BYTE sid[SECURITY_MAX_SID_SIZE]; - DWORD size_sid = SECURITY_MAX_SID_SIZE; - absl::optional<WELL_KNOWN_SID_TYPE> known_sid = WellKnownSidToEnum(type); - if (!known_sid) - return absl::nullopt; - if (!::CreateWellKnownSid(*known_sid, nullptr, sid, &size_sid)) - return absl::nullopt; - - return Sid(sid, size_sid); } absl::optional<Sid> Sid::FromSddlString(const wchar_t* sddl_sid) { PSID psid = nullptr; if (!::ConvertStringSidToSid(sddl_sid, &psid)) return absl::nullopt; - return FromPSID(TakeLocalAlloc(psid).get()); + auto psid_alloc = TakeLocalAlloc(psid); + return FromPSID(psid_alloc.get()); } absl::optional<Sid> Sid::FromPSID(PSID sid) { @@ -252,37 +226,62 @@ } absl::optional<Sid> Sid::GenerateRandomSid() { - SID_IDENTIFIER_AUTHORITY package_authority = {SECURITY_NULL_SID_AUTHORITY}; DWORD sub_authorities[4] = {}; RandBytes(&sub_authorities, sizeof(sub_authorities)); - return FromSubAuthorities(&package_authority, _countof(sub_authorities), - sub_authorities); + return FromSubAuthorities(SECURITY_NULL_SID_AUTHORITY, + std::size(sub_authorities), sub_authorities); } absl::optional<Sid> Sid::FromIntegrityLevel(DWORD integrity_level) { - SID_IDENTIFIER_AUTHORITY package_authority = { - SECURITY_MANDATORY_LABEL_AUTHORITY}; - return FromSubAuthorities(&package_authority, 1, &integrity_level); + return FromSubAuthorities(SECURITY_MANDATORY_LABEL_AUTHORITY, 1, + &integrity_level); } absl::optional<std::vector<Sid>> Sid::FromSddlStringVector( const std::vector<const wchar_t*>& sddl_sids) { - return FromVector(sddl_sids, Sid::FromSddlString); + std::vector<Sid> converted_sids; + converted_sids.reserve(sddl_sids.size()); + for (const wchar_t* sddl_sid : sddl_sids) { + absl::optional<Sid> sid = FromSddlString(sddl_sid); + if (!sid) + return absl::nullopt; + converted_sids.push_back(std::move(*sid)); + } + return converted_sids; } absl::optional<std::vector<Sid>> Sid::FromNamedCapabilityVector( const std::vector<const wchar_t*>& capability_names) { - return FromVector(capability_names, Sid::FromNamedCapability); + std::vector<Sid> converted_sids; + converted_sids.reserve(capability_names.size()); + for (const wchar_t* name : capability_names) { + absl::optional<Sid> sid = FromNamedCapability(name); + if (!sid) + return absl::nullopt; + converted_sids.push_back(std::move(*sid)); + } + return converted_sids; } absl::optional<std::vector<Sid>> Sid::FromKnownCapabilityVector( const std::vector<WellKnownCapability>& capabilities) { - return FromVector(capabilities, Sid::FromKnownCapability); + std::vector<Sid> sids; + std::transform(capabilities.cbegin(), capabilities.cend(), + std::back_inserter(sids), + [](WellKnownCapability known_cap) -> Sid { + return *Sid::FromKnownCapability(known_cap); + }); + return sids; } absl::optional<std::vector<Sid>> Sid::FromKnownSidVector( - const std::vector<WellKnownSid>& sids) { - return FromVector(sids, Sid::FromKnownSid); + const std::vector<WellKnownSid>& known_sids) { + std::vector<Sid> sids; + std::transform(known_sids.cbegin(), known_sids.cend(), + std::back_inserter(sids), [](WellKnownSid known_sid) -> Sid { + return *Sid::FromKnownSid(known_sid); + }); + return sids; } Sid::Sid(Sid&& sid) = default; @@ -299,7 +298,8 @@ LPWSTR sid = nullptr; if (!::ConvertSidToStringSid(GetPSID(), &sid)) return absl::nullopt; - return TakeLocalAlloc(sid).get(); + auto sid_ptr = TakeLocalAlloc(sid); + return sid_ptr.get(); } Sid Sid::Clone() const { @@ -318,5 +318,4 @@ return !(operator==(sid)); } -} // namespace win -} // namespace base +} // namespace base::win
diff --git a/base/win/sid_unittest.cc b/base/win/sid_unittest.cc index 70bd201..98ec8b2b 100644 --- a/base/win/sid_unittest.cc +++ b/base/win/sid_unittest.cc
@@ -74,16 +74,49 @@ return TestSidVector(Sid::FromSddlStringVector(sddl), sddl); } +bool EqualNamedCapSid(const Sid& sid, const std::wstring& capability_name) { + typedef decltype(::DeriveCapabilitySidsFromName)* + DeriveCapabilitySidsFromNameFunc; + static const DeriveCapabilitySidsFromNameFunc derive_capability_sids = + []() -> DeriveCapabilitySidsFromNameFunc { + HMODULE module = GetModuleHandle(L"api-ms-win-security-base-l1-2-2.dll"); + CHECK(module); + return reinterpret_cast<DeriveCapabilitySidsFromNameFunc>( + ::GetProcAddress(module, "DeriveCapabilitySidsFromName")); + }(); + CHECK(derive_capability_sids); + + // Pre-reserve some space for SID deleters. + std::vector<base::win::ScopedLocalAlloc> deleter_list; + deleter_list.reserve(16); + + PSID* capability_groups = nullptr; + DWORD capability_group_count = 0; + PSID* capability_sids = nullptr; + DWORD capability_sid_count = 0; + + CHECK(derive_capability_sids(capability_name.c_str(), &capability_groups, + &capability_group_count, &capability_sids, + &capability_sid_count)); + deleter_list.emplace_back(capability_groups); + deleter_list.emplace_back(capability_sids); + + for (DWORD i = 0; i < capability_group_count; ++i) { + deleter_list.emplace_back(capability_groups[i]); + } + for (DWORD i = 0; i < capability_sid_count; ++i) { + deleter_list.emplace_back(capability_sids[i]); + } + + CHECK_GE(capability_sid_count, 1U); + return sid.Equal(capability_sids[0]); +} + struct KnownCapabilityTestEntry { WellKnownCapability capability; const wchar_t* sddl_sid; }; -struct NamedCapabilityTestEntry { - const wchar_t* capability_name; - const wchar_t* sddl_sid; -}; - struct KnownSidTestEntry { WellKnownSid sid; WELL_KNOWN_SID_TYPE well_known_sid; @@ -135,28 +168,25 @@ } TEST(SidTest, NamedCapability) { - if (GetVersion() < Version::WIN10_RS2) - return; + const std::wstring capabilities[] = {L"InternetClient", + L"InternetClientServer", + L"PrivateNetworkClientServer", + L"PicturesLibrary", + L"VideosLibrary", + L"MusicLibrary", + L"DocumentsLibrary", + L"EnterpriseAuthentication", + L"SharedUserCertificates", + L"RemovableStorage", + L"Appointments", + L"Contacts", + L"registryRead", + L"lpacCryptoServices"}; - EXPECT_FALSE(Sid::FromNamedCapability(nullptr)); - EXPECT_FALSE(Sid::FromNamedCapability(L"")); - - const NamedCapabilityTestEntry capabilities[] = { - {L"internetClient", L"S-1-15-3-1"}, - {L"internetClientServer", L"S-1-15-3-2"}, - {L"registryRead", - L"S-1-15-3-1024-1065365936-1281604716-3511738428-" - "1654721687-432734479-3232135806-4053264122-3456934681"}, - {L"lpacCryptoServices", - L"S-1-15-3-1024-3203351429-2120443784-2872670797-" - "1918958302-2829055647-4275794519-765664414-2751773334"}, - {L"enterpriseAuthentication", L"S-1-15-3-8"}, - {L"privateNetworkClientServer", L"S-1-15-3-3"}}; - - for (auto capability : capabilities) { - EXPECT_TRUE(EqualSid(Sid::FromNamedCapability(capability.capability_name), - capability.sddl_sid)) - << "Named Capability: " << capability.sddl_sid; + for (const std::wstring& capability : capabilities) { + EXPECT_TRUE(EqualNamedCapSid(*Sid::FromNamedCapability(capability.c_str()), + capability)) + << "Named Capability: " << capability; } } @@ -254,28 +284,24 @@ } TEST(SidTest, FromNamedCapabilityVector) { - if (GetVersion() < Version::WIN10_RS2) - return; - std::vector<const wchar_t*> capabilities = {L"internetClient", - L"internetClientServer", + std::vector<const wchar_t*> capabilities = {L"InternetClient", + L"InternetClientServer", + L"PrivateNetworkClientServer", + L"PicturesLibrary", + L"VideosLibrary", + L"MusicLibrary", + L"DocumentsLibrary", + L"EnterpriseAuthentication", + L"SharedUserCertificates", + L"RemovableStorage", + L"Appointments", + L"Contacts", L"registryRead", - L"lpacCryptoServices", - L"enterpriseAuthentication", - L"privateNetworkClientServer"}; - std::vector<const wchar_t*> sddl_caps = { - L"S-1-15-3-1", - L"S-1-15-3-2", - L"S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-" - L"3232135806-4053264122-3456934681", - L"S-1-15-3-1024-3203351429-2120443784-2872670797-1918958302-2829055647-" - L"4275794519-765664414-2751773334", - L"S-1-15-3-8", - L"S-1-15-3-3"}; - ASSERT_TRUE( - TestSidVector(Sid::FromNamedCapabilityVector(capabilities), sddl_caps)); - ASSERT_FALSE(Sid::FromNamedCapabilityVector({L""})); - ASSERT_FALSE(Sid::FromNamedCapabilityVector({L"abc", nullptr})); - ASSERT_TRUE(Sid::FromNamedCapabilityVector({})); + L"lpacCryptoServices"}; + + ASSERT_TRUE(ranges::equal(*Sid::FromNamedCapabilityVector(capabilities), + capabilities, EqualNamedCapSid)); + EXPECT_EQ(Sid::FromNamedCapabilityVector({})->size(), 0U); } TEST(SidTest, FromKnownCapabilityVector) {
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 44e04b9..249ad4f2 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision vars in //DEPS. - libcxx_revision = "19ffb9c00636bcabb6c6ce76ccaa4370583d3649" + libcxx_revision = "2fc3d704672fbd3e85fad8492d39e02d49412891" }
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index 4978bf9..e1cfd7c 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -366,6 +366,8 @@ "java/res/drawable/adaptive_toolbar_preference_header.xml", "java/res/drawable/arrow_down.xml", "java/res/drawable/arrow_up.xml", + "java/res/drawable/bg_circle_new_tab_button_detached.xml", + "java/res/drawable/bg_circle_new_tab_button_folio.xml", "java/res/drawable/bg_tabstrip_tab_divider.xml", "java/res/drawable/bg_white_dialog.xml", "java/res/drawable/bookmark_save_flow_ripple.xml",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index e507315..63d7231 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -294,7 +294,6 @@ "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceRecognitionHandlerTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentBottomSheetTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentControllerTest.java", - "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModalTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceTest.java",
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java index 63282f9..17d91d5 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
@@ -184,6 +184,12 @@ void setLaunchOrigin(@NewTabPageLaunchOrigin int launchOrigin); /** + * Resets the scroll position. This is called when Start surface is showing but not via back + * operations. + */ + void resetScrollPosition(); + + /** * Called by the TabSwitcherLayout when the system back button is pressed. * @return Whether or not the TabSwitcher consumed the event. */
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java index f51bf5b..d9760264 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -508,6 +508,11 @@ } @Override + public void resetScrollPosition() { + mStartSurfaceMediator.resetScrollPosition(); + } + + @Override public boolean onBackPressed() { return mStartSurfaceMediator.onBackPressed(); }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index 5e81873..a3a6aeb 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -512,14 +512,6 @@ mIsHomepageShown = true; notifyShowStateChange(); - // TODO(crbug.com/1347089): When entering the Start surface by tapping back button or other - // back gestures, we shouldn't reset the scrolling position. Maybe we could add a boolean - // |mResetPosition| and set it as false only when this method is called because of back - // actions. - mPropertyModel.set(RESET_TASK_SURFACE_HEADER_SCROLL_POSITION, true); - mPropertyModel.set(RESET_FEED_SURFACE_SCROLL_POSITION, true); - StartSurfaceUserData.getInstance().saveFeedInstanceState(null); - mIsIncognito = mTabModelSelector.isIncognitoSelected(); mPropertyModel.set(IS_INCOGNITO, mIsIncognito); setMVTilesVisibility(!mIsIncognito); @@ -680,6 +672,14 @@ } } + void resetScrollPosition() { + if (mPropertyModel == null) return; + + mPropertyModel.set(RESET_TASK_SURFACE_HEADER_SCROLL_POSITION, true); + mPropertyModel.set(RESET_FEED_SURFACE_SCROLL_POSITION, true); + StartSurfaceUserData.getInstance().saveFeedInstanceState(null); + } + // TODO(crbug.com/1115757): After crrev.com/c/2315823, Overview state and Startsurface state are // two different things, audit the wording usage and see if we can rename this method to // setStartSurfaceStateInternal. @@ -687,10 +687,7 @@ if (mStartSurfaceState == StartSurfaceState.SHOWING_HOMEPAGE) { // When entering the Start surface by tapping home button or new tab page, we need to // reset the scrolling position. - mPropertyModel.set(RESET_TASK_SURFACE_HEADER_SCROLL_POSITION, true); - mPropertyModel.set(RESET_FEED_SURFACE_SCROLL_POSITION, true); - StartSurfaceUserData.getInstance().saveFeedInstanceState(null); - + resetScrollPosition(); } else if (mStartSurfaceState == StartSurfaceState.SHOWING_TABSWITCHER) { maybeDestroyFeedPlaceholder(); // Set secondary surface visible to make sure tab list recyclerview is updated in time
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 00bf6708..6db1704f 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -667,8 +667,6 @@ @Feature({"StartSurface"}) @CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS}) public void testShow_SingleAsHomepage_ResetScrollPosition() { - assumeTrue("https://crbug.com/1385547 - Disable for NoInstant.", mUseInstantStart); - if (!mImmediateReturn) { StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); } @@ -699,6 +697,40 @@ @Test @MediumTest @Feature({"StartSurface"}) + @EnableFeatures(ChromeFeatureList.START_SURFACE_REFACTOR) + @CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS}) + public void testShow_SingleAsHomepage_DoNotResetScrollPositionFromBack() { + assumeTrue(mImmediateReturn); + + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + StartSurfaceTestUtils.waitForStartSurfaceVisible( + mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta); + TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); + + // Scroll the toolbar. + StartSurfaceTestUtils.scrollToolbarAndVerify(cta); + AppBarLayout taskSurfaceHeader = cta.findViewById(R.id.task_surface_header); + assertNotEquals(taskSurfaceHeader.getBottom(), taskSurfaceHeader.getHeight()); + + // Verifies the case of scrolling Start surface -> MV tile -> tapping back -> + // Start surface. The Start surface should not reset its scroll position. + StartSurfaceTestUtils.launchFirstMVTile(cta, 1); + Assert.assertEquals("The launched tab should have the launch type FROM_START_SURFACE", + TabLaunchType.FROM_START_SURFACE, + cta.getActivityTabProvider().get().getLaunchType()); + StartSurfaceTestUtils.pressBack(mActivityTestRule); + // Back gesture on the tab should take us back to the start surface homepage. + StartSurfaceTestUtils.waitForStartSurfaceVisible( + mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta); + + // The Start surface should not reset its scroll position. + CriteriaHelper.pollInstrumentationThread( + () -> taskSurfaceHeader.getBottom() != taskSurfaceHeader.getHeight()); + } + + @Test + @MediumTest + @Feature({"StartSurface"}) @CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS}) public void singleAsHomepage_PressHomeButtonWillKeepTab() { if (!mImmediateReturn) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java index 6b60a8e..89486d6 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
@@ -60,6 +60,15 @@ } /** + * Returns the semantic color value that corresponds to colorPrimaryContainer. + * + * @param context {@link Context} used to retrieve color. + */ + public static @ColorInt int getDefaultContainerColor(Context context) { + return MaterialColors.getColor(context, R.attr.colorPrimaryContainer, TAG); + } + + /** * Returns the color for the tab strip background. * * @param context {@link Context} used to retrieve color.
diff --git a/chrome/android/java/res/drawable/bg_circle_new_tab_button_detached.xml b/chrome/android/java/res/drawable/bg_circle_new_tab_button_detached.xml new file mode 100644 index 0000000..cad27e1 --- /dev/null +++ b/chrome/android/java/res/drawable/bg_circle_new_tab_button_detached.xml
@@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2022 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> +<!-- Set New tab button background to 38 dp diameter for tab strip redesign detached--> + <size + android:width="38dp" + android:height="38dp" /> + <solid android:color="@color/modern_white" /> +</shape> \ No newline at end of file
diff --git a/chrome/android/java/res/drawable/bg_circle_new_tab_button_folio.xml b/chrome/android/java/res/drawable/bg_circle_new_tab_button_folio.xml new file mode 100644 index 0000000..a4063dc --- /dev/null +++ b/chrome/android/java/res/drawable/bg_circle_new_tab_button_folio.xml
@@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2022 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <!-- Set New tab button background to 36 dp diameter for tab strip redesign folio--> + <size + android:width="36dp" + android:height="36dp" /> + <solid android:color="@color/modern_white" /> +</shape> \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index d488e73..f340ea6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -2600,6 +2600,9 @@ layoutTypeToShow = LayoutType.START_SURFACE; if (state == StartSurfaceState.SHOWING_PREVIOUS) { ReturnToChromeUtil.recordBackNavigationToStart("FromTab"); + } else { + // Resets the scroll position when Start is showing not via back operations. + mStartSurfaceSupplier.get().resetScrollPosition(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java index 0f73e16..ddb7face 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java
@@ -64,6 +64,7 @@ private final CompositorOnClickHandler mClickHandler; protected int mResource; + protected int mBackgroundResource; private int mPressedResource; private int mIncognitoResource;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java index 64e3f50..279fa435 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java
@@ -21,6 +21,10 @@ private @ColorRes int mPressedTintResource; private @ColorRes int mIncognitoTintResource; private @ColorRes int mIncognitoPressedTintResource; + private @ColorInt int mBackgroundDefaultTint; + private @ColorInt int mBackgroundPressedTint; + private @ColorInt int mBackgroundIncognitoTint; + private @ColorInt int mBackgroundIncognitoPressedTint; public TintedCompositorButton( Context context, float width, float height, CompositorOnClickHandler clickHandler) { @@ -32,7 +36,6 @@ public TintedCompositorButton(Context context, float width, float height, CompositorOnClickHandler clickHandler, @DrawableRes int resource) { super(context, width, height, clickHandler); - mContext = context; mResource = resource; } @@ -62,6 +65,20 @@ } /** + * @param backgroundResource The default Android resource. + */ + public void setBackgroundResourceId(@DrawableRes int backgroundResource) { + mBackgroundResource = backgroundResource; + } + + /** + * @return The Android resource that represents button background. + */ + public int getBackgroundResourceId() { + return mBackgroundResource; + } + + /** * A set of Android resources to supply to the compositor. * @param defaultTint The default tint resource. * @param pressedTint The pressed tint resource. @@ -77,15 +94,42 @@ } /** - * @return The tint (color value, NOT the resource Id) depending on the state of the button and - * the tab (incognito or not). + * A set of Android color to supply to the compositor. + * @param backgroundDefaultTint The default background tint. + * @param backgroundPressedTint The pressed background tint. + * @param backgroundIncognitoTint The incognito background tint. + * @param backgroundIncognitoPressedTint The incognito pressed background tint. + */ + public void setBackgroundTint(@ColorInt int backgroundDefaultTint, + @ColorInt int backgroundPressedTint, @ColorInt int backgroundIncognitoTint, + @ColorInt int backgroundIncognitoPressedTint) { + mBackgroundDefaultTint = backgroundDefaultTint; + mBackgroundPressedTint = backgroundPressedTint; + mBackgroundIncognitoTint = backgroundIncognitoTint; + mBackgroundIncognitoPressedTint = backgroundIncognitoPressedTint; + } + + /** + * @return The icon tint (color value, NOT the resource Id) depending on the state of the button + * and the tab (incognito or not). */ public @ColorInt int getTint() { int tint = isIncognito() ? mIncognitoTintResource : mDefaultTintResource; if (isPressed()) { tint = isIncognito() ? mIncognitoPressedTintResource : mPressedTintResource; } - return AppCompatResources.getColorStateList(mContext, tint).getDefaultColor(); } + + /** + * @return The button background tint (color value, NOT the resource Id) depending on the state + * of the button and the tab. + */ + public @ColorInt int getBackgroundTint() { + int tint = isIncognito() ? mBackgroundIncognitoTint : mBackgroundDefaultTint; + if (isPressed()) { + tint = isIncognito() ? mBackgroundIncognitoPressedTint : mBackgroundPressedTint; + } + return tint; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index 23a5836..7923f06 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -51,10 +51,14 @@ import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; +import org.chromium.chrome.browser.tasks.tab_management.TabUiThemeProvider; +import org.chromium.components.browser_ui.styles.ChromeColors; +import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.components.browser_ui.widget.animation.Interpolators; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.base.LocalizationUtils; +import org.chromium.ui.util.ColorUtils; import java.util.ArrayList; import java.util.List; @@ -128,14 +132,22 @@ private static final float REORDER_EDGE_SCROLL_START_MIN_DP = 87.4f; private static final float REORDER_EDGE_SCROLL_START_MAX_DP = 18.4f; private static final float NEW_TAB_BUTTON_Y_OFFSET_DP = 10.f; + private static final float NEW_TAB_BUTTON_BACKGROUND_Y_OFFSET_DP = 0.f; private static final float NEW_TAB_BUTTON_CLICK_SLOP_DP = 12.f; private static final float NEW_TAB_BUTTON_WIDTH_DP = 24.f; private static final float NEW_TAB_BUTTON_HEIGHT_DP = 24.f; + private static final float NEW_TAB_BUTTON_BACKGROUND_WIDTH_DP_FOLIO = 36.f; + private static final float NEW_TAB_BUTTON_BACKGROUND_HEIGHT_DP_FOLIO = 36.f; + private static final float NEW_TAB_BUTTON_BACKGROUND_WIDTH_DP_DETACHED = 38.f; + private static final float NEW_TAB_BUTTON_BACKGROUND_HEIGHT_DP_DETACHED = 38.f; private static final float NEW_TAB_BUTTON_PADDING_DP = 24.f; private static final float NEW_TAB_BUTTON_TOUCH_TARGET_OFFSET = 12.f; private static final float FOLIO_ATTACHED_BOTTOM_MARGIN_DP = 0.f; private static final float FOLIO_ANIM_INTERMEDIATE_MARGIN_DP = -12.f; private static final float FOLIO_DETACHED_BOTTOM_MARGIN_DP = 4.f; + private static final float NEW_TAB_BUTTON_DESIRED_TOUCH_TARGET_SIZE = 48.f; + private static final float NEW_TAB_BUTTON_DEFAULT_PRESSED_OPACITY = 0.2f; + private static final float NEW_TAB_BUTTON_DARK_DETACHED_OPACITY = 0.15f; static final float BACKGROUND_TAB_BRIGHTNESS_DEFAULT = 1.f; static final float BACKGROUND_TAB_BRIGHTNESS_DIMMED = 0.65f; static final float DIVIDER_HIDDEN_OPACITY = 0.f; @@ -242,7 +254,15 @@ public StripLayoutHelper(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost, boolean incognito, CompositorButton modelSelectorButton) { mTabOverlapWidth = TAB_OVERLAP_WIDTH_DP; - mNewTabButtonWidth = NEW_TAB_BUTTON_WIDTH_DP; + if (ChromeFeatureList.sTabStripRedesign.isEnabled()) { + if (TabUiFeatureUtilities.isTabStripFolioEnabled()) { + mNewTabButtonWidth = NEW_TAB_BUTTON_BACKGROUND_WIDTH_DP_FOLIO; + } else { + mNewTabButtonWidth = NEW_TAB_BUTTON_BACKGROUND_WIDTH_DP_DETACHED; + } + } else { + mNewTabButtonWidth = NEW_TAB_BUTTON_WIDTH_DP; + } mModelSelectorButton = modelSelectorButton; mTabStripImpEnabled = ChromeFeatureList.sTabStripImprovements.isEnabled(); @@ -264,14 +284,78 @@ handleNewTabClick(); } }; - mNewTabButton = new TintedCompositorButton(context, NEW_TAB_BUTTON_WIDTH_DP, - NEW_TAB_BUTTON_HEIGHT_DP, newTabClickHandler, R.drawable.ic_new_tab_button); - mNewTabButton.setTintResources(R.color.new_tab_button_tint_list, - R.color.new_tab_button_pressed_tint_list, R.color.modern_white, - R.color.default_icon_color_blue_light); + if (ChromeFeatureList.sTabStripRedesign.isEnabled()) { + // Set new tab button background resource based on which TSR is enabled, background has + // different size. + if (TabUiFeatureUtilities.isTabStripFolioEnabled()) { + // Tab strip redesign folio enabled, bg size 36 * 36. + mNewTabButton = new TintedCompositorButton(context, + NEW_TAB_BUTTON_BACKGROUND_WIDTH_DP_FOLIO, + NEW_TAB_BUTTON_BACKGROUND_HEIGHT_DP_FOLIO, newTabClickHandler, + R.drawable.ic_new_tab_button); + mNewTabButton.setBackgroundResourceId(R.drawable.bg_circle_new_tab_button_folio); + } else { + // Tab strip redesign detached enabled, bg size 38 * 38. + mNewTabButton = new TintedCompositorButton(context, + NEW_TAB_BUTTON_BACKGROUND_WIDTH_DP_DETACHED, + NEW_TAB_BUTTON_BACKGROUND_HEIGHT_DP_DETACHED, newTabClickHandler, + R.drawable.ic_new_tab_button); + mNewTabButton.setBackgroundResourceId(R.drawable.bg_circle_new_tab_button_detached); + } + + // Primary container for default bg color. + int defaultBackgroundTint = TabUiThemeProvider.getDefaultContainerColor(context); + + // Primary @ 20% for default pressed bg color. + int pressedBackgroundTint = androidx.core.graphics.ColorUtils.setAlphaComponent( + SemanticColorUtils.getDefaultIconColorAccent1(context), + (int) (NEW_TAB_BUTTON_DEFAULT_PRESSED_OPACITY * 255)); + + // Surface 2 baseline for folio, surface 3 baseline for detached incognito bg color. + int incognitoBackgroundTint = TabUiFeatureUtilities.isTabStripFolioEnabled() + ? context.getResources().getColor(R.color.default_bg_color_dark_elev_2_baseline) + : context.getResources().getColor( + R.color.default_bg_color_dark_elev_3_baseline); + + // surface 5 baseline for incognito pressed bg color + int incognitoBackgroundPressedTint = + context.getResources().getColor(R.color.default_bg_color_dark_elev_5_baseline); + + // Tab strip redesign new tab button night mode bg color. + if (ColorUtils.inNightMode(context)) { + // Surface 1 for folio night mode bg color. + if (TabUiFeatureUtilities.isTabStripFolioEnabled()) { + defaultBackgroundTint = + ChromeColors.getSurfaceColor(context, R.dimen.default_elevation_1); + } else { + // Primary @ 15% for detached night mode bg color. + defaultBackgroundTint = androidx.core.graphics.ColorUtils.setAlphaComponent( + SemanticColorUtils.getDefaultIconColorAccent1(context), + (int) (NEW_TAB_BUTTON_DARK_DETACHED_OPACITY * 255)); + } + // Surface 5 for pressed night mode bg color. + pressedBackgroundTint = + ChromeColors.getSurfaceColor(context, R.dimen.default_elevation_5); + } + mNewTabButton.setBackgroundTint(defaultBackgroundTint, pressedBackgroundTint, + incognitoBackgroundTint, incognitoBackgroundPressedTint); + + // No pressed state color change for new tab button icon when TSR enabled. + mNewTabButton.setTintResources(R.color.default_icon_color_tint_list, + R.color.default_icon_color_tint_list, R.color.modern_white, + R.color.modern_white); + mNewTabButton.setY(NEW_TAB_BUTTON_BACKGROUND_Y_OFFSET_DP); + } else { + // when TSR disabled + mNewTabButton = new TintedCompositorButton(context, NEW_TAB_BUTTON_WIDTH_DP, + NEW_TAB_BUTTON_HEIGHT_DP, newTabClickHandler, R.drawable.ic_new_tab_button); + mNewTabButton.setTintResources(R.color.new_tab_button_tint_list, + R.color.new_tab_button_pressed_tint_list, R.color.modern_white, + R.color.default_icon_color_blue_light); + mNewTabButton.setY(NEW_TAB_BUTTON_Y_OFFSET_DP); + } mNewTabButton.setIncognito(incognito); - mNewTabButton.setY(NEW_TAB_BUTTON_Y_OFFSET_DP); mNewTabButton.setClickSlop(NEW_TAB_BUTTON_CLICK_SLOP_DP); Resources res = context.getResources(); mNewTabButton.setAccessibilityDescription( @@ -352,6 +436,11 @@ */ public float getNewTabButtonTouchTargetOffset() { boolean isRtl = LocalizationUtils.isLayoutRtl(); + if (ChromeFeatureList.sTabStripRedesign.isEnabled()) { + float newTabButtonTouchTargetOffsetTSR = + (NEW_TAB_BUTTON_DESIRED_TOUCH_TARGET_SIZE - mNewTabButtonWidth) / 2; + return isRtl ? newTabButtonTouchTargetOffsetTSR : -newTabButtonTouchTargetOffsetTSR; + } return isRtl ? NEW_TAB_BUTTON_TOUCH_TARGET_OFFSET : -NEW_TAB_BUTTON_TOUCH_TARGET_OFFSET; } @@ -1583,7 +1672,7 @@ // 2. Get offset from strip stacker. float offset = mStripStacker.computeNewTabButtonOffset(mStripTabs, mTabOverlapWidth, mLeftMargin, mRightMargin, mWidth, mNewTabButtonWidth, - NEW_TAB_BUTTON_TOUCH_TARGET_OFFSET, mCachedTabWidth, animate); + Math.abs(getNewTabButtonTouchTargetOffset()), mCachedTabWidth, animate); // 3. Hide the new tab button if it's not visible on the screen. boolean isRtl = LocalizationUtils.isLayoutRtl(); @@ -1601,7 +1690,6 @@ } else { mNewTabButton.setX(offset); } - return null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java index 99d4af1..94d2b2b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
@@ -133,13 +133,12 @@ CompositorButton modelSelectorButton = layoutHelper.getModelSelectorButton(); boolean newTabButtonVisible = newTabButton.isVisible(); boolean modelSelectorButtonVisible = modelSelectorButton.isVisible(); - TabStripSceneLayerJni.get().updateNewTabButton(mNativePtr, TabStripSceneLayer.this, - newTabButton.getResourceId(), newTabButton.getX() * mDpToPx, - newTabButton.getY() * mDpToPx, newTabButton.getWidth() * mDpToPx, - newTabButton.getHeight() * mDpToPx, + newTabButton.getResourceId(), newTabButton.getBackgroundResourceId(), + newTabButton.getX() * mDpToPx, newTabButton.getY() * mDpToPx, layoutHelper.getNewTabBtnTouchTargetOffset() * mDpToPx, newTabButtonVisible, - newTabButton.getTint(), newTabButton.getOpacity(), resourceManager); + newTabButton.getTint(), newTabButton.getBackgroundTint(), newTabButton.getOpacity(), + resourceManager); TabStripSceneLayerJni.get().updateModelSelectorButton(mNativePtr, TabStripSceneLayer.this, modelSelectorButton.getResourceId(), modelSelectorButton.getX() * mDpToPx, @@ -218,8 +217,8 @@ void updateStripScrim(long nativeTabStripSceneLayer, TabStripSceneLayer caller, float x, float y, float width, float height, int color, float alpha); void updateNewTabButton(long nativeTabStripSceneLayer, TabStripSceneLayer caller, - int resourceId, float x, float y, float width, float height, - float touchTargetOffset, boolean visible, int tint, float buttonAlpha, + int resourceId, int backgroundResourceId, float x, float y, float touchTargetOffset, + boolean visible, int tint, int backgroundTint, float buttonAlpha, ResourceManager resourceManager); void updateModelSelectorButton(long nativeTabStripSceneLayer, TabStripSceneLayer caller, int resourceId, float x, float y, float width, float height, boolean incognito,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java index a0878cf1..2b17cad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java
@@ -365,13 +365,22 @@ private class InitiatorTabObserver extends EmptyTabObserver { @Override + public void onClosingStateChanged(Tab tab, boolean closing) { + if (closing) { + PictureInPictureActivity.this.onExitPictureInPicture(/*closeByNative=*/false); + } + } + + @Override public void onDestroyed(Tab tab) { - if (tab.isClosing()) PictureInPictureActivity.this.finish(); + if (tab.isClosing()) { + PictureInPictureActivity.this.onExitPictureInPicture(/*closeByNative=*/false); + } } @Override public void onCrash(Tab tab) { - PictureInPictureActivity.this.finish(); + PictureInPictureActivity.this.onExitPictureInPicture(/*closeByNative=*/false); } } @@ -465,7 +474,7 @@ // or InitiatorTab has been destroyed by user or crashed. if (mNativeOverlayWindowAndroid != sPendingNativeOverlayWindowAndroid || TabUtils.getActivity(mInitiatorTab) == null) { - this.finish(); + onExitPictureInPicture(/*closeByNative=*/false); return; } sPendingNativeOverlayWindowAndroid = 0; @@ -497,14 +506,35 @@ } @Override - public void onStop() { - super.onStop(); - if (mCompositorView != null) mCompositorView.destroy(); + @RequiresApi(api = Build.VERSION_CODES.O) + public void onPictureInPictureModeChanged( + boolean isInPictureInPictureMode, Configuration newConfig) { + super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); + if (isInPictureInPictureMode) return; + PictureInPictureActivityJni.get().onBackToTab(mNativeOverlayWindowAndroid); + onExitPictureInPicture(/*closeByNative=*/false); } @Override - public void onDestroy() { - super.onDestroy(); + protected ActivityWindowAndroid createWindowAndroid() { + return new ActivityWindowAndroid( + this, /* listenToActivityState= */ true, getIntentRequestTracker()); + } + + @CalledByNative + public void close() { + onExitPictureInPicture(/*closeByNative=*/true); + } + + private void onExitPictureInPicture(boolean closeByNative) { + if (!closeByNative && mNativeOverlayWindowAndroid != 0) { + PictureInPictureActivityJni.get().destroy(mNativeOverlayWindowAndroid); + } + + if (mCompositorView != null) { + mCompositorView.destroy(); + mCompositorView = null; + } if (mMediaSessionReceiver != null) { unregisterReceiver(mMediaSessionReceiver); @@ -516,26 +546,7 @@ mInitiatorTab = null; } mTabObserver = null; - } - @Override - @RequiresApi(api = Build.VERSION_CODES.O) - public void onPictureInPictureModeChanged( - boolean isInPictureInPictureMode, Configuration newConfig) { - super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); - if (isInPictureInPictureMode) return; - PictureInPictureActivityJni.get().onBackToTab(mNativeOverlayWindowAndroid); - this.finish(); - } - - @Override - protected ActivityWindowAndroid createWindowAndroid() { - return new ActivityWindowAndroid( - this, /* listenToActivityState= */ true, getIntentRequestTracker()); - } - - @CalledByNative - public void close() { this.finish(); } @@ -682,7 +693,7 @@ PictureInPictureActivity pipActivity = (PictureInPictureActivity) activity; if (nativeOverlayWindowAndroid == pipActivity.getNativeOverlayWindowAndroid()) { pipActivity.resetNativeOverlayWindowAndroid(); - pipActivity.finish(); + pipActivity.onExitPictureInPicture(/*closeByNative=*/true); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java index 3a7c250..032140e70 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java
@@ -11,7 +11,10 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.util.ArrayMap; +import android.util.SizeF; import android.widget.RemoteViews; import androidx.annotation.NonNull; @@ -32,6 +35,9 @@ import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityPreferencesManager.SearchActivityPreferences; import org.chromium.components.embedder_support.util.UrlConstants; +import java.util.ArrayList; +import java.util.Map; + /** * {@link AppWidgetProvider} for a widget that provides an entry point for users to quickly perform * actions in Chrome. @@ -45,15 +51,10 @@ extends QuickActionSearchWidgetProvider { @Override @NonNull - RemoteViews getRemoteViews(@NonNull Context context, - @NonNull SearchActivityPreferences prefs, @NonNull AppWidgetManager manager, - int widgetId) { - Bundle options = manager.getAppWidgetOptions(widgetId); - return getDelegate().createSearchWidgetRemoteViews(context, prefs, - getPortraitModeTargetAreaWidth(options), - getPortraitModeTargetAreaHeight(options), - getLandscapeModeTargetAreaWidth(options), - getLandscapeModeTargetAreaHeight(options)); + RemoteViews createWidget(@NonNull Context context, @NonNull SearchActivityPreferences prefs, + int areaWidthDp, int areaHeightDp) { + return getDelegate().createSearchWidgetRemoteViews( + context, prefs, areaWidthDp, areaHeightDp); } } @@ -85,15 +86,10 @@ extends QuickActionSearchWidgetProvider { @Override @NonNull - RemoteViews getRemoteViews(@NonNull Context context, - @NonNull SearchActivityPreferences prefs, @NonNull AppWidgetManager manager, - int widgetId) { - Bundle options = manager.getAppWidgetOptions(widgetId); - return getDelegate().createDinoWidgetRemoteViews(context, prefs, - getPortraitModeTargetAreaWidth(options), - getPortraitModeTargetAreaHeight(options), - getLandscapeModeTargetAreaWidth(options), - getLandscapeModeTargetAreaHeight(options)); + RemoteViews createWidget(@NonNull Context context, @NonNull SearchActivityPreferences prefs, + int areaWidthDp, int areaHeightDp) { + return getDelegate().createDinoWidgetRemoteViews( + context, prefs, areaWidthDp, areaHeightDp); } } @@ -130,8 +126,8 @@ for (int index = 0; index < widgetIds.length; index++) { int widgetId = widgetIds[index]; - manager.updateAppWidget( - widgetId, getRemoteViews(context, preferences, manager, widgetId)); + Bundle options = manager.getAppWidgetOptions(widgetId); + manager.updateAppWidget(widgetId, getRemoteViews(context, preferences, options)); } } @@ -182,18 +178,95 @@ } /** - * Acquire screen orientation specific layouts that will be applied to the - * widget. - * The two layouts represent screen orientations in Landscape and Portrait mode. + * Construct the widget for specific dimensions. * * @param context Current context. - * @param manager The AppWidgetManager instance to query widget info. - * @param widgetId The widget to get the delegate for. + * @param prefs Widget settings and feature availability. + * @param areaWidthDp The width of the widget area, expressed in Dp. + * @param areaHeightDp The height of the widget area, expressed in Dp. + * @return RemoteViews description for a single widget layout. */ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) - abstract @NonNull RemoteViews getRemoteViews(@NonNull Context context, - @NonNull SearchActivityPreferences prefs, @NonNull AppWidgetManager manager, - int widgetId); + @NonNull + abstract RemoteViews createWidget(@NonNull Context context, + @NonNull SearchActivityPreferences prefs, int areaWidthDp, int areaHeightDp); + + /** + * Acquire the RemoteViews that represent the widget. + * + * @param context Current context. + * @param prefs Widget settings and feature availability. + * @param options Options bundle passed by AppWidgetManager. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) + @NonNull + RemoteViews getRemoteViews(@NonNull Context context, @NonNull SearchActivityPreferences prefs, + @NonNull Bundle options) { + var views = getSizeMappedRemoteViews(context, prefs, options); + if (views != null) { + return views; + } + return getOrientationSpecificRemoteViews(context, prefs, options); + } + + /** + * Acquire screen orientation specific layouts that will be applied to the + * widget. + * + * @param context Current context. + * @param prefs Widget settings and feature availability. + * @param options Widget parameters passed by the AppWidgetManager. + * @return RemoteViews describing widget for landscape and portrait screen orientations. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) + @NonNull + RemoteViews getOrientationSpecificRemoteViews(@NonNull Context context, + @NonNull SearchActivityPreferences prefs, @NonNull Bundle options) { + var portraitViews = createWidget(context, prefs, getPortraitModeTargetAreaWidth(options), + getPortraitModeTargetAreaHeight(options)); + + var landscapeViews = createWidget(context, prefs, getLandscapeModeTargetAreaWidth(options), + getLandscapeModeTargetAreaHeight(options)); + + return new RemoteViews(landscapeViews, portraitViews); + } + + /** + * Acquire size-specific layouts that will be applied to the widget. + * + * @param context Current context. + * @param prefs Widget settings and feature availability. + * @param options Widget parameters passed by the AppWidgetManager. + * @return RemoteViews describing widget for all sizes requested by the AppWidgetManager, or + * null, if the AppWidgetManager did not specify the sizes. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) + @Nullable + RemoteViews getSizeMappedRemoteViews(@NonNull Context context, + @NonNull SearchActivityPreferences prefs, @NonNull Bundle options) { + // On Android S and above, attempt to build widget from supplied array of sizes. + // This is reserved to Android S because appropriate RemoteViews constructor may not be + // available. + // Note that the creation may still fail, if the launcher is unable to offer appropriate + // details. + // Check for supported system version. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + return null; + } + + ArrayList<SizeF> sizes = + options.getParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES); + if (sizes == null || sizes.isEmpty()) { + return null; + } + Map<SizeF, RemoteViews> mappings = new ArrayMap<>(); + + for (var size : sizes) { + mappings.put(size, + createWidget(context, prefs, (int) size.getWidth(), (int) size.getHeight())); + } + return new RemoteViews(mappings); + } /** * This function initializes the QuickActionSearchWidgetProvider component. Namely, this
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java index 9bd0e52..2219902b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
@@ -158,7 +158,7 @@ public static boolean isGoogleLensFeatureEnabledOnTablet() { return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS, ENABLE_ON_TABLET_PARAM_NAME, - false); + true); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java index 6fd7128..4f3e32b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java
@@ -297,12 +297,22 @@ testExitOn(activity, () -> activity.close()); } + @Test + @MediumTest + @MinAndroidSdkLevel(Build.VERSION_CODES.O) + @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) + public void testNotifyNativeWhenTabClose() throws Throwable { + PictureInPictureActivity activity = startPictureInPictureActivity(); + testExitOn(activity, () -> mTab.setClosing(/*closing=*/true)); + verify(mNativeMock, times(1)).destroy(NATIVE_OVERLAY); + } + private WebContents getWebContents() { return mActivityTestRule.getActivity().getCurrentWebContents(); } private void testExitOn(Activity activity, Runnable runnable) throws Throwable { - runnable.run(); + TestThreadUtils.runOnUiThreadBlocking(() -> runnable.run()); CriteriaHelper.pollUiThread(() -> { Criteria.checkThat(activity == null || activity.isDestroyed(), Matchers.is(true));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java index ca0d2d3..455405e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java
@@ -25,7 +25,6 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.JniMocker; @@ -223,7 +222,6 @@ */ @Test @LargeTest - @DisableIf.Build(supported_abis_includes = "x86", message = "https://crbug.com/1062055") public void testErrorPageNotRecorded() throws Exception { runAndWaitForPageLoadMetricsRecorded( () -> mTabbedActivityTestRule.startMainActivityWithURL(mErrorPage));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentControllerTest.java index ee759ab..263036b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentControllerTest.java
@@ -111,29 +111,11 @@ @Test @MediumTest - @DisableFeatures(ChromeFeatureList.ASSISTANT_CONSENT_MODAL) public void testNoBottomSheetControllerAvailable() { ChromeTabbedActivity cta = mActivityTestRule.getActivity(); TestThreadUtils.runOnUiThreadBlocking(() -> { - AssistantVoiceSearchConsentController.show(cta.getWindowAndroid(), - mSharedPreferencesManager, - () -> {}, null, cta.getWindowAndroid().getModalDialogManager(), mCallback); - }); - Mockito.verify(mCallback, Mockito.timeout(1000)).onResult(false); - } - - @Test - @MediumTest - @EnableFeatures(ChromeFeatureList.ASSISTANT_CONSENT_MODAL) - public void testNoModalDialogManagerAvailable() { - ChromeTabbedActivity cta = mActivityTestRule.getActivity(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - AssistantVoiceSearchConsentController.show(cta.getWindowAndroid(), - mSharedPreferencesManager, - () - -> {}, - cta.getRootUiCoordinatorForTesting().getBottomSheetController(), null, - mCallback); + AssistantVoiceSearchConsentController.show( + cta.getWindowAndroid(), mSharedPreferencesManager, () -> {}, null, mCallback); }); Mockito.verify(mCallback, Mockito.timeout(1000)).onResult(false); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModalTest.java deleted file mode 100644 index 9b47402..0000000 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModalTest.java +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.omnibox.voice; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.matcher.ViewMatchers.withId; - -import androidx.test.filters.MediumTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.base.WindowAndroid; -import org.chromium.ui.modaldialog.DialogDismissalCause; -import org.chromium.ui.modaldialog.ModalDialogManager; - -/** Tests for AssistantVoiceSearchConsentDialog */ -@RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class AssistantVoiceSearchConsentModalTest { - @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - - @Rule - public MockitoRule mMockitoRule = MockitoJUnit.rule(); - - @Mock - AssistantVoiceSearchConsentUi.Observer mObserver; - - ModalDialogManager mModalDialogManager; - AssistantVoiceSearchConsentModal mModal; - - @Before - public void setUp() { - mActivityTestRule.startMainActivityOnBlankPage(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - WindowAndroid wa = mActivityTestRule.getActivity().getWindowAndroid(); - mModalDialogManager = wa.getModalDialogManager(); - mModal = new AssistantVoiceSearchConsentModal( - wa.getContext().get(), mModalDialogManager); - }); - } - - @After - public void tearDown() {} - - private void showModal() { - TestThreadUtils.runOnUiThreadBlocking(() -> { mModal.show(mObserver); }); - } - - @Test - @MediumTest - public void testAcceptButton() { - showModal(); - - onView(withId(org.chromium.chrome.R.id.positive_button)).perform(click()); - - Mockito.verify(mObserver, Mockito.timeout(1000)).onConsentAccepted(); - } - - @Test - @MediumTest - public void testRejectButton() { - showModal(); - - onView(withId(org.chromium.chrome.R.id.negative_button)).perform(click()); - - Mockito.verify(mObserver, Mockito.timeout(1000)).onConsentRejected(); - } - - @Test - @MediumTest - public void testLearnMoreButton() { - showModal(); - - onView(withId(R.id.avs_consent_ui_learn_more)).perform(click()); - - Mockito.verify(mObserver, Mockito.timeout(1000)).onLearnMoreClicked(); - } - - @Test - @MediumTest - public void testCancel() { - showModal(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mModalDialogManager.dismissAllDialogs( - DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE); - }); - - Mockito.verify(mObserver, Mockito.timeout(1000)).onConsentCanceled(); - } - - @Test - @MediumTest - public void testDismiss() { - showModal(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { mModal.dismiss(); }); - - Mockito.verifyNoMoreInteractions(mObserver); - } - - @Test - @MediumTest - public void testNonUserCancel() { - showModal(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mModalDialogManager.dismissAllDialogs(DialogDismissalCause.ACTION_ON_CONTENT); - }); - - Mockito.verify(mObserver, Mockito.timeout(1000)).onNonUserCancel(); - } -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java index 4978ed65..f69c169 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -123,7 +123,8 @@ when(mModelSelectorBtn.isVisible()).thenReturn(true); when(mTabGroupModelFilter.hasOtherRelatedTabs(any())).thenReturn(false); - mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity = Robolectric.setupActivity(Activity.class); + mActivity.setTheme(org.chromium.chrome.R.style.Theme_BrowserUI); TabUiFeatureUtilities.setTabMinWidthForTesting(190.f); } @@ -1450,6 +1451,7 @@ @Test @Feature("Tab Groups on Tab Strip") + @Features.DisableFeatures(ChromeFeatureList.TAB_STRIP_REDESIGN) public void testReorder_ExtraMinScroll() { // Mock 3 tabs. Group the first two tabs. initializeTest(false, false, true, 0, 3); @@ -1478,7 +1480,7 @@ // Assert: New tab button position before starting tab closure. mStripLayoutHelper.updateLayout(TIMESTAMP); - assertEquals("Unexpected starting newTabButton position.", 764.f, + assertEquals("Unexpected starting newTabButton position.", 743.f, mStripLayoutHelper.getNewTabButton().getX(), 0.0f); // Act: Call on close tab button handler. @@ -1500,7 +1502,7 @@ mStripLayoutHelper.getStripLayoutTabs().length); assertTrue("MultiStepAnimations should still be running.", mStripLayoutHelper.isMultiStepCloseAnimationsRunning()); - assertEquals("NewTabButton should not have moved.", 764.f, + assertEquals("NewTabButton should not have moved.", 743.f, mStripLayoutHelper.getNewTabButton().getX(), 0.0f); // Act: End next set of animations to apply final values. @@ -1508,14 +1510,14 @@ // Assert: Animations completed. The tab width is not resized and drawX does not change. float expectedDrawX = - -460.f; // Since we are focused on the last tab, start tabs are off screen. + -474.f; // Since we are focused on the last tab, start tabs are off screen. StripLayoutTab[] updatedTabs = mStripLayoutHelper.getStripLayoutTabs(); for (StripLayoutTab stripTab : updatedTabs) { assertEquals("Unexpected tab width after resize.", 156.f, stripTab.getWidth(), 0.0); assertEquals("Unexpected tab position.", expectedDrawX, stripTab.getDrawX(), 0.0); expectedDrawX += (TAB_WIDTH_MEDIUM - TAB_OVERLAP_WIDTH); } - assertEquals("NewTabButton should not have moved.", 764.f, + assertEquals("NewTabButton should not have moved.", 743.f, mStripLayoutHelper.getNewTabButton().getX(), 0.0f); assertFalse("MultiStepAnimations should have stopped running.", mStripLayoutHelper.isMultiStepCloseAnimationsRunning()); @@ -1535,7 +1537,7 @@ // Assert: New tab button position before starting tab closure. mStripLayoutHelper.updateLayout(TIMESTAMP); - assertEquals("Unexpected starting newTabButton position.", 764.f, + assertEquals("Unexpected starting newTabButton position.", 743.f, mStripLayoutHelper.getNewTabButton().getX(), 0.0f); // Act: Call on close tab button handler. @@ -1556,7 +1558,7 @@ assertEquals(expectedTabCount, mStripLayoutHelper.getStripLayoutTabs().length); assertTrue("MultiStepAnimations should still be running.", mStripLayoutHelper.isMultiStepCloseAnimationsRunning()); - assertEquals("NewTabButton should not have moved.", 764.f, + assertEquals("NewTabButton should not have moved.", 743.f, mStripLayoutHelper.getNewTabButton().getX(), 0.0f); // Act: Set animation time forward by 250ms for next set of animations. @@ -1565,7 +1567,7 @@ // Assert: Animations completed. The tab width is resized, tab.drawX is changed and // newTabButton.drawX is also changed. float expectedDrawX = 0.f; - float expectedWidthAfterResize = 265.f; + float expectedWidthAfterResize = 262.f; StripLayoutTab[] updatedTabs = mStripLayoutHelper.getStripLayoutTabs(); for (int i = 0; i < updatedTabs.length; i++) { StripLayoutTab stripTab = updatedTabs[i]; @@ -1574,7 +1576,7 @@ assertEquals("Unexpected tab position.", expectedDrawX, stripTab.getDrawX(), 0.0); expectedDrawX += (expectedWidthAfterResize - TAB_OVERLAP_WIDTH); } - assertEquals("NewTabButton position is incorrect.", 759.f, + assertEquals("NewTabButton position is incorrect.", 743.f, mStripLayoutHelper.getNewTabButton().getX(), 0.0f); assertFalse("MultiStepAnimations should have ended.", mStripLayoutHelper.isMultiStepCloseAnimationsRunning());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java index 9cdaf6a..3a9587f 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java
@@ -6,6 +6,8 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -13,8 +15,9 @@ import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; -import android.widget.RemoteViews; +import android.util.SizeF; import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; @@ -25,81 +28,202 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLog; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.browser.firstrun.FirstRunStatus; -import org.chromium.chrome.browser.ui.quickactionsearchwidget.QuickActionSearchWidgetProviderDelegate; +import org.chromium.chrome.browser.quickactionsearchwidget.QuickActionSearchWidgetProvider.QuickActionSearchWidgetProviderDino; import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityPreferencesManager.SearchActivityPreferences; +import java.util.ArrayList; +import java.util.Arrays; + /** * Tests for the (@link QuickActionSearchWidgetProvider}. */ @RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowLog.class}) public class QuickActionSearchWidgetProviderTest { + private static final int WIDGET_A_ID = 123; + private static final int WIDGET_B_ID = 987; // These are random unique identifiers, the value of these numbers have no special meaning. // The number of identifiers has no particular meaning either. - private static final int[] WIDGET_IDS = {1, 2}; + private static final int[] WIDGET_IDS = {WIDGET_A_ID, WIDGET_B_ID}; + public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule(); + private @Mock AppWidgetManager mAppWidgetManagerMock; - /** - * A sub class of {@link QuickActionSearchWidgetProvider} for testing, since - * QuickActionSearchWidgetProvider is abstract. - */ - private class TestProvider extends QuickActionSearchWidgetProvider { - @Override - RemoteViews getRemoteViews(Context context, SearchActivityPreferences prefs, - AppWidgetManager manager, int widgetId) { - return mRemoteViews; - } - - @Override - protected QuickActionSearchWidgetProviderDelegate getDelegate() { - return mDelegateMock; - } - } - - @Rule - public MockitoRule mMockitoRule = MockitoJUnit.rule(); - @Mock - private AppWidgetManager mAppWidgetManagerMock; - @Mock - private QuickActionSearchWidgetProviderDelegate mDelegateMock; - @Mock - private Bundle mBundleMock; - @Mock - private RemoteViews mRemoteViews; - + private SearchActivityPreferences mPreferences; private QuickActionSearchWidgetProvider mWidgetProvider; private Context mContext; + private Intent mIntent; + private Bundle mOptionsWidgetA; + private Bundle mOptionsWidgetB; @Before public void setUp() { - FirstRunStatus.setFirstRunFlowComplete(true); - MockitoAnnotations.initMocks(this); + ShadowLog.stream = System.out; mContext = Mockito.spy(ApplicationProvider.getApplicationContext()); + mOptionsWidgetA = new Bundle(); + mOptionsWidgetB = new Bundle(); + mPreferences = new SearchActivityPreferences( + "Search Engine", "https://search.engine.com", true, true, true); // Inflate an actual RemoteViews to avoid stubbing internal methods or making // any other assumptions about the class. - mWidgetProvider = Mockito.spy(new TestProvider()); + mWidgetProvider = Mockito.spy(new QuickActionSearchWidgetProviderDino()); when(mContext.getSystemService(Context.APPWIDGET_SERVICE)) .thenReturn(mAppWidgetManagerMock); - when(mAppWidgetManagerMock.getAppWidgetOptions(anyInt())).thenReturn(mBundleMock); + when(mAppWidgetManagerMock.getAppWidgetOptions(eq(WIDGET_A_ID))) + .thenReturn(mOptionsWidgetA); + when(mAppWidgetManagerMock.getAppWidgetOptions(eq(WIDGET_B_ID))) + .thenReturn(mOptionsWidgetB); + + // Blanket intent that defines which widget IDs we would be testing here. + mIntent = new Intent(); + mIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, WIDGET_IDS); + } + + private void updateReportedWidgetSizes(Bundle options, SizeF portrait, SizeF landscape) { + // - Portrait mode is narrow and tall, hence MIN_WIDTH and MAX_HEIGHT. + // - Landscape mode is wide and short, hence MAX_WIDTH and MIN_HEIGHT. + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, (int) portrait.getWidth()); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, (int) portrait.getHeight()); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, (int) landscape.getWidth()); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, (int) landscape.getHeight()); } @Test @SmallTest - public void testAppWidgetUpdateInvokesUpdateWidgets() { - Intent appWidgetUpdateIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); - appWidgetUpdateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, WIDGET_IDS); + public void testAppWidgetInstallationCreatesWidgets() { + mIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + updateReportedWidgetSizes(mOptionsWidgetA, new SizeF(80, 80), new SizeF(400, 40)); + updateReportedWidgetSizes(mOptionsWidgetB, new SizeF(30, 10), new SizeF(100, 30)); + mWidgetProvider.onReceive(mContext, mIntent); - mWidgetProvider.onReceive(mContext, appWidgetUpdateIntent); + // There are 2 fake widgets to be created, and each should be created for portrait and + // landscape screen orientation. + // Widget A, Portrait. + verify(mWidgetProvider).createWidget(any(), any(), eq(80), eq(80)); + // Widget A, Landscape. + verify(mWidgetProvider).createWidget(any(), any(), eq(400), eq(40)); + // Widget B, Portrait. + verify(mWidgetProvider).createWidget(any(), any(), eq(30), eq(10)); + // Widget B, Landscape. + verify(mWidgetProvider).createWidget(any(), any(), eq(100), eq(30)); + // 4 total, no more. + verify(mWidgetProvider, times(4)).createWidget(any(), any(), anyInt(), anyInt()); + } - verify(mWidgetProvider, times(1)).onUpdate(mContext, mAppWidgetManagerMock, WIDGET_IDS); - verify(mWidgetProvider, times(1)).onUpdate(any(), any(), any()); + @Test + @SmallTest + public void testAppWidgetResizeUpdatesWidgets() { + updateReportedWidgetSizes(mOptionsWidgetA, new SizeF(80, 80), new SizeF(400, 40)); + updateReportedWidgetSizes(mOptionsWidgetB, new SizeF(30, 10), new SizeF(100, 30)); + mIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + mWidgetProvider.onReceive(mContext, mIntent); + + verify(mWidgetProvider).createWidget(any(), any(), eq(80), eq(80)); + verify(mWidgetProvider).createWidget(any(), any(), eq(400), eq(40)); + verify(mWidgetProvider).createWidget(any(), any(), eq(30), eq(10)); + verify(mWidgetProvider).createWidget(any(), any(), eq(100), eq(30)); + verify(mWidgetProvider, times(4)).createWidget(any(), any(), anyInt(), anyInt()); + + clearInvocations(mWidgetProvider); + + // OPTIONS_CHANGED specifies which particular widget needs to be updated. Make sure we + // reflect that here. Below, we flip the sizes so that Widget B uses sizes of Widget A and + // vice versa. + when(mAppWidgetManagerMock.getAppWidgetOptions(eq(WIDGET_A_ID))) + .thenReturn(mOptionsWidgetB); + when(mAppWidgetManagerMock.getAppWidgetOptions(eq(WIDGET_B_ID))) + .thenReturn(mOptionsWidgetA); + + // First, resize Widget A with old Widget B size specs. + mIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED); + mIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, WIDGET_A_ID); + mIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, mOptionsWidgetB); + mWidgetProvider.onReceive(mContext, mIntent); + + verify(mWidgetProvider).createWidget(any(), any(), eq(30), eq(10)); + verify(mWidgetProvider).createWidget(any(), any(), eq(100), eq(30)); + verify(mWidgetProvider, times(2)).createWidget(any(), any(), anyInt(), anyInt()); + clearInvocations(mWidgetProvider); + + // Next, resize Widget B with old Widget A size specs. + mIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, WIDGET_B_ID); + mIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, mOptionsWidgetA); + mWidgetProvider.onReceive(mContext, mIntent); + verify(mWidgetProvider).createWidget(any(), any(), eq(80), eq(80)); + verify(mWidgetProvider).createWidget(any(), any(), eq(400), eq(40)); + verify(mWidgetProvider, times(2)).createWidget(any(), any(), anyInt(), anyInt()); + } + + @Test + @SmallTest + @Config(sdk = Build.VERSION_CODES.S) + public void testCreateWidgetsFromFallbackValues_missingSizes() { + updateReportedWidgetSizes(mOptionsWidgetA, new SizeF(80, 80), new SizeF(400, 40)); + mWidgetProvider.getRemoteViews(mContext, mPreferences, mOptionsWidgetA); // There are 2 fake widgets that we work with, so expect both being evaluated - verify(mWidgetProvider, times(2)).getRemoteViews(any(), any(), any(), anyInt()); + // One for portrait mode (max_width, min_height) and + // One for landscape mode (min_width, max_height). + verify(mWidgetProvider).createWidget(any(), any(), eq(400), eq(40)); + verify(mWidgetProvider).createWidget(any(), any(), eq(80), eq(80)); + verify(mWidgetProvider, times(2)).createWidget(any(), any(), anyInt(), anyInt()); + } + + @Test + @SmallTest + @Config(sdk = Build.VERSION_CODES.S) + public void testCreateWidgetFromFallbackValues_emptySizes() { + updateReportedWidgetSizes(mOptionsWidgetA, new SizeF(80, 80), new SizeF(400, 40)); + // Lastly, set the empty array of sizes. + mOptionsWidgetA.putParcelableArrayList( + AppWidgetManager.OPTION_APPWIDGET_SIZES, new ArrayList<SizeF>()); + mWidgetProvider.getRemoteViews(mContext, mPreferences, mOptionsWidgetA); + + // There are 2 fake widgets that we work with, so expect both being evaluated + // One for portrait mode (max_width, min_height) and + // One for landscape mode (min_width, max_height). + verify(mWidgetProvider).createWidget(any(), any(), eq(400), eq(40)); + verify(mWidgetProvider).createWidget(any(), any(), eq(80), eq(80)); + verify(mWidgetProvider, times(2)).createWidget(any(), any(), anyInt(), anyInt()); + } + + @Test + @SmallTest + @Config(sdk = Build.VERSION_CODES.S) + public void testCreateWidgetFromSizeSpecs() { + updateReportedWidgetSizes(mOptionsWidgetA, new SizeF(80, 80), new SizeF(400, 40)); + // Lastly, set a different array of sizes and confirm it is used instead. + mOptionsWidgetA.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, + new ArrayList<SizeF>(Arrays.asList(new SizeF(50, 50)))); + mWidgetProvider.getRemoteViews(mContext, mPreferences, mOptionsWidgetA); + + // Only one call is expected here, because we declare only one size in our list. + verify(mWidgetProvider).createWidget(any(), any(), eq(50), eq(50)); + verify(mWidgetProvider, times(1)).createWidget(any(), any(), anyInt(), anyInt()); + } + + @Test + @SmallTest + @Config(sdk = Build.VERSION_CODES.R) + public void testCreateWidgetFromLegacyMeasurements() { + updateReportedWidgetSizes(mOptionsWidgetA, new SizeF(80, 80), new SizeF(400, 40)); + // Define new sizes. These must be ignored, because RemoteViews constructor is not + // supported. + mOptionsWidgetA.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, + new ArrayList<SizeF>(Arrays.asList(new SizeF(50, 50)))); + mWidgetProvider.getRemoteViews(mContext, mPreferences, mOptionsWidgetA); + + // There are 2 fake widgets that we work with, so expect both being evaluated + // One for portrait mode (max_width, min_height) and + // One for landscape mode (min_width, max_height). + verify(mWidgetProvider).createWidget(any(), any(), eq(400), eq(40)); + verify(mWidgetProvider).createWidget(any(), any(), eq(80), eq(80)); + verify(mWidgetProvider, times(2)).createWidget(any(), any(), anyInt(), anyInt()); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/share/LensUtilsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/share/LensUtilsTest.java index 1d63bb67..812ce7f 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/share/LensUtilsTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/share/LensUtilsTest.java
@@ -114,9 +114,9 @@ } @Test - public void isGoogleLensFeatureEnabled_tabletDisabled() { + public void isGoogleLensFeatureEnabled_tabletEnabledByDefault() { configureFeature(ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS); - Assert.assertFalse("Feature incorrectly enabled when Lens on tablet was disabled", + Assert.assertTrue("Feature incorrectly disabled when Lens on tablet was enabled", LensUtils.isGoogleLensFeatureEnabledOnTablet()); }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 5eccb867..19b282f 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6674,6 +6674,9 @@ <message name="IDS_NTP_CUSTOMIZE_NO_BACKGROUND_LABEL" desc="The label for the 'Classic Chrome' tile in the customization menu on the New Tab Page"> Classic Chrome </message> + <message name="IDS_NTP_CUSTOMIZE_UPLOADED_IMAGE_LABEL" desc="The label for the 'Uploaded image' tile in the customization menu on the New Tab Page side panel."> + Uploaded image + </message> <message name="IDS_NTP_CUSTOMIZE_UPLOAD_FROM_DEVICE_LABEL" desc="The label for the 'Upload from device' tile in the customization menu on the New Tab Page"> Upload from device </message> @@ -13069,6 +13072,12 @@ <message name="IDS_WEBAUTHN_ERROR_NO_TRANSPORTS_DESCRIPTION" desc="Description in the dialog shown when the user could not sign in to a web site, because their computer did not support any of the hardware-based authentication mechanisms desired by the web site."> This device doesn't support the type of security key requested by this website </message> + <message name="IDS_WEBAUTHN_ERROR_NO_PASSKEYS_TITLE" desc="Title of the dialog shown when the user could not sign in to a web site because their computer did not have any of the passkeys registered with the site."> + No passkeys available + </message> + <message name="IDS_WEBAUTHN_ERROR_NO_PASSKEYS_DESCRIPTION" desc="Description in the dialog shown when the user could not sign in to a web site because their computer did not have any of the passkeys registered with the site."> + There aren't any passkeys for <ph name="APP_NAME">$1<ex>google.com</ex></ph> on this device + </message> <message name="IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_TITLE" desc="Title of the dialog informing the user that Chrome needs to turn on Bluetooth by itself so that security keys can be used over Bluetooth."> Turn on Bluetooth? </message>
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_CUSTOMIZE_UPLOADED_IMAGE_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_CUSTOMIZE_UPLOADED_IMAGE_LABEL.png.sha1 new file mode 100644 index 0000000..ee9f695 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_NTP_CUSTOMIZE_UPLOADED_IMAGE_LABEL.png.sha1
@@ -0,0 +1 @@ +e91b85af596088e04af1f5e35e42e39dd5173dac \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ERROR_NO_PASSKEYS_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ERROR_NO_PASSKEYS_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..68e115f --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ERROR_NO_PASSKEYS_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +d66e3b8f10c2f6b6ecb34b20b33ff19a3028450d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ERROR_NO_PASSKEYS_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ERROR_NO_PASSKEYS_TITLE.png.sha1 new file mode 100644 index 0000000..68e115f --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ERROR_NO_PASSKEYS_TITLE.png.sha1
@@ -0,0 +1 @@ +d66e3b8f10c2f6b6ecb34b20b33ff19a3028450d \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 44c56811..a6f5f77d 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -5590,6 +5590,8 @@ "lacros/task_manager_lacros.h", "lacros/ui_metric_recorder_lacros.cc", "lacros/ui_metric_recorder_lacros.h", + "lacros/views_text_services_context_menu_lacros.cc", + "lacros/views_text_services_context_menu_lacros.h", "lacros/vpn_extension_tracker_lacros.cc", "lacros/vpn_extension_tracker_lacros.h", "lacros/web_app_provider_bridge_lacros.cc", @@ -5661,6 +5663,7 @@ "//ui/chromeos/strings:strings_grit", "//ui/chromeos/styles:cros_styles_views", "//ui/platform_window", + "//ui/strings:ui_strings_grit", ] if (enable_plugins) { @@ -6393,6 +6396,8 @@ "enterprise/idle/idle_service.h", "enterprise/idle/idle_service_factory.cc", "enterprise/idle/idle_service_factory.h", + "enterprise/idle/idle_timeout_policy_handler.cc", + "enterprise/idle/idle_timeout_policy_handler.h", "enterprise/remote_commands/rotate_attestation_credential_job.cc", "enterprise/remote_commands/rotate_attestation_credential_job.h", "enterprise/signals/signals_aggregator_factory.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index a4b2e2e..0810df9 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4190,9 +4190,6 @@ flag_descriptions::kVoiceButtonInTopToolbarName, flag_descriptions::kVoiceButtonInTopToolbarDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kVoiceButtonInTopToolbar)}, - {"assistant-consent-modal", flag_descriptions::kAssistantConsentModalName, - flag_descriptions::kAssistantConsentModalDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kAssistantConsentModal)}, {"assistant-consent-simplified-text", flag_descriptions::kAssistantConsentSimplifiedTextName, flag_descriptions::kAssistantConsentSimplifiedTextDescription, kOsAndroid, @@ -9642,6 +9639,11 @@ entry.internal_name)) { return true; } + // Skip lacros-selection if it is controlled by LacrosSelection policy. + if (!strcmp(kLacrosSelectionInternalName, entry.internal_name)) { + return crosapi::browser_util::GetCachedLacrosSelectionPolicy() != + crosapi::browser_util::LacrosSelectionPolicy::kUserChoice; + } if (!strcmp(kPreferDcheckInternalName, entry.internal_name)) { return !crosapi::browser_util::IsLacrosAllowedToBeEnabled();
diff --git a/chrome/browser/accessibility/page_colors_factory.cc b/chrome/browser/accessibility/page_colors_factory.cc index 429b3166..cbc932a 100644 --- a/chrome/browser/accessibility/page_colors_factory.cc +++ b/chrome/browser/accessibility/page_colors_factory.cc
@@ -47,10 +47,11 @@ return true; } -KeyedService* PageColorsFactory::BuildServiceInstanceFor( +std::unique_ptr<KeyedService> +PageColorsFactory::BuildServiceInstanceForBrowserContext( content::BrowserContext* context) const { - std::unique_ptr<PageColors> page_colors = std::make_unique<PageColors>( + auto page_colors = std::make_unique<PageColors>( Profile::FromBrowserContext(context)->GetPrefs()); page_colors->Init(); - return page_colors.release(); + return page_colors; }
diff --git a/chrome/browser/accessibility/page_colors_factory.h b/chrome/browser/accessibility/page_colors_factory.h index e560f3a..1022b84a 100644 --- a/chrome/browser/accessibility/page_colors_factory.h +++ b/chrome/browser/accessibility/page_colors_factory.h
@@ -28,8 +28,8 @@ // BrowserContextKeyedServiceFactory: content::BrowserContext* GetBrowserContextToUse( content::BrowserContext* context) const override; - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* profile) const override; + std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const override; bool ServiceIsCreatedWithBrowserContext() const override; void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) override;
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc index af57558..881ef38 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
@@ -18,6 +18,7 @@ using base::android::JavaParamRef; using base::android::JavaRef; +bool tab_strip_redesign_enabled; namespace android { @@ -28,12 +29,14 @@ scrollable_strip_layer_(cc::Layer::Create()), scrim_layer_(cc::SolidColorLayer::Create()), new_tab_button_(cc::UIResourceLayer::Create()), + new_tab_button_background_(cc::UIResourceLayer::Create()), left_fade_(cc::UIResourceLayer::Create()), right_fade_(cc::UIResourceLayer::Create()), model_selector_button_(cc::UIResourceLayer::Create()), write_index_(0), content_tree_(nullptr) { new_tab_button_->SetIsDrawable(true); + new_tab_button_background_->SetIsDrawable(true); model_selector_button_->SetIsDrawable(true); left_fade_->SetIsDrawable(true); right_fade_->SetIsDrawable(true); @@ -45,6 +48,8 @@ scrollable_strip_layer_->SetIsDrawable(true); const bool tab_strip_improvements_enabled = base::FeatureList::IsEnabled(chrome::android::kTabStripImprovements); + tab_strip_redesign_enabled = + base::FeatureList::IsEnabled(chrome::android::kTabStripRedesign); if (!tab_strip_improvements_enabled) { scrollable_strip_layer_->AddChild(new_tab_button_); } @@ -56,6 +61,9 @@ tab_strip_layer_->AddChild(right_fade_); tab_strip_layer_->AddChild(model_selector_button_); if (tab_strip_improvements_enabled) { + if (tab_strip_redesign_enabled) { + tab_strip_layer_->AddChild(new_tab_button_background_); + } tab_strip_layer_->AddChild(new_tab_button_); } tab_strip_layer_->AddChild(scrim_layer_); @@ -163,13 +171,13 @@ JNIEnv* env, const JavaParamRef<jobject>& jobj, jint resource_id, + jint bg_resource_id, jfloat x, jfloat y, - jfloat width, - jfloat height, jfloat touch_target_offset, jboolean visible, jint tint, + jint background_tint, jfloat button_alpha, const JavaParamRef<jobject>& jresource_manager) { ui::ResourceManager* resource_manager = @@ -178,16 +186,40 @@ resource_manager->GetStaticResourceWithTint(resource_id, tint); new_tab_button_->SetUIResourceId(button_resource->ui_resource()->id()); - float left_offset = (width - button_resource->size().width()) / 2; - float top_offset = (height - button_resource->size().height()) / 2; // The touch target for the new tab button is skewed towards the end of the // strip. This ensures that the view itself is correctly aligned without // adjusting the touch target. - left_offset += touch_target_offset; - new_tab_button_->SetPosition(gfx::PointF(x + left_offset, y + top_offset)); + float left_offset = touch_target_offset; + new_tab_button_->SetBounds(button_resource->size()); new_tab_button_->SetHideLayerAndSubtree(!visible); new_tab_button_->SetOpacity(button_alpha); + + // Set Tab Strip Redesign new tab button background + if (tab_strip_redesign_enabled) { + ui::Resource* button_background_resource = + resource_manager->GetStaticResourceWithTint(bg_resource_id, + background_tint, true); + float background_left_offset = (button_background_resource->size().width() - + button_resource->size().width()) / + 2; + float background_top_offset = (button_background_resource->size().height() - + button_resource->size().height()) / + 2; + new_tab_button_background_->SetUIResourceId( + button_background_resource->ui_resource()->id()); + new_tab_button_background_->SetPosition(gfx::PointF(x + left_offset, y)); + + new_tab_button_background_->SetBounds(button_background_resource->size()); + new_tab_button_background_->SetHideLayerAndSubtree(!visible); + new_tab_button_background_->SetOpacity(button_alpha); + new_tab_button_->SetPosition( + gfx::PointF(background_left_offset, background_top_offset)); + new_tab_button_background_->AddChild(new_tab_button_); + } else { + // Only show new tab button icon when TSR is disabled + new_tab_button_->SetPosition(gfx::PointF(x + left_offset, y)); + } } void TabStripSceneLayer::UpdateModelSelectorButton(
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h index ef96dce..6a84473 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h
@@ -69,13 +69,13 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& jobj, jint resource_id, + jint bg_resource_id, jfloat x, jfloat y, - jfloat width, - jfloat height, jfloat touch_target_offset, jboolean visible, jint tint, + jint background_tint, jfloat button_alpha, const base::android::JavaParamRef<jobject>& jresource_manager); @@ -152,6 +152,7 @@ scoped_refptr<cc::Layer> scrollable_strip_layer_; scoped_refptr<cc::SolidColorLayer> scrim_layer_; scoped_refptr<cc::UIResourceLayer> new_tab_button_; + scoped_refptr<cc::UIResourceLayer> new_tab_button_background_; scoped_refptr<cc::UIResourceLayer> left_fade_; scoped_refptr<cc::UIResourceLayer> right_fade_; scoped_refptr<cc::UIResourceLayer> model_selector_button_;
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 77f999a..5de5844 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -523,6 +523,8 @@ "arc/session/arc_demo_mode_preference_handler.h", "arc/session/arc_disk_space_monitor.cc", "arc/session/arc_disk_space_monitor.h", + "arc/session/arc_initial_optin_notifier.cc", + "arc/session/arc_initial_optin_notifier.h", "arc/session/arc_play_store_enabled_preference_handler.cc", "arc/session/arc_play_store_enabled_preference_handler.h", "arc/session/arc_provisioning_result.cc", @@ -2315,6 +2317,8 @@ "policy/handlers/device_wifi_allowed_handler.h", "policy/handlers/lacros_availability_policy_handler.cc", "policy/handlers/lacros_availability_policy_handler.h", + "policy/handlers/lacros_selection_policy_handler.cc", + "policy/handlers/lacros_selection_policy_handler.h", "policy/handlers/lock_to_single_user_manager.cc", "policy/handlers/lock_to_single_user_manager.h", "policy/handlers/minimum_version_policy_handler.cc",
diff --git a/chrome/browser/ash/app_list/arc/DEPS b/chrome/browser/ash/app_list/arc/DEPS new file mode 100644 index 0000000..b118d9f --- /dev/null +++ b/chrome/browser/ash/app_list/arc/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "arc_app_list_prefs\.cc": [ + "+ash", + ], +}
diff --git a/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc index 0faafbfc..56f8471 100644 --- a/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc
@@ -18,6 +18,8 @@ #include "ash/components/arc/session/connection_holder.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" +#include "ash/metrics/login_unlock_throughput_recorder.h" +#include "ash/shell.h" #include "base/bind.h" #include "base/check.h" #include "base/containers/contains.h" @@ -43,6 +45,7 @@ #include "chrome/browser/ash/login/session/user_session_manager.h" #include "chrome/browser/image_decoder/image_decoder.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h" #include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" @@ -376,6 +379,44 @@ update.Get().Remove(kDeprecatePackagePrefsSystem); } +ash::LoginUnlockThroughputRecorder* GetLoginRecorder() { + return ash::Shell::HasInstance() + ? ash::Shell::Get()->login_unlock_throughput_recorder() + : nullptr; +} + +void OnArcAppListRefreshed(Profile* profile) { + if (!arc::IsArcPlayStoreEnabledForProfile(profile)) + return; + + ash::LoginUnlockThroughputRecorder* throughput_recorder = GetLoginRecorder(); + if (!throughput_recorder || !throughput_recorder->NeedReportArcAppListReady()) + return; + + DCHECK_EQ(ProfileManager::GetPrimaryUserProfile(), profile); + auto* prefs = ArcAppListPrefs::Get(profile); + if (!prefs) + return; + + const std::vector<std::string> app_ids = prefs->GetAppIds(); + int launchable = 0; + int ready = 0; + int error = 0; + for (const auto& app_id : app_ids) { + std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id); + if (app_info) { + if (app_info->launchable) + ++launchable; + + if (app_info->ready) + ++ready; + } else { + ++error; + } + } + if (ready + error >= launchable) + throughput_recorder->OnArcAppListReady(); +} } // namespace // static @@ -1589,6 +1630,7 @@ } } } + OnArcAppListRefreshed(profile_); } void ArcAppListPrefs::RemoveApp(const std::string& app_id) { @@ -1784,6 +1826,7 @@ MaybeSetDefaultAppLoadingTimeout(); } } + OnArcAppListRefreshed(profile_); } void ArcAppListPrefs::DetectDefaultAppAvailability() {
diff --git a/chrome/browser/ash/arc/session/arc_initial_optin_notifier.cc b/chrome/browser/ash/arc/session/arc_initial_optin_notifier.cc new file mode 100644 index 0000000..ea28e28 --- /dev/null +++ b/chrome/browser/ash/arc/session/arc_initial_optin_notifier.cc
@@ -0,0 +1,107 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/arc/session/arc_initial_optin_notifier.h" + +#include <string> + +#include "ash/components/arc/arc_util.h" +#include "ash/metrics/login_unlock_throughput_recorder.h" +#include "ash/shell.h" +#include "base/bind.h" +#include "base/logging.h" +#include "chrome/browser/ash/arc/arc_util.h" +#include "chrome/browser/ash/arc/session/arc_session_manager.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "content/public/browser/browser_thread.h" + +namespace arc { + +namespace { + +class ArcInitialOptInNotifierFactory + : public BrowserContextKeyedServiceFactory { + public: + ArcInitialOptInNotifierFactory(); + + ArcInitialOptInNotifierFactory(const ArcInitialOptInNotifierFactory&) = + delete; + ArcInitialOptInNotifierFactory& operator=( + const ArcInitialOptInNotifierFactory&) = delete; + + ~ArcInitialOptInNotifierFactory() override = default; + + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* browser_context) const override { + return new ArcInitialOptInNotifier(browser_context); + } + + // static + static ArcInitialOptInNotifier* GetForBrowserContext( + content::BrowserContext* context) { + return static_cast<ArcInitialOptInNotifier*>( + GetInstance()->GetServiceForBrowserContext(context, true)); + } + + // static + static ArcInitialOptInNotifierFactory* GetInstance() { + return base::Singleton<ArcInitialOptInNotifierFactory>::get(); + } +}; + +ArcInitialOptInNotifierFactory::ArcInitialOptInNotifierFactory() + : BrowserContextKeyedServiceFactory( + "ArcInitialOptInNotifierFactory", + BrowserContextDependencyManager::GetInstance()) {} + +} // anonymous namespace + +// static +ArcInitialOptInNotifier* ArcInitialOptInNotifier::GetForProfile( + Profile* profile) { + return ArcInitialOptInNotifierFactory::GetForBrowserContext(profile); +} + +ArcInitialOptInNotifier::ArcInitialOptInNotifier( + content::BrowserContext* context) { + ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get(); + // arc::ArcSessionManager might not be set in tests. + if (arc_session_manager) + arc_session_manager->AddObserver(this); +} + +ArcInitialOptInNotifier::~ArcInitialOptInNotifier() { + ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get(); + // arc::ArcSessionManager may be released first. + if (arc_session_manager) + arc_session_manager->RemoveObserver(this); +} + +void ArcInitialOptInNotifier::OnArcInitialStart() { + if (!IsArcPlayAutoInstallDisabled()) + return; + + LOG(WARNING) << "kArcDisablePlayAutoInstall flag is set. Force Arc apps " + "loaded metric."; + ash::LoginUnlockThroughputRecorder* throughput_recorder = + ash::Shell::HasInstance() + ? ash::Shell::Get()->login_unlock_throughput_recorder() + : nullptr; + if (throughput_recorder) { + throughput_recorder->OnArcAppListReady(); + } +} + +void ArcInitialOptInNotifier::OnArcOptInUserAction() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + ash::LoginUnlockThroughputRecorder* throughput_recorder = + ash::Shell::HasInstance() + ? ash::Shell::Get()->login_unlock_throughput_recorder() + : nullptr; + if (throughput_recorder) + throughput_recorder->OnArcOptedIn(); +} + +} // namespace arc
diff --git a/chrome/browser/ash/arc/session/arc_initial_optin_notifier.h b/chrome/browser/ash/arc/session/arc_initial_optin_notifier.h new file mode 100644 index 0000000..84b23b8 --- /dev/null +++ b/chrome/browser/ash/arc/session/arc_initial_optin_notifier.h
@@ -0,0 +1,45 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_ARC_SESSION_ARC_INITIAL_OPTIN_NOTIFIER_H_ +#define CHROME_BROWSER_ASH_ARC_SESSION_ARC_INITIAL_OPTIN_NOTIFIER_H_ + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ash/arc/session/arc_session_manager_observer.h" +#include "components/keyed_service/core/keyed_service.h" + +class Profile; + +namespace content { +class BrowserContext; +} + +namespace arc { + +// Observes Arc session manager opt-in status, and notifies metrics. +class ArcInitialOptInNotifier : public ArcSessionManagerObserver, + public KeyedService { + public: + // Returns singleton instance for the given Profile. + static ArcInitialOptInNotifier* GetForProfile(Profile* profile); + + explicit ArcInitialOptInNotifier(content::BrowserContext* context); + + ArcInitialOptInNotifier(const ArcInitialOptInNotifier&) = delete; + ArcInitialOptInNotifier& operator=(const ArcInitialOptInNotifier&) = delete; + + ~ArcInitialOptInNotifier() override; + + // ArcSessionManagerObserver: + void OnArcInitialStart() override; + void OnArcOptInUserAction() override; + + private: + // Must be the last member. + base::WeakPtrFactory<ArcInitialOptInNotifier> weak_ptr_factory_{this}; +}; + +} // namespace arc + +#endif // CHROME_BROWSER_ASH_ARC_SESSION_ARC_INITIAL_OPTIN_NOTIFIER_H_
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc index 00859b20..9be86d5 100644 --- a/chrome/browser/ash/arc/session/arc_service_launcher.cc +++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -83,6 +83,7 @@ #include "chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.h" #include "chrome/browser/ash/arc/session/arc_demo_mode_preference_handler.h" #include "chrome/browser/ash/arc/session/arc_disk_space_monitor.h" +#include "chrome/browser/ash/arc/session/arc_initial_optin_notifier.h" #include "chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler.h" #include "chrome/browser/ash/arc/session/arc_session_manager.h" #include "chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h" @@ -310,6 +311,7 @@ apps::ArcAppsFactory::GetForProfile(profile); ash::ApkWebAppService::Get(profile); ash::app_restore::AppRestoreArcTaskHandler::GetForProfile(profile); + ArcInitialOptInNotifier::GetForProfile(profile); if (arc::IsArcVmEnabled()) { // ARCVM-only services.
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.cc b/chrome/browser/ash/arc/session/arc_session_manager.cc index 0988602..5385f13 100644 --- a/chrome/browser/ash/arc/session/arc_session_manager.cc +++ b/chrome/browser/ash/arc/session/arc_session_manager.cc
@@ -1243,6 +1243,9 @@ switch (result) { case ArcRequirementChecker::RequirementCheckResult::kOk: VLOG(1) << "Starting ARC for first sign in."; + for (auto& observer : observer_list_) + observer.OnArcOptInUserAction(); + StartArc(); break; case ArcRequirementChecker::RequirementCheckResult::
diff --git a/chrome/browser/ash/arc/session/arc_session_manager_observer.h b/chrome/browser/ash/arc/session/arc_session_manager_observer.h index a4bcda3..f13f7f2 100644 --- a/chrome/browser/ash/arc/session/arc_session_manager_observer.h +++ b/chrome/browser/ash/arc/session/arc_session_manager_observer.h
@@ -18,6 +18,11 @@ // is represented by "arc.enabled" preference, is updated. virtual void OnArcPlayStoreEnabledChanged(bool enabled) {} + // Called with when user opted-in for ARC and ARC is going to be created for + // this user. I.e. successful user action triggered ARC user instance + // initialization. + virtual void OnArcOptInUserAction() {} + // Called to notify that checking of Android management status started // during the opt-in flow. virtual void OnArcOptInManagementCheckStarted() {}
diff --git a/chrome/browser/ash/crosapi/browser_loader.cc b/chrome/browser/ash/crosapi/browser_loader.cc index 90a0b2c5..839ccdb 100644 --- a/chrome/browser/ash/crosapi/browser_loader.cc +++ b/chrome/browser/ash/crosapi/browser_loader.cc
@@ -206,21 +206,19 @@ return; } - // If the user has specified to force using stateful or rootfs lacros-chrome - // binary, force the selection. - const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - if (cmdline->HasSwitch(browser_util::kLacrosSelectionSwitch)) { + // If the LacrosSelection policy or the user have specified to force using + // stateful or rootfs lacros-chrome binary, force the selection. + if (absl::optional<browser_util::LacrosSelection> lacros_selection = + browser_util::DetermineLacrosSelection()) { // TODO(crbug.com/1293250): We should check the version compatibility here, // too. - auto value = - cmdline->GetSwitchValueASCII(browser_util::kLacrosSelectionSwitch); - if (value == browser_util::kLacrosSelectionRootfs) { - LoadRootfsLacros(std::move(callback)); - return; - } - if (value == browser_util::kLacrosSelectionStateful) { - LoadStatefulLacros(std::move(callback)); - return; + switch (lacros_selection.value()) { + case browser_util::LacrosSelection::kRootfs: + LoadRootfsLacros(std::move(callback)); + return; + case browser_util::LacrosSelection::kStateful: + LoadStatefulLacros(std::move(callback)); + return; } }
diff --git a/chrome/browser/ash/crosapi/browser_loader_unittest.cc b/chrome/browser/ash/crosapi/browser_loader_unittest.cc index 034d6cafa22..fc6c330 100644 --- a/chrome/browser/ash/crosapi/browser_loader_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_loader_unittest.cc
@@ -10,13 +10,17 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" +#include "base/test/scoped_command_line.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" #include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/component_updater/fake_cros_component_manager.h" #include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chromeos/ash/components/dbus/upstart/fake_upstart_client.h" #include "components/component_updater/mock_component_updater_service.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/policy_constants.h" #include "components/update_client/update_client.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,6 +36,33 @@ constexpr char kLacrosMounterUpstartJob[] = "lacros_2dmounter"; constexpr char kLacrosUnmounterUpstartJob[] = "lacros_2dunmounter"; +// This implementation of RAII for LacrosSelection is to make it easy reset +// the state between runs. +class ScopedLacrosSelectionCache { + public: + explicit ScopedLacrosSelectionCache( + browser_util::LacrosSelectionPolicy lacros_selection) { + SetLacrosSelection(lacros_selection); + } + ScopedLacrosSelectionCache(const ScopedLacrosSelectionCache&) = delete; + ScopedLacrosSelectionCache& operator=(const ScopedLacrosSelectionCache&) = + delete; + ~ScopedLacrosSelectionCache() { + browser_util::ClearLacrosSelectionCacheForTest(); + } + + private: + void SetLacrosSelection( + browser_util::LacrosSelectionPolicy lacros_selection) { + policy::PolicyMap policy; + policy.Set(policy::key::kLacrosSelection, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, + base::Value(GetLacrosSelectionPolicyName(lacros_selection)), + /*external_data_fetcher=*/nullptr); + browser_util::CacheLacrosSelection(policy); + } +}; + } // namespace class BrowserLoaderTest : public testing::Test { @@ -229,4 +260,70 @@ EXPECT_TRUE(callback_called); } +TEST_F(BrowserLoaderTest, OnLoadSelectionPolicyIsRootfs) { + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kRootfs); + base::test::ScopedCommandLine command_line; + command_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionStateful); + + base::test::TestFuture<base::FilePath, LacrosSelection, base::Version> future; + browser_loader_->Load(future.GetCallback<const base::FilePath&, + LacrosSelection, base::Version>()); + + const LacrosSelection selection = future.Get<1>(); + EXPECT_EQ(selection, LacrosSelection::kRootfs); +} + +TEST_F(BrowserLoaderTest, OnLoadSelectionPolicyIsStateful) { + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kStateful); + base::test::ScopedCommandLine command_line; + command_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionRootfs); + + base::test::TestFuture<base::FilePath, LacrosSelection, base::Version> future; + browser_loader_->Load(future.GetCallback<const base::FilePath&, + LacrosSelection, base::Version>()); + + const LacrosSelection selection = future.Get<1>(); + EXPECT_EQ(selection, LacrosSelection::kStateful); +} + +TEST_F(BrowserLoaderTest, + OnLoadSelectionPolicyIsUserChoiceAndCommandLineIsRootfs) { + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kUserChoice); + base::test::ScopedCommandLine command_line; + command_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionRootfs); + + base::test::TestFuture<base::FilePath, LacrosSelection, base::Version> future; + browser_loader_->Load(future.GetCallback<const base::FilePath&, + LacrosSelection, base::Version>()); + + const LacrosSelection selection = future.Get<1>(); + EXPECT_EQ(selection, LacrosSelection::kRootfs); +} + +TEST_F(BrowserLoaderTest, + OnLoadSelectionPolicyIsUserChoiceAndCommandLineIsStateful) { + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kUserChoice); + base::test::ScopedCommandLine command_line; + command_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionStateful); + + base::test::TestFuture<base::FilePath, LacrosSelection, base::Version> future; + browser_loader_->Load(future.GetCallback<const base::FilePath&, + LacrosSelection, base::Version>()); + + const LacrosSelection selection = future.Get<1>(); + EXPECT_EQ(selection, LacrosSelection::kStateful); +} + } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index f1e7a51..1e9ac8b 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -61,12 +61,16 @@ absl::optional<LacrosDataBackwardMigrationMode> g_lacros_data_backward_migration_mode; +// At session start the value for LacrosSelection logic is applied and the +// result is stored in this variable which is used after that as a cache. +absl::optional<LacrosSelectionPolicy> g_lacros_selection_cache; + // The rootfs lacros-chrome metadata keys. constexpr char kLacrosMetadataContentKey[] = "content"; constexpr char kLacrosMetadataVersionKey[] = "version"; // The conversion map for LacrosAvailability policy data. The values must match -// the ones from policy_templates.json. +// the ones from LacrosAvailability.yaml. constexpr auto kLacrosAvailabilityMap = base::MakeFixedFlatMap<base::StringPiece, LacrosAvailability>({ {"user_choice", LacrosAvailability::kUserChoice}, @@ -90,6 +94,15 @@ LacrosDataBackwardMigrationMode::kKeepAll}, }); +// The conversion map for LacrosSelection policy data. The values must match +// the ones from LacrosSelection.yaml. +constexpr auto kLacrosSelectionPolicyMap = + base::MakeFixedFlatMap<base::StringPiece, LacrosSelectionPolicy>({ + {"user_choice", LacrosSelectionPolicy::kUserChoice}, + {"rootfs", LacrosSelectionPolicy::kRootfs}, + {"stateful", LacrosSelectionPolicy::kStateful}, + }); + // Some account types require features that aren't yet supported by lacros. // See https://crbug.com/1080693 bool IsUserTypeAllowed(const User* user) { @@ -904,6 +917,51 @@ value ? value->GetString() : base::StringPiece()); } +void CacheLacrosSelection(const policy::PolicyMap& map) { + if (g_lacros_selection_cache.has_value()) { + // Some browser tests might call this multiple times. + LOG(ERROR) << "Trying to cache LacrosSelection and the value was set"; + return; + } + + const base::Value* value = + map.GetValue(policy::key::kLacrosSelection, base::Value::Type::STRING); + g_lacros_selection_cache = ParseLacrosSelectionPolicy( + value ? value->GetString() : base::StringPiece()); +} + +LacrosSelectionPolicy GetCachedLacrosSelectionPolicy() { + if (g_lacros_selection_cache) + return g_lacros_selection_cache.value(); + + return LacrosSelectionPolicy::kUserChoice; +} + +absl::optional<LacrosSelection> DetermineLacrosSelection() { + switch (GetCachedLacrosSelectionPolicy()) { + case LacrosSelectionPolicy::kRootfs: + return LacrosSelection::kRootfs; + case LacrosSelectionPolicy::kStateful: + return LacrosSelection::kStateful; + case LacrosSelectionPolicy::kUserChoice: + break; + } + + const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + + if (!cmdline->HasSwitch(browser_util::kLacrosSelectionSwitch)) + return absl::nullopt; + + auto value = + cmdline->GetSwitchValueASCII(browser_util::kLacrosSelectionSwitch); + if (value == browser_util::kLacrosSelectionRootfs) + return LacrosSelection::kRootfs; + if (value == browser_util::kLacrosSelectionStateful) + return LacrosSelection::kStateful; + + return absl::nullopt; +} + ComponentInfo GetLacrosComponentInfoForChannel(version_info::Channel channel) { // We default to the Dev component for UNKNOWN channels. static const auto kChannelToComponentInfoMap = @@ -978,6 +1036,10 @@ g_lacros_data_backward_migration_mode.reset(); } +void ClearLacrosSelectionCacheForTest() { + g_lacros_selection_cache.reset(); +} + MigrationMode GetMigrationMode(const user_manager::User* user, PolicyInitState policy_init_state) { if (base::FeatureList::IsEnabled( @@ -1110,6 +1172,16 @@ return absl::nullopt; } +absl::optional<LacrosSelectionPolicy> ParseLacrosSelectionPolicy( + base::StringPiece value) { + auto* it = kLacrosSelectionPolicyMap.find(value); + if (it != kLacrosSelectionPolicyMap.end()) + return it->second; + + LOG(ERROR) << "Unknown LacrosSelection policy value is passed: " << value; + return absl::nullopt; +} + base::StringPiece GetLacrosAvailabilityPolicyName(LacrosAvailability value) { for (const auto& entry : kLacrosAvailabilityMap) { if (entry.second == value) @@ -1142,6 +1214,16 @@ return base::StringPiece(); } +base::StringPiece GetLacrosSelectionPolicyName(LacrosSelectionPolicy value) { + for (const auto& entry : kLacrosSelectionPolicyMap) { + if (entry.second == value) + return entry.first; + } + + NOTREACHED(); + return base::StringPiece(); +} + bool IsAshBrowserSyncEnabled() { // Turn off sync from Ash if Lacros is enabled and Ash web browser is // disabled.
diff --git a/chrome/browser/ash/crosapi/browser_util.h b/chrome/browser/ash/crosapi/browser_util.h index 5113159..4dfec38 100644 --- a/chrome/browser/ash/crosapi/browser_util.h +++ b/chrome/browser/ash/crosapi/browser_util.h
@@ -80,6 +80,20 @@ kLacrosOnly = 4 }; +// Represents the policy indicating which Lacros browser to launch, named +// LacrosSelection. The values shall be consistent with the controlling +// policy. Unlike `LacrosSelection` representing which lacros to select, +// `LacrosSelectionPolicy` represents how to decide which lacros to select. +enum class LacrosSelectionPolicy { + // Indicates that the user decides which Lacros browser to launch: rootfs or + // stateful. + kUserChoice = 0, + // Indicates that rootfs Lacros will always be launched. + kRootfs = 1, + // Indicates that stateful Lacros will always be launched. + kStateful = 2, +}; + // Represents the different options available for lacros selection. enum class LacrosSelection { kRootfs = 0, @@ -351,6 +365,20 @@ // LacrosDataBackwardMigrationMode policy. void CacheLacrosDataBackwardMigrationMode(const policy::PolicyMap& map); +// To be called at primary user login, to cache the policy value for +// LacrosSelection policy. The effective value of the policy does not +// change for the duration of the user session, so cached value shall be +// checked. +void CacheLacrosSelection(const policy::PolicyMap& map); + +// Returns cached value of LacrosSelection policy. See `CacheLacrosSelection` +// for details. +LacrosSelectionPolicy GetCachedLacrosSelectionPolicy(); + +// Returns lacros selection option according to LarcrosSelectionPolicy and +// lacros-selection flag. Returns nullopt if there is no preference. +absl::optional<LacrosSelection> DetermineLacrosSelection(); + // Returns the lacros ComponentInfo for a given channel. ComponentInfo GetLacrosComponentInfoForChannel(version_info::Channel channel); @@ -385,6 +413,9 @@ // Clears the cached value for LacrosDataBackwardMigrationMode. void ClearLacrosDataBackwardMigrationModeCacheForTest(); +// Clears the cached value for LacrosSelection policy. +void ClearLacrosSelectionCacheForTest(); + bool IsProfileMigrationEnabled(const AccountId& account_id); // Returns true if the profile migration can run, but not yet completed. @@ -458,7 +489,13 @@ absl::optional<LacrosAvailability> ParseLacrosAvailability( base::StringPiece value); -// Returns the policy value name from the given value. +// Parses the string representation of LacrosSelection policy value into the +// enum value. Returns nullopt on unknown value. +absl::optional<LacrosSelectionPolicy> ParseLacrosSelectionPolicy( + base::StringPiece value); + +// Returns the policy LacrosAvailability value name from the given value. +// Returned StringPiece is guaranteed to never be invalidated base::StringPiece GetLacrosAvailabilityPolicyName(LacrosAvailability value); // Parses the string representation of LacrosDataBackwardMigrationMode policy @@ -470,6 +507,10 @@ base::StringPiece GetLacrosDataBackwardMigrationModeName( LacrosDataBackwardMigrationMode value); +// Returns the LacrosSelection policy value name from the given value. Returned +// StringPiece is guaranteed to never be invalidated. +base::StringPiece GetLacrosSelectionPolicyName(LacrosSelectionPolicy value); + // Stores that "Go to files button" on the migration error screen is clicked. void SetGotoFilesClicked(PrefService* local_state, const std::string& user_id_hash);
diff --git a/chrome/browser/ash/crosapi/browser_util_unittest.cc b/chrome/browser/ash/crosapi/browser_util_unittest.cc index 36be553..0cd2a067 100644 --- a/chrome/browser/ash/crosapi/browser_util_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_util_unittest.cc
@@ -68,6 +68,33 @@ } }; +// This implementation of RAII for LacrosSelection is to make it easy reset +// the state between runs. +class ScopedLacrosSelectionCache { + public: + explicit ScopedLacrosSelectionCache( + browser_util::LacrosSelectionPolicy lacros_selection) { + SetLacrosSelection(lacros_selection); + } + ScopedLacrosSelectionCache(const ScopedLacrosSelectionCache&) = delete; + ScopedLacrosSelectionCache& operator=(const ScopedLacrosSelectionCache&) = + delete; + ~ScopedLacrosSelectionCache() { + browser_util::ClearLacrosSelectionCacheForTest(); + } + + private: + void SetLacrosSelection( + browser_util::LacrosSelectionPolicy lacros_selection) { + policy::PolicyMap policy; + policy.Set(policy::key::kLacrosSelection, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, + base::Value(GetLacrosSelectionPolicyName(lacros_selection)), + /*external_data_fetcher=*/nullptr); + browser_util::CacheLacrosSelection(policy); + } +}; + } // namespace class BrowserUtilTest : public testing::Test { @@ -1116,4 +1143,64 @@ EXPECT_EQ(serial_number.value(), expected_serial_number); } +TEST_F(BrowserUtilTest, LacrosSelection) { + // Neither policy nor command line have any preference on Lacros selection. + EXPECT_FALSE(browser_util::DetermineLacrosSelection()); + + { + // LacrosSelection policy has precedence over command line. + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kRootfs); + base::test::ScopedCommandLine cmd_line; + cmd_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionStateful); + EXPECT_EQ(browser_util::DetermineLacrosSelection(), + LacrosSelection::kRootfs); + } + + { + // LacrosSelection policy has precedence over command line. + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kStateful); + base::test::ScopedCommandLine cmd_line; + cmd_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionRootfs); + EXPECT_EQ(browser_util::DetermineLacrosSelection(), + LacrosSelection::kStateful); + } + + { + // LacrosSelection allows command line check, but command line is not set. + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kUserChoice); + EXPECT_FALSE(browser_util::DetermineLacrosSelection()); + } + + { + // LacrosSelection allows command line check. + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kUserChoice); + base::test::ScopedCommandLine cmd_line; + cmd_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionRootfs); + EXPECT_EQ(browser_util::DetermineLacrosSelection(), + LacrosSelection::kRootfs); + } + + { + // LacrosSelection allows command line check. + ScopedLacrosSelectionCache cache( + browser_util::LacrosSelectionPolicy::kUserChoice); + base::test::ScopedCommandLine cmd_line; + cmd_line.GetProcessCommandLine()->AppendSwitchASCII( + browser_util::kLacrosSelectionSwitch, + browser_util::kLacrosSelectionStateful); + EXPECT_EQ(browser_util::DetermineLacrosSelection(), + LacrosSelection::kStateful); + } +} + } // namespace crosapi
diff --git a/chrome/browser/ash/net/network_diagnostics/http_request_manager.cc b/chrome/browser/ash/net/network_diagnostics/http_request_manager.cc index 2bebce7..d951c08 100644 --- a/chrome/browser/ash/net/network_diagnostics/http_request_manager.cc +++ b/chrome/browser/ash/net/network_diagnostics/http_request_manager.cc
@@ -31,16 +31,18 @@ semantics { sender: "NetworkDiagnosticsRoutines" description: "Routines send network traffic (http requests) to " - "hosts in order to validate the internet connection on a device." - trigger: - "A routine makes an http request." + "hosts in order to validate the internet connection on a device." + trigger: "A routine makes an http request." data: - "No data other than the path is sent. No user identifier is " - "sent along with the data." + "No data other than the path is sent. No user identifier is " + "sent along with the data." destination: WEBSITE } policy { cookies_allowed: NO + policy_exception_justification: + "No policy defined to enable/disable or limit this request as this " + "is on-demand user initiated operation to do the network diagnostics." } )"); }
diff --git a/chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.cc b/chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.cc new file mode 100644 index 0000000..c8bbf43 --- /dev/null +++ b/chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.cc
@@ -0,0 +1,54 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.h" + +#if !BUILDFLAG(IS_CHROMEOS_ASH) +#error This file shall only be used in ash. +#endif + +#include "chrome/common/pref_names.h" +#include "components/policy/core/browser/policy_error_map.h" +#include "components/policy/policy_constants.h" +#include "components/prefs/pref_value_map.h" +#include "components/strings/grit/components_strings.h" + +namespace policy { + +LacrosSelectionPolicyHandler::LacrosSelectionPolicyHandler() + : TypeCheckingPolicyHandler(key::kLacrosSelection, + base::Value::Type::STRING) {} + +bool LacrosSelectionPolicyHandler::CheckPolicySettings( + const PolicyMap& policies, + PolicyErrorMap* errors) { + return GetValue(policies, errors).has_value(); +} + +void LacrosSelectionPolicyHandler::ApplyPolicySettings( + const PolicyMap& policies, + PrefValueMap* prefs) { + auto enum_value = GetValue(policies, nullptr); + if (enum_value.has_value()) + prefs->SetInteger(prefs::kLacrosSelection, static_cast<int>(*enum_value)); +} + +absl::optional<crosapi::browser_util::LacrosSelectionPolicy> +LacrosSelectionPolicyHandler::GetValue(const PolicyMap& policies, + PolicyErrorMap* errors) { + const base::Value* value; + const bool value_found = CheckAndGetValue(policies, errors, &value) && value; + if (!value_found) + return absl::nullopt; + + auto parsed = + crosapi::browser_util::ParseLacrosSelectionPolicy(value->GetString()); + if (!parsed.has_value() && errors) { + errors->AddError(policy_name(), IDS_POLICY_INVALID_SELECTION_ERROR, + "LacrosSelection value"); + } + return parsed; +} + +} // namespace policy
diff --git a/chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.h b/chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.h new file mode 100644 index 0000000..cc867d3 --- /dev/null +++ b/chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.h
@@ -0,0 +1,40 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_POLICY_HANDLERS_LACROS_SELECTION_POLICY_HANDLER_H_ +#define CHROME_BROWSER_ASH_POLICY_HANDLERS_LACROS_SELECTION_POLICY_HANDLER_H_ + +#include "build/chromeos_buildflags.h" +#include "chrome/browser/ash/crosapi/browser_util.h" +#include "components/policy/core/browser/configuration_policy_handler.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +class PrefValueMap; + +namespace policy { + +class PolicyMap; + +// The handler for LacrosSelection selection policy which maps string-enum +// policy values to `LacrosSelectionPolicy` enum stored in `PolicyMap`. +class LacrosSelectionPolicyHandler : public TypeCheckingPolicyHandler { + public: + LacrosSelectionPolicyHandler(); + + // ConfigurationPolicyHandler: + bool CheckPolicySettings(const PolicyMap& policies, + PolicyErrorMap* errors) override; + + void ApplyPolicySettings(const PolicyMap& policies, + PrefValueMap* prefs) override; + + private: + absl::optional<crosapi::browser_util::LacrosSelectionPolicy> GetValue( + const PolicyMap& policies, + PolicyErrorMap* errors); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_ASH_POLICY_HANDLERS_LACROS_SELECTION_POLICY_HANDLER_H_
diff --git a/chrome/browser/ash/preferences.cc b/chrome/browser/ash/preferences.cc index fdc83ae..5b32656 100644 --- a/chrome/browser/ash/preferences.cc +++ b/chrome/browser/ash/preferences.cc
@@ -146,6 +146,10 @@ registry->RegisterIntegerPref( ::prefs::kLacrosLaunchSwitch, static_cast<int>(crosapi::browser_util::LacrosAvailability::kUserChoice)); + registry->RegisterIntegerPref( + ::prefs::kLacrosSelection, + static_cast<int>( + crosapi::browser_util::LacrosSelectionPolicy::kUserChoice)); registry->RegisterStringPref(::prefs::kLacrosDataBackwardMigrationMode, ""); registry->RegisterBooleanPref(prefs::kDeviceSystemWideTracingEnabled, true); registry->RegisterBooleanPref(
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc index e74a539..89c62b2 100644 --- a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc +++ b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
@@ -368,19 +368,9 @@ // or `SetSystemAppsForTesting()` has been called. if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType) && skip_app_installation_in_test_) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce( - &SystemWebAppManager::OnAppsSynchronized, - weak_ptr_factory_.GetWeakPtr(), should_force_install_apps, - install_start_time, - /*install_results=*/ - std::map<GURL, - web_app::ExternallyManagedAppManager::InstallResult>(), - /*uninstall_results=*/std::map<GURL, bool>())); - - return; + install_options_list.clear(); } + provider_->externally_managed_app_manager().SynchronizeInstalledApps( std::move(install_options_list), web_app::ExternalInstallSource::kSystemInstalled,
diff --git a/chrome/browser/background/background_application_list_model_unittest.cc b/chrome/browser/background/background_application_list_model_unittest.cc index 0b62606f..83af0e8 100644 --- a/chrome/browser/background/background_application_list_model_unittest.cc +++ b/chrome/browser/background/background_application_list_model_unittest.cc
@@ -101,9 +101,9 @@ std::string error; scoped_refptr<Extension> extension; - extension = Extension::Create(bogus_file_pathname(name), - extensions::mojom::ManifestLocation::kInternal, - manifest, Extension::NO_FLAGS, &error); + extension = Extension::Create( + bogus_file_pathname(name), extensions::mojom::ManifestLocation::kInternal, + manifest.GetDict(), Extension::NO_FLAGS, &error); // Cannot ASSERT_* here because that attempts an illegitimate return. // Cannot EXPECT_NE here because that assumes non-pointers unlike EXPECT_EQ
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc index f9d2020..a6a2b9d 100644 --- a/chrome/browser/background/background_contents_service.cc +++ b/chrome/browser/background/background_contents_service.cc
@@ -641,17 +641,18 @@ // already an entry for this application, no need to do anything. // TODO(atwilson): Verify that this is the desired behavior based on developer // feedback (http://crbug.com/47118). - DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); - base::Value* pref = update.Get(); + ScopedDictPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); + base::Value::Dict& pref = update.Get(); const std::string& appid = GetParentApplicationId(background_contents); - if (pref->FindDictKey(appid)) + if (pref.FindDict(appid)) { return; + } // No entry for this application yet, so add one. - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey(kUrlKey, background_contents->GetURL().spec()); - dict.SetStringKey(kFrameNameKey, contents_map_[appid].frame_name); - pref->SetKey(appid, std::move(dict)); + base::Value::Dict dict; + dict.Set(kUrlKey, background_contents->GetURL().spec()); + dict.Set(kFrameNameKey, contents_map_[appid].frame_name); + pref.Set(appid, std::move(dict)); } bool BackgroundContentsService::HasRegisteredBackgroundContents( @@ -669,8 +670,8 @@ return; DCHECK(IsTracked(background_contents)); const std::string& appid = GetParentApplicationId(background_contents); - DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); - update.Get()->RemoveKey(appid); + ScopedDictPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); + update->Remove(appid); } void BackgroundContentsService::ShutdownAssociatedBackgroundContents(
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 778626ea..0b97572 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -1034,6 +1034,9 @@ RegisterWebUIControllerInterfaceBinder< metrics_reporter::mojom::PageMetricsHost, TabSearchUI, NewTabPageUI>( map); + } else { + RegisterWebUIControllerInterfaceBinder< + metrics_reporter::mojom::PageMetricsHost, NewTabPageUI>(map); } RegisterWebUIControllerInterfaceBinder<
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 03210d3..10cf5bb 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3298,18 +3298,21 @@ } bool ChromeContentBrowserClient::IsSharedStorageAllowed( + content::BrowserContext* browser_context, content::RenderFrameHost* rfh, const url::Origin& top_frame_origin, const url::Origin& accessing_origin) { - Profile* profile = Profile::FromBrowserContext(rfh->GetBrowserContext()); + Profile* profile = Profile::FromBrowserContext(browser_context); auto* privacy_sandbox_settings = PrivacySandboxSettingsFactory::GetForProfile(profile); DCHECK(privacy_sandbox_settings); bool allowed = privacy_sandbox_settings->IsSharedStorageAllowed( top_frame_origin, accessing_origin); - content_settings::PageSpecificContentSettings::BrowsingDataAccessed( - rfh, blink::StorageKey(accessing_origin), - BrowsingDataModel::StorageType::kSharedStorage, !allowed); + if (rfh) { + content_settings::PageSpecificContentSettings::BrowsingDataAccessed( + rfh, blink::StorageKey(accessing_origin), + BrowsingDataModel::StorageType::kSharedStorage, !allowed); + } return allowed; }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 3284619..ead5dfd 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -321,7 +321,8 @@ const url::Origin* impression_origin, const url::Origin* conversion_origin, const url::Origin* reporting_origin) override; - bool IsSharedStorageAllowed(content::RenderFrameHost* rfh, + bool IsSharedStorageAllowed(content::BrowserContext* browser_context, + content::RenderFrameHost* rfh, const url::Origin& top_frame_origin, const url::Origin& accessing_origin) override; bool IsPrivateAggregationAllowed(
diff --git a/chrome/browser/devtools/protocol/cast_handler_unittest.cc b/chrome/browser/devtools/protocol/cast_handler_unittest.cc index b6cbc67..b0bd35c 100644 --- a/chrome/browser/devtools/protocol/cast_handler_unittest.cc +++ b/chrome/browser/devtools/protocol/cast_handler_unittest.cc
@@ -83,8 +83,6 @@ protected: void EnableHandler() { - EXPECT_CALL(*router_, RegisterMediaRoutesObserver(_)) - .WillOnce(SaveArg<0>(&routes_observer_)); EXPECT_CALL(*router_, RegisterMediaSinksObserver(_)) .WillRepeatedly( WithArg<0>([this](media_router::MediaSinksObserver* observer) { @@ -102,7 +100,6 @@ std::unique_ptr<CastHandler> handler_; media_router::MockMediaRouter* router_ = nullptr; - media_router::MediaRoutesObserver* routes_observer_ = nullptr; media_router::MediaSinksObserver* desktop_sinks_observer_ = nullptr; media_router::MediaSinksObserver* sinks_observer_ = nullptr; }; @@ -201,14 +198,14 @@ TEST_F(CastHandlerTest, StopCasting) { sinks_observer_->OnSinksUpdated({sink1, sink2}, {}); - routes_observer_->OnRoutesUpdated({Route1()}); + router_->routes_observers().begin()->OnRoutesUpdated({Route1()}); EXPECT_CALL(*router_, TerminateRoute(kRouteId1)); EXPECT_TRUE(handler_->StopCasting(kSinkName1).IsSuccess()); } TEST_F(CastHandlerTest, StopCastingWithInvalidName) { sinks_observer_->OnSinksUpdated({sink1, sink2}, {}); - routes_observer_->OnRoutesUpdated({Route1()}); + router_->routes_observers().begin()->OnRoutesUpdated({Route1()}); // Attempting to stop casting to a sink without a route should fail. EXPECT_TRUE(handler_->StopCasting(kSinkName2).IsError()); }
diff --git a/chrome/browser/download/bubble/download_bubble_controller.cc b/chrome/browser/download/bubble/download_bubble_controller.cc index c13525e9..4aec509 100644 --- a/chrome/browser/download/bubble/download_bubble_controller.cc +++ b/chrome/browser/download/bubble/download_bubble_controller.cc
@@ -391,10 +391,12 @@ case DownloadCommands::DISCARD: DownloadItemWarningData::AddWarningActionEvent( model->GetDownloadItem(), - is_main_view ? DownloadItemWarningData::BUBBLE_MAINPAGE - : DownloadItemWarningData::BUBBLE_SUBPAGE, - command == DownloadCommands::KEEP ? DownloadItemWarningData::PROCEED - : DownloadItemWarningData::DISCARD); + is_main_view + ? DownloadItemWarningData::WarningSurface::BUBBLE_MAINPAGE + : DownloadItemWarningData::WarningSurface::BUBBLE_SUBPAGE, + command == DownloadCommands::KEEP + ? DownloadItemWarningData::WarningAction::PROCEED + : DownloadItemWarningData::WarningAction::DISCARD); commands.ExecuteCommand(command); break; case DownloadCommands::REVIEW:
diff --git a/chrome/browser/download/download_danger_prompt.cc b/chrome/browser/download/download_danger_prompt.cc index 58f7169d4..8dc335d7 100644 --- a/chrome/browser/download/download_danger_prompt.cc +++ b/chrome/browser/download/download_danger_prompt.cc
@@ -69,15 +69,16 @@ DownloadItemWarningData::WarningAction warning_action; switch (action) { case Action::ACCEPT: - warning_action = DownloadItemWarningData::PROCEED; + warning_action = DownloadItemWarningData::WarningAction::PROCEED; break; case Action::CANCEL: - warning_action = DownloadItemWarningData::CANCEL; + warning_action = DownloadItemWarningData::WarningAction::CANCEL; break; case Action::DISMISS: - warning_action = DownloadItemWarningData::CLOSE; + warning_action = DownloadItemWarningData::WarningAction::CLOSE; break; } DownloadItemWarningData::AddWarningActionEvent( - download, DownloadItemWarningData::DOWNLOAD_PROMPT, warning_action); + download, DownloadItemWarningData::WarningSurface::DOWNLOAD_PROMPT, + warning_action); }
diff --git a/chrome/browser/download/download_item_warning_data.cc b/chrome/browser/download/download_item_warning_data.cc index 3c729956..f20a3a5 100644 --- a/chrome/browser/download/download_item_warning_data.cc +++ b/chrome/browser/download/download_item_warning_data.cc
@@ -46,6 +46,10 @@ base::UmaHistogramEnumeration( "Download.WarningData.SurfaceWithoutWarningShown", surface); } + +void RecordWarningActionAdded(WarningAction action) { + base::UmaHistogramEnumeration("Download.WarningData.ActionAdded", action); +} } // namespace // static @@ -81,6 +85,7 @@ if (data->warning_first_shown_time_.is_null()) { RecordAddWarningActionEventOutcome( AddWarningActionEventOutcome::ADDED_WARNING_FIRST_SHOWN); + RecordWarningActionAdded(action); data->warning_first_shown_time_ = base::Time::Now(); } else { RecordAddWarningActionEventOutcome( @@ -102,12 +107,15 @@ int64_t action_latency = (base::Time::Now() - data->warning_first_shown_time_).InMilliseconds(); bool is_terminal_action = - (action == PROCEED || action == DISCARD) ? true : false; + (action == WarningAction::PROCEED || action == WarningAction::DISCARD) + ? true + : false; DCHECK_NE(WarningAction::SHOWN, action); data->action_events_.emplace_back(surface, action, action_latency, is_terminal_action); RecordAddWarningActionEventOutcome( AddWarningActionEventOutcome::ADDED_WARNING_ACTION); + RecordWarningActionAdded(action); } // static @@ -116,57 +124,57 @@ const WarningActionEvent& event) { ClientSafeBrowsingReportRequest::DownloadWarningAction action; switch (event.surface) { - case DownloadItemWarningData::BUBBLE_MAINPAGE: + case DownloadItemWarningData::WarningSurface::BUBBLE_MAINPAGE: action.set_surface(ClientSafeBrowsingReportRequest:: DownloadWarningAction::BUBBLE_MAINPAGE); break; - case DownloadItemWarningData::BUBBLE_SUBPAGE: + case DownloadItemWarningData::WarningSurface::BUBBLE_SUBPAGE: action.set_surface(ClientSafeBrowsingReportRequest:: DownloadWarningAction::BUBBLE_SUBPAGE); break; - case DownloadItemWarningData::DOWNLOADS_PAGE: + case DownloadItemWarningData::WarningSurface::DOWNLOADS_PAGE: action.set_surface(ClientSafeBrowsingReportRequest:: DownloadWarningAction::DOWNLOADS_PAGE); break; - case DownloadItemWarningData::DOWNLOAD_PROMPT: + case DownloadItemWarningData::WarningSurface::DOWNLOAD_PROMPT: action.set_surface(ClientSafeBrowsingReportRequest:: DownloadWarningAction::DOWNLOAD_PROMPT); break; } switch (event.action) { - case DownloadItemWarningData::PROCEED: + case DownloadItemWarningData::WarningAction::PROCEED: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::PROCEED); break; - case DownloadItemWarningData::DISCARD: + case DownloadItemWarningData::WarningAction::DISCARD: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::DISCARD); break; - case DownloadItemWarningData::KEEP: + case DownloadItemWarningData::WarningAction::KEEP: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::KEEP); break; - case DownloadItemWarningData::CLOSE: + case DownloadItemWarningData::WarningAction::CLOSE: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::CLOSE); break; - case DownloadItemWarningData::CANCEL: + case DownloadItemWarningData::WarningAction::CANCEL: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::CANCEL); break; - case DownloadItemWarningData::DISMISS: + case DownloadItemWarningData::WarningAction::DISMISS: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::DISMISS); break; - case DownloadItemWarningData::BACK: + case DownloadItemWarningData::WarningAction::BACK: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::BACK); break; - case DownloadItemWarningData::OPEN_SUBPAGE: + case DownloadItemWarningData::WarningAction::OPEN_SUBPAGE: action.set_action( ClientSafeBrowsingReportRequest::DownloadWarningAction::OPEN_SUBPAGE); break; - case DownloadItemWarningData::SHOWN: + case DownloadItemWarningData::WarningAction::SHOWN: NOTREACHED(); break; }
diff --git a/chrome/browser/download/download_item_warning_data.h b/chrome/browser/download/download_item_warning_data.h index 84f8838..92c2716 100644 --- a/chrome/browser/download/download_item_warning_data.h +++ b/chrome/browser/download/download_item_warning_data.h
@@ -24,8 +24,8 @@ // go/chrome-download-warning-surfaces for details. // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. - enum WarningSurface { - // Applicable actions: DISCARD + enum class WarningSurface { + // Applicable actions: DISCARD, OPEN_SUBPAGE BUBBLE_MAINPAGE = 1, // Applicable actions: PROCEED, DISCARD, DISMISS, CLOSE, BACK BUBBLE_SUBPAGE = 2, @@ -37,7 +37,9 @@ }; // Users action on the warning surface. - enum WarningAction { + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class WarningAction { // The warning is shown. This is a special action that may not be triggered // by user. We will use this action as the anchor to track the latency of // other actions. @@ -61,7 +63,8 @@ // to the bubble main page. BACK = 7, // The user has opened the subpage from the main page. - OPEN_SUBPAGE = 8 + OPEN_SUBPAGE = 8, + kMaxValue = OPEN_SUBPAGE }; struct WarningActionEvent {
diff --git a/chrome/browser/download/download_item_warning_data_unittest.cc b/chrome/browser/download/download_item_warning_data_unittest.cc index ebd0af6..47b130b8 100644 --- a/chrome/browser/download/download_item_warning_data_unittest.cc +++ b/chrome/browser/download/download_item_warning_data_unittest.cc
@@ -39,13 +39,14 @@ if (actual_event.surface != expected_surface) { success = false; ADD_FAILURE() << "Warning action event should have surface " - << expected_surface << ", but found " - << actual_event.surface; + << static_cast<int>(expected_surface) << ", but found " + << static_cast<int>(actual_event.surface); } if (actual_event.action != expected_action) { success = false; ADD_FAILURE() << "Warning action event should have action " - << expected_action << ", but found " << actual_event.action; + << static_cast<int>(expected_action) << ", but found " + << static_cast<int>(actual_event.action); } if (actual_event.action_latency_msec != expected_latency) { success = false;
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc index 123b67a..46de7ef 100644 --- a/chrome/browser/download/download_ui_model.cc +++ b/chrome/browser/download/download_ui_model.cc
@@ -1780,3 +1780,33 @@ void DownloadUIModel::DetermineAndSetShouldPreferOpeningInBrowser( const base::FilePath& target_path, bool is_filetype_handled_safely) {} + +std::u16string DownloadUIModel::GetInProgressAccessibleAlertText() const { + // Prefer to announce the time remaining, if known. + base::TimeDelta remaining; + if (TimeRemaining(&remaining)) { + // If complete, skip this round: a completion status update is coming soon. + if (remaining.is_zero()) + return std::u16string(); + + const std::u16string remaining_string = + ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING, + ui::TimeFormat::LENGTH_SHORT, remaining); + return l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_STATUS_TIME_REMAINING_ACCESSIBLE_ALERT, remaining_string); + } + + // Time remaining is unknown, try to announce percent remaining. + if (PercentComplete() > 0) { + DCHECK_LE(PercentComplete(), 100); + return l10n_util::GetStringFUTF16Int( + IDS_DOWNLOAD_STATUS_PERCENT_COMPLETE_ACCESSIBLE_ALERT, + 100 - PercentComplete()); + } + + // Percent remaining is also unknown, announce bytes to download. + return l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_STATUS_IN_PROGRESS_ACCESSIBLE_ALERT, + ui::FormatBytes(GetTotalBytes()), + GetFileNameToReportUser().LossyDisplayName()); +}
diff --git a/chrome/browser/download/download_ui_model.h b/chrome/browser/download/download_ui_model.h index 69103e5..d289774e 100644 --- a/chrome/browser/download/download_ui_model.h +++ b/chrome/browser/download/download_ui_model.h
@@ -536,6 +536,10 @@ const base::FilePath& target_path, bool is_filetype_handled_safely); + // Returns the accessible alert text that should be announced when the + // download is in progress. + virtual std::u16string GetInProgressAccessibleAlertText() const; + protected: // Returns the MIME type of the download. virtual std::string GetMimeType() const;
diff --git a/chrome/browser/enterprise/idle/action.cc b/chrome/browser/enterprise/idle/action.cc index 235da753..71d89a7 100644 --- a/chrome/browser/enterprise/idle/action.cc +++ b/chrome/browser/enterprise/idle/action.cc
@@ -30,10 +30,11 @@ CloseBrowsersAction() : Action(ActionType::kCloseBrowsers) {} void Run(Profile* profile, Continuation continuation) override { - int minutes = profile->GetPrefs()->GetInteger(prefs::kIdleTimeout); + base::TimeDelta timeout = + profile->GetPrefs()->GetTimeDelta(prefs::kIdleTimeout); continuation_ = std::move(continuation); subscription_ = BrowserCloser::GetInstance()->ShowDialogAndCloseBrowsers( - profile, base::Minutes(minutes), + profile, timeout, base::BindOnce(&CloseBrowsersAction::OnCloseFinished, base::Unretained(this))); }
diff --git a/chrome/browser/enterprise/idle/idle_service.cc b/chrome/browser/enterprise/idle/idle_service.cc index 0e749d7..8d112b08 100644 --- a/chrome/browser/enterprise/idle/idle_service.cc +++ b/chrome/browser/enterprise/idle/idle_service.cc
@@ -33,10 +33,11 @@ IdleService::~IdleService() = default; void IdleService::OnIdleTimeoutPrefChanged() { - int minutes = profile_->GetPrefs()->GetInteger(prefs::kIdleTimeout); - if (minutes > 0) { + base::TimeDelta timeout = + profile_->GetPrefs()->GetTimeDelta(prefs::kIdleTimeout); + if (timeout.is_positive()) { // `is_idle_` will auto-update in 1 second, no need to set it here. - idle_threshold_ = base::Minutes(minutes); + idle_threshold_ = timeout; if (!polling_service_observation_.IsObserving()) { polling_service_observation_.Observe( ui::IdlePollingService::GetInstance());
diff --git a/chrome/browser/enterprise/idle/idle_service_factory.cc b/chrome/browser/enterprise/idle/idle_service_factory.cc index 625a5c6..cced806 100644 --- a/chrome/browser/enterprise/idle/idle_service_factory.cc +++ b/chrome/browser/enterprise/idle/idle_service_factory.cc
@@ -36,8 +36,7 @@ void IdleServiceFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - // TODO(crbug.com/1316551): Use TimeDeltaPref instead. - registry->RegisterIntegerPref(prefs::kIdleTimeout, 0); + registry->RegisterTimeDeltaPref(prefs::kIdleTimeout, base::TimeDelta()); registry->RegisterListPref(prefs::kIdleTimeoutActions); }
diff --git a/chrome/browser/enterprise/idle/idle_timeout_policy_handler.cc b/chrome/browser/enterprise/idle/idle_timeout_policy_handler.cc new file mode 100644 index 0000000..770e073 --- /dev/null +++ b/chrome/browser/enterprise/idle/idle_timeout_policy_handler.cc
@@ -0,0 +1,139 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise/idle/idle_timeout_policy_handler.h" + +#include <string> + +#include "base/json/values_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/time/time.h" +#include "base/values.h" +#include "chrome/browser/enterprise/idle/action.h" +#include "chrome/browser/prefs/session_startup_pref.h" +#include "chrome/common/pref_names.h" +#include "components/policy/core/browser/configuration_policy_handler.h" +#include "components/policy/core/browser/policy_error_map.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/schema.h" +#include "components/policy/policy_constants.h" +#include "components/prefs/pref_value_map.h" +#include "components/strings/grit/components_strings.h" + +namespace enterprise_idle { + +namespace { + +// If `other_policy_name` is unset, adds an error to `errors` and returns false. +bool CheckOtherPolicySet(const policy::PolicyMap& policies, + const std::string& this_policy_name, + const std::string& other_policy_name, + policy::PolicyErrorMap* errors) { + if (policies.GetValueUnsafe(other_policy_name)) + return true; + + errors->AddError(this_policy_name, IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE, + other_policy_name); + return false; +} + +} // namespace + +IdleTimeoutPolicyHandler::IdleTimeoutPolicyHandler() + : policy::IntRangePolicyHandler(policy::key::kIdleTimeout, + prefs::kIdleTimeout, + 1, + INT_MAX, + true) {} + +IdleTimeoutPolicyHandler::~IdleTimeoutPolicyHandler() = default; + +void IdleTimeoutPolicyHandler::ApplyPolicySettings( + const policy::PolicyMap& policies, + PrefValueMap* prefs) { + const base::Value* value = + policies.GetValue(policy::key::kIdleTimeout, base::Value::Type::INTEGER); + DCHECK(value); + + // Apply a minimum of 1. + base::TimeDelta time_delta = base::Minutes(std::max(value->GetInt(), 1)); + prefs->SetValue(prefs::kIdleTimeout, base::TimeDeltaToValue(time_delta)); +} + +bool IdleTimeoutPolicyHandler::CheckPolicySettings( + const policy::PolicyMap& policies, + policy::PolicyErrorMap* errors) { + // Nothing to do if unset. + if (!policies.GetValueUnsafe(policy::key::kIdleTimeout)) + return false; + + // Check that it's an integer, and that it's >= 1. + if (!policy::IntRangePolicyHandler::CheckPolicySettings(policies, errors)) + return false; + + // If IdleTimeoutActions is unset, add an error and do nothing. + if (!CheckOtherPolicySet(policies, policy::key::kIdleTimeout, + policy::key::kIdleTimeoutActions, errors)) { + return false; + } + + return true; +} + +IdleTimeoutActionsPolicyHandler::IdleTimeoutActionsPolicyHandler( + policy::Schema schema) + : policy::SchemaValidatingPolicyHandler( + policy::key::kIdleTimeoutActions, + schema.GetKnownProperty(policy::key::kIdleTimeoutActions), + policy::SCHEMA_ALLOW_UNKNOWN_AND_INVALID_LIST_ENTRY) {} + +IdleTimeoutActionsPolicyHandler::~IdleTimeoutActionsPolicyHandler() = default; + +void IdleTimeoutActionsPolicyHandler::ApplyPolicySettings( + const policy::PolicyMap& policies, + PrefValueMap* prefs) { + const base::Value* policy_value = policies.GetValue( + policy::key::kIdleTimeoutActions, base::Value::Type::LIST); + DCHECK(policy_value); + + // Convert strings to integers (from the ActionType enum). + base::Value::List converted_actions; + for (const base::Value& action : policy_value->GetList()) { + if (!action.is_string()) + continue; + const std::string& name = action.GetString(); + if (name == "close_browsers") + converted_actions.Append(static_cast<int>(ActionType::kCloseBrowsers)); + else if (name == "show_profile_picker") + converted_actions.Append( + static_cast<int>(ActionType::kShowProfilePicker)); + // Silently drop unsupported values. + } + prefs->SetValue(prefs::kIdleTimeoutActions, + base::Value(std::move(converted_actions))); +} + +bool IdleTimeoutActionsPolicyHandler::CheckPolicySettings( + const policy::PolicyMap& policies, + policy::PolicyErrorMap* errors) { + // Nothing to do if unset. + if (!policies.GetValueUnsafe(policy::key::kIdleTimeoutActions)) + return false; + + // Check that it's a list of strings, and that they're supported enum values. + // Unsupported enum values are dropped, with a warning on chrome://policy. + if (!policy::SchemaValidatingPolicyHandler::CheckPolicySettings(policies, + errors)) { + return false; + } + + // If IdleTimeout is unset, add an error and do nothing. + if (!CheckOtherPolicySet(policies, policy::key::kIdleTimeoutActions, + policy::key::kIdleTimeout, errors)) { + return false; + } + + return true; +} +} // namespace enterprise_idle
diff --git a/chrome/browser/enterprise/idle/idle_timeout_policy_handler.h b/chrome/browser/enterprise/idle/idle_timeout_policy_handler.h new file mode 100644 index 0000000..c40759c --- /dev/null +++ b/chrome/browser/enterprise/idle/idle_timeout_policy_handler.h
@@ -0,0 +1,58 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ENTERPRISE_IDLE_IDLE_TIMEOUT_POLICY_HANDLER_H_ +#define CHROME_BROWSER_ENTERPRISE_IDLE_IDLE_TIMEOUT_POLICY_HANDLER_H_ + +#include "components/policy/core/browser/configuration_policy_handler.h" + +class PrefValueMap; + +namespace policy { +class PolicyErrorMap; +class PolicyMap; +} // namespace policy + +namespace enterprise_idle { + +// Handles IdleTimeout policy. +class IdleTimeoutPolicyHandler : public policy::IntRangePolicyHandler { + public: + IdleTimeoutPolicyHandler(); + + IdleTimeoutPolicyHandler(const IdleTimeoutPolicyHandler&) = delete; + IdleTimeoutPolicyHandler& operator=(const IdleTimeoutPolicyHandler&) = delete; + + ~IdleTimeoutPolicyHandler() override; + + // ConfigurationPolicyHandler methods: + void ApplyPolicySettings(const policy::PolicyMap& policies, + PrefValueMap* prefs) override; + bool CheckPolicySettings(const policy::PolicyMap& policies, + policy::PolicyErrorMap* errors) override; +}; + +// Handles IdleTimeoutActions policy. +class IdleTimeoutActionsPolicyHandler + : public policy::SchemaValidatingPolicyHandler { + public: + explicit IdleTimeoutActionsPolicyHandler(policy::Schema schema); + + IdleTimeoutActionsPolicyHandler(const IdleTimeoutActionsPolicyHandler&) = + delete; + IdleTimeoutActionsPolicyHandler& operator=( + const IdleTimeoutActionsPolicyHandler&) = delete; + + ~IdleTimeoutActionsPolicyHandler() override; + + // ConfigurationPolicyHandler methods: + void ApplyPolicySettings(const policy::PolicyMap& policies, + PrefValueMap* prefs) override; + bool CheckPolicySettings(const policy::PolicyMap& policies, + policy::PolicyErrorMap* errors) override; +}; + +} // namespace enterprise_idle + +#endif // CHROME_BROWSER_ENTERPRISE_IDLE_IDLE_TIMEOUT_POLICY_HANDLER_H_
diff --git a/chrome/browser/enterprise/idle/idle_timeout_policy_handler_unittest.cc b/chrome/browser/enterprise/idle/idle_timeout_policy_handler_unittest.cc new file mode 100644 index 0000000..f6b3583 --- /dev/null +++ b/chrome/browser/enterprise/idle/idle_timeout_policy_handler_unittest.cc
@@ -0,0 +1,272 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise/idle/idle_timeout_policy_handler.h" + +#include <string> + +#include "base/json/values_util.h" +#include "base/ranges/algorithm.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "base/values.h" +#include "chrome/browser/enterprise/idle/action.h" +#include "chrome/common/pref_names.h" +#include "components/policy/core/browser/configuration_policy_handler.h" +#include "components/policy/core/browser/policy_error_map.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/policy_types.h" +#include "components/policy/policy_constants.h" +#include "components/prefs/pref_value_map.h" +#include "components/strings/grit/components_strings.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" + +namespace enterprise_idle { + +using base::UTF8ToUTF16; + +class IdleTimeoutPolicyHandlerTest : public testing::Test { + protected: + void SetPolicyValue(const std::string& policy, base::Value value) { + policies_.Set(policy, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_PLATFORM, + std::move(value), nullptr); + } + + bool CheckPolicySettings() { + bool results[] = { + timeout_handler_.CheckPolicySettings(policies_, &errors_), + actions_handler_.CheckPolicySettings(policies_, &errors_), + }; + return base::ranges::all_of(base::span(results), std::identity{}); + } + + void ApplyPolicySettings() { + timeout_handler_.ApplyPolicySettings(policies_, &prefs_); + actions_handler_.ApplyPolicySettings(policies_, &prefs_); + } + + void CheckAndApplyPolicySettings() { + if (CheckPolicySettings()) + ApplyPolicySettings(); + } + + policy::PolicyErrorMap& errors() { return errors_; } + PrefValueMap& prefs() { return prefs_; } + + private: + policy::PolicyMap policies_; + policy::PolicyErrorMap errors_; + PrefValueMap prefs_; + policy::Schema schema_ = policy::Schema::Wrap(policy::GetChromeSchemaData()); + IdleTimeoutPolicyHandler timeout_handler_; + IdleTimeoutActionsPolicyHandler actions_handler_ = + IdleTimeoutActionsPolicyHandler(schema_); +}; + +TEST_F(IdleTimeoutPolicyHandlerTest, PoliciesNotSet) { + CheckAndApplyPolicySettings(); + + // Shouldn't error. + EXPECT_EQ(errors().size(), 0U); + + // Prefs should not be set. + const base::Value* pref_value; + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, JustTimeout) { + // IdleTimeout is set, but not IdleTimeoutActions. + SetPolicyValue(policy::key::kIdleTimeout, base::Value(15)); + + CheckAndApplyPolicySettings(); + + // Should have an error. + auto expected_error = + l10n_util::GetStringFUTF16(IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE, + UTF8ToUTF16(policy::key::kIdleTimeoutActions)); + EXPECT_EQ(errors().size(), 1U); + EXPECT_EQ(errors().begin()->second.message, expected_error); + + // Prefs should not be set. + const base::Value* pref_value; + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, JustActions) { + // IdleTimeoutActions is set, but not IdleTimeout. + SetPolicyValue(policy::key::kIdleTimeoutActions, + base::Value(base::Value::List())); + + CheckAndApplyPolicySettings(); + + // Should have an error. + auto expected_error = + l10n_util::GetStringFUTF16(IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE, + UTF8ToUTF16(policy::key::kIdleTimeout)); + EXPECT_EQ(errors().size(), 1U); + EXPECT_EQ(errors().begin()->second.message, expected_error); + + // Prefs should not be set. + const base::Value* pref_value; + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, InvalidTimeoutPolicyType) { + // Give an integer to a string policy. + SetPolicyValue(policy::key::kIdleTimeout, base::Value("invalid")); + SetPolicyValue(policy::key::kIdleTimeoutActions, + base::Value(base::Value::List())); + + CheckAndApplyPolicySettings(); + + // Should have an error. + auto expected_error = l10n_util::GetStringFUTF16( + IDS_POLICY_TYPE_ERROR, + UTF8ToUTF16(base::Value::GetTypeName(base::Value::Type::INTEGER))); + EXPECT_EQ(errors().size(), 1U); + EXPECT_EQ(errors().begin()->second.message, expected_error); + + // Prefs should not be set. + const base::Value* pref_value; + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, InvalidActionsPolicyType) { + // Give a string to a string-enum policy. + SetPolicyValue(policy::key::kIdleTimeout, base::Value(5)); + SetPolicyValue(policy::key::kIdleTimeoutActions, base::Value("invalid")); + + CheckAndApplyPolicySettings(); + + // Should have an error. + auto expected_error = l10n_util::GetStringFUTF16( + IDS_POLICY_SCHEMA_VALIDATION_ERROR, + u"Policy type mismatch: expected: \"list\", actual: \"string\"."); + EXPECT_EQ(errors().size(), 1U); + EXPECT_EQ(errors().begin()->second.message, expected_error); + + // Prefs should not be set. + const base::Value* pref_value; + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + EXPECT_FALSE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, InvalidActionWrongType) { + // IdleTimeoutActions is a list, but one of the elements is not even a string. + SetPolicyValue(policy::key::kIdleTimeout, base::Value(5)); + base::Value::List list; + list.Append("close_browsers"); + list.Append(34); + SetPolicyValue(policy::key::kIdleTimeoutActions, + base::Value(std::move(list))); + + CheckAndApplyPolicySettings(); + + // Should have an error. + auto expected_error = l10n_util::GetStringFUTF16( + IDS_POLICY_ERROR_WITH_PATH, + UTF8ToUTF16(policy::key::kIdleTimeoutActions) + u"[1]", + l10n_util::GetStringFUTF16( + IDS_POLICY_SCHEMA_VALIDATION_ERROR, + u"Policy type mismatch: expected: \"string\", actual: \"integer\".")); + EXPECT_EQ(errors().size(), 1U); + EXPECT_EQ(errors().begin()->second.message, expected_error); + + // Prefs should not be set. + const base::Value* pref_value; + EXPECT_TRUE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + EXPECT_TRUE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, ValidConfiguration) { + SetPolicyValue(policy::key::kIdleTimeout, base::Value(15)); + base::Value::List list; + list.Append("close_browsers"); + list.Append("show_profile_picker"); + SetPolicyValue(policy::key::kIdleTimeoutActions, + base::Value(std::move(list))); + + CheckAndApplyPolicySettings(); + + // Should have no errors. + EXPECT_TRUE(errors().empty()); + + // Prefs should be set. + const base::Value* pref_value; + EXPECT_TRUE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + ASSERT_THAT(pref_value, testing::NotNull()); + EXPECT_EQ(base::TimeDeltaToValue(base::Minutes(15)), *pref_value); + + EXPECT_TRUE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); + ASSERT_THAT(pref_value, testing::NotNull()); + EXPECT_TRUE(pref_value->is_list()); + EXPECT_THAT( + pref_value->GetList(), + testing::ElementsAre(static_cast<int>(ActionType::kCloseBrowsers), + static_cast<int>(ActionType::kShowProfilePicker))); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, OneMinuteMinimum) { + // Set the policy to 0, which should clamp the pref to 1. + SetPolicyValue(policy::key::kIdleTimeout, base::Value(0)); + SetPolicyValue(policy::key::kIdleTimeoutActions, + base::Value(base::Value::List())); + + CheckAndApplyPolicySettings(); + + // Should have an error. + auto expected_error = + l10n_util::GetStringFUTF16(IDS_POLICY_OUT_OF_RANGE_ERROR, u"0"); + EXPECT_EQ(errors().size(), 1U); + EXPECT_EQ(errors().begin()->second.message, expected_error); + + // Prefs should be set. + const base::Value* pref_value; + EXPECT_TRUE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + ASSERT_THAT(pref_value, testing::NotNull()); + EXPECT_EQ(base::TimeDeltaToValue(base::Minutes(1)), *pref_value); +} + +TEST_F(IdleTimeoutPolicyHandlerTest, ActionNotRecognized) { + // IdleTimeoutActions is a list, but one of the elements is not recognized + // as a valid option. Recognized actions are applied, but not the others. + SetPolicyValue(policy::key::kIdleTimeout, base::Value(5)); + base::Value::List list; + list.Append("close_browsers"); + list.Append("show_profile_picker"); + list.Append("added_in_future_version_of_chrome"); + SetPolicyValue(policy::key::kIdleTimeoutActions, + base::Value(std::move(list))); + + CheckAndApplyPolicySettings(); + + // Should have an error. + auto expected_error = l10n_util::GetStringFUTF16( + IDS_POLICY_ERROR_WITH_PATH, + UTF8ToUTF16(policy::key::kIdleTimeoutActions) + u"[2]", + l10n_util::GetStringFUTF16(IDS_POLICY_SCHEMA_VALIDATION_ERROR, + u"Invalid value for string")); + EXPECT_EQ(errors().size(), 1U); + EXPECT_EQ(errors().begin()->second.message, expected_error); + + // Prefs should not be set. + const base::Value* pref_value; + EXPECT_TRUE(prefs().GetValue(prefs::kIdleTimeout, &pref_value)); + EXPECT_TRUE(prefs().GetValue(prefs::kIdleTimeoutActions, &pref_value)); + ASSERT_THAT(pref_value, testing::NotNull()); + EXPECT_TRUE(pref_value->is_list()); + EXPECT_THAT( + pref_value->GetList(), + testing::ElementsAre(static_cast<int>(ActionType::kCloseBrowsers), + static_cast<int>(ActionType::kShowProfilePicker))); +} + +} // namespace enterprise_idle
diff --git a/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chrome/browser/extensions/api/debugger/debugger_apitest.cc index 3417a0681..6a45147 100644 --- a/chrome/browser/extensions/api/debugger/debugger_apitest.cc +++ b/chrome/browser/extensions/api/debugger/debugger_apitest.cc
@@ -148,10 +148,9 @@ extension_function_test_utils::RunFunctionAndReturnSingleResult( get_targets_function.get(), "[]", browser())); EXPECT_TRUE(value->is_list()); - const base::ListValue& targets = base::Value::AsListValue(*value); std::string debugger_target_id; - for (const base::Value& target_value : targets.GetList()) { + for (const base::Value& target_value : value->GetList()) { EXPECT_TRUE(target_value.is_dict()); absl::optional<int> id = target_value.FindIntKey("tabId"); if (id == tab_id) {
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc index d3f04c72..aae884a 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
@@ -375,11 +375,10 @@ function.get(), "[]" /* args */, browser_context()); ASSERT_TRUE(result); ASSERT_TRUE(result->is_list()); - const base::ListValue& ids_value = base::Value::AsListValue(*result); std::u16string error; std::vector<std::string> actual_ids; - for (const auto& val : ids_value.GetList()) + for (const auto& val : result->GetList()) actual_ids.push_back(val.GetString()); EXPECT_THAT(expected_ids, UnorderedElementsAreArray(actual_ids));
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc b/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc index 389c17f2..99582ef 100644 --- a/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc +++ b/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc
@@ -107,11 +107,9 @@ EXPECT_TRUE(base::PathService::Get(DIR_TEST_DATA, &path)); std::string error; - scoped_refptr<Extension> extension( - Extension::Create(path, mojom::ManifestLocation::kInternal, - base::Value::AsDictionaryValue( - base::Value(manifest_builder.BuildDict())), - Extension::NO_FLAGS, &error)); + scoped_refptr<Extension> extension(Extension::Create( + path, mojom::ManifestLocation::kInternal, manifest_builder.BuildDict(), + Extension::NO_FLAGS, &error)); ASSERT_TRUE(extension.get()) << error; ExtensionRegistry::Get(&profile_)->AddEnabled(extension); extension_id_ = extension->id();
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc index 02ee5ccf..0f7a550 100644 --- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc +++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -142,20 +142,20 @@ GetAudioDeviceDescriptions(false, &devices); std::unique_ptr<base::Value> result = InvokeGetSinks(); - const base::ListValue& sink_list = base::Value::AsListValue(*result); + const base::Value::List& sink_list = result->GetList(); std::string result_string; JSONWriter::Write(*result, &result_string); VLOG(2) << result_string; - EXPECT_EQ(devices.size(), sink_list.GetList().size()); + EXPECT_EQ(devices.size(), sink_list.size()); // Iterate through both lists in lockstep and compare. The order // should be identical. size_t ix = 0; AudioDeviceDescriptions::const_iterator it = devices.begin(); - for (; ix < sink_list.GetList().size() && it != devices.end(); ++ix, ++it) { - const base::Value& value = sink_list.GetList()[ix]; + for (; ix < sink_list.size() && it != devices.end(); ++ix, ++it) { + const base::Value& value = sink_list[ix]; EXPECT_TRUE(value.is_dict()); const base::Value::Dict& dict = value.GetDict(); const std::string* sink_id = dict.FindString("sinkId");
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc index f711ce3..855896ac 100644 --- a/chrome/browser/extensions/extension_install_prompt.cc +++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -37,6 +37,7 @@ #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/permissions/permission_set.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_types.h" @@ -476,30 +477,27 @@ // static scoped_refptr<Extension> ExtensionInstallPrompt::GetLocalizedExtensionForDisplay( - const base::DictAdapterForMigration manifest, + const base::Value::Dict& manifest, int flags, const std::string& id, const std::string& localized_name, const std::string& localized_description, std::string* error) { - std::unique_ptr<base::DictionaryValue> localized_manifest; + absl::optional<base::Value::Dict> localized_manifest; if (!localized_name.empty() || !localized_description.empty()) { - localized_manifest = base::DictionaryValue::From( - base::Value::ToUniquePtrValue(base::Value(manifest.Clone()))); + localized_manifest = manifest.Clone(); if (!localized_name.empty()) { - localized_manifest->SetStringKey(extensions::manifest_keys::kName, - localized_name); + localized_manifest->Set(extensions::manifest_keys::kName, localized_name); } if (!localized_description.empty()) { - localized_manifest->SetStringKey(extensions::manifest_keys::kDescription, - localized_description); + localized_manifest->Set(extensions::manifest_keys::kDescription, + localized_description); } } return Extension::Create( base::FilePath(), extensions::mojom::ManifestLocation::kInternal, - localized_manifest.get() ? *localized_manifest : manifest, flags, id, - error); + localized_manifest ? *localized_manifest : manifest, flags, id, error); } ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
diff --git a/chrome/browser/extensions/extension_install_prompt.h b/chrome/browser/extensions/extension_install_prompt.h index e67259d..a8feacb 100644 --- a/chrome/browser/extensions/extension_install_prompt.h +++ b/chrome/browser/extensions/extension_install_prompt.h
@@ -285,7 +285,7 @@ // Creates a dummy extension from the |manifest|, replacing the name and // description with the localizations if provided. static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay( - const base::DictAdapterForMigration manifest, + const base::Value::Dict& manifest, int flags, // Extension::InitFromValueFlags const std::string& id, const std::string& localized_name,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index b2e5bcd..f792675 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2290,7 +2290,7 @@ { "name": "enable-external-keyboards-in-diagnostics-app", "owners": [ "//ash/webui/diagnostics_ui/OWNERS" ], - "expiry_milestone": 110 + "expiry_milestone": 120 }, { "name": "enable-fake-keyboard-heuristic", @@ -2627,7 +2627,7 @@ { "name": "enable-log-controller-for-diagnostics-app", "owners": [ "//ash/webui/diagnostics_ui/OWNERS" ], - "expiry_milestone": 110 + "expiry_milestone": 120 }, { "name": "enable-logging-js-console-messages", @@ -3189,7 +3189,7 @@ { "name": "enable-touchpads-in-diagnostics-app", "owners": [ "//ash/webui/diagnostics_ui/OWNERS" ], - "expiry_milestone": 110 + "expiry_milestone": 120 }, { "name": "enable-touchscreen-calibration", @@ -3201,7 +3201,7 @@ { "name": "enable-touchscreens-in-diagnostics-app", "owners": [ "//ash/webui/diagnostics_ui/OWNERS" ], - "expiry_milestone": 110 + "expiry_milestone": 120 }, { "name": "enable-translate-sub-frames",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 8872845..64d529d 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -289,10 +289,6 @@ "grouped into processes based on their URL's site or origin. The default " "grouping when enabled is per-site."; -const char kAssistantConsentModalName[] = "AssistantConsentModal"; -const char kAssistantConsentModalDescription[] = - "Enables the modal version of the Assistant voice search consent dialog."; - const char kAssistantConsentSimplifiedTextName[] = "AssistantConsentSimplifiedText"; const char kAssistantConsentSimplifiedTextDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 752a9f4c..8acf4ea 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -168,9 +168,6 @@ extern const char kUseCustomMessagesDomainName[]; extern const char kUseCustomMessagesDomainDescription[]; -extern const char kAssistantConsentModalName[]; -extern const char kAssistantConsentModalDescription[]; - extern const char kAssistantConsentSimplifiedTextName[]; extern const char kAssistantConsentSimplifiedTextDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 1a39009..d704d449 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -174,7 +174,6 @@ &kAllowNewIncognitoTabIntents, &kAndroidScrollOptimizations, &kAndroidSearchEngineChoiceNotification, - &kAssistantConsentModal, &kAssistantConsentSimplifiedText, &kAssistantConsentV2, &kAssistantIntentExperimentId, @@ -476,10 +475,6 @@ "AndroidSearchEngineChoiceNotification", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kAssistantConsentModal, - "AssistantConsentModal", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kAssistantConsentSimplifiedText, "AssistantConsentSimplifiedText", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index c58a6f0..8e91bda3 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -20,7 +20,6 @@ BASE_DECLARE_FEATURE(kAllowNewIncognitoTabIntents); BASE_DECLARE_FEATURE(kAndroidScrollOptimizations); BASE_DECLARE_FEATURE(kAndroidSearchEngineChoiceNotification); -BASE_DECLARE_FEATURE(kAssistantConsentModal); BASE_DECLARE_FEATURE(kAssistantConsentSimplifiedText); BASE_DECLARE_FEATURE(kAssistantConsentV2); BASE_DECLARE_FEATURE(kAssistantIntentExperimentId);
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 fbfe38a..c4ab08ed 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
@@ -195,7 +195,6 @@ public static final String ANONYMOUS_UPDATE_CHECKS = "AnonymousUpdateChecks"; public static final String APP_LANGUAGE_PROMPT = "AppLanguagePrompt"; public static final String APP_LANGUAGE_PROMPT_ULP = "AppLanguagePromptULP"; - public static final String ASSISTANT_CONSENT_MODAL = "AssistantConsentModal"; public static final String ASSISTANT_CONSENT_SIMPLIFIED_TEXT = "AssistantConsentSimplifiedText"; public static final String ASSISTANT_CONSENT_V2 = "AssistantConsentV2"; public static final String ASSISTANT_INTENT_EXPERIMENT_ID = "AssistantIntentExperimentId"; @@ -660,7 +659,7 @@ public static final CachedFlag sInstantStart = new CachedFlag(INSTANT_START, false); public static final CachedFlag sInterestFeedV2 = new CachedFlag(INTEREST_FEED_V2, true); public static final CachedFlag sLensCameraAssistedSearch = - new CachedFlag(LENS_CAMERA_ASSISTED_SEARCH, false); + new CachedFlag(LENS_CAMERA_ASSISTED_SEARCH, true); public static final CachedFlag sNewWindowAppMenu = new CachedFlag(NEW_WINDOW_APP_MENU, true); public static final CachedFlag sOmahaMinSdkVersionAndroid = new CachedFlag(OMAHA_MIN_SDK_VERSION_ANDROID, false);
diff --git a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc index 71eab4c..be3e1fd 100644 --- a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc +++ b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc
@@ -34,6 +34,7 @@ #include "chrome/browser/lacros/sync/sync_crosapi_manager_lacros.h" #include "chrome/browser/lacros/task_manager_lacros.h" #include "chrome/browser/lacros/ui_metric_recorder_lacros.h" +#include "chrome/browser/lacros/views_text_services_context_menu_lacros.h" #include "chrome/browser/lacros/vpn_extension_tracker_lacros.h" #include "chrome/browser/lacros/web_app_provider_bridge_lacros.h" #include "chrome/browser/lacros/web_page_info_lacros.h" @@ -49,6 +50,7 @@ #include "chromeos/startup/browser_params_proxy.h" #include "components/arc/common/intent_helper/arc_icon_cache_delegate.h" #include "extensions/common/features/feature_session_type.h" +#include "ui/views/controls/views_text_services_context_menu_chromeos.h" namespace { @@ -231,4 +233,13 @@ chrome_kiosk_launch_controller_ = std::make_unique<ChromeKioskLaunchControllerLacros>(*profile); } + + views::ViewsTextServicesContextMenuChromeos::SetImplFactory( + base::BindRepeating( + [](ui::SimpleMenuModel* menu_model, views::Textfield* textfield) + -> std::unique_ptr<views::ViewsTextServicesContextMenu> { + return std::make_unique< + crosapi::ViewsTextServicesContextMenuLacros>(menu_model, + textfield); + })); }
diff --git a/chrome/browser/lacros/standalone_browser_test_controller.cc b/chrome/browser/lacros/standalone_browser_test_controller.cc index e848e1bc..313f529 100644 --- a/chrome/browser/lacros/standalone_browser_test_controller.cc +++ b/chrome/browser/lacros/standalone_browser_test_controller.cc
@@ -131,8 +131,7 @@ std::string error; auto extension = extensions::Extension::Create( base::FilePath(), extensions::mojom::ManifestLocation::kUnpacked, - base::Value::AsDictionaryValue( - base::Value(CreateVpnExtensionManifest(extension_name))), + CreateVpnExtensionManifest(extension_name), extensions::Extension::NO_FLAGS, &error); if (!error.empty()) { std::move(callback).Run(error);
diff --git a/chrome/browser/lacros/views_text_services_context_menu_lacros.cc b/chrome/browser/lacros/views_text_services_context_menu_lacros.cc new file mode 100644 index 0000000..6a4f95ce --- /dev/null +++ b/chrome/browser/lacros/views_text_services_context_menu_lacros.cc
@@ -0,0 +1,123 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/lacros/views_text_services_context_menu_lacros.h" + +#include "chrome/app/chrome_command_ids.h" +#include "chromeos/crosapi/mojom/clipboard_history.mojom.h" +#include "chromeos/lacros/lacros_service.h" +#include "ui/base/clipboard/clipboard.h" +#include "ui/base/data_transfer_policy/data_transfer_endpoint.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/pointer/touch_editing_controller.h" +#include "ui/strings/grit/ui_strings.h" +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/controls/views_text_services_context_menu_base.h" + +namespace { + +bool IsClipboardHistoryLacrosServiceAvailable() { + auto* const service = chromeos::LacrosService::Get(); + return service && service->IsAvailable<crosapi::mojom::ClipboardHistory>(); +} + +bool IsClipboardHistoryEmpty() { + ui::DataTransferEndpoint dte(ui::EndpointType::kClipboardHistory); + std::vector<std::u16string> types; + ui::Clipboard::GetForCurrentThread()->ReadAvailableTypes( + ui::ClipboardBuffer::kCopyPaste, &dte, &types); + return types.empty(); +} + +} // namespace + +namespace crosapi { + +ViewsTextServicesContextMenuLacros::ViewsTextServicesContextMenuLacros( + ui::SimpleMenuModel* menu, + views::Textfield* client) + : views::ViewsTextServicesContextMenuBase(menu, client) { + if (!IsClipboardHistoryLacrosServiceAvailable()) + return; + + // If the menu has a paste option, add a clipboard history option as well. + const absl::optional<size_t> paste_index = + menu->GetIndexOfCommandId(ui::TouchEditable::kPaste); + + if (!paste_index.has_value()) + return; + + const size_t target_index = paste_index.value() + 1; + menu->InsertItemAt(target_index, IDS_APP_SHOW_CLIPBOARD_HISTORY, + l10n_util::GetStringUTF16(IDS_APP_SHOW_CLIPBOARD_HISTORY)); +} + +ViewsTextServicesContextMenuLacros::~ViewsTextServicesContextMenuLacros() = + default; + +bool ViewsTextServicesContextMenuLacros::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) { + *accelerator = ui::Accelerator(ui::VKEY_V, ui::EF_COMMAND_DOWN); + return true; + } + + return ViewsTextServicesContextMenuBase::GetAcceleratorForCommandId( + command_id, accelerator); +} + +bool ViewsTextServicesContextMenuLacros::IsCommandIdChecked( + int command_id) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) + return true; + + return ViewsTextServicesContextMenuBase::IsCommandIdChecked(command_id); +} + +bool ViewsTextServicesContextMenuLacros::IsCommandIdEnabled( + int command_id) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) { + return IsClipboardHistoryLacrosServiceAvailable() && + !IsClipboardHistoryEmpty(); + } + + return ViewsTextServicesContextMenuBase::IsCommandIdEnabled(command_id); +} + +void ViewsTextServicesContextMenuLacros::ExecuteCommand(int command_id, + int event_flags) { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) { + if (!IsClipboardHistoryLacrosServiceAvailable()) + return; + + // Calculate the menu source type from `event_flags`. + ui::MenuSourceType source_type; + if (event_flags & ui::EF_LEFT_MOUSE_BUTTON) { + source_type = ui::MENU_SOURCE_MOUSE; + } else if (event_flags & ui::EF_FROM_TOUCH) { + source_type = ui::MENU_SOURCE_TOUCH; + } else { + source_type = ui::MENU_SOURCE_KEYBOARD; + } + + chromeos::LacrosService::Get() + ->GetRemote<mojom::ClipboardHistory>() + ->ShowClipboard( + client()->GetCaretBounds(), source_type, + mojom::ClipboardHistoryControllerShowSource::kTextfieldContextMenu); + return; + } + + ViewsTextServicesContextMenuBase::ExecuteCommand(command_id, event_flags); +} + +bool ViewsTextServicesContextMenuLacros::SupportsCommand(int command_id) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) + return true; + + return ViewsTextServicesContextMenuBase::SupportsCommand(command_id); +} + +} // namespace crosapi
diff --git a/chrome/browser/lacros/views_text_services_context_menu_lacros.h b/chrome/browser/lacros/views_text_services_context_menu_lacros.h new file mode 100644 index 0000000..4342bc6b --- /dev/null +++ b/chrome/browser/lacros/views_text_services_context_menu_lacros.h
@@ -0,0 +1,45 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_LACROS_VIEWS_TEXT_SERVICES_CONTEXT_MENU_LACROS_H_ +#define CHROME_BROWSER_LACROS_VIEWS_TEXT_SERVICES_CONTEXT_MENU_LACROS_H_ + +#include "ui/views/controls/views_text_services_context_menu_base.h" + +namespace ui { +class SimpleMenuModel; +} // namespace ui + +namespace views { +class Textfield; +} // namespace views + +namespace crosapi { + +// This class implements support for adding and handling text service items in +// lacros-chrome browser native textfields (i.e., the omnibox but not the WebUI +// embedded in the browser). +class ViewsTextServicesContextMenuLacros + : public views::ViewsTextServicesContextMenuBase { + public: + ViewsTextServicesContextMenuLacros(ui::SimpleMenuModel* menu, + views::Textfield* client); + ViewsTextServicesContextMenuLacros( + const ViewsTextServicesContextMenuLacros&) = delete; + ViewsTextServicesContextMenuLacros& operator=( + const ViewsTextServicesContextMenuLacros&) = delete; + ~ViewsTextServicesContextMenuLacros() override; + + // ViewsTextServicesContextMenuBase: + bool GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) const override; + bool IsCommandIdChecked(int command_id) const override; + bool IsCommandIdEnabled(int command_id) const override; + void ExecuteCommand(int command_id, int event_flags) override; + bool SupportsCommand(int command_id) const override; +}; + +} // namespace crosapi + +#endif // CHROME_BROWSER_LACROS_VIEWS_TEXT_SERVICES_CONTEXT_MENU_LACROS_H_
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc index 8779cdb..e4fd52c 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
@@ -106,8 +106,8 @@ void MediaRouterMojoImpl::Initialize() { DCHECK(!internal_routes_observer_); - // The observer calls virtual methods on MediaRouter; it must be created - // outside of the ctor + // Because observer calls virtual methods on MediaRouter, it must be created + // outside of the constructor. internal_routes_observer_ = std::make_unique<InternalMediaRoutesObserver>(this); } @@ -122,7 +122,7 @@ std::move(media_route_provider_remote)); bound_remote.set_disconnect_handler( base::BindOnce(&MediaRouterMojoImpl::OnProviderConnectionError, - weak_factory_.GetWeakPtr(), provider_id)); + AsWeakPtr(), provider_id)); media_route_providers_[provider_id] = std::move(bound_remote); } @@ -250,9 +250,9 @@ const mojom::MediaRouteProviderId provider_id = sink->provider_id(); const std::string presentation_id = MediaRouterBase::CreatePresentationId(); - auto mr_callback = base::BindOnce( - &MediaRouterMojoImpl::RouteResponseReceived, weak_factory_.GetWeakPtr(), - presentation_id, provider_id, off_the_record, std::move(callback), false); + auto mr_callback = base::BindOnce(&MediaRouterMojoImpl::RouteResponseReceived, + AsWeakPtr(), presentation_id, provider_id, + off_the_record, std::move(callback), false); if (source.IsDesktopMirroringSource()) { desktop_picker_.Show( @@ -260,9 +260,9 @@ {DesktopMediaList::Type::kScreen}, base::BindRepeating([](content::WebContents* wc) { return true; }), base::BindOnce(&MediaRouterMojoImpl::CreateRouteWithSelectedDesktop, - weak_factory_.GetWeakPtr(), provider_id, sink_id, - presentation_id, origin, web_contents, timeout, - off_the_record, std::move(mr_callback))); + AsWeakPtr(), provider_id, sink_id, presentation_id, + origin, web_contents, timeout, off_the_record, + std::move(mr_callback))); } else { const int frame_tree_node_id = web_contents ? web_contents->GetPrimaryMainFrame()->GetFrameTreeNodeId() @@ -296,9 +296,9 @@ const int frame_tree_node_id = web_contents ? web_contents->GetPrimaryMainFrame()->GetFrameTreeNodeId() : kDefaultFrameTreeNodeId; - auto mr_callback = base::BindOnce( - &MediaRouterMojoImpl::RouteResponseReceived, weak_factory_.GetWeakPtr(), - presentation_id, *provider_id, off_the_record, std::move(callback), true); + auto mr_callback = base::BindOnce(&MediaRouterMojoImpl::RouteResponseReceived, + AsWeakPtr(), presentation_id, *provider_id, + off_the_record, std::move(callback), true); media_route_providers_[*provider_id]->JoinRoute( source_id, presentation_id, origin, frame_tree_node_id, timeout, off_the_record, std::move(mr_callback)); @@ -313,9 +313,8 @@ mojom::RouteRequestResultCode::ROUTE_NOT_FOUND); return; } - auto callback = - base::BindOnce(&MediaRouterMojoImpl::OnTerminateRouteResult, - weak_factory_.GetWeakPtr(), route_id, *provider_id); + auto callback = base::BindOnce(&MediaRouterMojoImpl::OnTerminateRouteResult, + AsWeakPtr(), route_id, *provider_id); media_route_providers_[*provider_id]->TerminateRoute(route_id, std::move(callback)); } @@ -380,7 +379,7 @@ return; } auto callback = base::BindOnce(&MediaRouterMojoImpl::OnMediaControllerCreated, - weak_factory_.GetWeakPtr(), route_id); + AsWeakPtr(), route_id); media_route_providers_[*provider_id]->CreateMediaRouteController( route_id, std::move(controller), std::move(observer), std::move(callback)); @@ -562,7 +561,7 @@ void MediaRouterMojoImpl::RegisterMediaRoutesObserver( MediaRoutesObserver* observer) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - bool is_first_observer = !routes_query_.HasObservers(); + const bool is_first_observer = !routes_query_.HasObservers(); if (!is_first_observer) DCHECK(!routes_query_.HasObserver(observer)); @@ -578,19 +577,15 @@ // MediaRoutesObserver is calling this method from its constructor, and that // must complete before invoking its virtual OnRoutesUpdated() method. content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&MediaRouterMojoImpl::NotifyOfExistingRoutesIfRegistered, - weak_factory_.GetWeakPtr(), - // Safe because we check the routes_query_ in the notify - // method before usage. - base::Unretained(observer))); + FROM_HERE, base::BindOnce(&MediaRouterMojoImpl::NotifyOfExistingRoutes, + AsWeakPtr(), observer->AsWeakPtr())); } } -void MediaRouterMojoImpl::NotifyOfExistingRoutesIfRegistered( - MediaRoutesObserver* observer) const { +void MediaRouterMojoImpl::NotifyOfExistingRoutes( + base::WeakPtr<MediaRoutesObserver> observer) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (routes_query_.HasObserver(observer)) { + if (observer) { observer->OnRoutesUpdated( routes_query_.cached_route_list().value_or(std::vector<MediaRoute>{})); } @@ -598,6 +593,7 @@ void MediaRouterMojoImpl::UnregisterMediaRoutesObserver( MediaRoutesObserver* observer) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); routes_query_.RemoveObserver(observer); } @@ -694,12 +690,14 @@ void MediaRouterMojoImpl::OnRouteAdded(mojom::MediaRouteProviderId provider_id, const MediaRoute& route) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); routes_query_.AddRouteForProvider(provider_id, route); routes_query_.NotifyObservers(); } void MediaRouterMojoImpl::SyncStateToMediaRouteProvider( mojom::MediaRouteProviderId provider_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const auto& provider = media_route_providers_[provider_id]; // Sink queries. for (const auto& it : sinks_queries_) { @@ -799,6 +797,7 @@ absl::optional<mojom::MediaRouteProviderId> MediaRouterMojoImpl::GetProviderIdForRoute(const MediaRoute::Id& route_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); for (const auto& provider_to_routes : routes_query_.providers_to_routes()) { const mojom::MediaRouteProviderId provider_id = provider_to_routes.first; const std::vector<MediaRoute>& routes = provider_to_routes.second; @@ -820,6 +819,7 @@ absl::optional<mojom::MediaRouteProviderId> MediaRouterMojoImpl::GetProviderIdForPresentation( const std::string& presentation_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); for (const auto& provider_to_routes : routes_query_.providers_to_routes()) { const mojom::MediaRouteProviderId provider_id = provider_to_routes.first; const std::vector<MediaRoute>& routes = provider_to_routes.second; @@ -972,8 +972,7 @@ std::move(inner_callback) .Run(route, std::move(connection), error_text, result_code); }, - std::move(mr_callback), weak_factory_.GetWeakPtr(), - request.stream_id)); + std::move(mr_callback), AsWeakPtr(), request.stream_id)); } } // namespace media_router
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.h b/chrome/browser/media/router/mojo/media_router_mojo_impl.h index b9375b6c..b2b2b16 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.h +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.h
@@ -49,7 +49,9 @@ enum class MediaRouteProviderWakeReason; // MediaRouter implementation that delegates calls to a MediaRouteProvider. -class MediaRouterMojoImpl : public MediaRouterBase, public mojom::MediaRouter { +class MediaRouterMojoImpl : public MediaRouterBase, + public mojom::MediaRouter, + public base::SupportsWeakPtr<MediaRouterMojoImpl> { public: MediaRouterMojoImpl(const MediaRouterMojoImpl&) = delete; MediaRouterMojoImpl& operator=(const MediaRouterMojoImpl&) = delete; @@ -215,7 +217,7 @@ // Represents a query to the MediaRouteProviders for media routes and caches // media routes returned by MRPs. Holds observers for the query. // - // NOTE: If the to-do below for providers_for_routes_ is fixed, then this + // NOTE: If the to-do below for providers_to_routes_ is fixed, then this // entire class can be replaced with a std::vector<MediaRoute> and a // base::ObserverList of observers. class MediaRoutesQuery { @@ -264,7 +266,7 @@ base::flat_map<mojom::MediaRouteProviderId, std::vector<MediaRoute>> providers_to_routes_; - base::ObserverList<MediaRoutesObserver>::Unchecked observers_; + base::ObserverList<MediaRoutesObserver> observers_; }; // See note in OnDesktopPickerDone(). @@ -308,7 +310,8 @@ // Notifies |observer| of any existing cached routes, if it is still // registered. - void NotifyOfExistingRoutesIfRegistered(MediaRoutesObserver* observer) const; + void NotifyOfExistingRoutes( + base::WeakPtr<MediaRoutesObserver> observer) const; // mojom::MediaRouter implementation. void OnIssue(const IssueInfo& issue) override; @@ -424,7 +427,7 @@ sinks_queries_; // Holds observers for media route updates and a map of providers to route - // ids.. + // ids. MediaRoutesQuery routes_query_; using PresentationConnectionMessageObserverList = @@ -445,8 +448,6 @@ // Collects logs from the Media Router and the native Media Route Providers. // TODO(crbug.com/1077138): Limit logging before Media Router usage. LoggerImpl logger_; - - base::WeakPtrFactory<MediaRouterMojoImpl> weak_factory_{this}; }; } // namespace media_router
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc index 2a71c01b..8464b78 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
@@ -36,7 +36,6 @@ #include "components/media_router/common/media_source.h" #include "components/media_router/common/test/test_helper.h" #include "components/version_info/version_info.h" -#include "content/public/test/browser_task_environment.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "testing/gmock/include/gmock/gmock.h" @@ -619,33 +618,38 @@ TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaRoutesObserver) { MockMediaRouter mock_router; - MediaRoutesObserver* observer_captured; - EXPECT_CALL(mock_router, RegisterMediaRoutesObserver(_)) - .Times(3) - .WillRepeatedly(SaveArg<0>(&observer_captured)); - MockMediaRoutesObserver routes_observer(&mock_router); - EXPECT_EQ(observer_captured, &routes_observer); + auto routes_observer = + std::make_unique<MockMediaRoutesObserver>(&mock_router); + EXPECT_TRUE( + mock_router.routes_observers().HasObserver(routes_observer.get())); - MockMediaRoutesObserver extra_routes_observer(&mock_router); - EXPECT_EQ(observer_captured, &extra_routes_observer); + auto extra_routes_observer = + std::make_unique<MockMediaRoutesObserver>(&mock_router); + EXPECT_TRUE( + mock_router.routes_observers().HasObserver(extra_routes_observer.get())); - MockMediaRoutesObserver different_routes_observer(&mock_router); - EXPECT_EQ(observer_captured, &different_routes_observer); + routes_observer.reset(); + extra_routes_observer.reset(); + EXPECT_TRUE(mock_router.routes_observers().empty()); +} - EXPECT_CALL(mock_router, UnregisterMediaRoutesObserver(&routes_observer)); - EXPECT_CALL(mock_router, - UnregisterMediaRoutesObserver(&extra_routes_observer)); - EXPECT_CALL(mock_router, - UnregisterMediaRoutesObserver(&different_routes_observer)); - UnregisterMediaRoutesObserver(&routes_observer); - UnregisterMediaRoutesObserver(&extra_routes_observer); - UnregisterMediaRoutesObserver(&different_routes_observer); +TEST_F(MediaRouterMojoImplTest, UnregisterBeforeNotificationDoesntCrash) { + auto routes_observer = std::make_unique<MediaRoutesObserver>(router()); + auto routes_observer_two = std::make_unique<MediaRoutesObserver>(router()); + + // Resetting the observer immediately should cause it to be invalidated before + // the callback for NotifyOfExistingRoutesIfRegistered is called. + routes_observer_two.reset(); + + // Make sure the Notify task executes. + base::RunLoop().RunUntilIdle(); } TEST_F(MediaRouterMojoImplTest, RegisteredObserversGetMediaRouteUpdates) { - StrictMock<MockMediaRoutesObserver> routes_observer(router()); - StrictMock<MockMediaRoutesObserver> extra_routes_observer(router()); - StrictMock<MockMediaRoutesObserver> different_routes_observer(router()); + auto routes_observer = + std::make_unique<StrictMock<MockMediaRoutesObserver>>(router()); + auto extra_routes_observer = + std::make_unique<StrictMock<MockMediaRoutesObserver>>(router()); MediaSource media_source(kSource); std::vector<MediaRoute> expected_routes{ @@ -656,16 +660,14 @@ incognito_expected_route.set_off_the_record(true); expected_routes.push_back(incognito_expected_route); - EXPECT_CALL(routes_observer, OnRoutesUpdated(expected_routes)).Times(1); - EXPECT_CALL(extra_routes_observer, OnRoutesUpdated(expected_routes)).Times(1); - EXPECT_CALL(different_routes_observer, OnRoutesUpdated(expected_routes)) + EXPECT_CALL(*routes_observer, OnRoutesUpdated(expected_routes)).Times(1); + EXPECT_CALL(*extra_routes_observer, OnRoutesUpdated(expected_routes)) .Times(1); UpdateRoutes(mojom::MediaRouteProviderId::CAST, expected_routes); - UnregisterMediaRoutesObserver(&routes_observer); - UnregisterMediaRoutesObserver(&extra_routes_observer); - UnregisterMediaRoutesObserver(&different_routes_observer); + routes_observer.reset(); + extra_routes_observer.reset(); // No route observers should be notified. UpdateRoutes(mojom::MediaRouteProviderId::CAST, expected_routes);
diff --git a/chrome/browser/media/router/test/media_router_mojo_test.cc b/chrome/browser/media/router/test/media_router_mojo_test.cc index 914a264..230c92b 100644 --- a/chrome/browser/media/router/test/media_router_mojo_test.cc +++ b/chrome/browser/media/router/test/media_router_mojo_test.cc
@@ -141,8 +141,9 @@ void MediaRouterMojoTest::ProvideTestRoute( mojom::MediaRouteProviderId provider_id, const MediaRoute::Id& route_id) { - if (!routes_observer_) + if (!routes_observer_) { routes_observer_ = std::make_unique<MediaRoutesObserver>(router()); + } MediaRoute route = CreateMediaRoute(); route.set_media_route_id(route_id); router()->OnRoutesUpdated(provider_id, {route});
diff --git a/chrome/browser/metrics/structured/BUILD.gn b/chrome/browser/metrics/structured/BUILD.gn index 6e9c44e0..df9cd4f 100644 --- a/chrome/browser/metrics/structured/BUILD.gn +++ b/chrome/browser/metrics/structured/BUILD.gn
@@ -28,9 +28,14 @@ sources += [ "ash_structured_metrics_recorder.cc", "ash_structured_metrics_recorder.h", + "structured_metrics_user_session_observer.cc", + "structured_metrics_user_session_observer.h", ] - deps += [ "//chrome/browser/ash/crosapi" ] + deps += [ + "//chrome/browser/ash/crosapi", + "//components/user_manager:user_manager", + ] } if (is_chromeos_lacros) {
diff --git a/chrome/browser/metrics/structured/ash_structured_metrics_recorder.cc b/chrome/browser/metrics/structured/ash_structured_metrics_recorder.cc index b8fe8aa2..e2e6745a 100644 --- a/chrome/browser/metrics/structured/ash_structured_metrics_recorder.cc +++ b/chrome/browser/metrics/structured/ash_structured_metrics_recorder.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/metrics/structured/ash_structured_metrics_recorder.h" +#include <memory> #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/ash/crosapi/crosapi_ash.h" @@ -11,6 +12,7 @@ #include "components/metrics/structured/event.h" #include "components/metrics/structured/histogram_util.h" #include "components/metrics/structured/recorder.h" +#include "components/metrics/structured/structured_metrics_features.h" namespace metrics { namespace structured { @@ -22,13 +24,21 @@ DCHECK(!is_initialized_); // If already initialized, do nothing. - if (is_initialized_) + if (is_initialized_) { return; + } // Crosapi may not be initialized, in which case a pipe cannot be setup. if (crosapi::CrosapiManager::IsInitialized()) { crosapi::CrosapiManager::Get()->crosapi_ash()->BindStructuredMetricsService( remote_.BindNewPipeAndPassReceiver()); + + if (base::FeatureList::IsEnabled(kEventSequenceLogging)) { + auto* user_manager = user_manager::UserManager::Get(); + DCHECK(user_manager); + user_session_observer_ = + std::make_unique<StructuredMetricsUserSessionObserver>(user_manager); + } is_initialized_ = true; } else { VLOG(2) << "Initialize() called before CrosApi is initialized.";
diff --git a/chrome/browser/metrics/structured/ash_structured_metrics_recorder.h b/chrome/browser/metrics/structured/ash_structured_metrics_recorder.h index 411bcca..360c633 100644 --- a/chrome/browser/metrics/structured/ash_structured_metrics_recorder.h +++ b/chrome/browser/metrics/structured/ash_structured_metrics_recorder.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_METRICS_STRUCTURED_ASH_STRUCTURED_METRICS_RECORDER_H_ #define CHROME_BROWSER_METRICS_STRUCTURED_ASH_STRUCTURED_METRICS_RECORDER_H_ +#include "chrome/browser/metrics/structured/structured_metrics_user_session_observer.h" #include "chromeos/crosapi/mojom/structured_metrics_service.mojom.h" #include "components/metrics/structured/event.h" #include "components/metrics/structured/structured_metrics_client.h" @@ -38,7 +39,7 @@ private: mojo::Remote<crosapi::mojom::StructuredMetricsService> remote_; - + std::unique_ptr<StructuredMetricsUserSessionObserver> user_session_observer_; bool is_initialized_ = false; };
diff --git a/chrome/browser/metrics/structured/structured_metrics_user_session_observer.cc b/chrome/browser/metrics/structured/structured_metrics_user_session_observer.cc new file mode 100644 index 0000000..f76afbdb --- /dev/null +++ b/chrome/browser/metrics/structured/structured_metrics_user_session_observer.cc
@@ -0,0 +1,27 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/metrics/structured/structured_metrics_user_session_observer.h" +#include "components/metrics/structured/structured_events.h" + +namespace metrics::structured { + +StructuredMetricsUserSessionObserver::StructuredMetricsUserSessionObserver( + user_manager::UserManager* user_manager) + : user_manager_(user_manager) { + user_manager_->AddSessionStateObserver(this); +} + +StructuredMetricsUserSessionObserver::~StructuredMetricsUserSessionObserver() { + user_manager_->RemoveSessionStateObserver(this); +} + +void StructuredMetricsUserSessionObserver::ActiveUserChanged( + user_manager::User* active_user) { + if (active_user->is_active()) { + events::v2::cr_os_events::UserLogin().Record(); + } +} + +} // namespace metrics::structured
diff --git a/chrome/browser/metrics/structured/structured_metrics_user_session_observer.h b/chrome/browser/metrics/structured/structured_metrics_user_session_observer.h new file mode 100644 index 0000000..f68abcc --- /dev/null +++ b/chrome/browser/metrics/structured/structured_metrics_user_session_observer.h
@@ -0,0 +1,31 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_METRICS_STRUCTURED_STRUCTURED_METRICS_USER_SESSION_OBSERVER_H_ +#define CHROME_BROWSER_METRICS_STRUCTURED_STRUCTURED_METRICS_USER_SESSION_OBSERVER_H_ + +#include "components/user_manager/user_manager.h" + +namespace metrics::structured { + +// An UserSession observer to detect a login for an event to be recorded +// when such a user action takes place. +class StructuredMetricsUserSessionObserver + : public user_manager::UserManager::UserSessionStateObserver { + public: + explicit StructuredMetricsUserSessionObserver( + user_manager::UserManager* user_manager); + + ~StructuredMetricsUserSessionObserver() override; + + // user_manager::UserSessionStateObserver: + void ActiveUserChanged(user_manager::User* active_user) override; + + private: + user_manager::UserManager* user_manager_; +}; + +} // namespace metrics::structured + +#endif // CHROME_BROWSER_METRICS_STRUCTURED_STRUCTURED_METRICS_USER_SESSION_OBSERVER_H_
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 869ba08..046ecfe 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -20,6 +20,7 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/browsing_data/browsing_data_lifetime_policy_handler.h" #include "chrome/browser/enterprise/connectors/device_trust/prefs.h" +#include "chrome/browser/enterprise/idle/idle_timeout_policy_handler.h" #include "chrome/browser/first_party_sets/first_party_sets_overrides_policy_handler.h" #include "chrome/browser/net/disk_cache_dir_policy_handler.h" #include "chrome/browser/net/explicitly_allowed_network_ports_policy_handler.h" @@ -161,6 +162,7 @@ #include "chrome/browser/ash/plugin_vm/plugin_vm_pref_names.h" #include "chrome/browser/ash/policy/handlers/configuration_policy_handler_ash.h" #include "chrome/browser/ash/policy/handlers/lacros_availability_policy_handler.h" +#include "chrome/browser/ash/policy/handlers/lacros_selection_policy_handler.h" #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" #include "chrome/browser/policy/default_geolocation_policy_handler.h" #include "chrome/browser/policy/os_color_mode_policy_handler.h" @@ -1826,22 +1828,6 @@ } #endif // BUILDFLAG(ENABLE_EXTENSIONS) -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) -void GetIdleTimeoutActionsMap( - std::vector<std::unique_ptr<StringMappingListPolicyHandler::MappingEntry>>* - result) { - // Mapping from IdleTimeoutActions action names to ActionType. - for (size_t i = 0; i < enterprise_idle::kActionTypeMapSize; i++) { - const enterprise_idle::ActionTypeMapEntry& entry = - enterprise_idle::kActionTypeMap[i]; - result->push_back( - std::make_unique<StringMappingListPolicyHandler::MappingEntry>( - entry.name, std::make_unique<base::Value>( - static_cast<int>(entry.action_type)))); - } -} -#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) - // Future policies are not supported on Stable and Beta by default. bool AreFuturePoliciesSupported() { // Enable future policies for branded browser tests. @@ -2032,11 +2018,11 @@ SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED)); #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) - handlers->AddHandler(std::make_unique<IntRangePolicyHandler>( - key::kIdleTimeout, prefs::kIdleTimeout, 5, INT_MAX, /*clamp=*/true)); - handlers->AddHandler(std::make_unique<StringMappingListPolicyHandler>( - key::kIdleTimeoutActions, prefs::kIdleTimeoutActions, - base::BindRepeating(&GetIdleTimeoutActionsMap))); + handlers->AddHandler( + std::make_unique<enterprise_idle::IdleTimeoutPolicyHandler>()); + handlers->AddHandler( + std::make_unique<enterprise_idle::IdleTimeoutActionsPolicyHandler>( + chrome_schema)); #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) handlers->AddHandler(std::make_unique<RestoreOnStartupPolicyHandler>()); @@ -2408,6 +2394,7 @@ handlers->AddHandler(std::make_unique<BooleanDisablingPolicyHandler>( key::kNearbyShareAllowed, prefs::kNearbySharingEnabledPrefName)); handlers->AddHandler(std::make_unique<LacrosAvailabilityPolicyHandler>()); + handlers->AddHandler(std::make_unique<LacrosSelectionPolicyHandler>()); handlers->AddHandler(std::make_unique<BooleanDisablingPolicyHandler>( key::kFastPairEnabled, ash::prefs::kFastPairEnabled)); handlers->AddHandler(std::make_unique<arc::ArcPolicyHandler>());
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 0e17f238..a2a12efa 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -657,6 +657,7 @@ policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())); crosapi::browser_util::CacheLacrosAvailability(map); crosapi::browser_util::CacheLacrosDataBackwardMigrationMode(map); + crosapi::browser_util::CacheLacrosSelection(map); } #endif } @@ -1183,6 +1184,7 @@ policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())); crosapi::browser_util::CacheLacrosAvailability(map); crosapi::browser_util::CacheLacrosDataBackwardMigrationMode(map); + crosapi::browser_util::CacheLacrosSelection(map); } ash::UserSessionManager::GetInstance()->RespectLocalePreferenceWrapper(
diff --git a/chrome/browser/reading_list/OWNERS b/chrome/browser/reading_list/OWNERS index b4a76a2b..adf8b80d 100644 --- a/chrome/browser/reading_list/OWNERS +++ b/chrome/browser/reading_list/OWNERS
@@ -1,6 +1,6 @@ -dtrainor@chromium.org -shaktisahu@chromium.org +wylieb@chromium.org # Backup reviewers: twellington@chromium.org -wylieb@chromium.org +dtrainor@chromium.org +shaktisahu@chromium.org \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js index dcaf21cf..52a083f3 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
@@ -672,38 +672,6 @@ } /** @override */ - formatCellIndexText_(data, token, options) { - const buff = data.outputBuffer; - const node = data.node; - const formatLog = data.outputFormatLogger; - - if (node.htmlAttributes['aria-coltext']) { - let value = node.htmlAttributes['aria-coltext']; - let row = node; - while (row && row.role !== RoleType.ROW) { - row = row.parent; - } - if (!row || !row.htmlAttributes['aria-rowtext']) { - return; - } - value += row.htmlAttributes['aria-rowtext']; - this.append_(buff, value, options); - formatLog.writeTokenWithValue(token, value); - } else { - formatLog.write(token); - this.format_({ - node, - outputFormat: ` @cell_summary($if($tableCellAriaRowIndex, - $tableCellAriaRowIndex, $tableCellRowIndex), - $if($tableCellAriaColumnIndex, $tableCellAriaColumnIndex, - $tableCellColumnIndex))`, - outputBuffer: buff, - outputFormatLogger: formatLog, - }); - } - } - - /** @override */ formatNode_(data, token, tree, options) { const buff = data.outputBuffer; const node = data.node;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js index cfa54678..9031378d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js
@@ -97,7 +97,7 @@ token === 'tableCellRowIndex' || token === 'tableCellColumnIndex') { this.formatTableCellIndex_(this.params_, token, options); } else if (token === 'cellIndexText') { - this.output_.formatCellIndexText_(this.params_, token, options); + this.formatCellIndexText_(this.params_, token, options); } else if (token === 'node') { this.output_.formatNode_(this.params_, token, tree, options); } else if (token === 'nameOrTextContent' || token === 'textContent') { @@ -184,6 +184,43 @@ /** * @param {!outputTypes.OutputFormattingData} data * @param {string} token + * @param {!{annotation: Array<*>, isUnique: (boolean|undefined)}} options + * @private + */ + formatCellIndexText_(data, token, options) { + const buff = data.outputBuffer; + const node = data.node; + const formatLog = data.outputFormatLogger; + + if (node.htmlAttributes['aria-coltext']) { + let value = node.htmlAttributes['aria-coltext']; + let row = node; + while (row && row.role !== RoleType.ROW) { + row = row.parent; + } + if (!row || !row.htmlAttributes['aria-rowtext']) { + return; + } + value += row.htmlAttributes['aria-rowtext']; + this.output_.append_(buff, value, options); + formatLog.writeTokenWithValue(token, value); + } else { + formatLog.write(token); + this.output_.format_({ + node, + outputFormat: ` @cell_summary($if($tableCellAriaRowIndex, + $tableCellAriaRowIndex, $tableCellRowIndex), + $if($tableCellAriaColumnIndex, $tableCellAriaColumnIndex, + $tableCellColumnIndex))`, + outputBuffer: buff, + outputFormatLogger: formatLog, + }); + } + } + + /** + * @param {!outputTypes.OutputFormattingData} data + * @param {string} token * @private */ formatChecked_(data, token) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js index be41ead..7bae0e6 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js
@@ -65,13 +65,6 @@ /** * @param {!outputTypes.OutputFormattingData} data * @param {string} token - * @param {!{annotation: Array<*>, isUnique: (boolean|undefined)}} options - */ - formatCellIndexText_(data, token, options) {} - - /** - * @param {!outputTypes.OutputFormattingData} data - * @param {string} token * @param {!OutputFormatTree} tree * @param {!{annotation: Array<*>, isUnique: (boolean|undefined)}} options */
diff --git a/chrome/browser/resources/extensions/service.ts b/chrome/browser/resources/extensions/service.ts index 9fbe8e71..d6329613 100644 --- a/chrome/browser/resources/extensions/service.ts +++ b/chrome/browser/resources/extensions/service.ts
@@ -138,11 +138,10 @@ populateError: true, }, extraOptions); - return chrome.developerPrivate.loadUnpacked(options) .then(loadError => { if (loadError) { - throw new Error(loadError.error); + throw loadError; } // The load was successful if there's no loadError. return true;
diff --git a/chrome/browser/resources/management/management_ui.ts b/chrome/browser/resources/management/management_ui.ts index 767e7135..cc01578e 100644 --- a/chrome/browser/resources/management/management_ui.ts +++ b/chrome/browser/resources/management/management_ui.ts
@@ -379,8 +379,8 @@ } // </if> // <if expr="not chromeos_ash"> - this.managementNoticeHtml_ = - sanitizeInnerHtml(data.browserManagementNotice); + this.managementNoticeHtml_ = sanitizeInnerHtml( + data.browserManagementNotice, {attrs: ['aria-label']}); // </if> }); }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn index 6ed68ea..acec84f 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
@@ -20,7 +20,6 @@ ":internet_known_networks_page", ":internet_page", ":internet_page_browser_proxy", - ":internet_shared_css", ":internet_subpage", ":network_always_on_vpn", ":network_proxy_section", @@ -60,7 +59,6 @@ js_library("internet_config") { deps = [ - ":internet_shared_css", "//ash/webui/common/resources:i18n_behavior", "//ash/webui/common/resources:util", "//ash/webui/common/resources/network:network_config", @@ -99,7 +97,6 @@ js_library("internet_detail_page") { deps = [ ":internet_page_browser_proxy", - ":internet_shared_css", ":network_proxy_section", "//ash/webui/common/resources:assert", "//ash/webui/common/resources:i18n_behavior", @@ -140,7 +137,6 @@ js_library("internet_known_networks_page") { deps = [ - ":internet_shared_css", "//ash/webui/common/resources:assert", "//ash/webui/common/resources:i18n_behavior", "//ash/webui/common/resources/network:cr_policy_network_behavior_mojo", @@ -195,9 +191,6 @@ js_library("internet_page_browser_proxy") { } -js_library("internet_shared_css") { -} - js_library("internet_subpage") { deps = [ ":internet_page_browser_proxy", @@ -233,7 +226,6 @@ js_library("network_always_on_vpn") { deps = [ - ":internet_shared_css", "//ash/webui/common/resources:assert", "//ash/webui/common/resources:i18n_behavior", "//ash/webui/common/resources/network:onc_mojo", @@ -243,7 +235,6 @@ js_library("network_proxy_section") { deps = [ - ":internet_shared_css", "//ash/webui/common/resources:i18n_behavior", "//ash/webui/common/resources/network:cr_policy_network_behavior_mojo", "//ash/webui/common/resources/network:cr_policy_network_indicator_mojo", @@ -302,7 +293,6 @@ "internet_detail_page.js", "internet_known_networks_page.js", "internet_page.js", - "internet_shared_css.js", "internet_subpage.js", "network_always_on_vpn.js", "network_proxy_section.js",
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/apn_subpage.js b/chrome/browser/resources/settings/chromeos/internet_page/apn_subpage.js index 12e1ad2..947cd72 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/apn_subpage.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/apn_subpage.js
@@ -7,7 +7,7 @@ * Settings subpage for managing APNs. */ -import './internet_shared_css.js'; +import './internet_shared.css.js'; import 'chrome://resources/ash/common/network/apn_list.js'; import {assert} from 'chrome://resources/ash/common/assert.js'; @@ -232,4 +232,4 @@ } } -customElements.define(ApnSubpageElement.is, ApnSubpageElement); \ No newline at end of file +customElements.define(ApnSubpageElement.is, ApnSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/hotspot_subpage.js b/chrome/browser/resources/settings/chromeos/internet_page/hotspot_subpage.js index 973d495..e01b0a0 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/hotspot_subpage.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/hotspot_subpage.js
@@ -7,7 +7,7 @@ * Settings subpage for managing Hotspot. */ -import './internet_shared_css.js'; +import './internet_shared.css.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -23,4 +23,4 @@ } customElements.define( - SettingsHotspotSubpageElement.is, SettingsHotspotSubpageElement); \ No newline at end of file + SettingsHotspotSubpageElement.is, SettingsHotspotSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js index 571376c..23c39dd 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js
@@ -10,11 +10,11 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import './internet_shared_css.js'; +import './internet_shared.css.js'; -import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; import {HTMLEscape} from 'chrome://resources/ash/common/util.js'; import {NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js index 5b2d084..93c2fcd 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js
@@ -30,20 +30,20 @@ import '../../controls/settings_toggle_button.js'; import '../../prefs/prefs.js'; import './cellular_roaming_toggle_button.js'; -import './internet_shared_css.js'; +import './internet_shared.css.js'; import './network_proxy_section.js'; import './settings_traffic_counters.js'; import './tether_connection_dialog.js'; +import {assert} from 'chrome://resources/ash/common/assert.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; +import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; import {isActiveSim, processDeviceState} from 'chrome://resources/ash/common/network/cellular_utils.js'; import {CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojoInterface} from 'chrome://resources/ash/common/network/cr_policy_network_behavior_mojo.js'; import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js'; import {NetworkListenerBehavior, NetworkListenerBehaviorInterface} from 'chrome://resources/ash/common/network/network_listener_behavior.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; -import {assert} from 'chrome://resources/ash/common/assert.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; import {ActivationStateType, ApnProperties, ConfigProperties, CrosNetworkConfigRemote, FilterType, GlobalPolicy, HiddenSsidMode, IPConfigProperties, ManagedProperties, NetworkStateProperties, NO_LIMIT, ProxySettings, SecurityType, VpnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {ConnectionStateType, DeviceStateType, IPConfigType, NetworkType, OncSource, PolicySource, PortalState} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; import {afterNextRender, flush, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js index ad6184d0..51a6510 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js
@@ -12,24 +12,24 @@ import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; import 'chrome://resources/cr_elements/icons.html.js'; import '../../settings_shared.css.js'; -import './internet_shared_css.js'; +import './internet_shared.css.js'; +import {assert} from 'chrome://resources/ash/common/assert.js'; +import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; import {CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojoInterface} from 'chrome://resources/ash/common/network/cr_policy_network_behavior_mojo.js'; import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js'; import {NetworkListenerBehavior, NetworkListenerBehaviorInterface} from 'chrome://resources/ash/common/network/network_listener_behavior.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {assert} from 'chrome://resources/ash/common/assert.js'; import {ConfigProperties, CrosNetworkConfigRemote, FilterType, NO_LIMIT} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route} from '../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {recordSettingChange} from '../metrics_recorder.js'; import {routes} from '../os_route.js'; import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {Route} from '../router.js'; /** * @constructor
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_shared.css b/chrome/browser/resources/settings/chromeos/internet_page/internet_shared.css new file mode 100644 index 0000000..e6948c0 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_shared.css
@@ -0,0 +1,31 @@ +/* Copyright 2022 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* #css_wrapper_metadata_start + * #type=style + * #import=chrome://resources/cr_elements/cr_shared_vars.css.js + * #include=settings-shared + * #css_wrapper_metadata_end */ + +network-icon { + padding-inline-end: var(--cr-section-padding); +} + +iron-icon.policy { + margin-inline-end: var(--cr-controlled-by-spacing); +} + +.indented { + margin-inline-start: var(--cr-section-padding); +} + +.stretch { + align-items: stretch; +} + +.title { + font-size: 107.69%; /* 14px / 13px */ + font-weight: 500; +}
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.html b/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.html deleted file mode 100644 index f56ed93..0000000 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.html +++ /dev/null
@@ -1,25 +0,0 @@ - -<template> - <style include="settings-shared"> - network-icon { - padding-inline-end: var(--cr-section-padding); - } - - iron-icon.policy { - margin-inline-end: var(--cr-controlled-by-spacing); - } - - .indented { - margin-inline-start: var(--cr-section-padding); - } - - .stretch { - align-items: stretch; - } - - .title { - font-size: 107.69%; /* 14px / 13px */ - font-weight: 500; - } - </style> -</template>
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.js deleted file mode 100644 index bbfeab4c..0000000 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.js +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; -import '../../settings_shared.css.js'; -const template = document.createElement('template'); -template.innerHTML = ` -<dom-module id="internet-shared" assetpath="chrome://resources/">{__html_template__}</dom-module> -`; -document.body.appendChild(template.content.cloneNode(true));
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.js b/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.js index e8d97ce..a9cec8b 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.js
@@ -16,13 +16,13 @@ import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; import '../../controls/extension_controlled_indicator.js'; import '../../settings_vars.css.js'; -import './internet_shared_css.js'; +import './internet_shared.css.js'; import '../../controls/settings_toggle_button.js'; import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; +import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; import {CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojoInterface} from 'chrome://resources/ash/common/network/cr_policy_network_behavior_mojo.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; import {ManagedProperties, ManagedString} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {OncSource} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/settings_traffic_counters.ts b/chrome/browser/resources/settings/chromeos/internet_page/settings_traffic_counters.ts index 7091634..0940206 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/settings_traffic_counters.ts +++ b/chrome/browser/resources/settings/chromeos/internet_page/settings_traffic_counters.ts
@@ -7,7 +7,7 @@ * Settings UI. */ -import './internet_shared_css.js'; +import './internet_shared.css.js'; import 'chrome://resources/ash/common/network/network_shared.css.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts index c87d29b..095ec0f 100644 --- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts +++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
@@ -18,6 +18,7 @@ import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; +import {PrefsMixin, PrefsMixinInterface} from '../../prefs/prefs_mixin.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {DevicePageBrowserProxy, DevicePageBrowserProxyImpl} from '../device_page/device_page_browser_proxy.js'; import {routes} from '../os_route.js'; @@ -32,10 +33,11 @@ [ DeepLinkingBehavior, ], - RouteOriginMixin(WebUiListenerMixin(I18nMixin(PolymerElement)))) as { + RouteOriginMixin( + PrefsMixin(WebUiListenerMixin(I18nMixin(PolymerElement))))) as { new (): PolymerElement & I18nMixinInterface & - WebUiListenerMixinInterface & RouteOriginMixinInterface & - DeepLinkingBehaviorInterface, + WebUiListenerMixinInterface & PrefsMixinInterface & + RouteOriginMixinInterface & DeepLinkingBehaviorInterface, }; class SettingsTextToSpeechPageElement extends @@ -51,14 +53,6 @@ static get properties() { return { /** - * Preferences state. - */ - prefs: { - type: Object, - notify: true, - }, - - /** * |hasKeyboard_| starts undefined so observer doesn't trigger until it * has been populated. */ @@ -85,7 +79,6 @@ }; } - prefs: {[key: string]: any}; private deviceBrowserProxy_: DevicePageBrowserProxy; private hasKeyboard_: boolean; private route_: Route;
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index ffd35abc..278f7bd 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -204,6 +204,7 @@ # Files that are passed as input to css_to_wrapper(). css_files = [ + "chromeos/internet_page/internet_shared.css", "chromeos/os_apps_page/app_management_page/app_management_cros_shared_style.css", "chromeos/os_apps_page/app_management_page/app_management_cros_shared_vars.css", "chromeos/os_languages_page/shared_style.css", @@ -353,7 +354,6 @@ "chromeos/internet_page/internet_detail_page.js", "chromeos/internet_page/internet_known_networks_page.js", "chromeos/internet_page/internet_page.js", - "chromeos/internet_page/internet_shared_css.js", "chromeos/internet_page/internet_subpage.js", "chromeos/internet_page/network_always_on_vpn.js", "chromeos/internet_page/network_proxy_section.js",
diff --git a/chrome/browser/resources/side_panel/customize_chrome/color.html b/chrome/browser/resources/side_panel/customize_chrome/color.html index be49563..bfb971f 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/color.html +++ b/chrome/browser/resources/side_panel/customize_chrome/color.html
@@ -1,32 +1,51 @@ <style> :host { + align-items: center; cursor: pointer; + display: flex; + justify-content: center; } :host, svg { - border-radius: 25px; - display: block; height: 50px; width: 50px; } + :host([checked]) svg { + height: 46px; + width: 46px; + } + + customize-chrome-check-mark { + --customize-chrome-check-mark-wrapper-end: -1px; + } + + svg { + border-radius: 25px; + } + #background { fill: var(--customize-chrome-color-background-color); } + :host([checked]) #background { + r: 25px; + } + #foreground { fill: var(--customize-chrome-color-foreground-color); } </style> -<!-- TODO(crbug.com/1384229): Allow clicking. --> -<svg viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink"> - <circle id="foreground" cx="25" cy="25" r="25"> - </circle> - <clipPath id="bottomHalf"> - <rect x="1" y="25" width="48" height="24"></rect> - </clipPath> - <circle id="background" cx="25" cy="25" r="24" - clip-path="url(#bottomHalf)"></circle> -</svg> +<customize-chrome-check-mark-wrapper checked="[[checked]]"> + <svg viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <circle id="foreground" cx="25" cy="25" r="25"> + </circle> + <clipPath id="bottomHalf"> + <rect x="1" y="25" width="50" height="25"></rect> + </clipPath> + <circle id="background" cx="25" cy="25" r="24" + clip-path="url(#bottomHalf)"></circle> + </svg> +</customize-chrome-check-mark-wrapper>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/color.ts b/chrome/browser/resources/side_panel/customize_chrome/color.ts index 83312e8..5b3d943 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/color.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/color.ts
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './check_mark_wrapper.js'; + import {skColorToRgba} from 'chrome://resources/js/color_utils.js'; import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -36,11 +38,16 @@ value: 0, observer: 'onColorChange_', }, + checked: { + type: Boolean, + reflectToAttribute: true, + }, }; } public backgroundColor: SkColor; public foregroundColor: SkColor; + public checked: boolean; private onColorChange_() { this.updateStyles({
diff --git a/chrome/browser/resources/side_panel/customize_chrome/colors.html b/chrome/browser/resources/side_panel/customize_chrome/colors.html index 6138b869..f88e9dc9 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/colors.html +++ b/chrome/browser/resources/side_panel/customize_chrome/colors.html
@@ -5,33 +5,84 @@ justify-content: center; } - customize-chrome-check-mark { - --customize-chrome-check-mark-wrapper-end: -1px; + #customColorContainer { + position: relative; + } + + /* colorPicker is placed on top of the theme icon to work around + https://crbug.com/1162053. */ + #colorPicker { + border: 0; + height: 50px; + left: 0; + margin: 0; + opacity: 0; + padding: 0; + pointer-events: none; + position: absolute; + top: 0; + width: 50px; + } + + #colorPickerIcon { + -webkit-mask-image: url(chrome://resources/cr_components/customize_themes/colorize.svg); + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: 100%; + background-color: var(--google-grey-700); + height: 20px; + left: calc(50% - 10px); + pointer-events: none; + position: absolute; + top: calc(50% - 10px); + width: 20px; } </style> -<!-- TODO(crbug.com/1384229): Make grid adaptive. --> -<cr-grid columns="4"> - <!-- TODO(crbug.com/1384229): Add extracted color. --> - <customize-chrome-check-mark-wrapper checked> - <customize-chrome-color - id="defaultColor" - background-color="[[defaultColor_.background]]" - foreground-color="[[defaultColor_.foreground]]" - title="$i18n{defaultColorName}" - on-click="onDefaultColorClick_"> - </customize-chrome-color> - </customize-chrome-check-mark-wrapper> +<!-- TODO(crbug.com/1395210): Make grid adaptive. --> +<cr-grid columns="4" role="radiogroup" + aria-label="$i18n{colorsContainerLabel}"> + <!-- TODO(crbug.com/1401018): Add extracted color. --> + <customize-chrome-color + id="defaultColor" + background-color="[[defaultColor_.background]]" + foreground-color="[[defaultColor_.foreground]]" + title="$i18n{defaultColorName}" + aria-label="$i18n{defaultColorName}" + role="radio" + checked="[[isDefaultColorSelected_]]" + aria-checked$="[[isDefaultColorSelected_]]" + tabindex$="[[tabIndex_(isDefaultColorSelected_)]]" + on-click="onDefaultColorClick_"> + </customize-chrome-color> <template id="chromeColors" is="dom-repeat" items="[[colors_]]"> - <!-- TODO(crbug.com/1384229): Only set checked if selected. --> - <customize-chrome-check-mark-wrapper checked> - <customize-chrome-color - class="chrome-color" - background-color="[[item.background]]" - foreground-color="[[item.foreground]]" - title="[[item.name]]" - on-click="onChromeColorClick_"> - </customize-chrome-color> - </customize-chrome-check-mark-wrapper> + <customize-chrome-color + class="chrome-color" + background-color="[[item.background]]" + foreground-color="[[item.foreground]]" + title="[[item.name]]" + aria-label$="[[item.name]]" + role="radio" + checked="[[isChromeColorSelected_(item.foreground, theme_, colors_)]]" + aria-checked$= + "[[isChromeColorSelected_(item.foreground, theme_, colors_)]]" + tabindex$="[[chromeColorTabIndex_(item.foreground, theme_, colors_)]]" + on-click="onChromeColorClick_"> + </customize-chrome-color> </template> - <!-- TODO(crbug.com/1384229): Add color picker. --> + <div id="customColorContainer" + title="$i18n{colorPickerLabel}" + aria-label="$i18n{colorPickerLabel}" + role="radio" + aria-checked$="[[isCustomColorSelected_]]" + tabindex$="[[tabIndex_(isCustomColorSelected_)]]" + on-click="onCustomColorClick_"> + <customize-chrome-color + id="customColor" + background-color="[[customColor_.background]]" + foreground-color="[[customColor_.foreground]]" + checked="[[isCustomColorSelected_]]"> + </customize-chrome-color> + <div id="colorPickerIcon"></div> + <input id="colorPicker" type="color" tabindex="-1" aria-hidden="true" + on-change="onCustomColorChange_"> + </div> </cr-grid>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/colors.ts b/chrome/browser/resources/side_panel/customize_chrome/colors.ts index 926fd80..ac571877 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/colors.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/colors.ts
@@ -4,8 +4,8 @@ import 'chrome://resources/cr_elements/cr_grid/cr_grid.js'; import './color.js'; -import './check_mark_wrapper.js'; +import {hexColorToSkColor, skColorToRgba} from 'chrome://resources/js/color_utils.js'; import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js'; import {DomRepeat, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -29,10 +29,20 @@ foreground: {value: 0xff202124}, }; +function isChromeColorSelected( + theme: Theme|undefined, colors: ChromeColor[]|undefined, color: SkColor) { + return !!theme && !!colors && !!theme.foregroundColor && + theme.foregroundColor.value === color.value; +} + export interface ColorsElement { $: { defaultColor: ColorElement, chromeColors: DomRepeat, + customColorContainer: HTMLElement, + customColor: ColorElement, + colorPicker: HTMLInputElement, + colorPickerIcon: HTMLElement, }; } @@ -53,11 +63,34 @@ }, colors_: Array, theme_: Object, + isDefaultColorSelected_: { + type: Object, + computed: 'computeIsDefaultColorSelected_(theme_)', + }, + isCustomColorSelected_: { + type: Object, + computed: 'computeIsCustomColorSelected_(theme_, color_)', + }, + customColor_: { + type: Object, + value: { + background: {value: 0xffffffff}, + foreground: {value: 0xfff1f3f4}, + }, + }, }; } + static get observers() { + return [ + 'updateCustomColor_(colors_, theme_, isCustomColorSelected_)', + ]; + } + private colors_: ChromeColor[]; private theme_: Theme; + private isCustomColorSelected_: boolean; + private customColor_: Color; private setThemeListenerId_: number|null = null; constructor() { @@ -89,6 +122,29 @@ LIGHT_DEFAULT_COLOR; } + private computeIsDefaultColorSelected_(): boolean { + return this.theme_ && !this.theme_.foregroundColor; + } + + private computeIsCustomColorSelected_(): boolean { + return !!this.colors_ && !!this.theme_ && !!this.theme_.foregroundColor && + !this.colors_.find( + (color: ChromeColor) => + color.foreground.value === this.theme_.foregroundColor!.value); + } + + private isChromeColorSelected_(color: SkColor): boolean { + return isChromeColorSelected(this.theme_, this.colors_, color); + } + + private tabIndex_(selected: boolean): string { + return selected ? '0' : '-1'; + } + + private chromeColorTabIndex_(color: SkColor): string { + return isChromeColorSelected(this.theme_, this.colors_, color) ? '0' : '-1'; + } + private onDefaultColorClick_() { CustomizeChromeApiProxy.getInstance().handler.setDefaultColor(); } @@ -97,6 +153,30 @@ CustomizeChromeApiProxy.getInstance().handler.setForegroundColor( this.$.chromeColors.itemForElement(e.target as HTMLElement).foreground); } + + private onCustomColorClick_() { + this.$.colorPicker.focus(); + this.$.colorPicker.click(); + } + + private onCustomColorChange_(e: Event) { + CustomizeChromeApiProxy.getInstance().handler.setForegroundColor( + hexColorToSkColor((e.target as HTMLInputElement).value)); + } + + private updateCustomColor_() { + // We only change the custom color when theme updates to a new custom color + // so that the picked color persists while clicking on other color circles. + if (!this.isCustomColorSelected_) { + return; + } + this.customColor_ = { + background: this.theme_.backgroundColor, + foreground: this.theme_.foregroundColor!, + }; + this.$.colorPickerIcon.style.setProperty( + 'background-color', skColorToRgba(this.theme_.colorPickerIconColor)); + } } declare global {
diff --git a/chrome/browser/resources/side_panel/customize_chrome/icons/BUILD.gn b/chrome/browser/resources/side_panel/customize_chrome/icons/BUILD.gn index c6f0ebfd..60f2b9c1 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/icons/BUILD.gn +++ b/chrome/browser/resources/side_panel/customize_chrome/icons/BUILD.gn
@@ -9,7 +9,10 @@ generate_grd("build_grdp") { grd_prefix = "side_panel_customize_chrome" out_grd = "$target_gen_dir/resources.grdp" - input_files = [ "mini_new_tab_page.svg" ] + input_files = [ + "mini_new_tab_page.svg", + "uploaded_image.svg", + ] input_files_base_dir = rebase_path(".", "//") resource_path_prefix = "icons" }
diff --git a/chrome/browser/resources/side_panel/customize_chrome/icons/uploaded_image.svg b/chrome/browser/resources/side_panel/customize_chrome/icons/uploaded_image.svg new file mode 100644 index 0000000..a7b06bae --- /dev/null +++ b/chrome/browser/resources/side_panel/customize_chrome/icons/uploaded_image.svg
@@ -0,0 +1 @@ +<svg width="288" height="162" viewBox="0 0 288 162" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="-4" width="295" height="166" rx="20" fill="#F1F3F4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M152.333 71h-18.666A2.675 2.675 0 0 0 131 73.667v18.666C131 93.8 132.2 95 133.667 95h18.666C153.8 95 155 93.8 155 92.333V73.667C155 72.2 153.8 71 152.333 71Zm0 21.333h-18.666V73.667h18.666v18.666Zm-10.666-4.373 4-4.96L151 89.667h-16l4-5.334 2.667 3.627Z" fill="#5F6368"/></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.html b/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.html index 804b196..d1846f0a 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.html +++ b/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.html
@@ -1,13 +1,18 @@ <style> - #themeSnapshot { + .theme-snapshot { align-items: center; display: flex; flex-wrap: wrap; justify-content: center; + margin-bottom: 8px; margin-inline-start: 16px; width: 288px; } + .theme-snapshot img { + object-fit: fill; + } + .image { border: 1px solid rgba(0, 0, 0, .14); border-radius: 20px; @@ -16,11 +21,7 @@ width: inherit; } - #themeSnapshot img { - object-fit: fill; - } - - #classicChromeImageContainer { + #classicChrome { align-items: center; background-color: var(--customize-chrome-color-background-color); display: flex; @@ -33,22 +34,25 @@ } #themeTitle { - margin-bottom: 8px; overflow: hidden; white-space: nowrap; } </style> -<div id="themeSnapshot"> - <template is="dom-if" if="[[showThemeSnapshot_]]"> +<iron-pages selected="[[themeType_]]" attr-for-selected="theme-type"> + <div class="theme-snapshot" theme-type="customTheme"> <img class="image" is="cr-auto-img" auto-src="[[theme_.backgroundImage.url.url]]" draggable="false"> </img> <label id="themeTitle">[[theme_.backgroundImage.title]]</label> - </template> - <template is="dom-if" if="[[!showThemeSnapshot_]]"> - <div class="image" id="classicChromeImageContainer"> + </div> + <div class="theme-snapshot" theme-type="classicChrome"> + <div class="image" id="classicChrome"> <img id="miniNewTabPage" src="icons/mini_new_tab_page.svg"></img> </div> <label id="themeTitle">$i18n{classicChrome}</label> - </template> -</div> + </div> + <div class="theme-snapshot" theme-type="uploadedImage"> + <img class="image" src="icons/uploaded_image.svg"></img> + <label id="themeTitle">$i18n{uploadedImage}</label> + </div> +</iron-pages>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.ts b/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.ts index 22c030ae..692bff4 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/theme_snapshot.ts
@@ -3,6 +3,7 @@ // found in the LICENSE file. import 'chrome://resources/cr_elements/cr_auto_img/cr_auto_img.js'; +import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; import {skColorToRgba} from 'chrome://resources/js/color_utils.js'; @@ -12,7 +13,13 @@ import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js'; import {getTemplate} from './theme_snapshot.html.js'; -/** Element used to display a snapshot of a NTP custom background. */ +export enum CustomizeThemeType { + CLASSIC_CHROME = 'classicChrome', + CUSTOM_THEME = 'customTheme', + UPLOADED_IMAGE = 'uploadedImage', +} + +/** Element used to display a snapshot of the NTP. */ export class ThemeSnapshotElement extends PolymerElement { static get is() { return 'customize-chrome-theme-snapshot'; @@ -26,16 +33,16 @@ return { theme_: Object, - showThemeSnapshot_: { - type: Boolean, - computed: 'computeShowThemeSnapshot_(theme_)', + themeType_: { + type: String, + computed: 'computeThemeType_(theme_)', }, }; } - private theme_: Theme; + private theme_: Theme|undefined = undefined; private setThemeListenerId_: number|null = null; - private showThemeSnapshot_: boolean; + private themeType_: CustomizeThemeType|null = null; private callbackRouter_: CustomizeChromePageCallbackRouter; private pageHandler_: CustomizeChromePageHandlerInterface; @@ -51,10 +58,12 @@ this.setThemeListenerId_ = this.callbackRouter_.setTheme.addListener((theme: Theme) => { this.theme_ = theme; - this.updateStyles({ - '--customize-chrome-color-background-color': - skColorToRgba(this.theme_.backgroundColor), - }); + if (this.theme_) { + this.updateStyles({ + '--customize-chrome-color-background-color': + skColorToRgba(this.theme_.backgroundColor), + }); + } }); this.pageHandler_.updateTheme(); } @@ -66,8 +75,17 @@ this.callbackRouter_.removeListener(this.setThemeListenerId_); } - private computeShowThemeSnapshot_(): boolean { - return !!this.theme_.backgroundImage; + private computeThemeType_(): CustomizeThemeType|null { + if (!this.theme_) { + return null; + } + if (!this.theme_.backgroundImage) { + return CustomizeThemeType.CLASSIC_CHROME; + } else if (!this.theme_.backgroundImage.isUploadedImage) { + return CustomizeThemeType.CUSTOM_THEME; + } else { + return CustomizeThemeType.UPLOADED_IMAGE; + } } }
diff --git a/chrome/browser/search/background/ntp_background_data.h b/chrome/browser/search/background/ntp_background_data.h index 1426bbe..4cf64b8 100644 --- a/chrome/browser/search/background/ntp_background_data.h +++ b/chrome/browser/search/background/ntp_background_data.h
@@ -119,6 +119,9 @@ // Url of the custom background selected by the user. GURL custom_background_url; + // Whether the image is a local resource. + bool is_uploaded_image; + // First attribution string for custom background. std::string custom_background_attribution_line_1;
diff --git a/chrome/browser/search/background/ntp_custom_background_service.cc b/chrome/browser/search/background/ntp_custom_background_service.cc index fcdc2745..2c5b6b030 100644 --- a/chrome/browser/search/background/ntp_custom_background_service.cc +++ b/chrome/browser/search/background/ntp_custom_background_service.cc
@@ -398,6 +398,7 @@ std::string local_string(chrome::kChromeUIUntrustedNewTabPageBackgroundUrl); GURL timestamped_url(local_string + "?ts=" + time_string); custom_background->custom_background_url = timestamped_url; + custom_background->is_uploaded_image = true; custom_background->custom_background_attribution_line_1 = std::string(); custom_background->custom_background_attribution_line_2 = std::string(); custom_background->custom_background_attribution_action_url = GURL(); @@ -429,6 +430,7 @@ const base::Value* color = background_info.Find(kNtpCustomBackgroundMainColor); custom_background->custom_background_url = custom_background_url; + custom_background->is_uploaded_image = false; custom_background->collection_id = collection_id; if (attribution_line_1) {
diff --git a/chrome/browser/search/background/ntp_custom_background_service_unittest.cc b/chrome/browser/search/background/ntp_custom_background_service_unittest.cc index c4c4bd5..3348082 100644 --- a/chrome/browser/search/background/ntp_custom_background_service_unittest.cc +++ b/chrome/browser/search/background/ntp_custom_background_service_unittest.cc
@@ -100,6 +100,7 @@ auto custom_background = custom_background_service_->GetCustomBackground(); EXPECT_EQ(kUrl, custom_background->custom_background_url); + EXPECT_EQ(false, custom_background->is_uploaded_image); EXPECT_TRUE(custom_background_service_->IsCustomBackgroundSet()); } @@ -138,6 +139,7 @@ auto custom_background = custom_background_service_->GetCustomBackground(); EXPECT_EQ(kUrl, custom_background->custom_background_url); + EXPECT_EQ(false, custom_background->is_uploaded_image); EXPECT_EQ(kAttributionLine1, custom_background->custom_background_attribution_line_1); EXPECT_EQ(kAttributionLine2, @@ -168,6 +170,8 @@ EXPECT_EQ(true, profile_.GetTestingPrefService()->GetBoolean( prefs::kNtpCustomBackgroundLocalToDevice)); EXPECT_TRUE(custom_background_service_->IsCustomBackgroundSet()); + auto custom_background = custom_background_service_->GetCustomBackground(); + EXPECT_EQ(true, custom_background->is_uploaded_image); } TEST_F(NtpCustomBackgroundServiceTest, @@ -194,6 +198,8 @@ EXPECT_EQ(false, profile_.GetTestingPrefService()->GetBoolean( prefs::kNtpCustomBackgroundLocalToDevice)); ASSERT_TRUE(custom_background_service_->IsCustomBackgroundSet()); + auto custom_background = custom_background_service_->GetCustomBackground(); + EXPECT_EQ(false, custom_background->is_uploaded_image); } TEST_F(NtpCustomBackgroundServiceTest, UpdatingPrefUpdatesNtpTheme) { @@ -218,6 +224,7 @@ custom_background = custom_background_service_->GetCustomBackground(); EXPECT_EQ(kUrlBar, custom_background->custom_background_url); + EXPECT_EQ(false, custom_background->is_uploaded_image); EXPECT_EQ(false, pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice)); EXPECT_TRUE(custom_background_service_->IsCustomBackgroundSet()); @@ -247,6 +254,7 @@ EXPECT_TRUE( pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice)); EXPECT_TRUE(custom_background_service_->IsCustomBackgroundSet()); + EXPECT_EQ(true, custom_background->is_uploaded_image); } TEST_F(NtpCustomBackgroundServiceTest, SyncPrefOverridesAndRemovesLocalImage) { @@ -278,6 +286,7 @@ auto custom_background = custom_background_service_->GetCustomBackground(); EXPECT_EQ(kUrl, custom_background->custom_background_url); + EXPECT_EQ(false, custom_background->is_uploaded_image); EXPECT_FALSE( pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice)); EXPECT_FALSE(base::PathExists(path)); @@ -360,6 +369,7 @@ EXPECT_TRUE( pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice)); EXPECT_TRUE(custom_background_service_->IsCustomBackgroundSet()); + EXPECT_EQ(true, custom_background->is_uploaded_image); EXPECT_EQ("", custom_background->custom_background_attribution_line_1); EXPECT_EQ("", custom_background->custom_background_attribution_line_2); EXPECT_EQ(GURL(),
diff --git a/chrome/browser/share/share_features.cc b/chrome/browser/share/share_features.cc index 0b6d30dd..48fe6465 100644 --- a/chrome/browser/share/share_features.cc +++ b/chrome/browser/share/share_features.cc
@@ -34,7 +34,7 @@ #if !BUILDFLAG(IS_ANDROID) BASE_FEATURE(kDesktopSharePreview, "DesktopSharePreview", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); extern const char kDesktopSharePreviewVariant16[] = "16"; extern const char kDesktopSharePreviewVariant40[] = "40"; extern const char kDesktopSharePreviewVariant72[] = "72";
diff --git a/chrome/browser/speech/speech_recognition_browsertest.cc b/chrome/browser/speech/speech_recognition_browsertest.cc index be381c0f..f5e95dd5 100644 --- a/chrome/browser/speech/speech_recognition_browsertest.cc +++ b/chrome/browser/speech/speech_recognition_browsertest.cc
@@ -60,7 +60,7 @@ public: explicit SpeechWebContentsObserver(WebContents* web_contents) : WebContentsObserver(web_contents), - render_view_host_changed_(false), + render_frame_host_changed_(false), web_contents_destroyed_(false) {} SpeechWebContentsObserver(const SpeechWebContentsObserver&) = delete; @@ -70,23 +70,23 @@ ~SpeechWebContentsObserver() override {} // content::WebContentsObserver overrides. - void RenderViewHostChanged(content::RenderViewHost* old_host, - content::RenderViewHost* new_host) override { - render_view_host_changed_ = true; + void RenderFrameHostChanged(content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) override { + render_frame_host_changed_ = true; } void WebContentsDestroyed() override { web_contents_destroyed_ = true; } bool web_contents_destroyed() { return web_contents_destroyed_; } - bool render_view_host_changed() { return render_view_host_changed_; } + bool render_frame_host_changed() { return render_frame_host_changed_; } private: - bool render_view_host_changed_; + bool render_frame_host_changed_; bool web_contents_destroyed_; }; // Tests that ChromeSpeechRecognitionManagerDelegate works properly -// when a WebContents goes away (WCO::WebContentsDestroyed) or the RVH -// changes within a WebContents (WCO::RenderViewHostChanged). +// when a WebContents goes away (WCO::WebContentsDestroyed) or the RFH +// changes within a WebContents (WCO::RenderFrameHostChanged). IN_PROC_BROWSER_TEST_F(ChromeSpeechRecognitionTest, BasicTearDown) { ASSERT_TRUE(embedded_test_server()->Start()); net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); @@ -128,11 +128,11 @@ EXPECT_EQ(kExpectedTranscript, output); } - // Navigating to an https page will force RVH change within - // |web_contents|, results in WCO::RenderViewHostChanged(). + // Navigating to an https page will force RFH change within + // |web_contents|, results in WCO::RenderFrameHostChanged(). ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), https_url)); - EXPECT_TRUE(speech_contents_observer.render_view_host_changed()); + EXPECT_TRUE(speech_contents_observer.render_frame_host_changed()); { content::TitleWatcher title_watcher(web_contents, success_title);
diff --git a/chrome/browser/supervised_user/android/java/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetrics.java b/chrome/browser/supervised_user/android/java/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetrics.java index cc2356d1..25acd717 100644 --- a/chrome/browser/supervised_user/android/java/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetrics.java +++ b/chrome/browser/supervised_user/android/java/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetrics.java
@@ -11,10 +11,14 @@ class WebsiteParentApprovalMetrics { // Histogram name static final String WEB_APPOVAL_OUTCOME_NAME = "FamilyLinkUser.LocalWebApprovalOutcome"; + static final String WEB_APPOVAL_PACP_ERROR_CODE = + "Android.FamilyLinkUser.LocalWebApprovalParentAuthenticationError"; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. // The values need to be in sync with FamilyLinkUserLocalWebApprovalOutcome in enums.xml. + // TODO (b/261403529): Remove the unused values once the solution that records directly + // GMS error codes is integrated in Clank. @IntDef({FamilyLinkUserLocalWebApprovalOutcome.APPROVED_BY_PARENT, FamilyLinkUserLocalWebApprovalOutcome.DENIED_BY_PARENT, FamilyLinkUserLocalWebApprovalOutcome.PARENT_APPROVAL_CANCELLED, @@ -42,4 +46,8 @@ RecordHistogram.recordEnumeratedHistogram( WEB_APPOVAL_OUTCOME_NAME, outcome, FamilyLinkUserLocalWebApprovalOutcome.COUNT); } + + public static void recordParentAuthenticationErrorCode(int errorCode) { + RecordHistogram.recordSparseHistogram(WEB_APPOVAL_PACP_ERROR_CODE, errorCode); + } } \ No newline at end of file
diff --git a/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java b/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java index c8c1dea..c40bfa8 100644 --- a/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java +++ b/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java
@@ -61,4 +61,25 @@ count = mHistogramTestRule.getHistogramTotalCount(histogramName); Assert.assertEquals(3, count); } + + @Test + @SmallTest + public void recordParentAuthenticationErrorMetrics() { + final String histogramName = + "Android.FamilyLinkUser.LocalWebApprovalParentAuthenticationError"; + final int negativeErrorCode = -1; + final int lowValueCode = 10; // Example: value of CommonStatusCode.DEVELOPER_ERROR. + + WebsiteParentApprovalMetrics.recordParentAuthenticationErrorCode(negativeErrorCode); + int count = mHistogramTestRule.getHistogramValueCount(histogramName, negativeErrorCode); + Assert.assertEquals(1, count); + + WebsiteParentApprovalMetrics.recordParentAuthenticationErrorCode(lowValueCode); + WebsiteParentApprovalMetrics.recordParentAuthenticationErrorCode(lowValueCode); + count = mHistogramTestRule.getHistogramValueCount(histogramName, lowValueCode); + Assert.assertEquals(2, count); + + count = mHistogramTestRule.getHistogramTotalCount(histogramName); + Assert.assertEquals(3, count); + } } \ No newline at end of file
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn index be8ec10..83de8451 100644 --- a/chrome/browser/ui/android/omnibox/BUILD.gn +++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -130,7 +130,6 @@ "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java", "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentBottomSheet.java", "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentController.java", - "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModal.java", "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java", "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java", "java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java", @@ -307,7 +306,6 @@ "java/res/drawable-xxxhdpi/btn_suggestion_refine.png", "java/res/drawable-xxxhdpi/ic_history_googblue_24dp.png", "java/res/drawable-xxxhdpi/ic_suggestion_magnifier.png", - "java/res/drawable/assistant_consent_illustration.xml", "java/res/drawable/ic_book_round.xml", "java/res/drawable/ic_colorful_mic.xml", "java/res/drawable/ic_content_copy_black.xml", @@ -324,7 +322,6 @@ "java/res/drawable/trending_up_black_24dp.xml", "java/res/layout-sw600dp/location_bar.xml", "java/res/layout/assistant_voice_search_consent_ui.xml", - "java/res/layout/assistant_voice_search_modal_consent_ui.xml", "java/res/layout/assistant_voice_search_simplified_consent_ui.xml", "java/res/layout/location_bar.xml", "java/res/layout/location_bar_base.xml",
diff --git a/chrome/browser/ui/android/omnibox/java/res/drawable/assistant_consent_illustration.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/assistant_consent_illustration.xml deleted file mode 100644 index 7a1597f..0000000 --- a/chrome/browser/ui/android/omnibox/java/res/drawable/assistant_consent_illustration.xml +++ /dev/null
@@ -1,120 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2022 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<!--VectorRaster is ignored because: The image should be shown rarely enough to - prioritize binary size over inflation time.--> -<vector - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:width="256dp" - android:height="181dp" - android:viewportWidth="256" - android:viewportHeight="181" - tools:ignore="VectorRaster"> - <group> - <clip-path - android:pathData="M-36,0h332v181h-332z"/> - <path - android:pathData="m161,19.5h-62c-4.142,0 -7.5,3.358 -7.5,7.5v122c0,4.142 3.358,7.5 7.5,7.5h62c4.142,0 7.5,-3.358 7.5,-7.5L168.5,27c0,-4.142 -3.358,-7.5 -7.5,-7.5z" - android:strokeWidth="5" - android:fillColor="#ffffff" - android:strokeColor="#9aa0a6"/> - <path - android:pathData="m145,30h-42c-2.761,0 -5,2.239 -5,5 0,2.761 2.239,5 5,5h42c2.761,0 5,-2.239 5,-5 0,-2.761 -2.239,-5 -5,-5z" - android:fillColor="#9aa0a6"/> - <path - android:pathData="m152,35c0,2.761 2.239,5 5,5 2.761,0 5,-2.239 5,-5 0,-2.761 -2.239,-5 -5,-5 -2.761,0 -5,2.239 -5,5z" - android:fillColor="#9aa0a6"/> - <path - android:pathData="m146.502,83.128c1.476,0 2.673,-1.164 2.673,-2.601 0,-1.436 -1.197,-2.601 -2.673,-2.601 -1.475,0 -2.672,1.164 -2.672,2.601 0,1.436 1.197,2.601 2.672,2.601z" - android:fillColor="#33a853"/> - <path - android:pathData="m138.49,91.788c2.949,0 5.34,-2.327 5.34,-5.197 0,-2.87 -2.391,-5.197 -5.34,-5.197 -2.95,0 -5.34,2.327 -5.34,5.197 0,2.87 2.39,5.197 5.34,5.197z" - android:fillColor="#e55145"/> - <path - android:pathData="m138.49,105.645c3.442,0 6.232,-2.715 6.232,-6.064 0,-3.349 -2.79,-6.064 -6.232,-6.064 -3.442,0 -6.233,2.715 -6.233,6.064 0,3.349 2.791,6.064 6.233,6.064z" - android:fillColor="#fcc934"/> - <path - android:pathData="m120.685,91.788c5.901,0 10.684,-4.654 10.684,-10.394C131.369,75.654 126.586,71 120.685,71 114.784,71 110,75.654 110,81.394c0,5.74 4.784,10.394 10.685,10.394z" - android:fillColor="#4284f4"/> - <path - android:pathData="M82.484,132.567L55.478,132.567C45.825,132.567 38,140.422 38,150.111v0.005c0,9.69 7.825,17.545 17.478,17.545h27.006c9.653,0 17.478,-7.855 17.478,-17.545v-0.005c0,-9.689 -7.825,-17.544 -17.478,-17.544z" - android:fillColor="#fde293"/> - <path - android:pathData="M68.063,135.249 L82.058,118v17.249z" - android:fillColor="#fde293"/> - <path - android:pathData="m56.973,143.863 l0.682,13.839c0.003,0.148 0.047,0.293 0.129,0.418 0.082,0.125 0.197,0.225 0.333,0.289 0.136,0.064 0.288,0.089 0.438,0.073 0.15,-0.016 0.292,-0.073 0.411,-0.164l11.888,-8.648c0.121,-0.083 0.216,-0.196 0.276,-0.329 0.059,-0.132 0.082,-0.277 0.064,-0.421 -0.017,-0.144 -0.074,-0.28 -0.164,-0.394 -0.09,-0.115 -0.209,-0.203 -0.346,-0.256l-12.582,-5.199c-0.128,-0.054 -0.268,-0.075 -0.406,-0.06 -0.138,0.015 -0.27,0.064 -0.384,0.144 -0.113,0.079 -0.204,0.186 -0.263,0.31 -0.059,0.124 -0.085,0.261 -0.076,0.398z" - android:fillColor="#e29a64"/> - <path - android:pathData="m77.87,142.637 l-0.101,-0.007c-0.506,-0.041 -0.949,0.339 -0.989,0.847l-1.163,14.811c-0.04,0.508 0.338,0.952 0.844,0.992l0.1,0.008c0.507,0.04 0.949,-0.339 0.989,-0.847l1.164,-14.811c0.04,-0.508 -0.338,-0.952 -0.844,-0.993z" - android:fillColor="#e29a64"/> - <path - android:pathData="m82.141,142.974 l-0.101,-0.008c-0.506,-0.04 -0.949,0.339 -0.989,0.847l-1.164,14.811c-0.04,0.508 0.338,0.952 0.845,0.992l0.1,0.008c0.506,0.04 0.949,-0.339 0.989,-0.847l1.164,-14.811c0.04,-0.508 -0.338,-0.952 -0.844,-0.992z" - android:fillColor="#e29a64"/> - <path - android:pathData="M228.147,105L198.86,105c-13.786,0 -24.962,11.218 -24.962,25.056v0.006c0,13.838 11.176,25.056 24.962,25.056h29.287c13.786,0 24.962,-11.218 24.962,-25.056v-0.006C253.109,116.218 241.933,105 228.147,105Z" - android:fillColor="#4285f4"/> - <path - android:pathData="M193.684,109.785 L161,106.713l23.15,22.589z" - android:fillColor="#4285f4"/> - <path - android:pathData="m191,122h13" - android:strokeWidth="3" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="m209,122h28" - android:strokeWidth="3" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="m188,137h15" - android:strokeWidth="3" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="m210,137h8" - android:strokeWidth="3" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="m224,137h16" - android:strokeWidth="3" - android:fillColor="#00000000" - android:strokeColor="#ffffff"/> - <path - android:pathData="m161.876,66.669 l31.476,-41.265 8.888,18.441z" - android:fillColor="#aecbfa"/> - <path - android:pathData="m217.116,48.732c9.833,-9.87 9.767,-25.938 -0.147,-35.89 -9.913,-9.951 -25.921,-10.017 -35.754,-0.147 -9.832,9.87 -9.767,25.938 0.147,35.89 9.914,9.951 25.922,10.017 35.754,0.147z" - android:fillColor="#aecbfa"/> - <path - android:pathData="m190.806,43.51c-0.099,0.001 -0.197,-0.027 -0.282,-0.078 -0.086,-0.052 -0.155,-0.126 -0.201,-0.215 -0.046,-0.089 -0.066,-0.188 -0.059,-0.288 0.006,-0.1 0.041,-0.196 0.098,-0.277l6.457,-9.278c0.039,-0.062 0.09,-0.115 0.15,-0.157 0.061,-0.041 0.129,-0.07 0.2,-0.085 0.072,-0.014 0.146,-0.014 0.217,0.001 0.072,0.015 0.14,0.044 0.2,0.086 0.06,0.042 0.111,0.096 0.149,0.158 0.039,0.062 0.065,0.132 0.076,0.204 0.011,0.072 0.008,0.147 -0.01,0.218 -0.018,0.071 -0.05,0.138 -0.094,0.196l-6.457,9.298c-0.051,0.069 -0.119,0.124 -0.196,0.162 -0.077,0.038 -0.162,0.056 -0.248,0.055z" - android:strokeWidth="0.5" - android:fillColor="#2e4469" - android:strokeColor="#2e4469"/> - <path - android:strokeWidth="1" - android:pathData="m201.495,34.841c4.463,0 8.082,-3.632 8.082,-8.112 0,-4.48 -3.619,-8.112 -8.082,-8.112 -4.463,0 -8.082,3.632 -8.082,8.112 0,4.48 3.619,8.112 8.082,8.112z" - android:fillColor="#00000000" - android:strokeColor="#000000"/> - <path - android:pathData="m201.495,35.385c-1.706,0 -3.373,-0.508 -4.791,-1.459 -1.418,-0.951 -2.523,-2.303 -3.176,-3.885 -0.653,-1.582 -0.823,-3.322 -0.491,-5.001 0.333,-1.679 1.154,-3.221 2.36,-4.432 1.206,-1.211 2.743,-2.035 4.416,-2.369 1.673,-0.334 3.406,-0.163 4.982,0.493 1.576,0.655 2.923,1.765 3.87,3.188 0.948,1.423 1.454,3.097 1.454,4.809 -0.004,2.295 -0.913,4.495 -2.53,6.117 -1.616,1.623 -3.808,2.536 -6.094,2.539zM201.495,19.16c-1.491,0 -2.949,0.444 -4.189,1.276 -1.24,0.832 -2.206,2.014 -2.777,3.397 -0.571,1.383 -0.72,2.905 -0.429,4.373 0.291,1.468 1.009,2.817 2.064,3.875 1.054,1.059 2.397,1.779 3.86,2.071 1.463,0.292 2.979,0.142 4.356,-0.431 1.378,-0.573 2.556,-1.543 3.384,-2.788 0.829,-1.245 1.271,-2.708 1.271,-4.205 -0.004,-2.005 -0.8,-3.927 -2.214,-5.344 -1.413,-1.417 -3.328,-2.214 -5.326,-2.216z" - android:strokeWidth="0.5" - android:fillColor="#2e4469" - android:strokeColor="#2e4469"/> - <path - android:pathData="m226.5,72c3.038,0 5.5,-2.462 5.5,-5.5 0,-3.038 -2.462,-5.5 -5.5,-5.5 -3.038,0 -5.5,2.462 -5.5,5.5 0,3.038 2.462,5.5 5.5,5.5z" - android:fillColor="#dadce0"/> - <path - android:pathData="m179.404,165.212 l-5.037,2.908c-0.905,0.522 -1.215,1.679 -0.693,2.584l2.908,5.037c0.523,0.905 1.68,1.215 2.585,0.692l5.036,-2.908c0.905,-0.522 1.215,-1.679 0.693,-2.584l-2.908,-5.037c-0.523,-0.905 -1.68,-1.215 -2.584,-0.692z" - android:fillColor="#dadce0"/> - <path - android:pathData="m52.757,67.708 l9.765,3.234c0.185,0.062 0.384,0.075 0.577,0.038 0.192,-0.037 0.371,-0.122 0.519,-0.248 0.148,-0.125 0.259,-0.286 0.322,-0.467 0.064,-0.18 0.077,-0.373 0.038,-0.56l-1.999,-9.83c-0.038,-0.187 -0.126,-0.361 -0.255,-0.504 -0.129,-0.143 -0.295,-0.251 -0.48,-0.313 -0.186,-0.062 -0.385,-0.074 -0.577,-0.037 -0.192,0.037 -0.371,0.123 -0.519,0.248l-7.766,6.596c-0.148,0.125 -0.259,0.286 -0.323,0.466 -0.064,0.18 -0.077,0.374 -0.039,0.561 0.038,0.187 0.126,0.361 0.255,0.504 0.129,0.143 0.295,0.251 0.481,0.312z" - android:fillColor="#dadce0"/> - </group> -</vector>
diff --git a/chrome/browser/ui/android/omnibox/java/res/layout/assistant_voice_search_modal_consent_ui.xml b/chrome/browser/ui/android/omnibox/java/res/layout/assistant_voice_search_modal_consent_ui.xml deleted file mode 100644 index 16c47da..0000000 --- a/chrome/browser/ui/android/omnibox/java/res/layout/assistant_voice_search_modal_consent_ui.xml +++ /dev/null
@@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2022 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<org.chromium.components.browser_ui.widget.FadingEdgeScrollView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/avs_consent_ui" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:importantForAccessibility="no"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:gravity="center_vertical" - android:paddingHorizontal="20dp" - android:paddingVertical="10dp" - android:importantForAccessibility="no"> - <ImageView - android:layout_width="match_parent" - android:layout_height="122dp" - android:layout_marginTop="20dp" - android:importantForAccessibility="no" - android:src="@drawable/assistant_consent_illustration"/> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="20dp" - style="@style/TextAppearance.Headline.Primary" - android:text="@string/avs_consent_ui_simplified_title" /> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="20dp" - style="@style/TextAppearance.TextSmall.Secondary" - android:text="@string/avs_consent_ui_simplified_body" /> - - <TextView - android:id="@+id/avs_consent_ui_learn_more" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="2dp" - style="@style/TextAppearance.TextSmall.Link" - android:text="@string/learn_more" /> - - </LinearLayout> -</org.chromium.components.browser_ui.widget.FadingEdgeScrollView>
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentController.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentController.java index 83d93aa..c07cc9d7 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentController.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentController.java
@@ -18,7 +18,6 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.ui.base.WindowAndroid; -import org.chromium.ui.modaldialog.ModalDialogManager; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -40,9 +39,6 @@ * @param bottomSheetController The {@link BottomSheetController} used to show the bottom sheet * UI. This can be null when starting the consent flow from * SearchActivity. - * @param modalDialogManager The {@link ModalDialogManager} used to show the modal dialog UI. - * This can be null when starting the consent flow from - * SearchActivity. * @param completionCallback A callback to be invoked if the user is continuing with the * requested voice search. */ @@ -50,38 +46,24 @@ @NonNull SharedPreferencesManager sharedPreferencesManager, @NonNull Runnable launchAssistantSettingsAction, @Nullable BottomSheetController bottomSheetController, - @Nullable ModalDialogManager modalDialogManager, @NonNull Callback<Boolean> completionCallback) { AssistantVoiceSearchConsentUi consentUi; assert (!ChromeFeatureList.isEnabled( ChromeFeatureList.ASSISTANT_NON_PERSONALIZED_VOICE_SEARCH)); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.ASSISTANT_CONSENT_MODAL)) { - // If the modal manager isn't available, bail out of the consent flow and fallback to - // system-ui. Consent will be retried the next time. - if (modalDialogManager == null) { - PostTask.postTask(TaskTraits.USER_VISIBLE, - () -> { completionCallback.onResult(/* useAssistant= */ false); }); - return; - } - - consentUi = new AssistantVoiceSearchConsentModal( - windowAndroid.getContext().get(), modalDialogManager); - } else { - // When attempting voice search through the search widget, the bottom sheet isn't - // available. When this happens, bail out of the consent flow and fallback to system-ui. - // Consent will be retried the next time. - if (bottomSheetController == null) { - PostTask.postTask(TaskTraits.USER_VISIBLE, - () -> { completionCallback.onResult(/* useAssistant= */ false); }); - return; - } - - // Use the bottom sheet consent by default. - consentUi = new AssistantVoiceSearchConsentBottomSheet( - windowAndroid.getContext().get(), bottomSheetController); + // When attempting voice search through the search widget, the bottom sheet isn't + // available. When this happens, bail out of the consent flow and fallback to system-ui. + // Consent will be retried the next time. + if (bottomSheetController == null) { + PostTask.postTask(TaskTraits.USER_VISIBLE, + () -> { completionCallback.onResult(/* useAssistant= */ false); }); + return; } + // Use the bottom sheet consent by default. + consentUi = new AssistantVoiceSearchConsentBottomSheet( + windowAndroid.getContext().get(), bottomSheetController); + AssistantVoiceSearchConsentController consent = new AssistantVoiceSearchConsentController(windowAndroid, sharedPreferencesManager, completionCallback, launchAssistantSettingsAction, consentUi);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModal.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModal.java deleted file mode 100644 index 2411a16..0000000 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentModal.java +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.omnibox.voice; - -import android.content.Context; -import android.content.res.Resources; -import android.view.LayoutInflater; -import android.view.View; - -import androidx.annotation.NonNull; - -import org.chromium.chrome.browser.omnibox.R; -import org.chromium.ui.modaldialog.DialogDismissalCause; -import org.chromium.ui.modaldialog.ModalDialogManager; -import org.chromium.ui.modaldialog.ModalDialogProperties; -import org.chromium.ui.modaldialog.SimpleModalDialogController; -import org.chromium.ui.modelutil.PropertyModel; - -/** - * The modal dialog implementation of the ConsentUI shown to users upon first using Assistant Voice - * Search. - */ -class AssistantVoiceSearchConsentModal implements AssistantVoiceSearchConsentUi { - private View mContentView; - private AssistantVoiceSearchConsentUi.Observer mObserver; - - private ModalDialogManager mModalDialogManager; - private PropertyModel mConsentModal; - - public AssistantVoiceSearchConsentModal( - @NonNull Context context, @NonNull ModalDialogManager modalDialogManager) { - mModalDialogManager = modalDialogManager; - - mContentView = LayoutInflater.from(context).inflate( - R.layout.assistant_voice_search_modal_consent_ui, /* root= */ null); - - View learnMore = mContentView.findViewById(R.id.avs_consent_ui_learn_more); - learnMore.setOnClickListener((v) -> mObserver.onLearnMoreClicked()); - - Resources resources = context.getResources(); - mConsentModal = - new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) - .with(ModalDialogProperties.CONTROLLER, - new SimpleModalDialogController( - mModalDialogManager, this::onDismissConsentModal)) - .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, - R.string.avs_consent_ui_simplified_accept) - .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources, - R.string.avs_consent_ui_simplified_deny) - .with(ModalDialogProperties.BUTTON_STYLES, - ModalDialogProperties.ButtonStyles.PRIMARY_FILLED_NEGATIVE_OUTLINE) - .with(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true) - .with(ModalDialogProperties.CUSTOM_VIEW, mContentView) - .build(); - } - - // AssistantVoiceSearchConsentUi implementation. - - @Override - public void show(AssistantVoiceSearchConsentUi.Observer observer) { - assert mObserver == null; - - mObserver = observer; - mModalDialogManager.showDialog(mConsentModal, ModalDialogManager.ModalDialogType.APP); - } - - @Override - public void dismiss() { - mObserver = null; - mModalDialogManager.dismissDialog(mConsentModal, DialogDismissalCause.ACTION_ON_CONTENT); - } - - private void onDismissConsentModal(@DialogDismissalCause int dismissalCause) { - if (mObserver == null) { - // The observer was already notified of a result, so the UI was dismissed by the - // controller. - return; - } - - if (dismissalCause == DialogDismissalCause.POSITIVE_BUTTON_CLICKED) { - mObserver.onConsentAccepted(); - } else if (dismissalCause == DialogDismissalCause.NEGATIVE_BUTTON_CLICKED) { - mObserver.onConsentRejected(); - } else if (dismissalCause == DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE) { - mObserver.onConsentCanceled(); - } else { - mObserver.onNonUserCancel(); - } - mObserver = null; - } -}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java index 6054406..56f299f 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
@@ -863,8 +863,7 @@ mDelegate.clearOmniboxFocus(); AssistantVoiceSearchConsentController.show(windowAndroid, SharedPreferencesManager.getInstance(), mLaunchAssistanceSettingsAction, - BottomSheetControllerProvider.from(windowAndroid), - windowAndroid.getModalDialogManager(), (useAssistant) -> { + BottomSheetControllerProvider.from(windowAndroid), (useAssistant) -> { // Notify the service about the consent completion. assistantVoiceSearchService.onAssistantConsentDialogComplete(useAssistant);
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java index bb51425..8b496f47 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java
@@ -363,29 +363,21 @@ * * @param context Current context. * @param prefs Structure describing current preferences and feature availability. - * @param portraitModeWidthDp Width of the widget area in portrait mode. - * @param portraitModeHeightDp Height of the widget area in portrait mode. - * @param landscapeModeWidthDp Width of the widget area in landscape mode. - * @param landscapeModeHeightDp Height of the widget area in landscape mode. + * @param areaWidthDp Width of the widget area. + * @param areaHeightDp Height of the widget area. * @return RemoteViews to be installed on the Dino widget. */ public @NonNull RemoteViews createDinoWidgetRemoteViews(@NonNull Context context, - @NonNull SearchActivityPreferences prefs, int portraitModeWidthDp, - int portraitModeHeightDp, int landscapeModeWidthDp, int landscapeModeHeightDp) { - RemoteViews landscapeViews = - createWidgetRemoteViews(context, R.layout.quick_action_search_widget_dino_layout); - RemoteViews portraitViews = + @NonNull SearchActivityPreferences prefs, int areaWidthDp, int areaHeightDp) { + RemoteViews views = createWidgetRemoteViews(context, R.layout.quick_action_search_widget_dino_layout); // Dino widget is specific; we want to scale up a lot of dimensions based on the actual size // of the widget area. This makes layout a lot more responsive but also a lot more // complicated since we have to compute everything manually. - Resources res = context.getApplicationContext().getResources(); resizeDinoWidgetToFillTargetCellArea( - res, landscapeViews, landscapeModeWidthDp, landscapeModeHeightDp); - resizeDinoWidgetToFillTargetCellArea( - res, portraitViews, portraitModeWidthDp, portraitModeHeightDp); - return new RemoteViews(landscapeViews, portraitViews); + context.getApplicationContext().getResources(), views, areaWidthDp, areaHeightDp); + return views; } /** @@ -396,26 +388,16 @@ * * @param context Current context. * @param prefs Structure describing current preferences and feature availability. - * @param portraitModeWidthDp Width of the widget area in portrait mode. - * @param portraitModeHeightDp Height of the widget area in portrait mode. - * @param landscapeModeWidthDp Width of the widget area in landscape mode. - * @param landscapeModeHeightDp Height of the widget area in landscape mode. - * @return RemoteViews to be installed on the Search widget. + * @param areaWidthDp Width of the widget area. + * @param areaHeightDp Height of the widget area. + * @return RemoteViews to be installed on the Search widget for the passed variant. */ public @NonNull RemoteViews createSearchWidgetRemoteViews(@NonNull Context context, - @NonNull SearchActivityPreferences prefs, int portraitModeWidthDp, - int portraitModeHeightDp, int landscapeModeWidthDp, int landscapeModeHeightDp) { - WidgetVariant landscapeVariant = getSearchWidgetVariantForHeight(landscapeModeHeightDp); - RemoteViews landscapeViews = createWidgetRemoteViews(context, landscapeVariant.layout); - applyRemoteViewsButtonVisibilityToFitWidth( - landscapeViews, prefs, landscapeVariant, landscapeModeWidthDp); - - WidgetVariant portraitVariant = getSearchWidgetVariantForHeight(portraitModeHeightDp); - RemoteViews portraitViews = createWidgetRemoteViews(context, portraitVariant.layout); - applyRemoteViewsButtonVisibilityToFitWidth( - portraitViews, prefs, portraitVariant, portraitModeWidthDp); - - return new RemoteViews(landscapeViews, portraitViews); + @NonNull SearchActivityPreferences prefs, int areaWidthDp, int areaHeightDp) { + WidgetVariant variant = getSearchWidgetVariantForHeight(areaHeightDp); + RemoteViews views = createWidgetRemoteViews(context, variant.layout); + applyRemoteViewsButtonVisibilityToFitWidth(views, prefs, variant, areaWidthDp); + return views; } /**
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java index 377fb0e..381f7e5 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java
@@ -179,18 +179,13 @@ float density = res.getDisplayMetrics().density; mWidgetView = mDelegate - .createSearchWidgetRemoteViews(mContext, prefs, - // Simulate optimally sized rectangular screen: - // Portrait mode dimensions: - mDefaultWidgetWidthDp, mMediumWidgetMinHeightDp, - // Landscape mode dimensions: - mDefaultWidgetWidthDp, mMediumWidgetMinHeightDp) + .createSearchWidgetRemoteViews(mContext, prefs, mDefaultWidgetWidthDp, + mMediumWidgetMinHeightDp) .apply(mContext, null); - mDinoWidgetView = - mDelegate - .createDinoWidgetRemoteViews(mContext, prefs, mDinoWidgetEdgeSizeDp, - mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp) - .apply(mContext, null); + mDinoWidgetView = mDelegate + .createDinoWidgetRemoteViews(mContext, prefs, + mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp) + .apply(mContext, null); } /**
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 97d6b46..fef7816 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -3558,7 +3558,7 @@ Restore tab group of <ph name="TAB_COUNT">%1$s<ex>5</ex></ph> tabs as a new background tab group. </message> <message name="IDS_WEB_FEED_AWARENESS" desc="Educating the user about the web feed."> - See sites you follow here + See content you follow here </message> <!-- Explore sites strings -->
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_WEB_FEED_AWARENESS.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_WEB_FEED_AWARENESS.png.sha1 index d9a5695..52cc55de 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_WEB_FEED_AWARENESS.png.sha1 +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_WEB_FEED_AWARENESS.png.sha1
@@ -1 +1 @@ -ad4be6652099b56efeedc53b02a1fee65ea4f81d \ No newline at end of file +839ef508d898ad0600a9995d2b24a4f10287f37b \ No newline at end of file
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc index a35409c..74b470e 100644 --- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -537,11 +537,6 @@ provider->Start(); system_web_app_manager->ScheduleStart(); - - base::RunLoop run_loop; - provider->on_external_managers_synchronized().Post(FROM_HERE, - run_loop.QuitClosure()); - run_loop.Run(); } // Note that this resets previously installed SWAs.
diff --git a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc index 78729c7..8c82cfe 100644 --- a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc
@@ -131,8 +131,7 @@ } media_router::MediaRoutesObserver* media_routes_observer() const { - DCHECK(media_routes_observer_); - return media_routes_observer_; + return &(*media_router_->routes_observers().begin()); } private: @@ -149,9 +148,6 @@ ON_CALL(*media_router_, RegisterMediaSinksObserver(_)) .WillByDefault(Invoke( this, &SystemTrayTrayCastMediaRouterChromeOSTest::CaptureSink)); - ON_CALL(*media_router_, RegisterMediaRoutesObserver(_)) - .WillByDefault(Invoke( - this, &SystemTrayTrayCastMediaRouterChromeOSTest::CaptureRoutes)); CastConfigControllerMediaRouter::SetMediaRouterForTest(media_router_.get()); InProcessBrowserTest::PreRunTestOnMainThread(); } @@ -171,13 +167,8 @@ return true; } - void CaptureRoutes(media_router::MediaRoutesObserver* media_routes_observer) { - media_routes_observer_ = media_routes_observer; - } - std::unique_ptr<media_router::MockMediaRouter> media_router_; media_router::MediaSinksObserver* media_sinks_observer_ = nullptr; - media_router::MediaRoutesObserver* media_routes_observer_ = nullptr; std::unique_ptr<ash::SystemTrayTestApi> tray_test_api_; };
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index 7e90858..6c2e7da1 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -318,9 +318,7 @@ } std::u16string GetTooltipText(const gfx::Point& p) const override { - return label()->GetPreferredSize().width() > label()->size().width() - ? GetAccessibleName() - : std::u16string(); + return GetAccessibleName(); } bool OnMousePressed(const ui::MouseEvent& event) override {
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc index 6c91bc8..cfba815 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc
@@ -81,8 +81,10 @@ SavedTabGroupRemoved(removed_group->saved_guid()); } -void SavedTabGroupBar::SavedTabGroupUpdatedLocally(const base::GUID& guid) { - SavedTabGroupUpdated(guid); +void SavedTabGroupBar::SavedTabGroupUpdatedLocally( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid) { + SavedTabGroupUpdated(group_guid); } void SavedTabGroupBar::SavedTabGroupReorderedLocally() { @@ -104,8 +106,10 @@ SavedTabGroupRemoved(removed_group->saved_guid()); } -void SavedTabGroupBar::SavedTabGroupUpdatedFromSync(const base::GUID& guid) { - SavedTabGroupUpdated(guid); +void SavedTabGroupBar::SavedTabGroupUpdatedFromSync( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid) { + SavedTabGroupUpdated(group_guid); } int SavedTabGroupBar::CalculatePreferredWidthRestrictedBy(int max_x) {
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.h b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.h index c7eb73c..db9100c 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.h +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.h
@@ -11,6 +11,7 @@ #include "components/saved_tab_groups/saved_tab_group_model.h" #include "components/saved_tab_groups/saved_tab_group_model_observer.h" #include "content/public/browser/page.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/views/accessible_pane_view.h" class Browser; @@ -47,12 +48,16 @@ // SavedTabGroupModelObserver void SavedTabGroupAddedLocally(const base::GUID& guid) override; void SavedTabGroupRemovedLocally(const SavedTabGroup* removed_group) override; - void SavedTabGroupUpdatedLocally(const base::GUID& guid) override; + void SavedTabGroupUpdatedLocally( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid = absl::nullopt) override; void SavedTabGroupReorderedLocally() override; void SavedTabGroupAddedFromSync(const base::GUID& guid) override; void SavedTabGroupRemovedFromSync( const SavedTabGroup* removed_group) override; - void SavedTabGroupUpdatedFromSync(const base::GUID& guid) override; + void SavedTabGroupUpdatedFromSync( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid = absl::nullopt) override; // Calculates what the visible width would be when a restriction on width is // placed on the bar.
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc index a0f7a9a5..e7ab662 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -136,6 +136,17 @@ GetViewAccessibility().AnnounceText(alert_text); } + // When in progress, announce the progress immediately and start the timer for + // further updates. + if (state == download::DownloadItem::IN_PROGRESS && + (initial_setup || state_ != state)) { + AnnounceInProgressAlert(); + accessible_alert_in_progress_timer_.Reset(); + } else if (!initial_setup && state_ == download::DownloadItem::IN_PROGRESS && + state != state_) { + accessible_alert_in_progress_timer_.Stop(); + } + mode_ = mode; state_ = state; is_paused_ = is_paused; @@ -285,7 +296,12 @@ navigation_handler_(navigation_handler), browser_(browser), inkdrop_container_( - AddChildView(std::make_unique<views::InkDropContainerView>())) { + AddChildView(std::make_unique<views::InkDropContainerView>())), + accessible_alert_in_progress_timer_( + FROM_HERE, + base::Minutes(3), + base::BindRepeating(&DownloadBubbleRowView::AnnounceInProgressAlert, + base::Unretained(this))) { model_->SetDelegate(this); SetBorder(views::CreateEmptyBorder(GetLayoutInsets(DOWNLOAD_ROW))); @@ -569,8 +585,9 @@ void DownloadBubbleRowView::OnMainButtonPressed() { if (ui_info_.has_subpage) { DownloadItemWarningData::AddWarningActionEvent( - model_->GetDownloadItem(), DownloadItemWarningData::BUBBLE_MAINPAGE, - DownloadItemWarningData::OPEN_SUBPAGE); + model_->GetDownloadItem(), + DownloadItemWarningData::WarningSurface::BUBBLE_MAINPAGE, + DownloadItemWarningData::WarningAction::OPEN_SUBPAGE); navigation_handler_->OpenSecurityDialog(this); } else { RecordDownloadOpenButtonPressed(model_->IsDone()); @@ -677,8 +694,9 @@ void DownloadBubbleRowView::RecordDownloadDisplayed() { if (model_->IsDangerous()) { DownloadItemWarningData::AddWarningActionEvent( - model_->GetDownloadItem(), DownloadItemWarningData::BUBBLE_MAINPAGE, - DownloadItemWarningData::SHOWN); + model_->GetDownloadItem(), + DownloadItemWarningData::WarningSurface::BUBBLE_MAINPAGE, + DownloadItemWarningData::WarningAction::SHOWN); } if (!model_->GetEphemeralWarningUiShownTime().has_value() && model_->IsEphemeralWarning()) { @@ -821,5 +839,10 @@ base::RepeatingClosure()); } +void DownloadBubbleRowView::AnnounceInProgressAlert() { + GetViewAccessibility().AnnounceText( + model_->GetInProgressAccessibleAlertText()); +} + BEGIN_METADATA(DownloadBubbleRowView, views::View) END_METADATA
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h index c137677..c9b94589 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h +++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
@@ -127,6 +127,8 @@ void OnDiscardButtonPressed(); void OnMainButtonPressed(); + void AnnounceInProgressAlert(); + // The icon for the file. We get platform-specific icons from IconLoader. raw_ptr<views::ImageView> icon_ = nullptr; raw_ptr<views::ImageView> subpage_icon_ = nullptr; @@ -210,6 +212,9 @@ // avoid inaccurate repeated logging. bool has_download_completion_been_logged_ = false; + // A timer for accessible alerts of progress updates + base::RepeatingTimer accessible_alert_in_progress_timer_; + base::WeakPtrFactory<DownloadBubbleRowView> weak_factory_{this}; };
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc index a97ace7..ab7c9a0 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
@@ -99,7 +99,8 @@ void DownloadBubbleSecurityView::BackButtonPressed() { DownloadItemWarningData::AddWarningActionEvent( download_row_view_->model()->GetDownloadItem(), - DownloadItemWarningData::BUBBLE_SUBPAGE, DownloadItemWarningData::BACK); + DownloadItemWarningData::WarningSurface::BUBBLE_SUBPAGE, + DownloadItemWarningData::WarningAction::BACK); navigation_handler_->OpenPrimaryDialog(); base::UmaHistogramEnumeration( kSubpageActionHistogram, DownloadBubbleSubpageAction::kPressedBackButton); @@ -114,7 +115,8 @@ void DownloadBubbleSecurityView::CloseBubble() { DownloadItemWarningData::AddWarningActionEvent( download_row_view_->model()->GetDownloadItem(), - DownloadItemWarningData::BUBBLE_SUBPAGE, DownloadItemWarningData::CLOSE); + DownloadItemWarningData::WarningSurface::BUBBLE_SUBPAGE, + DownloadItemWarningData::WarningAction::CLOSE); // CloseDialog will delete the object. Do not access any members below. navigation_handler_->CloseDialog( views::Widget::ClosedReason::kCloseButtonClicked);
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc index 75a714d2..1aece888 100644 --- a/chrome/browser/ui/views/download/download_item_view.cc +++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -948,33 +948,7 @@ if (model_->GetOpenWhenComplete() || has_warning_label(mode_)) return accessible_name_; - // Prefer to announce the time remaining, if known. - base::TimeDelta remaining; - if (model_->TimeRemaining(&remaining)) { - // If complete, skip this round: a completion status update is coming soon. - if (remaining.is_zero()) - return std::u16string(); - - const std::u16string remaining_string = - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING, - ui::TimeFormat::LENGTH_SHORT, remaining); - return l10n_util::GetStringFUTF16( - IDS_DOWNLOAD_STATUS_TIME_REMAINING_ACCESSIBLE_ALERT, remaining_string); - } - - // Time remaining is unknown, try to announce percent remaining. - if (model_->PercentComplete() > 0) { - DCHECK_LE(model_->PercentComplete(), 100); - return l10n_util::GetStringFUTF16Int( - IDS_DOWNLOAD_STATUS_PERCENT_COMPLETE_ACCESSIBLE_ALERT, - 100 - model_->PercentComplete()); - } - - // Percent remaining is also unknown, announce bytes to download. - return l10n_util::GetStringFUTF16( - IDS_DOWNLOAD_STATUS_IN_PROGRESS_ACCESSIBLE_ALERT, - ui::FormatBytes(model_->GetTotalBytes()), - model_->GetFileNameToReportUser().LossyDisplayName()); + return model_->GetInProgressAccessibleAlertText(); } void DownloadItemView::AnnounceAccessibleAlert() {
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc index ddd9301..fba0a13 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -316,24 +316,13 @@ return logger_.get(); } - void RegisterMediaRoutesObserver( - media_router::MediaRoutesObserver* observer) override { - routes_observers_.push_back(observer); - } - - void UnregisterMediaRoutesObserver( - media_router::MediaRoutesObserver* observer) override { - base::Erase(routes_observers_, observer); - } - void NotifyMediaRoutesChanged( const std::vector<media_router::MediaRoute>& routes) { - for (auto* observer : routes_observers_) - observer->OnRoutesUpdated(routes); + for (auto& observer : routes_observers_) + observer.OnRoutesUpdated(routes); } private: - std::vector<media_router::MediaRoutesObserver*> routes_observers_; std::unique_ptr<media_router::LoggerImpl> logger_; };
diff --git a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc index f2ba822..4eec2f5c 100644 --- a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc
@@ -269,6 +269,9 @@ test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); SetUpLookalikeTestParams(); + // Check that the test top domain list contains google. + ASSERT_TRUE(IsTopDomain(GetDomainInfo("google.com"))); + InProcessBrowserTest::SetUpOnMainThread(); } @@ -567,6 +570,10 @@ NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_FALSE(IsUIShowing()); ASSERT_NO_FATAL_FAILURE(CheckPageInfoDoesNotShowSafetyTipInfo(browser())); + + // TODO(crbug.com/1401102): Only one UKM should have been recorded, but + // allowlisted domain also records one. + CheckRecordedHeuristicsUkmCount(2); } // Ensure sites allowed by enterprise policy don't get blocked. @@ -584,11 +591,15 @@ EXPECT_FALSE(IsUIShowing()); ASSERT_NO_FATAL_FAILURE(CheckPageInfoDoesNotShowSafetyTipInfo(browser())); } + + // TODO(crbug.com/1401102): This shouldn't record a UKM. + CheckRecordedHeuristicsUkmCount(2); } // After the user clicks 'leave site', the user should end up on a safe domain. IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest, LeaveSiteLeavesSite) { + ASSERT_TRUE(IsTopDomain(GetDomainInfo("google.sk"))); // This domain is a lookalike of a top domain not in the top 500. const GURL kNavigatedUrl = GetURL("googlé.sk"); SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); @@ -753,6 +764,7 @@ browser()->tab_strip_model()->active_index() + 1); EXPECT_FALSE(IsUIShowing()); ASSERT_NO_FATAL_FAILURE(CheckPageInfoDoesNotShowSafetyTipInfo(browser())); + CheckRecordedHeuristicsUkmCount(0); } // Tests that Safety Tips do NOT trigger on lookalike domains that trigger an @@ -763,12 +775,14 @@ SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_FALSE(IsUIShowing()); + CheckRecordedHeuristicsUkmCount(0); } // Tests that Safety Tips trigger on lookalike domains that don't qualify for an -// interstitial, but do not impact Page Info. +// interstitial and Page Info shows Safety Tip information. IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest, TriggersOnLookalike) { + ASSERT_TRUE(IsTopDomain(GetDomainInfo("google.sk"))); // This domain is a lookalike of a top domain not in the top 500. const GURL kNavigatedUrl = GetURL("googlé.sk"); SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); @@ -778,12 +792,14 @@ ASSERT_NO_FATAL_FAILURE(CheckPageInfoShowsSafetyTipInfo( browser(), security_state::SafetyTipStatus::kLookalike, GURL("https://google.sk"))); + CheckRecordedHeuristicsUkmCount(0); } // Tests that Safety Tips don't trigger on lookalike domains that are explicitly // allowed by the allowlist. IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest, NoTriggersOnLookalikeAllowlist) { + ASSERT_TRUE(IsTopDomain(GetDomainInfo("google.sk"))); // This domain is a lookalike of a top domain not in the top 500. const GURL kNavigatedUrl = GetURL("googlé.sk"); @@ -802,6 +818,10 @@ EXPECT_FALSE(IsUIShowing()); ASSERT_NO_FATAL_FAILURE(CheckPageInfoDoesNotShowSafetyTipInfo(browser())); + + // TODO(crbug.com/1401102): Only one UKM should have been recorded, but + // allowlisted domain also records one. + CheckRecordedHeuristicsUkmCount(2); } // Tests that Safety Tips don't trigger on lookalike domains that are explicitly @@ -833,6 +853,10 @@ SetEngagementScore(browser(), kTargetUrl, kHighEngagement); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_TRUE(IsUIShowing()); + CheckRecordedHeuristicsUkmCount(0); + + CloseWarningLeaveSite(browser()); + CheckRecordedHeuristicsUkmCount(1); } // Tests that Safety Tips don't trigger when using a scoped allowlist. @@ -847,6 +871,9 @@ NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_FALSE(IsUIShowing()); ASSERT_NO_FATAL_FAILURE(CheckPageInfoDoesNotShowSafetyTipInfo(browser())); + + // TODO(crbug.com/1401102): This shouldn't record metrics. + CheckRecordedHeuristicsUkmCount(1); } // Tests that Safety Tips trigger when the URL is on the allowlist, but is @@ -861,6 +888,10 @@ SetEngagementScore(browser(), kTargetUrl, kHighEngagement); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_TRUE(IsUIShowing()); + CheckRecordedHeuristicsUkmCount(0); + + CloseWarningLeaveSite(browser()); + CheckRecordedHeuristicsUkmCount(1); } // Tests that Character Swap is enabled for lookalikes matching engaged sites. @@ -872,6 +903,10 @@ SetEngagementScore(browser(), kTargetUrl, kHighEngagement); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_TRUE(IsUIShowing()); + CheckRecordedHeuristicsUkmCount(0); + + CloseWarningLeaveSite(browser()); + CheckRecordedHeuristicsUkmCount(1); } // Same as TriggersOnCharacterSwap_SiteEngagement, but this time @@ -886,11 +921,17 @@ SetEngagementScore(browser(), kTargetUrl, kHighEngagement); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_TRUE(IsUIShowing()); + CheckRecordedHeuristicsUkmCount(0); + + CloseWarningLeaveSite(browser()); + CheckRecordedHeuristicsUkmCount(1); } // Tests that Character Swap is enabled for lookalikes matching top sites. IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest, TriggersOnCharacterSwap_TopSite) { + base::HistogramTester histograms; + const GURL kNavigatedUrl = GetURL("goolge.com"); const GURL kTargetUrl = GetURL("google.com"); // Both the lookalike and the target have low engagement. @@ -898,18 +939,28 @@ SetEngagementScore(browser(), kTargetUrl, kLowEngagement); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_TRUE(IsUIShowing()); + CheckRecordedHeuristicsUkmCount(0); + + CloseWarningLeaveSite(browser()); + CheckRecordedHeuristicsUkmCount(1); } // Tests that a hostname on a safe TLD can spoof another hostname without a // lookalike warning. IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest, TriggersOnCharacterSwapSafeTLD_CanSpoof) { + base::HistogramTester histograms; + const GURL kNavigatedUrl = GetURL("digitla.gov"); const GURL kTargetUrl = GetURL("digital.gov"); SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); SetEngagementScore(browser(), kTargetUrl, kHighEngagement); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_FALSE(IsUIShowing()); + + histograms.ExpectTotalCount(lookalikes::kHistogramName, 0); + // TODO(crbug.com/1401102): This shouldn't record metrics. + CheckRecordedHeuristicsUkmCount(1); } // Navigate to a domain within a character swap of 1 to a top domain, @@ -918,6 +969,8 @@ IN_PROC_BROWSER_TEST_F( SafetyTipPageInfoBubbleViewBrowserTest, DoesntTriggerOnCharacterSwap_TopSiteWithDifferentRegistry) { + ASSERT_TRUE(IsTopDomain(GetDomainInfo("google.rs"))); + base::HistogramTester histograms; // google.sr is within one character swap of google.rs which is a top domain. const GURL kNavigatedUrl = GetURL("google.sr"); @@ -925,11 +978,11 @@ // considered for lookalike suggestions. SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); - // TestInterstitialNotShown(browser(), kNavigatedUrl); - // histograms.ExpectTotalCount(lookalikes::kHistogramName, 0); - // CheckNoUkm(); NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB); EXPECT_FALSE(IsUIShowing()); + + histograms.ExpectTotalCount(lookalikes::kHistogramName, 0); + CheckRecordedHeuristicsUkmCount(0); } // Tests that Safety Tips trigger on lookalike domains with tail embedding when @@ -1009,6 +1062,7 @@ // the safety tip. histogram_tester.ExpectTotalCount( GetInteractionHistogram("SafetyTip_Lookalike"), 0); + CloseWarningLeaveSite(browser()); histogram_tester.ExpectUniqueSample( GetInteractionHistogram("SafetyTip_Lookalike"),
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index ee4e67a..dbe08461 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -791,13 +791,13 @@ case AppMenuIconController::Severity::NONE: return GetColorProvider()->GetColor(kColorToolbarButtonIcon); case AppMenuIconController::Severity::LOW: - color_id = ui::kColorAlertLowSeverity; + color_id = kColorAppMenuHighlightSeverityLow; break; case AppMenuIconController::Severity::MEDIUM: - color_id = ui::kColorAlertMediumSeverity; + color_id = kColorAppMenuHighlightSeverityMedium; break; case AppMenuIconController::Severity::HIGH: - color_id = ui::kColorAlertHighSeverity; + color_id = kColorAppMenuHighlightSeverityHigh; break; } return GetColorProvider()->GetColor(color_id);
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index 4b5068c..8963382 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -1189,7 +1189,9 @@ FilesOptions files_options, AllowDenyOptions allow_deny, AskAgainOptions ask_again) { - BeforeStateChangeAction(__FUNCTION__); + if (!BeforeStateChangeAction(__FUNCTION__)) { + return; + } AppId app_id = GetAppIdBySiteMode(site); views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{}, "FileHandlerLaunchDialogView"); @@ -1229,7 +1231,9 @@ void WebAppIntegrationTestDriver::LaunchFileExpectNoDialog( Site site, FilesOptions files_options) { - BeforeStateChangeAction(__FUNCTION__); + if (!BeforeStateChangeAction(__FUNCTION__)) { + return; + } AppId app_id = GetAppIdBySiteMode(site); base::RunLoop run_loop; #if BUILDFLAG(IS_MAC) @@ -1787,7 +1791,9 @@ } void WebAppIntegrationTestDriver::SwitchIncognitoProfile() { - BeforeStateChangeAction(__FUNCTION__); + if (!BeforeStateChangeAction(__FUNCTION__)) { + return; + } content::WebContentsAddedObserver nav_observer; CHECK(chrome::ExecuteCommand(browser(), IDC_NEW_INCOGNITO_WINDOW)); ASSERT_EQ(1U, BrowserList::GetIncognitoBrowserCount()); @@ -2069,7 +2075,9 @@ } void WebAppIntegrationTestDriver::CheckAppInListIconCorrect(Site site) { - BeforeStateCheckAction(__FUNCTION__); + if (!BeforeStateCheckAction(__FUNCTION__)) { + return; + } GURL icon_url = apps::AppIconSource::GetIconURL(active_app_id_, icon_size::k128); SkBitmap icon_bitmap; @@ -2307,13 +2315,17 @@ } void WebAppIntegrationTestDriver::CheckCreateShortcutNotShown() { - BeforeStateCheckAction(__FUNCTION__); + if (!BeforeStateCheckAction(__FUNCTION__)) { + return; + } EXPECT_EQ(GetAppMenuCommandState(IDC_CREATE_SHORTCUT, browser()), kDisabled); AfterStateCheckAction(); } void WebAppIntegrationTestDriver::CheckCreateShortcutShown() { - BeforeStateCheckAction(__FUNCTION__); + if (!BeforeStateCheckAction(__FUNCTION__)) { + return; + } EXPECT_EQ(GetAppMenuCommandState(IDC_CREATE_SHORTCUT, browser()), kEnabled); AfterStateCheckAction(); }
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h index 169b9e6..1f7759c 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
@@ -337,12 +337,12 @@ private: // Must be called at the beginning of every state change action function. // Returns if the test should continue. - bool BeforeStateChangeAction(const char* function); + [[nodiscard]] bool BeforeStateChangeAction(const char* function); // Must be called at the end of every state change action function. void AfterStateChangeAction(); // Must be called at the beginning of every state check action function. // Returns if the test should continue. - bool BeforeStateCheckAction(const char* function); + [[nodiscard]] bool BeforeStateCheckAction(const char* function); // Must be called at the end of every state check action function. void AfterStateCheckAction();
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc index 48241ec..2e31c04 100644 --- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc +++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -136,6 +136,10 @@ std::make_unique<AuthenticatorNoAvailableTransportsErrorModel>( dialog_model)); break; + case Step::kErrorNoPasskeys: + sheet_view = std::make_unique<AuthenticatorRequestSheetView>( + std::make_unique<AuthenticatorNoPasskeysErrorModel>(dialog_model)); + break; case Step::kTimedOut: sheet_view = std::make_unique<AuthenticatorRequestSheetView>( std::make_unique<AuthenticatorTimeoutErrorModel>(dialog_model));
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc index 953b0af..03961d46 100644 --- a/chrome/browser/ui/webauthn/sheet_models.cc +++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -337,6 +337,36 @@ IDS_WEBAUTHN_ERROR_NO_TRANSPORTS_DESCRIPTION); } +// AuthenticatorNoPasskeysErrorModel ------------------------------------------ + +bool AuthenticatorNoPasskeysErrorModel::IsBackButtonVisible() const { + return false; +} + +std::u16string AuthenticatorNoPasskeysErrorModel::GetCancelButtonLabel() const { + return l10n_util::GetStringUTF16(IDS_CLOSE); +} + +const gfx::VectorIcon& AuthenticatorNoPasskeysErrorModel::GetStepIllustration( + ImageColorScheme color_scheme) const { + if (base::FeatureList::IsEnabled( + device::kWebAuthnNewDiscoverableCredentialsUi)) { + return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon + : kPasskeyErrorIcon; + } + return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon + : kWebauthnErrorIcon; +} + +std::u16string AuthenticatorNoPasskeysErrorModel::GetStepTitle() const { + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_NO_PASSKEYS_TITLE); +} + +std::u16string AuthenticatorNoPasskeysErrorModel::GetStepDescription() const { + return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_ERROR_NO_PASSKEYS_DESCRIPTION, + GetRelyingPartyIdString(dialog_model())); +} + // AuthenticatorNotRegisteredErrorModel --------------------------------------- bool AuthenticatorNotRegisteredErrorModel::IsBackButtonVisible() const {
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h index a458e7f..8373c89 100644 --- a/chrome/browser/ui/webauthn/sheet_models.h +++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -152,6 +152,20 @@ std::u16string GetStepDescription() const override; }; +class AuthenticatorNoPasskeysErrorModel : public AuthenticatorSheetModelBase { + public: + using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase; + + private: + // AuthenticatorSheetModelBase: + bool IsBackButtonVisible() const override; + std::u16string GetCancelButtonLabel() const override; + const gfx::VectorIcon& GetStepIllustration( + ImageColorScheme color_scheme) const override; + std::u16string GetStepTitle() const override; + std::u16string GetStepDescription() const override; +}; + class AuthenticatorNotRegisteredErrorModel : public AuthenticatorSheetModelBase { public:
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc index e52dad0..01283fb9 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
@@ -212,7 +212,7 @@ scoped_refptr<extensions::Extension> extension = extensions::Extension::Create( base::FilePath(), extensions::mojom::ManifestLocation::kUnpacked, - manifest, 0, &error); + manifest.GetDict(), 0, &error); extension_service()->AddExtension(extension.get()); return extension;
diff --git a/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_network_ui.cc b/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_network_ui.cc index 5c404fd..a6afd58 100644 --- a/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_network_ui.cc +++ b/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_network_ui.cc
@@ -72,7 +72,7 @@ content::WebUIDataSource* html = content::WebUIDataSource::Create(chrome::kChromeUILockScreenNetworkHost); - // TODO(crbug.com/1098690): Trusted Type Polymer. + // TODO(crbug.com/1400799): Enable TrustedTypes html->DisableTrustedTypesCSP(); html->AddLocalizedStrings(localized_strings);
diff --git a/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_start_reauth_ui.cc b/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_start_reauth_ui.cc index 0f750dcd..15f75ca0 100644 --- a/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_start_reauth_ui.cc +++ b/chrome/browser/ui/webui/ash/lock_screen_reauth/lock_screen_start_reauth_ui.cc
@@ -49,7 +49,7 @@ web_ui->AddMessageHandler(std::move(main_handler)); web_ui->AddMessageHandler(std::make_unique<MetricsHandler>()); - // TODO(crbug.com/1098690): Trusted Type Polymer + // TODO(crbug.com/1400799): Enable TrustedTypes. source->DisableTrustedTypesCSP(); source->EnableReplaceI18nInJS();
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 9c930c56..e912fbd 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -189,15 +189,7 @@ ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(url))); - - if (url == "chrome://network-error" || url == "chrome://dino") { - // We don't ASSERT_TRUE here because some WebUI pages are - // PAGE_TYPE_ERROR by design. - content::WaitForLoadStop(content); - } else { - ASSERT_TRUE(content::WaitForLoadStop(content)); - } - + ASSERT_TRUE(content::WaitForLoadStop(content)); EXPECT_TRUE(console_observer.messages().empty()); } @@ -206,14 +198,7 @@ browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(url))); - - if (url == "chrome://network-error" || url == "chrome://dino") { - // We don't ASSERT_TRUE here because some WebUI pages are - // PAGE_TYPE_ERROR by design. - content::WaitForLoadStop(content); - } else { - ASSERT_TRUE(content::WaitForLoadStop(content)); - } + ASSERT_TRUE(content::WaitForLoadStop(content)); const char kIsTrustedTypesEnabled[] = "(function isTrustedTypesEnabled() {" @@ -260,17 +245,11 @@ // Non-exhaustive list of chrome:// URLs to test for // 1) TrustedTypes violations (see NoTrustedTypesViolation test). // 2) Presence of TrustedTypes checks (see TrustedTypesEnabled test). -// This list was derived from chrome://about. :) -// -// TODO(crbug.com/1098690): For all commented out URLs below, uncomment after -// enabling TrustedTypes, unless they are commented out for another reason -// (like flaky failures). static constexpr const char* const kChromeUrls[] = { "chrome://accessibility", "chrome://app-service-internals", "chrome://attribution-internals", "chrome://autofill-internals", - // "chrome://blob-internals", "chrome://bookmarks", "chrome://bookmarks-side-panel.top-chrome", "chrome://chrome-urls", @@ -281,10 +260,7 @@ "chrome://crashes", "chrome://credits", "chrome://customize-chrome-side-panel.top-chrome", - // TODO(crbug/1396866): Enable when bug is fixed. - // "chrome://customize-chrome-side-panel.top-chrome", "chrome://device-log", - // "chrome://dino", // TODO(crbug.com/1113446): Test failure due to excessive output. // "chrome://discards", "chrome://download-internals", @@ -316,7 +292,6 @@ // "chrome://memory-internals", "chrome://net-export", "chrome://net-internals", - // "chrome://network-error", "chrome://network-errors", "chrome://new-tab-page", "chrome://new-tab-page-third-party", @@ -354,7 +329,6 @@ // "chrome://tab-strip", "chrome://terms", "chrome://topics-internals", - // "chrome://tracing", "chrome://translate-internals", "chrome://ukm", "chrome://usb-internals", @@ -381,38 +355,23 @@ #endif #if BUILDFLAG(IS_CHROMEOS_ASH) - // "chrome://account-manager-error", - // "chrome://account-migration-welcome", - // "chrome://add-supervision", + // TODO(crbug.com/1400799): Add CrOS-only WebUI URLs here as TrustedTypes + // are deployed to more WebUIs. + // TODO(crbug.com/1102129): DCHECK failure in // ArcGraphicsTracingHandler::ArcGraphicsTracingHandler. // "chrome://arc-graphics-tracing", - // "chrome://arc-overview-tracing", - // "chrome://assistant-optin", - // "chrome://bluetooth-pairing", - // "chrome://certificate-manager", - // "chrome://crostini-credits", - // "chrome://crostini-installer", "chrome://cryptohome", "chrome://drive-internals", "chrome://family-link-user-internals", "chrome://help-app", - // "chrome://internet-config-dialog", - // "chrome://internet-detail-dialog", "chrome://linux-proxy-config", - // "chrome://multidevice-setup", - // "chrome://network", - // "chrome://os-credits", - // "chrome://os-settings", + "chrome://multidevice-internals", + "chrome://nearby-internals", "chrome://power", "chrome://projector", "chrome://proximity-auth/proximity_auth.html", - // "chrome://set-time", "chrome://slow", - // "chrome://smb-credentials-dialog", - // "chrome://smb-share-dialog", - // "chrome://sys-internals", - // "chrome-untrusted://terminal", #endif #if !BUILDFLAG(IS_CHROMEOS) "chrome://apps",
diff --git a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc index 7cd951a..0d131dc 100644 --- a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc +++ b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
@@ -179,8 +179,8 @@ download::DownloadItem* file = GetDownloadByStringId(id); if (file) { DownloadItemWarningData::AddWarningActionEvent( - file, DownloadItemWarningData::DOWNLOADS_PAGE, - DownloadItemWarningData::KEEP); + file, DownloadItemWarningData::WarningSurface::DOWNLOADS_PAGE, + DownloadItemWarningData::WarningAction::KEEP); ShowDangerPrompt(file); } } @@ -192,8 +192,8 @@ // The warning action event needs to be added before Safe Browsing report is // sent, because this event should be included in the report. DownloadItemWarningData::AddWarningActionEvent( - download, DownloadItemWarningData::DOWNLOADS_PAGE, - DownloadItemWarningData::DISCARD); + download, DownloadItemWarningData::WarningSurface::DOWNLOADS_PAGE, + DownloadItemWarningData::WarningAction::DISCARD); // If this download is no longer dangerous, is already canceled or // completed, don't send any report. // Only sends dangerous download discard report if :
diff --git a/chrome/browser/ui/webui/management/management_ui_browsertest.cc b/chrome/browser/ui/webui/management/management_ui_browsertest.cc index f109a589..be8dbab 100644 --- a/chrome/browser/ui/webui/management/management_ui_browsertest.cc +++ b/chrome/browser/ui/webui/management/management_ui_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/json/json_reader.h" +#include "base/strings/escape.h" #include "base/strings/utf_string_conversions.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" @@ -84,7 +85,9 @@ {"browserManagementNotice", l10n_util::GetStringFUTF16( IDS_MANAGEMENT_NOT_MANAGED_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))}, + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))}, {"extensionReportingTitle", l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)}, {"pageSubtitle", @@ -117,7 +120,9 @@ {"browserManagementNotice", l10n_util::GetStringFUTF16( IDS_MANAGEMENT_BROWSER_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))}, + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))}, {"extensionReportingTitle", l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)}, {"pageSubtitle", l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE)},
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.cc b/chrome/browser/ui/webui/management/management_ui_handler.cc index f611708..f8ed735 100644 --- a/chrome/browser/ui/webui/management/management_ui_handler.cc +++ b/chrome/browser/ui/webui/management/management_ui_handler.cc
@@ -18,6 +18,7 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/user_metrics.h" +#include "base/strings/escape.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -841,7 +842,9 @@ l10n_util::GetStringFUTF16( managed_() ? IDS_MANAGEMENT_BROWSER_NOTICE : IDS_MANAGEMENT_NOT_MANAGED_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))); #endif if (enterprise_manager.empty()) {
diff --git a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc index 2c45f3b..378817b 100644 --- a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc +++ b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
@@ -13,6 +13,7 @@ #include "base/json/json_reader.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" +#include "base/strings/escape.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" #include "build/chromeos_buildflags.h" @@ -714,7 +715,9 @@ EXPECT_EQ(GetBrowserManagementNotice(), l10n_util::GetStringFUTF16( IDS_MANAGEMENT_NOT_MANAGED_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))); EXPECT_EQ(GetPageSubtitle(), l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE)); } @@ -732,7 +735,9 @@ EXPECT_EQ(GetBrowserManagementNotice(), l10n_util::GetStringFUTF16( IDS_MANAGEMENT_BROWSER_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))); EXPECT_EQ(GetPageSubtitle(), l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE)); EXPECT_TRUE(GetManaged()); @@ -752,7 +757,9 @@ EXPECT_EQ(GetBrowserManagementNotice(), l10n_util::GetStringFUTF16( IDS_MANAGEMENT_BROWSER_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))); EXPECT_EQ(GetPageSubtitle(), l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE)); EXPECT_TRUE(GetManaged()); @@ -777,7 +784,9 @@ EXPECT_EQ(GetBrowserManagementNotice(), l10n_util::GetStringFUTF16( IDS_MANAGEMENT_NOT_MANAGED_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))); EXPECT_EQ(GetPageSubtitle(), l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE)); EXPECT_FALSE(GetManaged()); @@ -797,7 +806,9 @@ EXPECT_EQ(GetBrowserManagementNotice(), l10n_util::GetStringFUTF16( IDS_MANAGEMENT_NOT_MANAGED_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))); EXPECT_EQ(GetPageSubtitle(), l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE)); EXPECT_FALSE(GetManaged()); @@ -821,7 +832,9 @@ EXPECT_EQ(GetBrowserManagementNotice(), l10n_util::GetStringFUTF16( IDS_MANAGEMENT_BROWSER_NOTICE, - base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl), + base::EscapeForHTML(l10n_util::GetStringUTF16( + IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT)))); EXPECT_EQ(GetPageSubtitle(), l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY, base::UTF8ToUTF16(domain)));
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom index f28a707..183df02 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom
@@ -11,6 +11,8 @@ struct BackgroundImage { // URL to the background image. Can point to untrusted content. url.mojom.Url url; + // Whether the image is a local resource. + bool is_uploaded_image; // Title of the background image. string title; }; @@ -25,6 +27,8 @@ skia.mojom.SkColor background_color; // The current theme foreground color. If not set, we use the default theme. skia.mojom.SkColor? foreground_color; + // The color of the color picker icon. + skia.mojom.SkColor color_picker_icon_color; }; struct ChromeColor {
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc index 1733c816..9a9b5107 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc
@@ -103,6 +103,7 @@ auto background_image = side_panel::mojom::BackgroundImage::New(); if (custom_background.has_value()) { background_image->url = custom_background->custom_background_url; + background_image->is_uploaded_image = custom_background->is_uploaded_image; background_image->title = custom_background->custom_background_attribution_line_1; } else { @@ -116,6 +117,8 @@ theme->foreground_color = web_contents_->GetColorProvider().GetColor(ui::kColorFrameActive); } + theme->color_picker_icon_color = + web_contents_->GetColorProvider().GetColor(kColorNewTabPageText); auto* native_theme = ui::NativeTheme::GetInstanceForNativeUi(); CHECK(native_theme); theme->system_dark_mode = native_theme->ShouldUseDarkColors();
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc index 7a2b33e..df9063e 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
@@ -270,6 +270,7 @@ CustomBackground custom_background; custom_background.custom_background_url = GURL("https://foo.com/img.png"); custom_background.custom_background_attribution_line_1 = "foo line"; + custom_background.is_uploaded_image = false; ON_CALL(mock_ntp_custom_background_service_, GetCustomBackground()) .WillByDefault(testing::Return(absl::make_optional(custom_background))); ON_CALL(mock_theme_service(), UsingDefaultTheme()) @@ -284,6 +285,7 @@ ASSERT_TRUE(theme); ASSERT_TRUE(theme->background_image); EXPECT_EQ("https://foo.com/img.png", theme->background_image->url); + ASSERT_FALSE(theme->background_image->is_uploaded_image); EXPECT_EQ("foo line", theme->background_image->title); EXPECT_TRUE(theme->system_dark_mode); EXPECT_EQ( @@ -291,6 +293,34 @@ theme->background_color); EXPECT_EQ(web_contents().GetColorProvider().GetColor(ui::kColorFrameActive), theme->foreground_color); + EXPECT_EQ(web_contents().GetColorProvider().GetColor(kColorNewTabPageText), + theme->color_picker_icon_color); +} + +TEST_P(CustomizeChromePageHandlerSetThemeTest, SetUploadedImage) { + side_panel::mojom::ThemePtr theme; + EXPECT_CALL(mock_page_, SetTheme) + .Times(1) + .WillOnce(testing::Invoke([&theme](side_panel::mojom::ThemePtr arg) { + theme = std::move(arg); + })); + CustomBackground custom_background; + custom_background.custom_background_url = GURL("https://foo.com/img.png"); + custom_background.is_uploaded_image = true; + ON_CALL(mock_ntp_custom_background_service_, GetCustomBackground()) + .WillByDefault(testing::Return(absl::make_optional(custom_background))); + ON_CALL(mock_theme_service(), UsingDefaultTheme()) + .WillByDefault(testing::Return(false)); + ON_CALL(mock_theme_service(), UsingSystemTheme()) + .WillByDefault(testing::Return(false)); + + UpdateTheme(); + mock_page_.FlushForTesting(); + + ASSERT_TRUE(theme); + ASSERT_TRUE(theme->background_image); + EXPECT_EQ("https://foo.com/img.png", theme->background_image->url); + ASSERT_TRUE(theme->background_image->is_uploaded_image); } INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc index 9d2b08b5..160e331c 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc
@@ -30,6 +30,8 @@ static constexpr webui::LocalizedString kLocalizedStrings[] = { {"classicChrome", IDS_NTP_CUSTOMIZE_NO_BACKGROUND_LABEL}, + {"colorsContainerLabel", IDS_NTP_THEMES_CONTAINER_LABEL}, + {"colorPickerLabel", IDS_NTP_CUSTOMIZE_COLOR_PICKER_LABEL}, {"customizeThisPage", IDS_NTP_CUSTOM_BG_CUSTOMIZE_NTP_LABEL}, {"appearanceHeader", IDS_NTP_CUSTOMIZE_APPEARANCE_LABEL}, {"defaultColorName", IDS_NTP_CUSTOMIZE_DEFAULT_LABEL}, @@ -40,6 +42,7 @@ {"shortcutsSuggested", IDS_NTP_CUSTOMIZE_MOST_VISITED_DESC}, {"showShortcutsToggle", IDS_NTP_CUSTOMIZE_SHOW_SHORTCUTS_LABEL}, {"title", IDS_SIDE_PANEL_CUSTOMIZE_CHROME_TITLE}, + {"uploadedImage", IDS_NTP_CUSTOMIZE_UPLOADED_IMAGE_LABEL}, }; source->AddLocalizedStrings(kLocalizedStrings);
diff --git a/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc b/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc index ceb3b878..da667a5 100644 --- a/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc +++ b/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc
@@ -335,7 +335,6 @@ #if BUILDFLAG(IS_MAC) root.Append(BuildAppShimRegistryLocalStorageJson()); #endif - root.Append(BuildInstallProcessErrorLogJson(*provider)); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, base::BindOnce(&BuildWebAppDiskStateJson,
diff --git a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc index fe92068..54e98d5 100644 --- a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc +++ b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
@@ -537,6 +537,8 @@ if (ShouldSkipPWASpecificTest()) return; + base::RunLoop().RunUntilIdle(); + const auto& install_requests = externally_managed_app_manager().install_requests(); EXPECT_TRUE(install_requests.empty()); @@ -918,7 +920,6 @@ TEST_P(WebAppPolicyManagerTest, UninstallAppInstalledInPreviousSession) { if (ShouldSkipPWASpecificTest()) return; - // Simulate two policy apps and a regular app that were installed in the // previous session. SimulatePreviouslyInstalledApp(GURL(kWindowedUrl), @@ -952,6 +953,7 @@ TEST_P(WebAppPolicyManagerTest, UninstallAppInstalledInCurrentSession) { if (ShouldSkipPWASpecificTest()) return; + base::RunLoop().RunUntilIdle(); // Add two sites, one that opens in a window and one that opens in a tab. base::Value::List first_list; @@ -1103,7 +1105,7 @@ TEST_P(WebAppPolicyManagerTest, SayRefreshTwoTimesQuickly) { if (ShouldSkipPWASpecificTest()) return; - + base::RunLoop().RunUntilIdle(); // Add an app. { base::Value::List list; @@ -1118,17 +1120,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); } - - // `OnAppsSynchronized` should be triggered twice. - base::RunLoop loop; - policy_manager().SetOnAppsSynchronizedCompletedCallbackForTesting( - loop.QuitClosure()); - loop.Run(); - - base::RunLoop loop2; - policy_manager().SetOnAppsSynchronizedCompletedCallbackForTesting( - loop2.QuitClosure()); - loop2.Run(); + base::RunLoop().RunUntilIdle(); // Both apps should have been installed. std::vector<ExternalInstallOptions> expected_options_list; @@ -1193,6 +1185,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) TEST_P(WebAppPolicyManagerTest, DisableSystemWebApps) { + base::RunLoop().RunUntilIdle(); + auto disabled_apps = policy_manager().GetDisabledSystemWebApps(); EXPECT_TRUE(disabled_apps.empty());
diff --git a/chrome/browser/web_applications/externally_managed_app_manager.cc b/chrome/browser/web_applications/externally_managed_app_manager.cc index f382c6b..5c2844c 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager.cc
@@ -15,8 +15,6 @@ #include "base/stl_util.h" #include "base/task/single_thread_task_runner.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/web_applications/locks/full_system_lock.h" -#include "chrome/browser/web_applications/web_app_command_scheduler.h" #include "chrome/browser/web_applications/web_app_install_utils.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "components/webapps/browser/install_result_code.h" @@ -90,6 +88,7 @@ std::vector<ExternalInstallOptions> desired_apps_install_options, ExternalInstallSource install_source, SynchronizeCallback callback) { + DCHECK(registrar_); DCHECK(base::ranges::all_of( desired_apps_install_options, [&install_source](const ExternalInstallOptions& install_options) { @@ -98,29 +97,14 @@ // Only one concurrent SynchronizeInstalledApps() expected per // ExternalInstallSource. DCHECK(!base::Contains(synchronize_requests_, install_source)); - command_scheduler_->ScheduleCallbackWithLock<FullSystemLock>( - "ExternallyManagedAppManager::SynchronizeInstalledApps", - std::make_unique<FullSystemLockDescription>(), - base::BindOnce( - &ExternallyManagedAppManager::SynchronizeInstalledAppsOnLockAcquired, - weak_ptr_factory_.GetWeakPtr(), - std::move(desired_apps_install_options), std::move(install_source), - std::move(callback))); -} -void ExternallyManagedAppManager::SynchronizeInstalledAppsOnLockAcquired( - std::vector<ExternalInstallOptions> desired_apps_install_options, - ExternalInstallSource install_source, - SynchronizeCallback callback, - FullSystemLock& lock) { std::vector<GURL> installed_urls; for (const auto& apps_it : - lock.registrar().GetExternallyInstalledApps(install_source)) { + registrar_->GetExternallyInstalledApps(install_source)) { // TODO(crbug.com/1339965): Remove this check once we cleanup // ExternallyInstalledWebAppPrefs on external app uninstall. bool has_same_external_source = - lock.registrar() - .GetAppById(apps_it.first) + registrar_->GetAppById(apps_it.first) ->GetSources() .test(ConvertExternalInstallSourceToSource(install_source)); if (has_same_external_source) {
diff --git a/chrome/browser/web_applications/externally_managed_app_manager.h b/chrome/browser/web_applications/externally_managed_app_manager.h index 8e15a41..1b7eb9d0 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager.h +++ b/chrome/browser/web_applications/externally_managed_app_manager.h
@@ -24,7 +24,6 @@ namespace web_app { -class FullSystemLock; class WebAppRegistrar; class WebAppInstallFinalizer; class WebAppCommandScheduler; @@ -191,12 +190,6 @@ std::map<GURL, bool> uninstall_results; }; - void SynchronizeInstalledAppsOnLockAcquired( - std::vector<ExternalInstallOptions> desired_apps_install_options, - ExternalInstallSource install_source, - SynchronizeCallback callback, - FullSystemLock& lock); - void InstallForSynchronizeCallback( ExternalInstallSource source, const GURL& install_url,
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl.cc index 2228de8..73a6064 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager_impl.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager_impl.cc
@@ -12,12 +12,9 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/feature_list.h" -#include "base/functional/bind.h" #include "base/task/single_thread_task_runner.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/web_applications/externally_managed_app_manager.h" #include "chrome/browser/web_applications/externally_managed_app_registration_task.h" -#include "chrome/browser/web_applications/locks/full_system_lock.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_command_scheduler.h" #include "chrome/browser/web_applications/web_app_install_finalizer.h" @@ -161,19 +158,6 @@ void ExternallyManagedAppManagerImpl::MaybeStartNext() { if (current_install_ || is_in_shutdown_) return; - command_scheduler()->ScheduleCallbackWithLock<FullSystemLock>( - "ExternallyManagedAppManagerImpl::MaybeStartNext", - std::make_unique<FullSystemLockDescription>(), - base::BindOnce( - &ExternallyManagedAppManagerImpl::MaybeStartNextOnLockAcquired, - weak_ptr_factory_.GetWeakPtr())); -} - -void ExternallyManagedAppManagerImpl::MaybeStartNextOnLockAcquired( - FullSystemLock& lock) { - if (current_install_ || is_in_shutdown_) { - return; - } while (!pending_installs_.empty()) { std::unique_ptr<TaskAndCallback> front = @@ -189,7 +173,7 @@ } absl::optional<AppId> app_id = - lock.registrar().LookupExternalAppId(install_options.install_url); + registrar()->LookupExternalAppId(install_options.install_url); // If the URL is not in web_app registrar, // then no external source has installed it. @@ -198,10 +182,10 @@ return; } - if (lock.registrar().IsInstalled(app_id.value())) { + if (registrar()->IsInstalled(app_id.value())) { if (install_options.wait_for_windows_closed && - lock.ui_manager().GetNumWindowsForApp(app_id.value()) != 0) { - lock.ui_manager().NotifyOnAllAppWindowsClosed( + ui_manager()->GetNumWindowsForApp(app_id.value()) != 0) { + ui_manager()->NotifyOnAllAppWindowsClosed( app_id.value(), base::BindOnce(&ExternallyManagedAppManagerImpl::Install, weak_ptr_factory_.GetWeakPtr(), install_options, @@ -212,9 +196,9 @@ // If the app is already installed, only reinstall it if the app is a // placeholder app and the client asked for it to be reinstalled. if (install_options.reinstall_placeholder && - lock.registrar().IsPlaceholderApp( - app_id.value(), ConvertExternalInstallSourceToSource( - install_options.install_source))) { + registrar()->IsPlaceholderApp(app_id.value(), + ConvertExternalInstallSourceToSource( + install_options.install_source))) { StartInstallationTask(std::move(front)); return; } @@ -227,7 +211,7 @@ return; } else { // Add install source before returning the result. - ScopedRegistryUpdate update(&lock.sync_bridge()); + ScopedRegistryUpdate update(sync_bridge()); WebApp* app_to_update = update->UpdateApp(app_id.value()); app_to_update->AddSource(ConvertExternalInstallSourceToSource( install_options.install_source));
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl.h b/chrome/browser/web_applications/externally_managed_app_manager_impl.h index 794125722..9fe18dd 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager_impl.h +++ b/chrome/browser/web_applications/externally_managed_app_manager_impl.h
@@ -27,7 +27,6 @@ namespace web_app { -class FullSystemLock; class ExternallyManagedAppRegistrationTaskBase; // Installs, uninstalls, and updates any External Web Apps. This class should @@ -75,7 +74,6 @@ void PostMaybeStartNext(); void MaybeStartNext(); - void MaybeStartNextOnLockAcquired(FullSystemLock& lock); void StartInstallationTask(std::unique_ptr<TaskAndCallback> task);
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc index 1ca55fcf..596ca26 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
@@ -466,7 +466,7 @@ } void TearDown() override { - provider().Shutdown(); + command_scheduler().Shutdown(); WebAppTest::TearDown(); } @@ -510,6 +510,7 @@ barrier_closure.Run(); })); run_loop.Run(); + return results; }
diff --git a/chrome/browser/web_applications/isolated_web_apps/OWNERS b/chrome/browser/web_applications/isolated_web_apps/OWNERS new file mode 100644 index 0000000..5c9ed56 --- /dev/null +++ b/chrome/browser/web_applications/isolated_web_apps/OWNERS
@@ -0,0 +1,2 @@ +cmfcmf@chromium.org +rmcelrath@chromium.org
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc index 4893400..83ccc9a 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -118,11 +118,7 @@ system_web_apps_delegate_map_ = system_web_apps_delegate_map; } -void WebAppPolicyManager::Start(base::OnceClosure initialization_complete) { - DCHECK(initialization_complete_.is_null()); - - initialization_complete_ = std::move(initialization_complete); - +void WebAppPolicyManager::Start(base::OnceClosure on_done) { // When Lacros is enabled, don't run PWA-specific logic in Ash. // TODO(crbug.com/1251491): Consider factoring out logic that should only run // in Ash into a separate class. This way, when running in Ash, we won't need @@ -135,7 +131,8 @@ ->PostTask(FROM_HERE, base::BindOnce( &WebAppPolicyManager::InitChangeRegistrarAndRefreshPolicy, - weak_ptr_factory_.GetWeakPtr(), enable_pwa_support)); + weak_ptr_factory_.GetWeakPtr(), enable_pwa_support) + .Then(std::move(on_done))); } void WebAppPolicyManager::ReinstallPlaceholderAppIfNecessary(const GURL& url) { @@ -207,10 +204,6 @@ weak_ptr_factory_.GetWeakPtr())); RefreshPolicyInstalledIsolatedWebApps(); #endif - } else { - if (initialization_complete_) { - std::move(initialization_complete_).Run(); - } } ObserveDisabledSystemFeaturesPolicy(); } @@ -545,7 +538,7 @@ void WebAppPolicyManager::SetOnAppsSynchronizedCompletedCallbackForTesting( base::OnceClosure callback) { - on_apps_synchronized_for_testing_ = std::move(callback); + on_apps_synchronized_ = std::move(callback); } void WebAppPolicyManager::SetRefreshPolicySettingsCompletedCallbackForTesting( @@ -638,13 +631,8 @@ url_and_result.second.code); } - if (on_apps_synchronized_for_testing_) { - std::move(on_apps_synchronized_for_testing_).Run(); - } - - if (initialization_complete_) { - std::move(initialization_complete_).Run(); - } + if (on_apps_synchronized_) + std::move(on_apps_synchronized_).Run(); } WebAppPolicyManager::WebAppSetting::WebAppSetting() {
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.h b/chrome/browser/web_applications/policy/web_app_policy_manager.h index 8bf8375..6ea29f7 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.h +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.h
@@ -65,8 +65,6 @@ void SetSystemWebAppDelegateMap( const ash::SystemWebAppDelegateMap* system_web_apps_delegate_map); - // `initialization_complete` waits for the first `SynchronizeInstalledApps` to - // finish if it's triggered on `Start`. void Start(base::OnceClosure initialization_complete); void ReinstallPlaceholderAppIfNecessary(const GURL& url); @@ -192,7 +190,7 @@ // Testing callbacks base::OnceClosure refresh_policy_settings_completed_; - base::OnceClosure on_apps_synchronized_for_testing_; + base::OnceClosure on_apps_synchronized_; bool is_refreshing_ = false; bool needs_refresh_ = false; @@ -202,9 +200,6 @@ std::unique_ptr<WebAppSetting> default_settings_; ExternallyInstalledWebAppPrefs externally_installed_app_prefs_; - - base::OnceClosure initialization_complete_; - #if BUILDFLAG(IS_CHROMEOS) std::unique_ptr<IsolatedWebAppPolicyManager> iwa_policy_manager_; #endif
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index 651b7ab..9cfccebe 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -245,7 +245,12 @@ SetCurrentStep(*pending_step_); pending_step_.reset(); } else if (mechanisms_.empty()) { - SetCurrentStep(Step::kErrorNoAvailableTransports); + if (base::FeatureList::IsEnabled(device::kWebAuthnNoPasskeysError) && + transport_availability_.transport_list_did_include_internal) { + SetCurrentStep(Step::kErrorNoPasskeys); + } else { + SetCurrentStep(Step::kErrorNoAvailableTransports); + } } else if (mechanisms_.size() == 1) { mechanisms_[0].callback.Run(); } else if (priority_mechanism_it != mechanisms_.end()) {
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index 2bcd8fdd..3a5986da4 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -73,6 +73,7 @@ // The request errored out before completing. Error will only be sent // after user interaction. kErrorNoAvailableTransports, + kErrorNoPasskeys, kErrorInternalUnrecognized, // The request is already complete, but the error dialog should wait
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 8d4b0b0..2dec125 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1671019116-6b9cae0d3e8c73277c9f214478366172a511d31a.profdata +chrome-linux-main-1671040780-7354adbba216d8d22545e6cbff01983a0ef786cc.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 3178b67b..846237e3 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1670997253-a4bdf1b52f9c04eb5ecbbf26461b8564531d27cc.profdata +chrome-mac-arm-main-1671040780-ab587c46ae159837cb1901b47db9f541feb1ec6f.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index d401ef2..7dd319db 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1671008076-19a9c8909deb1a4f7619d99c4ef88613e515e068.profdata +chrome-win32-main-1671029899-f511e3be18f418e934aad5640a3a4197391f4ec1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 0d62531af..5106b24 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1671029899-ba84905e9939d7394e959eb36f6891b3bd5d0d8c.profdata +chrome-win64-main-1671040780-fa17ea6b4718dc5c5320f88590d164f43c2aa427.profdata
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 314d831b..f3e79a7 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -3478,13 +3478,21 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) // Enum pref indicating how to launch the Lacros browser. It is managed by -// LacrosAvailability policy can have one of the following values: +// LacrosAvailability policy and can have one of the following values: // 0: User choice (default value). // 1: Lacros is disallowed. // 2: Lacros is enabled but not the pimary browser. // 3: Lacros is enabled as the primary browser. // 4: Lacros is the only available browser. const char kLacrosLaunchSwitch[] = "lacros_launch_switch"; + +// Enum pref indicating which Lacros browser to launch: rootfs or stateful. It +// is managed by LacrosSelection policy and can have one of the following +// values: +// 0: User choice (default value). +// 1: Always load rootfs Lacros. +// 2: Always load stateful Lacros. +const char kLacrosSelection[] = "lacros_selection"; #endif #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index e3b12b2..6230f1a 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -1208,6 +1208,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) extern const char kLacrosLaunchSwitch[]; +extern const char kLacrosSelection[]; #endif #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 6a1f4147..ca11bd4 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -8618,6 +8618,7 @@ "../browser/enterprise/idle/action_runner_unittest.cc", "../browser/enterprise/idle/action_unittest.cc", "../browser/enterprise/idle/browser_closer_unittest.cc", + "../browser/enterprise/idle/idle_timeout_policy_handler_unittest.cc", "../browser/enterprise/remote_commands/rotate_attestation_credential_job_unittest.cc", "../browser/enterprise/signals/user_delegate_impl_unittest.cc", "../browser/net/disk_cache_dir_policy_handler_unittest.cc",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 99e44fae7..033b3fb 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -18779,6 +18779,56 @@ } ] }, + "LacrosSelection": { + "os": [ + "chromeos_ash" + ], + "can_be_recommended": false, + "policy_pref_mapping_tests": [ + { + "policies": {}, + "prefs": { + "lacros_selection": { + "location": "local_state", + "value": 1 + } + } + }, + { + "policies": { + "LacrosSelection": "user_choice" + }, + "prefs": { + "lacros_selection": { + "location": "local_state", + "value": 0 + } + } + }, + { + "policies": { + "LacrosSelection": "rootfs" + }, + "prefs": { + "lacros_selection": { + "location": "local_state", + "value": 1 + } + } + }, + { + "policies": { + "LacrosSelection": "stateful" + }, + "prefs": { + "lacros_selection": { + "location": "local_state", + "value": 2 + } + } + } + ] + }, "LacrosDataBackwardMigrationMode": { "os": [ "chromeos_ash" @@ -20603,18 +20653,18 @@ }, "prefs": { "idle_timeout": { - "value": 10 + "value": "600000000" } } }, { "policies": { - "IdleTimeout": 1, + "IdleTimeout": 0, "IdleTimeoutActions": [] }, "prefs": { "idle_timeout": { - "value": 5 + "value": "60000000" } } }
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 5dabfeb2..f941d99 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -169,12 +169,12 @@ "chromeos/emoji_picker/emoji_picker_browsertest.js", "chromeos/gaia_action_buttons/gaia_action_buttons_browsertest.js", "chromeos/internet_detail_dialog_browsertest.js", + "chromeos/set_time_dialog_browsertest.js", + "chromeos/sys_internals/sys_internals_browsertest.js", "cr_components/chromeos/cr_components_chromeos_v3_browsertest.js", "js/i18n_process_test.js", - "set_time_dialog_browsertest.js", "settings/chromeos/a11y/v3_os_a11y_browsertest.js", "settings/chromeos/os_settings_v3_browsertest.js", - "sys_internals/sys_internals_browsertest.js", ] } else { sources += [ "signin/signin_browsertest.js" ] @@ -461,16 +461,16 @@ if (is_chromeos_ash) { input_files += [ + "chromeos/arc_account_picker/test_util.js", + "chromeos/ash_common/i18n_behavior_test.js", "chromeos/chai_assert.js", + "chromeos/fake_network_config_mojom.js", "chromeos/mock_controller.js", "chromeos/mock_controller.m.js", + "chromeos/set_time_dialog_test.js", "chromeos/test_browser_proxy.js", "chromeos/test_store.js", "chromeos/test_util.js", - "chromeos/arc_account_picker/test_util.js", - "chromeos/ash_common/i18n_behavior_test.js", - "chromeos/fake_network_config_mojom.js", - "set_time_dialog_test.js", ] }
diff --git a/chrome/test/data/webui/set_time_dialog_browsertest.js b/chrome/test/data/webui/chromeos/set_time_dialog_browsertest.js similarity index 85% rename from chrome/test/data/webui/set_time_dialog_browsertest.js rename to chrome/test/data/webui/chromeos/set_time_dialog_browsertest.js index 0767e75f..2f466b9 100644 --- a/chrome/test/data/webui/set_time_dialog_browsertest.js +++ b/chrome/test/data/webui/chromeos/set_time_dialog_browsertest.js
@@ -10,7 +10,7 @@ var SetTimeDialogBrowserTest = class extends PolymerTest { /** @override */ get browsePreload() { - return 'chrome://set-time/test_loader.html?module=set_time_dialog_test.js'; + return 'chrome://set-time/test_loader.html?module=chromeos/set_time_dialog_test.js'; } };
diff --git a/chrome/test/data/webui/set_time_dialog_test.js b/chrome/test/data/webui/chromeos/set_time_dialog_test.js similarity index 99% rename from chrome/test/data/webui/set_time_dialog_test.js rename to chrome/test/data/webui/chromeos/set_time_dialog_test.js index 4f19c3e9..6b6ede7 100644 --- a/chrome/test/data/webui/set_time_dialog_test.js +++ b/chrome/test/data/webui/chromeos/set_time_dialog_test.js
@@ -7,7 +7,6 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SetTimeBrowserProxyImpl} from 'chrome://set-time/set_time_browser_proxy.js'; - import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; suite('SetTimeDialog', function() {
diff --git a/chrome/test/data/webui/sys_internals/all_tests.js b/chrome/test/data/webui/chromeos/sys_internals/all_tests.js similarity index 100% rename from chrome/test/data/webui/sys_internals/all_tests.js rename to chrome/test/data/webui/chromeos/sys_internals/all_tests.js
diff --git a/chrome/test/data/webui/sys_internals/api_test.js b/chrome/test/data/webui/chromeos/sys_internals/api_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/api_test.js rename to chrome/test/data/webui/chromeos/sys_internals/api_test.js
diff --git a/chrome/test/data/webui/sys_internals/line_chart/data_series_test.js b/chrome/test/data/webui/chromeos/sys_internals/line_chart/data_series_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/line_chart/data_series_test.js rename to chrome/test/data/webui/chromeos/sys_internals/line_chart/data_series_test.js
diff --git a/chrome/test/data/webui/sys_internals/line_chart/line_chart_test.js b/chrome/test/data/webui/chromeos/sys_internals/line_chart/line_chart_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/line_chart/line_chart_test.js rename to chrome/test/data/webui/chromeos/sys_internals/line_chart/line_chart_test.js
diff --git a/chrome/test/data/webui/sys_internals/line_chart/menu_test.js b/chrome/test/data/webui/chromeos/sys_internals/line_chart/menu_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/line_chart/menu_test.js rename to chrome/test/data/webui/chromeos/sys_internals/line_chart/menu_test.js
diff --git a/chrome/test/data/webui/sys_internals/line_chart/scrollbar_test.js b/chrome/test/data/webui/chromeos/sys_internals/line_chart/scrollbar_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/line_chart/scrollbar_test.js rename to chrome/test/data/webui/chromeos/sys_internals/line_chart/scrollbar_test.js
diff --git a/chrome/test/data/webui/sys_internals/line_chart/sub_chart_test.js b/chrome/test/data/webui/chromeos/sys_internals/line_chart/sub_chart_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/line_chart/sub_chart_test.js rename to chrome/test/data/webui/chromeos/sys_internals/line_chart/sub_chart_test.js
diff --git a/chrome/test/data/webui/sys_internals/line_chart/unit_label_test.js b/chrome/test/data/webui/chromeos/sys_internals/line_chart/unit_label_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/line_chart/unit_label_test.js rename to chrome/test/data/webui/chromeos/sys_internals/line_chart/unit_label_test.js
diff --git a/chrome/test/data/webui/sys_internals/page_drawer_test.js b/chrome/test/data/webui/chromeos/sys_internals/page_drawer_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/page_drawer_test.js rename to chrome/test/data/webui/chromeos/sys_internals/page_drawer_test.js
diff --git a/chrome/test/data/webui/sys_internals/page_infopage_test.js b/chrome/test/data/webui/chromeos/sys_internals/page_infopage_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/page_infopage_test.js rename to chrome/test/data/webui/chromeos/sys_internals/page_infopage_test.js
diff --git a/chrome/test/data/webui/sys_internals/page_switch_test.js b/chrome/test/data/webui/chromeos/sys_internals/page_switch_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/page_switch_test.js rename to chrome/test/data/webui/chromeos/sys_internals/page_switch_test.js
diff --git a/chrome/test/data/webui/sys_internals/page_unit_test.js b/chrome/test/data/webui/chromeos/sys_internals/page_unit_test.js similarity index 100% rename from chrome/test/data/webui/sys_internals/page_unit_test.js rename to chrome/test/data/webui/chromeos/sys_internals/page_unit_test.js
diff --git a/chrome/test/data/webui/sys_internals/sys_internals_browsertest.js b/chrome/test/data/webui/chromeos/sys_internals/sys_internals_browsertest.js similarity index 94% rename from chrome/test/data/webui/sys_internals/sys_internals_browsertest.js rename to chrome/test/data/webui/chromeos/sys_internals/sys_internals_browsertest.js index f05096f..60d011f0 100644 --- a/chrome/test/data/webui/sys_internals/sys_internals_browsertest.js +++ b/chrome/test/data/webui/chromeos/sys_internals/sys_internals_browsertest.js
@@ -18,7 +18,7 @@ __proto__: testing.Test.prototype, browsePreload: - 'chrome://sys-internals/index.html?module=sys_internals/all_tests.js&host=test', + 'chrome://sys-internals/index.html?module=chromeos/sys_internals/all_tests.js&host=test', isAsync: true,
diff --git a/chrome/test/data/webui/sys_internals/test_util.js b/chrome/test/data/webui/chromeos/sys_internals/test_util.js similarity index 100% rename from chrome/test/data/webui/sys_internals/test_util.js rename to chrome/test/data/webui/chromeos/sys_internals/test_util.js
diff --git a/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js b/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js index 782fe7b..15a07159 100644 --- a/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js
@@ -4,32 +4,24 @@ import 'chrome://os-settings/chromeos/lazy_load.js'; -import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; +import {CrSettingsPrefs, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {waitAfterNextRender, waitBeforeNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; - suite('TextToSpeechPageTests', function() { let page = null; - function initPage(opt_prefs) { - page = document.createElement('settings-text-to-speech-page'); - page.prefs = opt_prefs || getDefaultPrefs(); - document.body.appendChild(page); - } + async function initPage() { + const prefElement = document.createElement('settings-prefs'); + document.body.appendChild(prefElement); - function getDefaultPrefs() { - return { - 'settings': { - 'accessibility': { - key: 'settings.accessibility', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - }, - }; + await CrSettingsPrefs.initialized; + page = document.createElement('settings-text-to-speech-page'); + page.prefs = prefElement.prefs; + document.body.appendChild(page); + flush(); } setup(function() { @@ -50,8 +42,7 @@ `should focus ${selector} button when returning from ${ route.path} subpage`, async () => { - initPage(); - flush(); + await initPage(); const router = Router.getInstance(); const subpageButton = page.shadowRoot.querySelector(selector); @@ -75,13 +66,12 @@ }); }); - test('only allowed subpages are available in kiosk mode', function() { + test('only allowed subpages are available in kiosk mode', async function() { loadTimeData.overrideValues({ isKioskModeActive: true, showTabletModeShelfNavigationButtonsSettings: true, }); - initPage(); - flush(); + await initPage(); const allowed_subpages = [ 'chromeVoxSubpageButton',
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts index 5990693f..ebb12f6 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts
@@ -5,6 +5,7 @@ import 'chrome://webui-test/mojo_webui_test_support.js'; import {ColorElement} from 'chrome://customize-chrome-side-panel.top-chrome/color.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {assertStyle} from './test_support.js'; @@ -24,4 +25,30 @@ assertStyle(colorElement.$.background, 'fill', 'rgb(255, 0, 0)'); assertStyle(colorElement.$.foreground, 'fill', 'rgb(0, 255, 0)'); }); + + test('color can be checked', () => { + colorElement.checked = true; + + const wrapper = colorElement.shadowRoot!.querySelector( + 'customize-chrome-check-mark-wrapper')!; + assertTrue(wrapper.checked); + const svg = colorElement.shadowRoot!.querySelector('svg')!; + assertStyle(svg, 'width', '46px'); + assertStyle(svg, 'height', '46px'); + const background = colorElement.shadowRoot!.querySelector('#background')!; + assertStyle(background, 'r', '25px'); + }); + + test('color can be unchecked', () => { + colorElement.checked = false; + + const wrapper = colorElement.shadowRoot!.querySelector( + 'customize-chrome-check-mark-wrapper')!; + assertFalse(wrapper.checked); + const svg = colorElement.shadowRoot!.querySelector('svg')!; + assertStyle(svg, 'width', '50px'); + assertStyle(svg, 'height', '50px'); + const background = colorElement.shadowRoot!.querySelector('#background')!; + assertStyle(background, 'r', '24px'); + }); });
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/colors_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/colors_test.ts index 16a1964..06dda2220 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/colors_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/colors_test.ts
@@ -9,11 +9,11 @@ import {ChromeColor, CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, CustomizeChromePageRemote, Theme} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js'; -import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chai_assert.js'; +import {assertDeepEquals, assertEquals, assertGE, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; -import {createTheme, installMock} from './test_support.js'; +import {assertStyle, capture, createTheme, installMock} from './test_support.js'; suite('ColorsTest', () => { let colorsElement: ColorsElement; @@ -100,4 +100,114 @@ assertEquals(1, handler.getCallCount('setForegroundColor')); assertEquals(2, handler.getArgs('setForegroundColor')[0].value); }); + + test('opens color picker', () => { + const focus = capture(colorsElement.$.colorPicker, 'focus'); + const click = capture(colorsElement.$.colorPicker, 'click'); + + colorsElement.$.customColor.click(); + + assertTrue(focus.received); + assertTrue(click.received); + }); + + test('sets custom color', () => { + colorsElement.$.colorPicker.value = '#ff0000'; + colorsElement.$.colorPicker.dispatchEvent(new Event('change')); + + const args = handler.getArgs('setForegroundColor'); + assertGE(1, args.length); + assertEquals(0xffff0000, args.at(-1).value); + }); + + test('updates custom color for theme', async () => { + const colors = { + colors: [ + {id: 1, name: 'foo', background: {value: 1}, foreground: {value: 2}}, + ], + }; + chromeColorsResolver.resolve(colors); + + // Set a custom color theme. + const customColortheme = createTheme(); + customColortheme.backgroundColor = {value: 0xffff0000}; + customColortheme.foregroundColor = {value: 0xff00ff00}; + customColortheme.colorPickerIconColor = {value: 0xff0000ff}; + callbackRouter.setTheme(customColortheme); + await callbackRouter.$.flushForTesting(); + + // Custom color circle should be updated. + assertEquals(0xffff0000, colorsElement.$.customColor.backgroundColor.value); + assertEquals(0xff00ff00, colorsElement.$.customColor.foregroundColor.value); + assertStyle( + colorsElement.$.colorPickerIcon, 'background-color', 'rgb(0, 0, 255)'); + + // Set a theme that is not a custom color theme. + const otherTheme = createTheme(); + otherTheme.backgroundColor = {value: 0xffffffff}; + otherTheme.foregroundColor = undefined; // Makes a default theme. + otherTheme.colorPickerIconColor = {value: 0xffffffff}; + callbackRouter.setTheme(otherTheme); + await callbackRouter.$.flushForTesting(); + + // Custom color circle should be not be updated. + assertEquals(0xffff0000, colorsElement.$.customColor.backgroundColor.value); + assertEquals(0xff00ff00, colorsElement.$.customColor.foregroundColor.value); + assertStyle( + colorsElement.$.colorPickerIcon, 'background-color', 'rgb(0, 0, 255)'); + }); + + test('checks selected color', async () => { + const colors = { + colors: [ + {id: 1, name: 'foo', background: {value: 1}, foreground: {value: 2}}, + {id: 2, name: 'bar', background: {value: 3}, foreground: {value: 4}}, + ], + }; + chromeColorsResolver.resolve(colors); + const theme = createTheme(); + + // Set default color. + theme.foregroundColor = undefined; + callbackRouter.setTheme(theme); + await callbackRouter.$.flushForTesting(); + + // Check default color selected. + let checkedColors = colorsElement.shadowRoot!.querySelectorAll('[checked]'); + assertEquals(1, checkedColors.length); + assertEquals(colorsElement.$.defaultColor, checkedColors[0]); + let indexedColors = + colorsElement.shadowRoot!.querySelectorAll('[tabindex="0"]'); + assertEquals(1, indexedColors.length); + assertEquals(colorsElement.$.defaultColor, indexedColors[0]); + + // Set Chrome color. + theme.foregroundColor = {value: 2}; + callbackRouter.setTheme(theme); + await callbackRouter.$.flushForTesting(); + + // Check Chrome color selected. + checkedColors = colorsElement.shadowRoot!.querySelectorAll('[checked]'); + assertEquals(1, checkedColors.length); + assertEquals('chrome-color', checkedColors[0]!.className); + assertEquals(2, (checkedColors[0]! as ColorElement).foregroundColor.value); + indexedColors = + colorsElement.shadowRoot!.querySelectorAll('[tabindex="0"]'); + assertEquals(1, indexedColors.length); + assertEquals('chrome-color', indexedColors[0]!.className); + + // Set custom color. + theme.foregroundColor = {value: 5}; + callbackRouter.setTheme(theme); + await callbackRouter.$.flushForTesting(); + + // Check custom color selected. + checkedColors = colorsElement.shadowRoot!.querySelectorAll('[checked]'); + assertEquals(1, checkedColors.length); + assertEquals(colorsElement.$.customColor, checkedColors[0]); + indexedColors = + colorsElement.shadowRoot!.querySelectorAll('[tabindex="0"]'); + assertEquals(1, indexedColors.length); + assertEquals(colorsElement.$.customColorContainer, indexedColors[0]); + }); });
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/test_support.ts b/chrome/test/data/webui/side_panel/customize_chrome/test_support.ts index dd47307..3107b072 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/test_support.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/test_support.ts
@@ -41,6 +41,7 @@ export function createBackgroundImage(url: string): BackgroundImage { return { url: {url}, + isUploadedImage: false, title: '', }; } @@ -51,5 +52,13 @@ systemDarkMode, backgroundColor: {value: 0xffff0000}, foregroundColor: undefined, + colorPickerIconColor: {value: 0xffff0000}, }; } + +export function capture( + target: HTMLElement, event: string): {received: boolean} { + const capture = {received: false}; + target.addEventListener(event, () => capture.received = true); + return capture; +}
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/theme_snapshot_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/theme_snapshot_test.ts index 3fcfa8b..3ff7543 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/theme_snapshot_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/theme_snapshot_test.ts
@@ -8,7 +8,7 @@ import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, CustomizeChromePageRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; import {ThemeSnapshotElement} from 'chrome://customize-chrome-side-panel.top-chrome/theme_snapshot.js'; -import {assertEquals} from 'chrome://webui-test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; import {$$, assertStyle, createBackgroundImage, createTheme, installMock} from './test_support.js'; @@ -52,13 +52,16 @@ // Assert. assertEquals(1, handler.getCallCount('updateTheme')); + const selector = + themeSnapshotElement.shadowRoot!.querySelector('iron-pages'); + assertTrue(!!selector); + assertEquals('customTheme', selector.selected); assertEquals( 'chrome://theme/foo', - $$<HTMLImageElement>( - themeSnapshotElement, '#themeSnapshot .image')!.src); + $$<HTMLImageElement>(themeSnapshotElement, '.theme-snapshot img')!.src); }); - test('having no theme set updates preview background color', async () => { + test('not setting a theme updates preview background color', async () => { // Arrange. createThemeSnapshotElement(); const theme = createTheme(); @@ -70,8 +73,31 @@ // Assert. assertEquals(1, handler.getCallCount('updateTheme')); + const selector = + themeSnapshotElement.shadowRoot!.querySelector('iron-pages'); + assertTrue(!!selector); + assertEquals('classicChrome', selector.selected); assertStyle( - $$(themeSnapshotElement, '#themeSnapshot .image')!, 'background-color', - 'rgb(20, 83, 154)'); + $$(themeSnapshotElement, '.theme-snapshot #classicChrome')!, + 'background-color', 'rgb(20, 83, 154)'); + }); + + test('uploading a background updates theme snapshot', async () => { + // Arrange. + createThemeSnapshotElement(); + const theme = createTheme(); + theme.backgroundImage = createBackgroundImage('chrome://theme/foo'); + theme.backgroundImage.isUploadedImage = true; + + // Act. + callbackRouterRemote.setTheme(theme); + await callbackRouterRemote.$.flushForTesting(); + + // Assert. + assertEquals(1, handler.getCallCount('updateTheme')); + const selector = + themeSnapshotElement.shadowRoot!.querySelector('iron-pages'); + assertTrue(!!selector); + assertEquals('uploadedImage', selector.selected); }); });
diff --git a/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc b/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc index 257e75b..a29f59e2 100644 --- a/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc +++ b/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc
@@ -143,22 +143,6 @@ } }); - ON_CALL(*media_router_, RegisterMediaRoutesObserver(_)) - .WillByDefault([this](MediaRoutesObserver* observer) { - media_routes_observers_.push_back(observer); - return true; - }); - - // Remove route observers as appropriate (destructing handlers will cause - // this to occur). - ON_CALL(*media_router_, UnregisterMediaRoutesObserver(_)) - .WillByDefault([this](MediaRoutesObserver* observer) { - auto it = base::ranges::find(media_routes_observers_, observer); - if (it != media_routes_observers_.end()) { - media_routes_observers_.erase(it); - } - }); - // Handler so MockMediaRouter will respond to requests to create a route. // Will construct a RouteRequestResult based on the set result code and // then call the handler's callback, which should call the page's callback. @@ -547,8 +531,9 @@ void AccessCodeCastIntegrationBrowserTest::UpdateRoutes( const std::vector<MediaRoute>& routes) { - for (MediaRoutesObserver* routes_observer : media_routes_observers_) { - routes_observer->OnRoutesUpdated(routes); + for (MediaRoutesObserver& routes_observer : + media_router_->routes_observers()) { + routes_observer.OnRoutesUpdated(routes); } }
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc index cc299e54..a5f50c3c 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -220,7 +220,7 @@ // TerminateRoute, or add pass callback to the TestProvider to run when all // routes are gone. base::RunLoop run_loop; - NoRoutesObserver no_routes_observer( + auto no_routes_observer = std::make_unique<NoRoutesObserver>( MediaRouterFactory::GetApiForBrowserContext( web_contents->GetBrowserContext()), run_loop.QuitClosure());
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java index 809ee0e..e0bf8cff7 100644 --- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java
@@ -5,6 +5,8 @@ package org.chromium.chromecast.shell; import android.content.Context; +import android.hardware.display.DisplayManager; +import android.view.Display; import org.chromium.base.ContextUtils; import org.chromium.base.Log; @@ -40,12 +42,29 @@ @CalledByNative private static CastContentWindowAndroid create(long nativeCastContentWindowAndroid, boolean enableTouchInput, boolean isRemoteControlMode, boolean turnOnScreen, - boolean keepScreenOn, String sessionId) { + boolean keepScreenOn, String sessionId, String displayId) { return new CastContentWindowAndroid(nativeCastContentWindowAndroid, - ContextUtils.getApplicationContext(), enableTouchInput, isRemoteControlMode, + getContextWithDisplay(displayId), enableTouchInput, isRemoteControlMode, turnOnScreen, keepScreenOn, sessionId); } + private static Context getContextWithDisplay(String displayId) { + Context context = ContextUtils.getApplicationContext(); + try { + int id = Integer.parseInt(displayId); + DisplayManager displayManager = context.getSystemService(DisplayManager.class); + Display display = displayManager.getDisplay(id); + if (display != null) { + return context.createDisplayContext(display); + } + } catch (NumberFormatException e) { + } + Log.i(TAG, + "Display with the given cast display id is not available, " + + "use the default display to create the web view."); + return context; + } + private CastContentWindowAndroid(long nativeCastContentWindowAndroid, final Context context, boolean enableTouchInput, boolean isRemoteControlMode, boolean turnOnScreen, boolean keepScreenOn, String sessionId) {
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java index 836cf997..16d5abd 100644 --- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java
@@ -10,14 +10,17 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.net.Uri; +import android.os.Bundle; import android.os.IBinder; import android.os.PatternMatcher; import androidx.annotation.VisibleForTesting; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Log; import org.chromium.chromecast.base.Controller; import org.chromium.content_public.browser.WebContents; +import org.chromium.ui.display.DisplayAndroidManager; /** * A layer of indirection between CastContentWindowAndroid and CastWebContents(Activity|Service). @@ -100,9 +103,11 @@ boolean isRemoteControlMode, boolean turnOnScreen) { Intent intent = CastWebContentsIntentUtils.requestStartCastActivity(context, webContents, enableTouch, isRemoteControlMode, turnOnScreen, mKeepScreenOn, mSessionId); - if (DEBUG) Log.d(TAG, "start activity by intent: " + intent); + int displayId = DisplayAndroidManager.getDefaultDisplayForContext(context).getDisplayId(); + if (DEBUG) Log.d(TAG, "start activity by intent: " + intent + " on display: " + displayId); sResumeIntent.set(intent); - context.startActivity(intent); + Bundle bundle = ApiCompatibilityUtils.createLaunchDisplayIdActivityOptions(displayId); + context.startActivity(intent, bundle); } private void sendStopWebContentEvent() {
diff --git a/chromecast/browser/android/cast_content_window_android.cc b/chromecast/browser/android/cast_content_window_android.cc index 7315c85..29efb38 100644 --- a/chromecast/browser/android/cast_content_window_android.cc +++ b/chromecast/browser/android/cast_content_window_android.cc
@@ -24,11 +24,13 @@ bool is_remote_control_mode, bool turn_on_screen, bool keep_screen_on, - const std::string& session_id) { + const std::string& session_id, + const std::string& display_id) { JNIEnv* env = base::android::AttachCurrentThread(); return Java_CastContentWindowAndroid_create( env, native_window, enable_touch_input, is_remote_control_mode, - turn_on_screen, keep_screen_on, ConvertUTF8ToJavaString(env, session_id)); + turn_on_screen, keep_screen_on, ConvertUTF8ToJavaString(env, session_id), + ConvertUTF8ToJavaString(env, display_id)); } } // namespace @@ -42,7 +44,8 @@ params_->is_remote_control_mode, params_->turn_on_screen, params_->keep_screen_on, - params_->session_id)) {} + params_->session_id, + params_->display_id)) {} CastContentWindowAndroid::~CastContentWindowAndroid() { JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java index 0d6bb44..bdc6e69 100644 --- a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java +++ b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java
@@ -10,13 +10,18 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; +import android.view.Display; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.test.core.app.ApplicationProvider; @@ -51,7 +56,11 @@ private static final String SESSION_ID = "123456789"; + private static final int DISPLAY_ID = 1; + private static final String ACTIVITY_OPTIONS_DISPLAY_ID = "android.activity.launchDisplayId"; + private @Mock WebContents mWebContents; + private @Mock Display mDisplay; private Activity mActivity; private ShadowActivity mShadowActivity; private StartParams mStartParams; @@ -62,6 +71,7 @@ @Before public void setUp() { MockitoAnnotations.initMocks(this); + when(mDisplay.getDisplayId()).thenReturn(DISPLAY_ID); mActivity = Mockito.spy(Robolectric.buildActivity(Activity.class).setup().get()); mShadowActivity = Shadows.shadowOf(mActivity); mStartParams = new StartParams(mActivity, mWebContents, APP_ID); @@ -82,6 +92,29 @@ } @Test + @Config(minSdk = VERSION_CODES.R) + public void testStartStartsWebContentsActivityWithDisplayId() { + Assume.assumeFalse(BuildConfig.DISPLAY_WEB_CONTENTS_IN_SERVICE); + + ContextWrapper context = + Mockito.spy(new ContextWrapper(ContextUtils.getApplicationContext()) { + @Override + public Display getDisplay() { + return mDisplay; + } + }); + StartParams startParams = new StartParams(context, mWebContents, APP_ID); + + CastWebContentsComponent component = + new CastWebContentsComponent(SESSION_ID, null, null, false, false, true, false); + component.start(startParams, false); + + ArgumentCaptor<Bundle> bundle = ArgumentCaptor.forClass(Bundle.class); + verify(context).startActivity(any(Intent.class), bundle.capture()); + Assert.assertEquals(bundle.getValue().getInt(ACTIVITY_OPTIONS_DISPLAY_ID), DISPLAY_ID); + } + + @Test public void testStartStartsWebContentsService() { Assume.assumeFalse(BuildConfig.DISPLAY_WEB_CONTENTS_IN_SERVICE);
diff --git a/chromecast/browser/mojom/cast_web_service.mojom b/chromecast/browser/mojom/cast_web_service.mojom index 7f002d14..90f4a64 100644 --- a/chromecast/browser/mojom/cast_web_service.mojom +++ b/chromecast/browser/mojom/cast_web_service.mojom
@@ -55,6 +55,9 @@ // Cast Application/Activity session ID. string session_id = ""; + // Cast display ID to create the web view (if available). + string display_id = ""; + // Cast Receiver SDK version of the application (if available). string sdk_version = "";
diff --git a/chromeos/ash/components/cryptohome/auth_factor_conversions.cc b/chromeos/ash/components/cryptohome/auth_factor_conversions.cc index 2add076..543543a 100644 --- a/chromeos/ash/components/cryptohome/auth_factor_conversions.cc +++ b/chromeos/ash/components/cryptohome/auth_factor_conversions.cc
@@ -10,6 +10,7 @@ #include "base/check_op.h" #include "base/logging.h" #include "base/notreached.h" +#include "base/strings/string_number_conversions.h" #include "chromeos/ash/components/dbus/cryptohome/auth_factor.pb.h" namespace cryptohome { @@ -152,7 +153,9 @@ proto_input->set_recovery_response(recovery_auth.recovery_data); } else { const auto& recovery_creation = auth_input.GetRecoveryCreationInput(); - proto_input->set_mediator_pub_key(recovery_creation.pub_key); + DCHECK( + base::HexStringToString(recovery_creation.pub_key, + proto_input->mutable_mediator_pub_key())); proto_input->set_user_gaia_id(recovery_creation.user_gaia_id); proto_input->set_device_user_id(recovery_creation.device_user_id); }
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn index 14ff114..12d04d1 100644 --- a/chromeos/crosapi/mojom/BUILD.gn +++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -106,6 +106,7 @@ "web_page_info.mojom", ] disable_variants = true + cpp_only = true public_deps = [ "//chromeos/components/remote_apps/mojom",
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index d1e7399..023bc02 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -18,6 +18,7 @@ #include "base/containers/contains.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/feature_list.h" #include "base/i18n/case_conversion.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_functions.h" @@ -499,6 +500,31 @@ return std::u16string(); } +// Detects a label declared after the `element`, which is visually positioned +// above the element (usually using CCS). Such labels often act as a +// placeholders. E.g. +// <div> +// <input> +// <span>Placeholder</span> +// </div> +std::u16string InferLabelFromOverlayingSuccessor( + const WebFormControlElement& element) { + if (!base::FeatureList::IsEnabled( + features::kAutofillSupportPoorMansPlaceholder)) { + return std::u16string(); + } + + WebNode next = element.NextSibling(); + while (!next.IsNull() && !next.IsElementNode()) + next = next.NextSibling(); + if (!next.IsNull()) { + gfx::Rect bounds = next.To<WebElement>().BoundsInWidget(); + if (!bounds.IsEmpty() && element.BoundsInWidget().Contains(bounds)) + return FindChildText(next); + } + return std::u16string(); +} + // Helper for |InferLabelForElement()| that infers a label, from // the value attribute when it is present and user has not typed in (if // element's value attribute is same as the element's value). @@ -800,6 +826,13 @@ return true; } + inferred_label = InferLabelFromOverlayingSuccessor(element); + if (IsLabelValid(inferred_label)) { + label_source = FormFieldData::LabelSource::kOverlayingLabel; + label = std::move(inferred_label); + return true; + } + // If we didn't find a placeholder, check for aria-label text. inferred_label = GetAriaLabel(element.GetDocument(), element); if (IsLabelValid(inferred_label)) {
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc index 26791bb..19952796 100644 --- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc +++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -59,6 +59,22 @@ const char16_t* expected_label; }; +// An <input> with a label placed on top of it (usually used as a placeholder +// replacement). +const char* kPoorMansPlaceholder = R"( + <style> + .fixed_position_and_size { + position: fixed; + top: 0; + left: 0; + width: 100px; + height: 20px; + } + </style> + <input id='target' class=fixed_position_and_size> + <span class=fixed_position_and_size>label</span> +)"; + void VerifyButtonTitleCache(const WebFormElement& form_target, const ButtonTitleList& expected_button_titles, const ButtonTitlesCache& actual_cache) { @@ -172,6 +188,9 @@ } TEST_F(FormAutofillUtilsTest, InferLabelForElementTest) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillSupportPoorMansPlaceholder); + static const AutofillFieldUtilCase test_cases[] = { {"DIV table test 1", R"( <div> @@ -215,6 +234,7 @@ u""}, {"Infer from next sibling", "<input id='target' type='checkbox'>hello <b>world</b>", u"hello world"}, + {"Poor man's placeholder", kPoorMansPlaceholder, u"label"}, }; for (auto test_case : test_cases) { SCOPED_TRACE(test_case.description); @@ -233,6 +253,9 @@ } TEST_F(FormAutofillUtilsTest, InferLabelSourceTest) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillSupportPoorMansPlaceholder); + struct AutofillFieldLabelSourceCase { const char* html; const FormFieldData::LabelSource label_source; @@ -263,7 +286,7 @@ FormFieldData::LabelSource::kTdTag}, {"<dl><dt>label</dt><dd><input id='target'></dd></dl>", FormFieldData::LabelSource::kDdTag}, - }; + {kPoorMansPlaceholder, FormFieldData::LabelSource::kOverlayingLabel}}; for (auto test_case : test_cases) { SCOPED_TRACE(testing::Message() << test_case.label_source);
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 24da4705..af6d86f7 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -488,6 +488,13 @@ "AutofillSkipComparingInferredLabels", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables support for artificial placeholders, implemented by placing text on +// top of the input field using CSS. +// TODO(crbug.com/1396374): Remove when launched. +BASE_FEATURE(kAutofillSupportPoorMansPlaceholder, + "AutofillSupportPoorMansPlaceholder", + base::FEATURE_DISABLED_BY_DEFAULT); + // Controls whether Autofill should search prefixes of all words/tokens when // filtering profiles, or only on prefixes of the whole string. BASE_FEATURE(kAutofillTokenPrefixMatching,
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index db665334..9c093072 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -148,6 +148,8 @@ COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillTokenPrefixMatching); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUploadThrottling); COMPONENT_EXPORT(AUTOFILL) +BASE_DECLARE_FEATURE(kAutofillSupportPoorMansPlaceholder); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUseAlternativeStateNameMap); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUseImprovedLabelDisambiguation);
diff --git a/components/autofill/core/common/mojom/autofill_types.mojom b/components/autofill/core/common/mojom/autofill_types.mojom index 46a45154..7e4368f 100644 --- a/components/autofill/core/common/mojom/autofill_types.mojom +++ b/components/autofill/core/common/mojom/autofill_types.mojom
@@ -284,18 +284,19 @@ // From which source the label is inferred. enum LabelSource { - kUnknown, // The source is unknown. - kLabelTag, - kPTag, - kDivTable, - kTdTag, - kDdTag, - kLiTag, - kPlaceHolder, - kAriaLabel, - kCombined, // Combined with various elements. - kValue, // label is the value of element. - kFor, // Derived from the "for" attribute of a label element. + kUnknown, // No label. + kLabelTag, // <label> sibling/ancestor. + kPTag, // <p> sibling. + kDivTable, // <div> ancestor. + kTdTag, // <td> sibling. + kDdTag, // <dd> sibling. + kLiTag, // <li> ancestor. + kPlaceHolder, // placeholder attribute. + kAriaLabel, // aria-label attribute. + kCombined, // Text node sibling (includes <b>, etc). + kValue, // value attribute. + kFor, // <label> for-attribute + kOverlayingLabel, // Succeeding DOM node overlaying the input. }; mojo_base.mojom.String16 label;
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn index 9bc7f19..631b786 100644 --- a/components/browser_ui/widget/android/BUILD.gn +++ b/components/browser_ui/widget/android/BUILD.gn
@@ -148,14 +148,6 @@ "java/res/anim/chip_out.xml", "java/res/anim/image_grid_enter.xml", "java/res/anim/image_tile_enter.xml", - "java/res/anim/menu_enter.xml", - "java/res/anim/menu_enter_from_bottom.xml", - "java/res/anim/menu_enter_from_bottom_left.xml", - "java/res/anim/menu_enter_from_top_left.xml", - "java/res/anim/menu_exit.xml", - "java/res/anim/menu_exit_from_bottom.xml", - "java/res/anim/menu_exit_from_bottom_left.xml", - "java/res/anim/menu_exit_from_top_left.xml", "java/res/anim/textbubble_in.xml", "java/res/anim/textbubble_out.xml", "java/res/color/chip_background_color.xml", @@ -270,11 +262,9 @@ "java/res/layout/tile_view_modern.xml", "java/res/layout/tile_view_modern_condensed.xml", "java/res/layout/title_and_description_layout.xml", - "java/res/values-ldrtl/values.xml", "java/res/values-night/colors.xml", "java/res/values-night/dimens.xml", "java/res/values-night/drawables.xml", - "java/res/values-sw600dp/dimens.xml", "java/res/values-v23/drawables.xml", "java/res/values/attrs.xml", "java/res/values/colors.xml",
diff --git a/components/browser_ui/widget/android/java/res/values-ldrtl/values.xml b/components/browser_ui/widget/android/java/res/values-ldrtl/values.xml deleted file mode 100644 index 7c7ab04..0000000 --- a/components/browser_ui/widget/android/java/res/values-ldrtl/values.xml +++ /dev/null
@@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2019 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<resources> - <!-- Menu Animation Constants --> - <item type="fraction" format="fraction" name="menu_animation_pivot_x">5%</item> - <item type="fraction" format="fraction" name="menu_start_animation_pivot_x">95%</item> -</resources>
diff --git a/components/browser_ui/widget/android/java/res/values-sw600dp/dimens.xml b/components/browser_ui/widget/android/java/res/values-sw600dp/dimens.xml deleted file mode 100644 index b469f2f1..0000000 --- a/components/browser_ui/widget/android/java/res/values-sw600dp/dimens.xml +++ /dev/null
@@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2019 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<resources> - <!-- Menu Dimensions --> - <!-- Necessary to align the menu icon with the actual button. --> - <dimen name="menu_negative_software_vertical_offset">6dp</dimen> -</resources> -
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 c8672d3b..7ab6fd8 100644 --- a/components/browser_ui/widget/android/java/res/values/dimens.xml +++ b/components/browser_ui/widget/android/java/res/values/dimens.xml
@@ -42,7 +42,6 @@ <dimen name="list_menu_width">180dp</dimen> <!-- Custom Menu dimensions --> - <dimen name="menu_negative_software_vertical_offset">0dp</dimen> <dimen name="menu_divider_padding">8dp</dimen> <dimen name="menu_padding_start">16dp</dimen>
diff --git a/components/browser_ui/widget/android/java/res/values/styles.xml b/components/browser_ui/widget/android/java/res/values/styles.xml index c11fd0f..00c37d2 100644 --- a/components/browser_ui/widget/android/java/res/values/styles.xml +++ b/components/browser_ui/widget/android/java/res/values/styles.xml
@@ -61,22 +61,10 @@ <item name="android:paddingEnd">@dimen/default_list_row_padding</item> </style> - <style name="EndIconMenuAnim"> - <item name="android:windowEnterAnimation">@anim/menu_enter</item> - <item name="android:windowExitAnimation">@anim/menu_exit</item> - </style> - <style name="EndIconMenuAnimBottom"> - <item name="android:windowEnterAnimation">@anim/menu_enter_from_bottom</item> - <item name="android:windowExitAnimation">@anim/menu_exit_from_bottom</item> - </style> - <style name="StartIconMenuAnim"> - <item name="android:windowEnterAnimation">@anim/menu_enter_from_top_left</item> - <item name="android:windowExitAnimation">@anim/menu_exit_from_top_left</item> - </style> - <style name="StartIconMenuAnimBottom"> - <item name="android:windowEnterAnimation">@anim/menu_enter_from_bottom_left</item> - <item name="android:windowExitAnimation">@anim/menu_exit_from_bottom_left</item> - </style> + <style name="EndIconMenuAnim" parent="AnchoredPopupAnimEndTop" /> + <style name="EndIconMenuAnimBottom" parent="AnchoredPopupAnimEndBottom" /> + <style name="StartIconMenuAnim" parent="AnchoredPopupAnimStartTop" /> + <style name="StartIconMenuAnimBottom" parent="AnchoredPopupAnimStartBottom" /> <!-- Modern List Item --> <style name="ListItemContainer">
diff --git a/components/browser_ui/widget/android/java/res/values/values.xml b/components/browser_ui/widget/android/java/res/values/values.xml index e80066d..ad03559 100644 --- a/components/browser_ui/widget/android/java/res/values/values.xml +++ b/components/browser_ui/widget/android/java/res/values/values.xml
@@ -6,10 +6,6 @@ --> <resources> - <!-- Menu Animation Constants --> - <item type="fraction" format="fraction" name="menu_animation_pivot_x">95%</item> - <item type="fraction" format="fraction" name="menu_start_animation_pivot_x">5%</item> - <!-- Drag-Reorderable List Item --> <!-- Used for 90% = 230/255 alpha --> <integer name="list_item_dragged_alpha">230</integer>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java index 9ffbf96..e8cea36 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java
@@ -188,6 +188,7 @@ mPopupWindow.setSmartAnchorWithMaxWidth(true); mPopupWindow.setVerticalOverlapAnchor(true); mPopupWindow.setOutsideTouchable(false); + mPopupWindow.setAnimateFromAnchor(true); // Set popup focusable so the screen reader can announce the popup properly. if (mAccessibilityUtil != null && mAccessibilityUtil.isTouchExplorationEnabled()) {
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc index 94ab0f1..c7c61df 100644 --- a/components/history_clusters/core/config.cc +++ b/components/history_clusters/core/config.cc
@@ -107,6 +107,9 @@ "JourneysPersistClustersInHistoryDbPeriodMinutes", persist_clusters_in_history_db_period_minutes); + persist_on_query = base::GetFieldTrialParamByFeatureAsBool( + internal::kPersistedClusters, "persist_on_query", persist_on_query); + max_persisted_clusters_to_fetch = base::GetFieldTrialParamByFeatureAsInt( internal::kPersistedClusters, "max_persisted_clusters_to_fetch", max_persisted_clusters_to_fetch);
diff --git a/components/history_clusters/core/config.h b/components/history_clusters/core/config.h index 42c0800..69edc4e 100644 --- a/components/history_clusters/core/config.h +++ b/components/history_clusters/core/config.h
@@ -107,6 +107,16 @@ // every hour. int persist_clusters_in_history_db_period_minutes = 60; + // No effect if `persist_clusters_in_history_db` is disabled. If disabled, + // persistence occurs on a timer (see the above 2 params). If enabled, will + // instead occur on query like refreshing the keyword cache does. This may + // help bound the number of persistence requests. If enabled, will continue to + // also be capped to at most 1 request per + // `persist_clusters_in_history_db_period_minutes`, but + // `persist_clusters_in_history_db_after_startup_delay_minutes` will be + // unused. + bool persist_on_query = false; + // Hard cap on max clusters to fetch after exhausting unclustered visits and // fetching persisted clusters for the get most recent flow. Doesn't affect // the update flow, which uses day boundaries as well as
diff --git a/components/history_clusters/core/history_clusters_service.cc b/components/history_clusters/core/history_clusters_service.cc index ba1407e2..e079b85e 100644 --- a/components/history_clusters/core/history_clusters_service.cc +++ b/components/history_clusters/core/history_clusters_service.cc
@@ -184,8 +184,13 @@ } void HistoryClustersService::RepeatedlyUpdateClusters() { - if (!GetConfig().persist_clusters_in_history_db) + // If `persist_on_query` is enabled, clusters are updated on query and not on + // a timer. + if (!GetConfig().persist_clusters_in_history_db || + GetConfig().persist_on_query) { return; + } + // Update clusters, both periodically and once after startup because: // 1) To avoid having very stale (up to 90 days) clusters for the initial // period after startup. @@ -205,8 +210,38 @@ void HistoryClustersService::UpdateClusters() { DCHECK(history_service_); + + // TODO(manukh): This logic (if task not done, if time since < period) is + // repeated for both keyword caches and here. Should probably share it in + // some kind of base task that all 3 inherit from. + if (update_clusters_task_ && !update_clusters_task_->Done()) return; + + // Make sure clusters aren't updated too frequently. If `persist_on_query` is + // false, this is already ensured by `update_clusters_period_timer_`. If + // update_clusters_task_ is null, this is the 1st request which shouldn't be + // delayed. + if (GetConfig().persist_on_query && + update_clusters_timer_.Elapsed() <= + base::Minutes( + GetConfig().persist_clusters_in_history_db_period_minutes) && + update_clusters_task_) { + return; + } + + // Using custom histogram as this occurs too infrequently to be captured by + // the built in histograms. `persist_clusters_in_history_db_period_minutes` + // ranges from 1 to 12 hours while the built in timing histograms go up to 1 + // hr. + base::UmaHistogramCustomTimes( + "History.Clusters.UpdateClusters.TimeBetweenTasks", + update_clusters_timer_.Elapsed(), base::Minutes(60), base::Hours(48), + 100); + + // Reset the timer. + update_clusters_timer_ = {}; + update_clusters_task_ = std::make_unique<HistoryClustersServiceTaskUpdateClusters>( weak_ptr_factory_.GetWeakPtr(), incomplete_visit_context_annotations_, @@ -223,6 +258,8 @@ return absl::nullopt; StartKeywordCacheRefresh(); + if (GetConfig().persist_on_query) + UpdateClusters(); // Early exit for single-character queries, even if it's an exact match. // We still want to allow for two-character exact matches like "uk". @@ -254,6 +291,8 @@ return false; StartKeywordCacheRefresh(); + if (GetConfig().persist_on_query) + UpdateClusters(); return short_url_keywords_cache_.find(url_keyword) != short_url_keywords_cache_.end() ||
diff --git a/components/history_clusters/core/history_clusters_service.h b/components/history_clusters/core/history_clusters_service.h index 96ab6d32..e40926e 100644 --- a/components/history_clusters/core/history_clusters_service.h +++ b/components/history_clusters/core/history_clusters_service.h
@@ -210,6 +210,11 @@ friend class HistoryClustersServiceTestApi; // Starts a keyword cache refresh, if necessary. + // TODO(manukh): `StartKeywordCacheRefresh()` and + // `PopulateClusterKeywordCache()` should be encapsulated into their own task + // to avoid cluttering `HistoryClusterService` with their callbacks. Similar + // to the `HistoryClustersServiceTaskGetMostRecentClusters` and + // `HistoryClustersServiceTaskUpdateClusters` tasks. void StartKeywordCacheRefresh(); // This is a callback used for the `QueryClusters()` call from @@ -281,6 +286,10 @@ // `RepeatedlyUpdateClusters()`'s comment. base::RepeatingTimer update_clusters_period_timer_; + // The time of the last `UpdateClusters()` call. Used for logging and to limit + // requests when `persist_on_query` is enabled. + base::ElapsedTimer update_clusters_timer_; + // A list of observers for this service. base::ObserverList<Observer> observers_;
diff --git a/components/keyed_service/content/browser_context_keyed_service_factory.cc b/components/keyed_service/content/browser_context_keyed_service_factory.cc index 417ff7d..b2d52be 100644 --- a/components/keyed_service/content/browser_context_keyed_service_factory.cc +++ b/components/keyed_service/content/browser_context_keyed_service_factory.cc
@@ -87,12 +87,24 @@ } std::unique_ptr<KeyedService> +BrowserContextKeyedServiceFactory::BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const { + // TODO(tsepez): fully deprecate the form below. + return base::WrapUnique(BuildServiceInstanceFor(context)); +} + +KeyedService* BrowserContextKeyedServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + // Stub to prevent converted sub-classes from needing to implement this form. + NOTREACHED(); + return nullptr; +} + +std::unique_ptr<KeyedService> BrowserContextKeyedServiceFactory::BuildServiceInstanceFor( void* context) const { - // TODO(isherman): The wrapped BuildServiceInstanceFor() should return a - // scoped_ptr as well. - return base::WrapUnique( - BuildServiceInstanceFor(static_cast<content::BrowserContext*>(context))); + return BuildServiceInstanceForBrowserContext( + static_cast<content::BrowserContext*>(context)); } bool BrowserContextKeyedServiceFactory::IsOffTheRecord(void* context) const {
diff --git a/components/keyed_service/content/browser_context_keyed_service_factory.h b/components/keyed_service/content/browser_context_keyed_service_factory.h index f546244..dda3f0c 100644 --- a/components/keyed_service/content/browser_context_keyed_service_factory.h +++ b/components/keyed_service/content/browser_context_keyed_service_factory.h
@@ -141,8 +141,15 @@ // // This should not return nullptr; instead, return nullptr from // `GetBrowserContextToUse()`. + // + // Sub-classes implement one of these two forms: + virtual std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const; + + // DEPRECATED: allows incremental conversion to the unique_ptr<> form + // above. New code should not be using this form. virtual KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const = 0; + content::BrowserContext* context) const; // A helper object actually listens for notifications about BrowserContext // destruction, calculates the order in which things are destroyed and then
diff --git a/components/management_strings.grdp b/components/management_strings.grdp index 7ede678..153625b6 100644 --- a/components/management_strings.grdp +++ b/components/management_strings.grdp
@@ -61,20 +61,23 @@ <if expr="not chromeos_ash"> <if expr="_google_chrome"> <message name="IDS_MANAGEMENT_BROWSER_NOTICE" desc="Message shown when the (Google-branded) Chrome browser is managed, it indicates what the administrator can do on the browser."> - Your administrator can change your browser setup remotely. Activity on this device may also be managed outside of Chrome. <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>Learn more<ph name="END_LINK"></a></ph> + Your administrator can change your browser setup remotely. Activity on this device may also be managed outside of Chrome. <ph name="BEGIN_LINK"><a target="_blank" href="$1" aria-label="$2"></ph>Learn more<ph name="END_LINK"></a></ph> </message> <message name="IDS_MANAGEMENT_NOT_MANAGED_NOTICE" desc="Message indicating that the (Google-branded) Chrome browser is not managed"> - This browser is not managed by a company or other organization. Activity on this device may be managed outside of Chrome. <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>Learn more<ph name="END_LINK"></a></ph> + This browser is not managed by a company or other organization. Activity on this device may be managed outside of Chrome. <ph name="BEGIN_LINK"><a target="_blank" href="$1" aria-label="$2"></ph>Learn more<ph name="END_LINK"></a></ph> </message> </if> <if expr="not _google_chrome"> <message name="IDS_MANAGEMENT_BROWSER_NOTICE" desc="Message shown when the (non-Google-branded) Chromium browser is managed, it indicates what the administrator can do on the browser."> - Your administrator can change your browser setup remotely. Activity on this device may also be managed outside of Chromium. <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>Learn more<ph name="END_LINK"></a></ph> + Your administrator can change your browser setup remotely. Activity on this device may also be managed outside of Chromium. <ph name="BEGIN_LINK"><a target="_blank" href="$1" aria-label="$2"></ph>Learn more<ph name="END_LINK"></a></ph> </message> <message name="IDS_MANAGEMENT_NOT_MANAGED_NOTICE" desc="Message indicating that the (non-Google-branded) Chromium browser is not managed"> - This browser is not managed by a company or other organization. Activity on this device may be managed outside of Chromium. <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>Learn more<ph name="END_LINK"></a></ph> + This browser is not managed by a company or other organization. Activity on this device may be managed outside of Chromium. <ph name="BEGIN_LINK"><a target="_blank" href="$1" aria-label="$2"></ph>Learn more<ph name="END_LINK"></a></ph> </message> </if> + <message name="IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT" desc="Accessibility text for a 'Learn more' link that links to a help article about how the browser is managed."> + Learn more about how your browser is managed + </message> </if> </if>
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_BROWSER_NOTICE.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_BROWSER_NOTICE.png.sha1 index 2ea1997..16e39345 100644 --- a/components/management_strings_grdp/IDS_MANAGEMENT_BROWSER_NOTICE.png.sha1 +++ b/components/management_strings_grdp/IDS_MANAGEMENT_BROWSER_NOTICE.png.sha1
@@ -1 +1 @@ -ad0a9ae496e2d8a74660cd371bcc9acc79b475a2 \ No newline at end of file +4a860cd9622b611c3b76432b7d4b84ed1eeb0460 \ No newline at end of file
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT.png.sha1 new file mode 100644 index 0000000..4ecf846 --- /dev/null +++ b/components/management_strings_grdp/IDS_MANAGEMENT_LEARN_MORE_ACCCESSIBILITY_TEXT.png.sha1
@@ -0,0 +1 @@ +6734674614d77faf8b2ac866ca1da0c22d06a495 \ No newline at end of file
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_NOT_MANAGED_NOTICE.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_NOT_MANAGED_NOTICE.png.sha1 index 20ed25a..84b7d02 100644 --- a/components/management_strings_grdp/IDS_MANAGEMENT_NOT_MANAGED_NOTICE.png.sha1 +++ b/components/management_strings_grdp/IDS_MANAGEMENT_NOT_MANAGED_NOTICE.png.sha1
@@ -1 +1 @@ -1a56c5e54aeb312486f7f3b4564cc6f64525aac3 \ No newline at end of file +17731ccf8561565d284cbd30a16f7d9a88a5c8f5 \ No newline at end of file
diff --git a/components/media_router/browser/android/media_router_android.h b/components/media_router/browser/android/media_router_android.h index c53880a..69186a6 100644 --- a/components/media_router/browser/android/media_router_android.h +++ b/components/media_router/browser/android/media_router_android.h
@@ -168,7 +168,7 @@ std::unique_ptr<MediaSinksObserverList>>; MediaSinkObservers sinks_observers_; - base::ObserverList<MediaRoutesObserver>::Unchecked routes_observers_; + base::ObserverList<MediaRoutesObserver> routes_observers_; struct MediaRouteRequest { MediaRouteRequest(const MediaSource& source,
diff --git a/components/media_router/browser/media_routes_observer.cc b/components/media_router/browser/media_routes_observer.cc index b94975c..0b68da1 100644 --- a/components/media_router/browser/media_routes_observer.cc +++ b/components/media_router/browser/media_routes_observer.cc
@@ -6,16 +6,20 @@ #include "base/check.h" #include "components/media_router/browser/media_router.h" +#include "content/public/browser/browser_thread.h" namespace media_router { MediaRoutesObserver::MediaRoutesObserver(MediaRouter* router) : router_(router) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(router_); router_->RegisterMediaRoutesObserver(this); } MediaRoutesObserver::~MediaRoutesObserver() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + CHECK(IsInObserverList()); router_->UnregisterMediaRoutesObserver(this); }
diff --git a/components/media_router/browser/media_routes_observer.h b/components/media_router/browser/media_routes_observer.h index c7fb0cc..251fbb8 100644 --- a/components/media_router/browser/media_routes_observer.h +++ b/components/media_router/browser/media_routes_observer.h
@@ -8,6 +8,8 @@ #include <vector> #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list_types.h" #include "components/media_router/common/media_route.h" namespace media_router { @@ -20,14 +22,17 @@ // |OnRoutesUpdated| that match the route IDs contained in the // |joinable_route_ids| can be connected joined by the source. If no // |source_id| is supplied, then the idea of joinable routes no longer applies. -class MediaRoutesObserver { +class MediaRoutesObserver : public base::CheckedObserver, + public base::SupportsWeakPtr<MediaRoutesObserver> { public: explicit MediaRoutesObserver(MediaRouter* router); MediaRoutesObserver(const MediaRoutesObserver&) = delete; MediaRoutesObserver& operator=(const MediaRoutesObserver&) = delete; - virtual ~MediaRoutesObserver(); + // NOTE: must be destroyed on the Browser UI thread to avoid threading issues + // with access. + ~MediaRoutesObserver() override; // Invoked when the list of routes and their associated sinks have been // updated.
diff --git a/components/media_router/browser/test/mock_media_router.h b/components/media_router/browser/test/mock_media_router.h index 6235c7b..ff2f589 100644 --- a/components/media_router/browser/test/mock_media_router.h +++ b/components/media_router/browser/test/mock_media_router.h
@@ -10,9 +10,11 @@ #include <string> #include <vector> +#include "base/observer_list.h" #include "build/build_config.h" #include "components/media_router/browser/logger_impl.h" #include "components/media_router/browser/media_router_base.h" +#include "components/media_router/browser/media_routes_observer.h" #include "components/media_router/common/media_route.h" #include "components/media_router/common/media_sink.h" #include "components/media_router/common/media_source.h" @@ -127,16 +129,25 @@ MOCK_METHOD1(RegisterMediaSinksObserver, bool(MediaSinksObserver* observer)); MOCK_METHOD1(UnregisterMediaSinksObserver, void(MediaSinksObserver* observer)); - MOCK_METHOD1(RegisterMediaRoutesObserver, - void(MediaRoutesObserver* observer)); - MOCK_METHOD1(UnregisterMediaRoutesObserver, - void(MediaRoutesObserver* observer)); + void RegisterMediaRoutesObserver(MediaRoutesObserver* observer) override { + routes_observers_.AddObserver(observer); + } + void UnregisterMediaRoutesObserver(MediaRoutesObserver* observer) override { + routes_observers_.RemoveObserver(observer); + } MOCK_METHOD1(RegisterPresentationConnectionMessageObserver, void(PresentationConnectionMessageObserver* observer)); MOCK_METHOD1(UnregisterPresentationConnectionMessageObserver, void(PresentationConnectionMessageObserver* observer)); MOCK_METHOD0(GetMediaSinkServiceStatus, std::string()); + base::ObserverList<MediaRoutesObserver>& routes_observers() { + return routes_observers_; + } + + protected: + base::ObserverList<MediaRoutesObserver> routes_observers_; + private: #if !BUILDFLAG(IS_ANDROID) IssueManager issue_manager_;
diff --git a/components/messages/android/internal/java/res/layout/message_banner_view.xml b/components/messages/android/internal/java/res/layout/message_banner_view.xml index ef8b723d..a2824757 100644 --- a/components/messages/android/internal/java/res/layout/message_banner_view.xml +++ b/components/messages/android/internal/java/res/layout/message_banner_view.xml
@@ -71,7 +71,7 @@ android:visibility="gone" android:contentDescription="@null" android:background="?actionBarItemBackground" - android:layout_width="@dimen/message_banner_button_width" + android:layout_width="@dimen/min_touch_target_size" android:layout_height="@dimen/min_touch_target_size" /> <ImageView
diff --git a/components/messages/android/internal/java/res/values/dimens.xml b/components/messages/android/internal/java/res/values/dimens.xml index 337256a..9cd54a1 100644 --- a/components/messages/android/internal/java/res/values/dimens.xml +++ b/components/messages/android/internal/java/res/values/dimens.xml
@@ -14,8 +14,6 @@ <dimen name="message_banner_elevation">6dp</dimen> <!-- For messages below the front messages, used in stacking animation. --> <dimen name="message_banner_back_elevation">5dp</dimen> - <!-- Min width to ensure the min touchable size. --> - <dimen name="message_banner_button_width">44dp</dimen> <dimen name="message_primary_button_max_width">100dp</dimen> <dimen name="message_icon_margin">12dp</dimen> <dimen name="message_icon_size">24dp</dimen>
diff --git a/components/omnibox/browser/omnibox_prefs.cc b/components/omnibox/browser/omnibox_prefs.cc index 9c93f02..efe11e3 100644 --- a/components/omnibox/browser/omnibox_prefs.cc +++ b/components/omnibox/browser/omnibox_prefs.cc
@@ -83,8 +83,8 @@ SuggestionGroupVisibility visibility) { DCHECK(prefs); - DictionaryPrefUpdate update(prefs, kSuggestionGroupVisibility); - update->SetIntKey(base::NumberToString(suggestion_group_id), visibility); + ScopedDictPrefUpdate update(prefs, kSuggestionGroupVisibility); + update->Set(base::NumberToString(suggestion_group_id), visibility); base::SparseHistogram::FactoryGet( visibility == SuggestionGroupVisibility::SHOWN
diff --git a/components/payments/content/BUILD.gn b/components/payments/content/BUILD.gn index 2b3eeae..0846734 100644 --- a/components/payments/content/BUILD.gn +++ b/components/payments/content/BUILD.gn
@@ -88,7 +88,7 @@ ] if (is_chromeos_ash) { - sources += [ "android_app_communication_chrome_os.cc" ] + sources += [ "android_app_communication_ash.cc" ] deps += [ "//ash/components/arc",
diff --git a/components/payments/content/android_app_communication_chrome_os.cc b/components/payments/content/android_app_communication_ash.cc similarity index 96% rename from components/payments/content/android_app_communication_chrome_os.cc rename to components/payments/content/android_app_communication_ash.cc index 3a8d4da..2710288d 100644 --- a/components/payments/content/android_app_communication_chrome_os.cc +++ b/components/payments/content/android_app_communication_ash.cc
@@ -155,8 +155,9 @@ // at this time. auto supported_method_iterator = stringified_method_data.find(methods::kGooglePlayBilling); - if (supported_method_iterator == stringified_method_data.end()) + if (supported_method_iterator == stringified_method_data.end()) { return nullptr; + } // Chrome OS TWA supports only one set of payment method specific data. if (supported_method_iterator->second.size() > 1) { @@ -193,20 +194,19 @@ } // Invokes the TWA Android app in Android subsystem on Chrome OS. -class AndroidAppCommunicationChromeOS : public AndroidAppCommunication { +class AndroidAppCommunicationAsh : public AndroidAppCommunication { public: - explicit AndroidAppCommunicationChromeOS(content::BrowserContext* context) + explicit AndroidAppCommunicationAsh(content::BrowserContext* context) : AndroidAppCommunication(context), get_app_service_(base::BindRepeating( &arc::ArcPaymentAppBridge::GetForBrowserContext)) {} - ~AndroidAppCommunicationChromeOS() override = default; + ~AndroidAppCommunicationAsh() override = default; // Disallow copy and assign. - AndroidAppCommunicationChromeOS( - const AndroidAppCommunicationChromeOS& other) = delete; - AndroidAppCommunicationChromeOS& operator=( - const AndroidAppCommunicationChromeOS& other) = delete; + AndroidAppCommunicationAsh(const AndroidAppCommunicationAsh& other) = delete; + AndroidAppCommunicationAsh& operator=( + const AndroidAppCommunicationAsh& other) = delete; // AndroidAppCommunication implementation: void GetAppDescriptions(const std::string& twa_package_name, @@ -371,7 +371,7 @@ // static std::unique_ptr<AndroidAppCommunication> AndroidAppCommunication::Create( content::BrowserContext* context) { - return std::make_unique<AndroidAppCommunicationChromeOS>(context); + return std::make_unique<AndroidAppCommunicationAsh>(context); } } // namespace payments
diff --git a/components/policy/resources/templates/policies.yaml b/components/policy/resources/templates/policies.yaml index 68770da1..ca758916 100644 --- a/components/policy/resources/templates/policies.yaml +++ b/components/policy/resources/templates/policies.yaml
@@ -1043,6 +1043,7 @@ 1042: ShowCastSessionsStartedByOtherDevices 1043: CloudAPAuthEnabled 1044: UsbDetectorNotificationEnabled + 1045: LacrosSelection atomic_groups: 1: Homepage 2: RemoteAccess
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/LacrosSelection.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/LacrosSelection.yaml new file mode 100644 index 0000000..0850325 --- /dev/null +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/LacrosSelection.yaml
@@ -0,0 +1,66 @@ +caption: Select <ph name="LACROS_NAME">Lacros</ph> browser binary +default: user_choice +default_for_enterprise_users: rootfs +desc: |- + This setting configures which <ph name="LACROS_NAME">Lacros</ph> browser to use. + + If the policy is set to <ph name="LACROS_SELECTION_USER_CHOICE_VALUE">user_choice</ph>, + the user can decide which <ph name="LACROS_NAME">Lacros</ph> browser to load: binary from + <ph name="LACROS_ROOTFS_NAME">rootfs</ph> or <ph name="LACROS_STATEFUL_NAME">stateful</ph> partition. + If the user has not set any preference, the binary with the newest version will be chosen. + + If the policy is set to <ph name="LACROS_SELECTION_ROOTFS_VALUE">rootfs</ph>, + always load <ph name="LACROS_ROOTFS_NAME">rootfs</ph> binary of + <ph name="LACROS_NAME">Lacros</ph> browser. + + If the policy is set to <ph name="LACROS_SELECTION_STATEFUL_VALUE">stateful</ph>, + always load <ph name="LACROS_STATEFUL_NAME">stateful</ph> binary of + <ph name="LACROS_NAME">Lacros</ph> browser. + Using this value may cause unexpected behavior if the <ph name="LACROS_STATEFUL_NAME">stateful</ph> + browser version becomes older than the <ph name="PRODUCT_OS_NAME">$2<ex>Google ChromeOS</ex></ph> version. + This case is not supported and is not guaranteed to work correctly. + + If the policy is unset, the default is <ph name="LACROS_SELECTION_ROOTFS_VALUE">rootfs</ph> for enterprise-managed users and + <ph name="LACROS_SELECTION_USER_CHOICE_VALUE">user_choice</ph> for non-managed users. + + Note that changing the policy's value may cause + <ph name="LACROS_NAME">Lacros</ph> browser's data loss if the browser's + version it changes to is older than the current one. For example, if the + policy changes from <ph name="LACROS_SELECTION_STATEFUL_VALUE">stateful</ph> + to <ph name="LACROS_SELECTION_ROOTFS_VALUE">rootfs</ph>, and the first one was + updated. Or if <ph name="PRODUCT_OS_NAME">$2<ex>Google ChromeOS</ex></ph> was + updated together with <ph name="LACROS_ROOTFS_NAME">rootfs</ph> + <ph name="LACROS_NAME">Lacros</ph> browser, and + <ph name="LACROS_STATEFUL_NAME">stateful</ph> has not been updated yet. + In such scenarios the correct data migration is not guaranteed. + + Using <ph name="LACROS_SELECTION_USER_CHOICE_VALUE">user_choice</ph> or <ph name="LACROS_SELECTION_ROOTFS_VALUE">rootfs</ph> + is a safe option. Switching from <ph name="LACROS_SELECTION_ROOTFS_VALUE">rootfs</ph> to <ph name="LACROS_SELECTION_USER_CHOICE_VALUE">user_choice</ph> + is safe as well. + +example_value: stateful +features: + dynamic_refresh: false + per_profile: false +items: +- caption: Allow users to select <ph name="LACROS_NAME">Lacros</ph> browser binary + name: user_choice + value: user_choice +- caption: Always load <ph name="LACROS_ROOTFS_NAME">rootfs</ph> <ph name="LACROS_NAME">Lacros</ph> browser + name: rootfs + value: rootfs +- caption: Always load <ph name="LACROS_STATEFUL_NAME">stateful</ph> <ph name="LACROS_NAME">Lacros</ph> browser + name: stateful + value: stateful +owners: +- asumaneev@google.com +schema: + enum: + - user_choice + - rootfs + - stateful + type: string +supported_on: +- chrome_os:110- +tags: [] +type: string-enum
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp index d189d8e..f4c2dc75 100644 --- a/components/policy_strings.grdp +++ b/components/policy_strings.grdp
@@ -326,6 +326,9 @@ <message name="IDS_POLICY_DEPENDENCY_ERROR" desc="The text displayed in the status column when a policy is ignored as another policies is not set properly."> Ignored because <ph name="POLICY_NAME">$1<ex>CloudReportingEnabled</ex></ph> is not set to <ph name="VALUE">$2<ex>Enabled</ex></ph>. </message> + <message name="IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE" desc="The text displayed in the status column when a policy is ignored as another policies is not set at all."> + Ignored because <ph name="POLICY_NAME">$1<ex>CloudReportingEnabled</ex></ph> is not set. + </message> <message name="IDS_POLICY_USER_IS_NOT_AFFILIATED_ERROR" desc="The text displayed in the status column when a user cloud policy is ignored due to user is not affiliated to the machine management."> Ignored because user is not affiliated to the machine management or the machine is not managed. </message>
diff --git a/components/policy_strings_grdp/IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE.png.sha1 b/components/policy_strings_grdp/IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE.png.sha1 new file mode 100644 index 0000000..face0ce --- /dev/null +++ b/components/policy_strings_grdp/IDS_POLICY_DEPENDENCY_ERROR_ANY_VALUE.png.sha1
@@ -0,0 +1 @@ +6e7315f3cbbe1df993996f5128e7b2e3c01d2b71 \ No newline at end of file
diff --git a/components/remote_cocoa/app_shim/immersive_mode_controller.h b/components/remote_cocoa/app_shim/immersive_mode_controller.h index 940775a1..299777e 100644 --- a/components/remote_cocoa/app_shim/immersive_mode_controller.h +++ b/components/remote_cocoa/app_shim/immersive_mode_controller.h
@@ -59,7 +59,8 @@ void RevealUnlock(); int reveal_lock_count() { return reveal_lock_count_; } - NSWindow* overlay_widget() { return overlay_widget_; } + NSWindow* browser_window() { return browser_window_; } + NSWindow* overlay_window() { return overlay_window_; } private: // Pin or unpin the titlebar. @@ -73,8 +74,8 @@ bool enabled_ = false; - NSWindow* const browser_widget_; - NSWindow* const overlay_widget_; + NSWindow* const browser_window_; + NSWindow* const overlay_window_; // A controller for top chrome. base::scoped_nsobject<ImmersiveModeTitlebarViewController> @@ -127,13 +128,12 @@ // // This class will keep the position of the overlay window in sync with its // original content (top chrome). -REMOTE_COCOA_APP_SHIM_EXPORT @interface ImmersiveModeTitlebarObserver - : NSObject { - NSWindow* _overlay_window; - NSView* _overlay_view; -} -- (instancetype)initWithOverlayWindow:(NSWindow*)overlay_window - overlayView:(NSView*)overlay_view; +REMOTE_COCOA_APP_SHIM_EXPORT @interface ImmersiveModeTitlebarObserver : NSObject + +- (instancetype)initWithController: + (base::WeakPtr<remote_cocoa::ImmersiveModeController>) + controller + overlayView:(NSView*)overlay_view; @end #endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_CONTROLLER_H_
diff --git a/components/remote_cocoa/app_shim/immersive_mode_controller.mm b/components/remote_cocoa/app_shim/immersive_mode_controller.mm index d9cf7a8..2f17d51 100644 --- a/components/remote_cocoa/app_shim/immersive_mode_controller.mm +++ b/components/remote_cocoa/app_shim/immersive_mode_controller.mm
@@ -4,6 +4,7 @@ #include "components/remote_cocoa/app_shim/immersive_mode_controller.h" +#include "base/auto_reset.h" #include "base/check.h" #include "base/mac/foundation_util.h" #include "base/mac/scoped_block.h" @@ -38,13 +39,22 @@ } // namespace +@interface ImmersiveModeTitlebarObserver () { + base::WeakPtr<remote_cocoa::ImmersiveModeController> _controller; + NSView* _overlay_view; + BOOL _barrier; +} +@end + @implementation ImmersiveModeTitlebarObserver -- (instancetype)initWithOverlayWindow:(NSWindow*)overlay_window - overlayView:(NSView*)overlay_view { +- (instancetype)initWithController: + (base::WeakPtr<remote_cocoa::ImmersiveModeController>) + controller + overlayView:(NSView*)overlay_view { self = [super init]; if (self) { - _overlay_window = overlay_window; + _controller = std::move(controller); _overlay_view = overlay_view; } return self; @@ -80,9 +90,29 @@ if (_overlay_view.visibleRect.size.height != _overlay_view.frame.size.height) { point_on_screen.y = -_overlay_view.frame.size.height; + } else { + // If there are sub-windows and the titlebar is fully visible (a y origin of + // 0), pin the titlebar. This will prevent the titlebar from autohiding and + // causing the sub-windows from moving up when the mouse leaves top chrome. + NSRect frame = [change[@"new"] rectValue]; + if (!_barrier && frame.origin.y == 0 && + _controller->titlebar_lock_count() > 0) { + // Add a barrier to prevent re-entry, which is a byproduct of + // TitlebarLock() and TitlebarUnlock(). + base::AutoReset<BOOL> set_barrier(&_barrier, YES); + // This lock / unlock scheme is to force the titlebar to be pinned in + // place, which can only be done when the titlebar is fully visible. + // Existing sub-windows hold a lock, however since the titlebar isn't + // fully revealed until this point the existing locks don't actually pin + // the titlebar. The existing locks are still important for knowing when + // to unpin the titlebar. When all outstanding locks are released the + // titlebar be unpinned. + _controller->TitlebarLock(); + _controller->TitlebarUnlock(); + } } - [_overlay_window setFrameOrigin:point_on_screen]; + [_controller->overlay_window() setFrameOrigin:point_on_screen]; } @end @@ -284,8 +314,8 @@ ImmersiveModeController::ImmersiveModeController(NSWindow* browser_widget, NSWindow* overlay_widget, base::OnceClosure callback) - : browser_widget_(browser_widget), - overlay_widget_(overlay_widget), + : browser_window_(browser_widget), + overlay_window_(overlay_widget), weak_ptr_factory_(this) { immersive_mode_window_observer_.reset([[ImmersiveModeWindowObserver alloc] initWithController:weak_ptr_factory_.GetWeakPtr()]); @@ -295,20 +325,20 @@ // bit. We do not want a separator. Pre-macOS 11 there is no titlebar // separator. if (@available(macOS 11.0, *)) { - browser_widget_.titlebarSeparatorStyle = NSTitlebarSeparatorStyleNone; + browser_window_.titlebarSeparatorStyle = NSTitlebarSeparatorStyleNone; } // Create a new NSTitlebarAccessoryViewController that will host the // overlay_view_. immersive_mode_titlebar_view_controller_.reset( [[ImmersiveModeTitlebarViewController alloc] - initWithOverlayWindow:overlay_widget_ + initWithOverlayWindow:overlay_window_ viewWillAppearCallback:std::move(callback)]); // Create a NSWindow delegate that will be used to map the AppKit created // NSWindow to the overlay view widget's NSWindow. immersive_mode_mapper_.reset([[ImmersiveModeMapper alloc] init]); - immersive_mode_mapper_.get().originalHostingWindow = overlay_widget_; + immersive_mode_mapper_.get().originalHostingWindow = overlay_window_; immersive_mode_titlebar_view_controller_.get().view = [[ImmersiveModeView alloc] initWithImmersiveModeDelegate:immersive_mode_mapper_.get()]; @@ -317,7 +347,7 @@ // view will be re-parented into the AppKit created NSWindow. BridgedContentView* overlay_content_view = base::mac::ObjCCastStrict<BridgedContentView>( - overlay_widget_.contentView); + overlay_window_.contentView); [overlay_content_view retain]; [overlay_content_view removeFromSuperview]; @@ -326,15 +356,15 @@ // window. ImmersiveModeTitlebarObserver* titlebar_observer = [[[ImmersiveModeTitlebarObserver alloc] - initWithOverlayWindow:overlay_widget_ - overlayView:overlay_content_view] autorelease]; + initWithController:weak_ptr_factory_.GetWeakPtr() + overlayView:overlay_content_view] autorelease]; [immersive_mode_titlebar_view_controller_ setTitlebarObserver:titlebar_observer]; // The original content view (top chrome) has been moved to the AppKit // created NSWindow. Create a new content view but reuse the original bridge // so that mouse drags are handled. - overlay_widget_.contentView = + overlay_window_.contentView = [[[BridgedContentView alloc] initWithBridge:overlay_content_view.bridge bounds:gfx::Rect()] autorelease]; @@ -350,6 +380,9 @@ [[NSTitlebarAccessoryViewController alloc] init]); thin_titlebar_view_controller_.get().view = [[[NSView alloc] init] autorelease]; + thin_titlebar_view_controller_.get().view.wantsLayer = YES; + thin_titlebar_view_controller_.get().view.layer.backgroundColor = + NSColor.blackColor.CGColor; thin_titlebar_view_controller_.get().layoutAttribute = NSLayoutAttributeBottom; thin_titlebar_view_controller_.get().fullScreenMinHeight = @@ -358,7 +391,7 @@ // Move sub-widgets from the browser widget to the overlay widget so that // they are rendered above the toolbar. ObserveOverlayChildWindows(); - ReparentChildWindows(browser_widget_, overlay_widget_); + ReparentChildWindows(browser_window_, overlay_window_); } ImmersiveModeController::~ImmersiveModeController() { @@ -370,25 +403,25 @@ NSView* overlay_content_view = immersive_mode_titlebar_view_controller_.get().view.subviews.firstObject; [overlay_content_view removeFromSuperview]; - overlay_widget_.contentView = overlay_content_view; + overlay_window_.contentView = overlay_content_view; [immersive_mode_titlebar_view_controller_ removeFromParentViewController]; [immersive_mode_titlebar_view_controller_.get().view release]; immersive_mode_titlebar_view_controller_.reset(); - browser_widget_.styleMask |= NSWindowStyleMaskFullSizeContentView; + browser_window_.styleMask |= NSWindowStyleMaskFullSizeContentView; if (@available(macOS 11.0, *)) { - browser_widget_.titlebarSeparatorStyle = NSTitlebarSeparatorStyleAutomatic; + browser_window_.titlebarSeparatorStyle = NSTitlebarSeparatorStyleAutomatic; } // Move sub-widgets back to the browser widget. - ReparentChildWindows(overlay_widget_, browser_widget_); + ReparentChildWindows(overlay_window_, browser_window_); } void ImmersiveModeController::Enable() { DCHECK(!enabled_); enabled_ = true; - [browser_widget_ addTitlebarAccessoryViewController: + [browser_window_ addTitlebarAccessoryViewController: immersive_mode_titlebar_view_controller_]; - [browser_widget_ + [browser_window_ addTitlebarAccessoryViewController:thin_titlebar_view_controller_]; NSRect frame = thin_titlebar_view_controller_.get().view.frame; frame.size.height = kThinControllerHeight; @@ -422,7 +455,7 @@ immersive_mode_titlebar_view_controller_.get().fullScreenMinHeight = immersive_mode_titlebar_view_controller_.get().view.frame.size.height; thin_titlebar_view_controller_.get().hidden = YES; - browser_widget_.styleMask &= ~NSWindowStyleMaskFullSizeContentView; + browser_window_.styleMask &= ~NSWindowStyleMaskFullSizeContentView; // Toggling the controller will allow the content view to resize below Top // Chrome. @@ -438,7 +471,7 @@ thin_titlebar_view_controller_.get().hidden = NO; immersive_mode_titlebar_view_controller_.get().fullScreenMinHeight = 0; - browser_widget_.styleMask |= NSWindowStyleMaskFullSizeContentView; + browser_window_.styleMask |= NSWindowStyleMaskFullSizeContentView; break; case mojom::ToolbarVisibilityStyle::kNone: thin_titlebar_view_controller_.get().hidden = YES; @@ -457,8 +490,15 @@ // will reveal and auto-hide itself based on mouse movement (controlled by // AppKit). void ImmersiveModeController::SetTitlebarPinned(bool pinned) { - // Remove the current, if any, clear controller from the window. - [clear_titlebar_view_controller_.get() removeFromParentViewController]; + // Remove current, if any, clear controllers from the window. For some reason + // -removeFromParentViewController does not always remove the controller. + // Attempt to remove the current and any stale controllers. + for (NSTitlebarAccessoryViewController* c in browser_window_ + .titlebarAccessoryViewControllers) { + if ([c isKindOfClass:[ClearTitlebarViewController class]]) { + [c removeFromParentViewController]; + } + } if (!pinned) { clear_titlebar_view_controller_.reset(); @@ -466,13 +506,13 @@ } clear_titlebar_view_controller_.reset([[ClearTitlebarViewController alloc] - initWithHeight:browser_widget_.contentView.frame.size.height - + initWithHeight:browser_window_.contentView.frame.size.height - kThinControllerHeight]); clear_titlebar_view_controller_.get().view = [[[NSView alloc] init] autorelease]; clear_titlebar_view_controller_.get().layoutAttribute = NSLayoutAttributeBottom; - [browser_widget_ + [browser_window_ addTitlebarAccessoryViewController:clear_titlebar_view_controller_]; } @@ -486,7 +526,7 @@ context:nullptr]; }; NativeWidgetMacNSWindow* overlay_window = - base::mac::ObjCCastStrict<NativeWidgetMacNSWindow>(overlay_widget_); + base::mac::ObjCCastStrict<NativeWidgetMacNSWindow>(overlay_window_); overlay_window.childWindowAddedHandler = ^(NSWindow* child) { // Ignore non-visible children. if (!child.visible) {
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm index 5085d15..fd71a76d 100644 --- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm +++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -1301,7 +1301,7 @@ // break cross-display fullscreen transitions by losing focus of the // transitioning window (crbug.com/1338659) or changing the z-order of // windows on the previous space. Making the window key here seems to - // alleviate those apparent defects (crbug.com/1392542). + // alleviate those apparent defects (crbug.com/1392542). if (is_key_window) [window_ makeKeyAndOrderFront:nil]; } @@ -1591,7 +1591,7 @@ if (child_window.parentWindow == window) continue; if (immersive_mode_controller_ && - immersive_mode_controller_->overlay_widget() == child_window) { + immersive_mode_controller_->overlay_window() == child_window) { continue; } [window addChildWindow:child_window ordered:NSWindowAbove];
diff --git a/components/reporting/storage/storage_queue.cc b/components/reporting/storage/storage_queue.cc index 9b0550b7..8f0a9d9 100644 --- a/components/reporting/storage/storage_queue.cc +++ b/components/reporting/storage/storage_queue.cc
@@ -1529,6 +1529,14 @@ ScopedReservation scoped_reservation( wrapped_record.ByteSizeLong(), storage_queue_->options().memory_resource()); + // Inject "memory unavailable" failure, if requested. + if (storage_queue_->test_injection_handler_ && + !storage_queue_->test_injection_handler_ + .Run(test::StorageQueueOperationKind::kWrappedRecordLowMemory, + storage_queue_->next_sequencing_id_) + .ok()) { + scoped_reservation.Reduce(0); + } if (!scoped_reservation.reserved()) { Schedule(&ReadContext::Response, base::Unretained(this), Status(error::RESOURCE_EXHAUSTED, @@ -1604,6 +1612,14 @@ ScopedReservation scoped_reservation( encrypted_record_result.ValueOrDie().ByteSizeLong(), storage_queue_->options().memory_resource()); + // Inject "memory unavailable" failure, if requested. + if (storage_queue_->test_injection_handler_ && + !storage_queue_->test_injection_handler_ + .Run(test::StorageQueueOperationKind::kEncryptedRecordLowMemory, + storage_queue_->next_sequencing_id_) + .ok()) { + scoped_reservation.Reduce(0); + } if (!scoped_reservation.reserved()) { Schedule(&ReadContext::Response, base::Unretained(this), Status(error::RESOURCE_EXHAUSTED, @@ -1789,7 +1805,12 @@ } Status StorageQueue::ReserveNewRecordDiskSpace(const size_t total_size) { - if (!options_.disk_space_resource()->Reserve(total_size)) { + if ((test_injection_handler_ && // Test only: Simulate failure if requested + !test_injection_handler_ + .Run(test::StorageQueueOperationKind::kWriteLowDiskSpace, + next_sequencing_id_) + .ok()) || + !options_.disk_space_resource()->Reserve(total_size)) { const uint64_t space_used = options_.disk_space_resource()->GetUsed(); const uint64_t space_total = options_.disk_space_resource()->GetTotal(); return Status( @@ -2080,6 +2101,7 @@ scoped_refptr<ResourceManager> memory_resource, scoped_refptr<ResourceManager> disk_space_resource, scoped_refptr<RefCountedClosureList> completion_closure_list) { + // Reserve specified disk space for the file. if (!disk_space_resource->Reserve(size)) { LOG(WARNING) << "Disk space exceeded adding file " << filename.MaybeAsASCII(); @@ -2088,6 +2110,7 @@ base::StrCat({"Not enough disk space available to include file=", filename.MaybeAsASCII()})); } + // Cannot use base::MakeRefCounted, since the constructor is private. return scoped_refptr<StorageQueue::SingleFile>( new SingleFile(filename, size, memory_resource, disk_space_resource,
diff --git a/components/reporting/storage/storage_queue.h b/components/reporting/storage/storage_queue.h index a2c93c06..39edd8b 100644 --- a/components/reporting/storage/storage_queue.h +++ b/components/reporting/storage/storage_queue.h
@@ -47,6 +47,9 @@ kReadBlock, kWriteBlock, kWriteMetadata, + kWrappedRecordLowMemory, + kEncryptedRecordLowMemory, + kWriteLowDiskSpace, }; } // namespace test
diff --git a/components/reporting/storage/storage_queue_unittest.cc b/components/reporting/storage/storage_queue_unittest.cc index dbaa07e6..635ccae 100644 --- a/components/reporting/storage/storage_queue_unittest.cc +++ b/components/reporting/storage/storage_queue_unittest.cc
@@ -2173,12 +2173,17 @@ TEST_P(StorageQueueTest, WriteRecordWithInsufficientDiskSpace) { CreateTestStorageQueueOrDie(BuildStorageQueueOptionsOnlyManual()); - // Update total disk space and reset after running the write operation so it - // does not affect other tests - const auto original_disk_space = options_.disk_space_resource()->GetTotal(); - options_.disk_space_resource()->Test_SetTotal(0); + // Inject simulated failures. + auto inject = InjectFailures(); + EXPECT_CALL( + *inject, + Call(Eq(test::StorageQueueOperationKind::kWriteLowDiskSpace), Eq(0))) + .WillRepeatedly(WithArg<1>(Invoke([](int64_t seq_id) { + return Status(error::INTERNAL, + base::StrCat({"Simulated data write low disk space, seq=", + base::NumberToString(seq_id)})); + }))); Status write_result = WriteString(kData[0]); - options_.disk_space_resource()->Test_SetTotal(original_disk_space); EXPECT_FALSE(write_result.ok()); EXPECT_EQ(write_result.error_code(), error::RESOURCE_EXHAUSTED); } @@ -2196,6 +2201,64 @@ EXPECT_EQ(write_result.error_code(), error::RESOURCE_EXHAUSTED); } +TEST_P(StorageQueueTest, WrappedRecordWithInsufficientMemoryWithFailure) { + CreateTestStorageQueueOrDie(BuildStorageQueueOptionsOnlyManual()); + + // Inject "low memory" error multiple times, then retire and return success. + auto inject = InjectFailures(); + EXPECT_CALL( + *inject, + Call(Eq(test::StorageQueueOperationKind::kWrappedRecordLowMemory), Eq(0))) + .WillRepeatedly(WithArg<1>(Invoke([](int64_t seq_id) { + return Status(error::RESOURCE_EXHAUSTED, + base::StrCat({"Not enough memory for WrappedRecord, seq=", + base::NumberToString(seq_id)})); + }))) + .RetiresOnSaturation(); + Record record; + record.set_data(std::string(kData[0])); + record.set_destination(UPLOAD_EVENTS); + if (!dm_token_.empty()) { + record.set_dm_token(dm_token_); + } + test::TestEvent<Status> write_event; + LOG(ERROR) << "Write data='" << record.data() << "'"; + storage_queue_->Write(std::move(record), write_event.cb()); + Status write_result = write_event.result(); + EXPECT_FALSE(write_result.ok()); + EXPECT_EQ(write_result.error_code(), error::RESOURCE_EXHAUSTED); +} + +TEST_P(StorageQueueTest, EncryptedRecordWithInsufficientMemoryWithFailure) { + CreateTestStorageQueueOrDie(BuildStorageQueueOptionsOnlyManual()); + + // Inject "low memory" error multiple times, then retire and return success. + auto inject = InjectFailures(); + EXPECT_CALL( + *inject, + Call(Eq(test::StorageQueueOperationKind::kEncryptedRecordLowMemory), + Eq(0))) + .WillRepeatedly(WithArg<1>(Invoke([](int64_t seq_id) { + return Status( + error::RESOURCE_EXHAUSTED, + base::StrCat({"Not enough memory for EncryptedRecord, seq=", + base::NumberToString(seq_id)})); + }))) + .RetiresOnSaturation(); + Record record; + record.set_data(std::string(kData[0])); + record.set_destination(UPLOAD_EVENTS); + if (!dm_token_.empty()) { + record.set_dm_token(dm_token_); + } + test::TestEvent<Status> write_event; + LOG(ERROR) << "Write data='" << record.data() << "'"; + storage_queue_->Write(std::move(record), write_event.cb()); + Status write_result = write_event.result(); + EXPECT_FALSE(write_result.ok()); + EXPECT_EQ(write_result.error_code(), error::RESOURCE_EXHAUSTED); +} + TEST_P(StorageQueueTest, WriteRecordWithReservedSpace) { CreateTestStorageQueueOrDie(BuildStorageQueueOptionsOnlyManual());
diff --git a/components/saved_tab_groups/saved_tab_group_model.cc b/components/saved_tab_groups/saved_tab_group_model.cc index 7c29cd8..e0ee868 100644 --- a/components/saved_tab_groups/saved_tab_group_model.cc +++ b/components/saved_tab_groups/saved_tab_group_model.cc
@@ -226,11 +226,12 @@ if (!Contains(group_id)) return; + const base::GUID tab_id = tab.saved_tab_guid(); absl::optional<int> group_index = GetIndexOf(group_id); saved_tab_groups_[group_index.value()].AddTab(index, tab); for (auto& observer : observers_) - observer.SavedTabGroupUpdatedLocally(group_id); + observer.SavedTabGroupUpdatedLocally(group_id, tab_id); } void SavedTabGroupModel::RemoveTabFromGroup(const base::GUID& group_id, @@ -252,7 +253,7 @@ // TODO(dljames): Update to use SavedTabGroupRemoveLocally and update the API // to pass a group_id and an optional tab_id. for (auto& observer : observers_) - observer.SavedTabGroupUpdatedLocally(group_id); + observer.SavedTabGroupUpdatedLocally(group_id, tab_id); } void SavedTabGroupModel::ReplaceTabInGroupAt(const base::GUID& group_id, @@ -261,11 +262,14 @@ if (!Contains(group_id)) return; + const base::GUID guid = new_tab.saved_tab_guid(); absl::optional<int> index = GetIndexOf(group_id); saved_tab_groups_[index.value()].ReplaceTabAt(tab_id, new_tab); - for (auto& observer : observers_) - observer.SavedTabGroupUpdatedLocally(group_id); + for (auto& observer : observers_) { + observer.SavedTabGroupUpdatedLocally(group_id, tab_id); + observer.SavedTabGroupUpdatedLocally(group_id, guid); + } } void SavedTabGroupModel::MoveTabInGroupTo(const base::GUID& group_id, @@ -278,7 +282,7 @@ saved_tab_groups_[index.value()].MoveTab(tab_id, new_index); for (auto& observer : observers_) - observer.SavedTabGroupUpdatedLocally(group_id); + observer.SavedTabGroupUpdatedLocally(group_id, tab_id); } std::unique_ptr<sync_pb::SavedTabGroupSpecifics> SavedTabGroupModel::MergeGroup( @@ -315,7 +319,7 @@ tab->MergeTab(std::move(sync_specific)); for (auto& observer : observers_) - observer.SavedTabGroupUpdatedFromSync(tab->saved_group_guid()); + observer.SavedTabGroupUpdatedFromSync(group_id, tab->saved_group_guid()); return tab->ToSpecifics(); }
diff --git a/components/saved_tab_groups/saved_tab_group_model_observer.h b/components/saved_tab_groups/saved_tab_group_model_observer.h index f1eee43..4b4a9aed 100644 --- a/components/saved_tab_groups/saved_tab_group_model_observer.h +++ b/components/saved_tab_groups/saved_tab_group_model_observer.h
@@ -9,6 +9,7 @@ #include "components/saved_tab_groups/saved_tab_group_model.h" #include "components/saved_tab_groups/saved_tab_group_tab.h" #include "components/tab_groups/tab_group_id.h" +#include "third_party/abseil-cpp/absl/types/optional.h" // Serves to notify any SavedTabGroupModel listeners that a change has occurred // supply the SavedTabGroup that was changed. @@ -25,10 +26,13 @@ virtual void SavedTabGroupRemovedLocally(const SavedTabGroup* removed_group) { } - // Called when the title, tabs, or color change. - // TODO(dljames): Update parameters to take 2 guids. 1 for the group and an - // optional guid for the tab. Do the same for the sync version. - virtual void SavedTabGroupUpdatedLocally(const base::GUID& guid) {} + // Called when the title, tabs, or color change. `group_guid` denotes the + // group that is currently being updated. `tab_guid` denotes if a tab in this + // group was changed (added, removed, updated). Otherwise, only the group is + // being changed. + virtual void SavedTabGroupUpdatedLocally( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid = absl::nullopt) {} // Called when the order of saved tab groups in the bookmark bar are changed. // TODO(crbug/1372052): Figure out if we can maintain ordering of groups and @@ -43,7 +47,13 @@ virtual void SavedTabGroupRemovedFromSync( const SavedTabGroup* removed_group) {} - virtual void SavedTabGroupUpdatedFromSync(const base::GUID& guid) {} + // Called when the title, tabs, or color change. `group_guid` denotes the + // group that is currently being updated. `tab_guid` denotes if a tab in this + // group was changed (added, removed, updated). Specifically, this is called + // when addressing merge conflicts for duplicate groups and tabs. + virtual void SavedTabGroupUpdatedFromSync( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid = absl::nullopt) {} protected: SavedTabGroupModelObserver() = default;
diff --git a/components/saved_tab_groups/saved_tab_group_model_unittest.cc b/components/saved_tab_groups/saved_tab_group_model_unittest.cc index a38d946..8b28dc4 100644 --- a/components/saved_tab_groups/saved_tab_group_model_unittest.cc +++ b/components/saved_tab_groups/saved_tab_group_model_unittest.cc
@@ -129,9 +129,12 @@ retrieved_guid_ = removed_group->saved_guid(); } - void SavedTabGroupUpdatedLocally(const base::GUID& guid) override { - retrieved_group_.emplace_back(*saved_tab_group_model_->Get(guid)); - retrieved_index_ = saved_tab_group_model_->GetIndexOf(guid).value_or(-1); + void SavedTabGroupUpdatedLocally( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid = absl::nullopt) override { + retrieved_group_.emplace_back(*saved_tab_group_model_->Get(group_guid)); + retrieved_index_ = + saved_tab_group_model_->GetIndexOf(group_guid).value_or(-1); } void SavedTabGroupAddedFromSync(const base::GUID& guid) override { @@ -144,9 +147,12 @@ retrieved_guid_ = removed_group->saved_guid(); } - void SavedTabGroupUpdatedFromSync(const base::GUID& guid) override { - retrieved_group_.emplace_back(*saved_tab_group_model_->Get(guid)); - retrieved_index_ = saved_tab_group_model_->GetIndexOf(guid).value_or(-1); + void SavedTabGroupUpdatedFromSync( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid = absl::nullopt) override { + retrieved_group_.emplace_back(*saved_tab_group_model_->Get(group_guid)); + retrieved_index_ = + saved_tab_group_model_->GetIndexOf(group_guid).value_or(-1); } void SavedTabGroupReorderedLocally() override { reordered_called_ = true; } @@ -1002,4 +1008,4 @@ saved_tab_group_model_->GetGroupContainingTab(GenerateNextGUID())); EXPECT_EQ(nullptr, saved_tab_group_model_->GetGroupContainingTab(base::Token())); -} \ No newline at end of file +}
diff --git a/components/saved_tab_groups/saved_tab_group_sync_bridge.cc b/components/saved_tab_groups/saved_tab_group_sync_bridge.cc index f64eba4..4e0447a 100644 --- a/components/saved_tab_groups/saved_tab_group_sync_bridge.cc +++ b/components/saved_tab_groups/saved_tab_group_sync_bridge.cc
@@ -231,15 +231,25 @@ } void SavedTabGroupSyncBridge::SavedTabGroupUpdatedLocally( - const base::GUID& guid) { + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid) { std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch = store_->CreateWriteBatch(); - const SavedTabGroup* group = model_->Get(guid); + const SavedTabGroup* group = model_->Get(group_guid); DCHECK(group); - UpsertEntitySpecific(group->ToSpecifics(), write_batch.get()); - for (const SavedTabGroupTab& tab : group->saved_tabs()) - UpsertEntitySpecific(tab.ToSpecifics(), write_batch.get()); + + if (tab_guid.has_value()) { + if (!group->ContainsTab(tab_guid.value())) { + RemoveEntitySpecific(tab_guid.value(), write_batch.get()); + } else { + int tab_index = group->GetIndexOfTab(tab_guid.value()).value(); + UpsertEntitySpecific(group->saved_tabs()[tab_index].ToSpecifics(), + write_batch.get()); + } + } else { + UpsertEntitySpecific(group->ToSpecifics(), write_batch.get()); + } store_->CommitWriteBatch( std::move(write_batch),
diff --git a/components/saved_tab_groups/saved_tab_group_sync_bridge.h b/components/saved_tab_groups/saved_tab_group_sync_bridge.h index dc6e6ce..0e882054 100644 --- a/components/saved_tab_groups/saved_tab_group_sync_bridge.h +++ b/components/saved_tab_groups/saved_tab_group_sync_bridge.h
@@ -16,6 +16,7 @@ #include "components/sync/model/model_type_change_processor.h" #include "components/sync/model/model_type_store.h" #include "components/sync/model/model_type_sync_bridge.h" +#include "third_party/abseil-cpp/absl/types/optional.h" class SavedTabGroupModel; @@ -59,7 +60,9 @@ // SavedTabGroupModelObserver void SavedTabGroupAddedLocally(const base::GUID& guid) override; void SavedTabGroupRemovedLocally(const SavedTabGroup* removed_group) override; - void SavedTabGroupUpdatedLocally(const base::GUID& guid) override; + void SavedTabGroupUpdatedLocally( + const base::GUID& group_guid, + const absl::optional<base::GUID>& tab_guid = absl::nullopt) override; void SavedTabGroupReorderedLocally() override; private:
diff --git a/components/saved_tab_groups/saved_tab_group_sync_bridge_unittest.cc b/components/saved_tab_groups/saved_tab_group_sync_bridge_unittest.cc index f60b8a8..88ff2ee 100644 --- a/components/saved_tab_groups/saved_tab_group_sync_bridge_unittest.cc +++ b/components/saved_tab_groups/saved_tab_group_sync_bridge_unittest.cc
@@ -614,14 +614,10 @@ base::GUID tab_2_guid = tab_2.saved_tab_guid(); saved_tab_group_model_.Add(std::move(group)); - EXPECT_CALL(processor_, Put(tab_1_guid.AsLowercaseString(), _, _)); - EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)); EXPECT_CALL(processor_, Put(group_guid.AsLowercaseString(), _, _)); + EXPECT_CALL(processor_, Put(tab_1_guid.AsLowercaseString(), _, _)).Times(0); + EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)).Times(0); - // TODO(dljames): For now, updating a groups visual data also notifies - // observers of the tabs in the group. This is done for simplicity. Once the - // observer function changes are made this test will fail and we can remove - // the Put() calls for the tabs. tab_groups::TabGroupVisualData visual_data( u"New Title", tab_groups::TabGroupColorId::kYellow); saved_tab_group_model_.UpdateVisualData(group_guid, &visual_data); @@ -646,10 +642,10 @@ base::GUID tab_3_guid = tab_3.saved_tab_guid(); saved_tab_group_model_.Add(std::move(group)); - EXPECT_CALL(processor_, Put(tab_1_guid.AsLowercaseString(), _, _)); - EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)); EXPECT_CALL(processor_, Put(tab_3_guid.AsLowercaseString(), _, _)); - EXPECT_CALL(processor_, Put(group_guid.AsLowercaseString(), _, _)); + EXPECT_CALL(processor_, Put(tab_1_guid.AsLowercaseString(), _, _)).Times(0); + EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)).Times(0); + EXPECT_CALL(processor_, Put(group_guid.AsLowercaseString(), _, _)).Times(0); // TODO(dljames): Because `tab_3` was added to the middle of the group, only // `tab_2` will have its position updated. Once tab ordering is implemented, @@ -659,8 +655,6 @@ } // Verify that locally removed tabs remove the correct tabs from the processor. -// TODO(dljames): Update the test with delete calls once the observer API is -// updated. TEST_F(SavedTabGroupSyncBridgeTest, RemoveTabLocally) { EXPECT_TRUE(saved_tab_group_model_.saved_tab_groups().empty()); @@ -676,9 +670,9 @@ base::GUID tab_2_guid = tab_2.saved_tab_guid(); saved_tab_group_model_.Add(std::move(group)); - EXPECT_CALL(processor_, Put(tab_1_guid.AsLowercaseString(), _, _)).Times(0); - EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)); - EXPECT_CALL(processor_, Put(group_guid.AsLowercaseString(), _, _)); + EXPECT_CALL(processor_, Delete(tab_1_guid.AsLowercaseString(), _)); + EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)).Times(0); + EXPECT_CALL(processor_, Put(group_guid.AsLowercaseString(), _, _)).Times(0); saved_tab_group_model_.RemoveTabFromGroup(group_guid, tab_1_guid); } @@ -702,12 +696,10 @@ base::GUID tab_3_guid = tab_3.saved_tab_guid(); saved_tab_group_model_.Add(std::move(group)); - // TODO(dljames): Ensure Delete() is called on tab_1 once the observer api - // changes are made. - EXPECT_CALL(processor_, Put(tab_1_guid.AsLowercaseString(), _, _)).Times(0); - EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)); + EXPECT_CALL(processor_, Delete(tab_1_guid.AsLowercaseString(), _)); EXPECT_CALL(processor_, Put(tab_3_guid.AsLowercaseString(), _, _)); - EXPECT_CALL(processor_, Put(group_guid.AsLowercaseString(), _, _)); + EXPECT_CALL(processor_, Put(tab_2_guid.AsLowercaseString(), _, _)).Times(0); + EXPECT_CALL(processor_, Put(group_guid.AsLowercaseString(), _, _)).Times(0); saved_tab_group_model_.ReplaceTabInGroupAt(group_guid, tab_1_guid, tab_3); }
diff --git a/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.cc b/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.cc index 2e170f1..b3d8574 100644 --- a/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.cc +++ b/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.cc
@@ -108,7 +108,9 @@ // most space efficient Huffman table for the given inputs. This table is used // for the second run. + // Tables must outlive `trie_entries` and `raw_trie_entries`. HuffmanRepresentationTable approximate_table = ApproximateHuffman(entries); + HuffmanRepresentationTable optimal_table; HuffmanBuilder huffman_builder; // Create trie entries for the first pass. @@ -126,7 +128,7 @@ if (!writer.WriteEntries(raw_trie_entries, &root_position)) return std::string(); - HuffmanRepresentationTable optimal_table = huffman_builder.ToTable(); + optimal_table = huffman_builder.ToTable(); TrieWriter new_writer(optimal_table, &huffman_builder); // Create trie entries using the optimal table for the second pass.
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc index ae3b11d..c8f5020 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.cc +++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -18,7 +18,6 @@ #include "components/viz/service/display_embedder/skia_output_surface_dependency.h" #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/service/shared_context_state.h" -#include "gpu/ipc/common/gpu_surface_lookup.h" #include "ui/display/types/display_snapshot.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -29,6 +28,7 @@ #include "ui/gl/gl_surface.h" #if BUILDFLAG(IS_ANDROID) +#include "gpu/ipc/common/gpu_surface_lookup.h" #include "ui/gl/android/scoped_a_native_window.h" #include "ui/gl/android/scoped_java_surface.h" #include "ui/gl/gl_surface_egl_surface_control.h"
diff --git a/components/viz/service/display_embedder/skia_output_device_dcomp.cc b/components/viz/service/display_embedder/skia_output_device_dcomp.cc index 2efce022..d528235 100644 --- a/components/viz/service/display_embedder/skia_output_device_dcomp.cc +++ b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
@@ -90,7 +90,7 @@ gpu::MailboxManager* mailbox_manager, gpu::SharedImageRepresentationFactory* shared_image_representation_factory, gpu::SharedContextState* context_state, - scoped_refptr<gl::GLSurface> gl_surface, + gl::GLSurface* gl_surface, scoped_refptr<gpu::gles2::FeatureInfo> feature_info, gpu::MemoryTracker* memory_tracker, DidSwapBufferCompleteCallback did_swap_buffer_complete_callback) @@ -99,89 +99,60 @@ std::move(did_swap_buffer_complete_callback)), mailbox_manager_(mailbox_manager), shared_image_representation_factory_(shared_image_representation_factory), - context_state_(context_state), - gl_surface_(std::move(gl_surface)), - supports_async_swap_(gl_surface_->SupportsAsyncSwap()) { + context_state_(context_state) { + DCHECK(gl_surface->SupportsPostSubBuffer()); + DCHECK(!gl_surface->SupportsAsyncSwap()); + DCHECK(!feature_info->workarounds() + .disable_post_sub_buffers_for_onscreen_surfaces); + DCHECK(gl_surface->SupportsDCLayers()); + DCHECK_EQ(gl_surface->GetOrigin(), gfx::SurfaceOrigin::kTopLeft); + DCHECK(gl_surface->SupportsGpuVSync()); + DCHECK(!gl_surface->SupportsCommitOverlayPlanes()); + capabilities_.uses_default_gl_framebuffer = true; - capabilities_.output_surface_origin = gl_surface_->GetOrigin(); - capabilities_.supports_post_sub_buffer = gl_surface_->SupportsPostSubBuffer(); - if (gl_surface_->SupportsDCLayers()) { - // DWM handles preserving the contents of the backbuffer in Present1, so we - // don't need to have SkiaOutputSurface handle it. - capabilities_.preserve_buffer_content = false; - capabilities_.number_of_buffers = - gl::DirectCompositionRootSurfaceBufferCount(); - capabilities_.supports_delegated_ink = gl_surface_->SupportsDelegatedInk(); - } - if (feature_info->workarounds() - .disable_post_sub_buffers_for_onscreen_surfaces) { - capabilities_.supports_post_sub_buffer = false; - } + capabilities_.output_surface_origin = gfx::SurfaceOrigin::kTopLeft; + capabilities_.supports_post_sub_buffer = true; + // DWM handles preserving the contents of the backbuffer in Present1, so we + // don't need to have SkiaOutputSurface handle it. + capabilities_.preserve_buffer_content = false; + capabilities_.number_of_buffers = + gl::DirectCompositionRootSurfaceBufferCount(); + capabilities_.supports_delegated_ink = gl_surface->SupportsDelegatedInk(); if (feature_info->workarounds().supports_two_yuv_hardware_overlays) { capabilities_.supports_two_yuv_hardware_overlays = true; } capabilities_.pending_swap_params.max_pending_swaps = - gl_surface_->GetBufferCount() - 1; - capabilities_.supports_commit_overlay_planes = - gl_surface_->SupportsCommitOverlayPlanes(); - capabilities_.supports_gpu_vsync = gl_surface_->SupportsGpuVSync(); - capabilities_.supports_dc_layers = gl_surface_->SupportsDCLayers(); + gl_surface->GetBufferCount() - 1; + capabilities_.supports_commit_overlay_planes = false; + capabilities_.supports_gpu_vsync = true; + capabilities_.supports_dc_layers = true; DCHECK(context_state_); - DCHECK(gl_surface_); + DCHECK(gl_surface); - if (gl_surface_->SupportsSwapTimestamps()) { - gl_surface_->SetEnableSwapTimestamps(); + if (gl_surface->SupportsSwapTimestamps()) { + gl_surface->SetEnableSwapTimestamps(); // Changes to swap timestamp queries are only picked up when making current. context_state_->ReleaseCurrent(nullptr); - context_state_->MakeCurrent(gl_surface_.get()); + context_state_->MakeCurrent(gl_surface); } DCHECK(context_state_->gr_context()); DCHECK(context_state_->context()); - GrDirectContext* gr_context = context_state_->gr_context(); - gl::CurrentGL* current_gl = context_state_->context()->GetCurrentGL(); - - // Get alpha bits from the default frame buffer. - int alpha_bits = 0; - glBindFramebufferEXT(GL_FRAMEBUFFER, 0); - gr_context->resetContext(kRenderTarget_GrGLBackendState); - const auto* version = current_gl->Version.get(); - if (version->is_desktop_core_profile) { - glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, - &alpha_bits); - } else { - glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); - } - CHECK_GL_ERROR(); - - auto color_type = kRGBA_8888_SkColorType; - - if (alpha_bits == 0) { - color_type = gl_surface_->GetFormat().GetBufferSize() == 16 - ? kRGB_565_SkColorType - : kRGB_888x_SkColorType; - // Skia disables RGBx on some GPUs, fallback to RGBA if it's the - // case. This doesn't change framebuffer itself, as we already allocated it, - // but will change any temporary buffer Skia needs to allocate. - if (!context_state_->gr_context() - ->defaultBackendFormat(color_type, GrRenderable::kYes) - .isValid()) { - color_type = kRGBA_8888_SkColorType; - } - } // SRGB + constexpr SkColorType kSrgbColorType = kRGBA_8888_SkColorType; + // TODO(tangm): switch to kRGB_888x_SkColorType + constexpr SkColorType kSrgbColorTypeOpaque = kRGBA_8888_SkColorType; capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = - color_type; + kSrgbColorType; capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = - color_type; + kSrgbColorTypeOpaque; capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = - color_type; + kSrgbColorType; capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = - color_type; + kSrgbColorTypeOpaque; // HDR10 capabilities_ .sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_1010102)] = @@ -191,12 +162,127 @@ kRGBA_F16_SkColorType; } -SkiaOutputDeviceDComp::~SkiaOutputDeviceDComp() { +SkiaOutputDeviceDComp::~SkiaOutputDeviceDComp() = default; + +void SkiaOutputDeviceDComp::SwapBuffers(BufferPresentedCallback feedback, + OutputSurfaceFrame frame) { + NOTREACHED(); +} + +void SkiaOutputDeviceDComp::PostSubBuffer(const gfx::Rect& rect, + BufferPresentedCallback feedback, + OutputSurfaceFrame frame) { + StartSwapBuffers({}); + + gfx::SwapResult result = + DoPostSubBuffer(rect, std::move(feedback), frame.data); + + // Remove entries from |overlays_| for textures that weren't scheduled as an + // overlay this frame. + if (!overlays_.empty()) { + base::EraseIf(overlays_, [this](auto& entry) { + const gpu::Mailbox& mailbox = entry.first; + return !scheduled_overlay_mailboxes_.contains(mailbox); + }); + scheduled_overlay_mailboxes_.clear(); + // End access for the remaining overlays that were scheduled this frame. + for (auto& kv : overlays_) + kv.second.EndOverlayAccess(); + } + + FinishSwapBuffers(gfx::SwapCompletionResult(result), GetRootSurfaceSize(), + std::move(frame)); +} + +void SkiaOutputDeviceDComp::ScheduleOverlays( + SkiaOutputSurface::OverlayList overlays) { + for (auto& dc_layer : overlays) { + auto params = std::make_unique<ui::DCRendererLayerParams>(); + // Get GLImages for DC layer textures. + bool success = true; + for (size_t i = 0; i < DCLayerOverlay::kNumResources; ++i) { + const gpu::Mailbox& mailbox = dc_layer.mailbox[i]; + if (i > 0 && mailbox.IsZero()) + break; + + auto* read_access = BeginOverlayAccess(mailbox); + if (!read_access) { + success = false; + break; + } + + if (auto dcomp_surface_proxy = read_access->GetDCOMPSurfaceProxy()) { + params->dcomp_surface_proxy = std::move(dcomp_surface_proxy); + } else if (auto* image = read_access->gl_image()) { + image->SetColorSpace(dc_layer.color_space); + params->images[i] = std::move(image); + } else { + success = false; + break; + } + + scheduled_overlay_mailboxes_.insert(mailbox); + } + + if (!success) { + DLOG(ERROR) << "Failed to get GLImage for DC layer."; + continue; + } + + params->z_order = dc_layer.z_order; + params->content_rect = dc_layer.content_rect; + params->quad_rect = dc_layer.quad_rect; + DCHECK(dc_layer.transform.IsFlat()); + params->transform = dc_layer.transform; + params->clip_rect = dc_layer.clip_rect; + params->protected_video_type = dc_layer.protected_video_type; + params->hdr_metadata = dc_layer.hdr_metadata; + params->is_video_fullscreen_letterboxing = + dc_layer.is_video_fullscreen_letterboxing; + + // Schedule DC layer overlay to be presented at next SwapBuffers(). + if (!ScheduleDCLayer(std::move(params))) + DLOG(ERROR) << "ScheduleDCLayer failed"; + } +} + +gpu::OverlayImageRepresentation::ScopedReadAccess* +SkiaOutputDeviceDComp::BeginOverlayAccess(const gpu::Mailbox& mailbox) { + auto it = overlays_.find(mailbox); + if (it != overlays_.end()) + return it->second.BeginOverlayAccess(); + + auto overlay = shared_image_representation_factory_->ProduceOverlay(mailbox); + if (!overlay) + return nullptr; + + std::tie(it, std::ignore) = overlays_.emplace(mailbox, std::move(overlay)); + return it->second.BeginOverlayAccess(); +} + +SkiaOutputDeviceDCompGLSurface::SkiaOutputDeviceDCompGLSurface( + gpu::MailboxManager* mailbox_manager, + gpu::SharedImageRepresentationFactory* shared_image_representation_factory, + gpu::SharedContextState* context_state, + scoped_refptr<gl::GLSurface> gl_surface, + scoped_refptr<gpu::gles2::FeatureInfo> feature_info, + gpu::MemoryTracker* memory_tracker, + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback) + : SkiaOutputDeviceDComp(mailbox_manager, + shared_image_representation_factory, + context_state, + gl_surface.get(), + std::move(feature_info), + memory_tracker, + std::move(did_swap_buffer_complete_callback)), + gl_surface_(std::move(gl_surface)) {} + +SkiaOutputDeviceDCompGLSurface::~SkiaOutputDeviceDCompGLSurface() { // gl_surface_ will be destructed soon. memory_type_tracker_->TrackMemFree(backbuffer_estimated_size_); } -bool SkiaOutputDeviceDComp::Reshape( +bool SkiaOutputDeviceDCompGLSurface::Reshape( const SkSurfaceCharacterization& characterization, const gfx::ColorSpace& color_space, float device_scale_factor, @@ -277,198 +363,42 @@ return !!sk_surface_; } -void SkiaOutputDeviceDComp::SwapBuffers(BufferPresentedCallback feedback, - OutputSurfaceFrame frame) { - StartSwapBuffers({}); - - gfx::Size surface_size = - gfx::Size(sk_surface_->width(), sk_surface_->height()); - - auto data = frame.data; - if (supports_async_swap_) { - auto callback = base::BindOnce( - &SkiaOutputDeviceDComp::DoFinishSwapBuffersAsync, - weak_ptr_factory_.GetWeakPtr(), surface_size, std::move(frame)); - gl_surface_->SwapBuffersAsync(std::move(callback), std::move(feedback), - data); - } else { - gfx::SwapResult result = - gl_surface_->SwapBuffers(std::move(feedback), data); - DoFinishSwapBuffers(surface_size, std::move(frame), - gfx::SwapCompletionResult(result)); - } -} - -void SkiaOutputDeviceDComp::PostSubBuffer(const gfx::Rect& rect, - BufferPresentedCallback feedback, - OutputSurfaceFrame frame) { - StartSwapBuffers({}); - - gfx::Size surface_size = - gfx::Size(sk_surface_->width(), sk_surface_->height()); - - auto data = frame.data; - if (supports_async_swap_) { - auto callback = base::BindOnce( - &SkiaOutputDeviceDComp::DoFinishSwapBuffersAsync, - weak_ptr_factory_.GetWeakPtr(), surface_size, std::move(frame)); - gl_surface_->PostSubBufferAsync(rect.x(), rect.y(), rect.width(), - rect.height(), std::move(callback), - std::move(feedback), data); - } else { - gfx::SwapResult result = - gl_surface_->PostSubBuffer(rect.x(), rect.y(), rect.width(), - rect.height(), std::move(feedback), data); - DoFinishSwapBuffers(surface_size, std::move(frame), - gfx::SwapCompletionResult(result)); - } -} - -void SkiaOutputDeviceDComp::CommitOverlayPlanes( - BufferPresentedCallback feedback, - OutputSurfaceFrame frame) { - StartSwapBuffers({}); - - gfx::Size surface_size = - gfx::Size(sk_surface_->width(), sk_surface_->height()); - - auto data = frame.data; - if (supports_async_swap_) { - auto callback = base::BindOnce( - &SkiaOutputDeviceDComp::DoFinishSwapBuffersAsync, - weak_ptr_factory_.GetWeakPtr(), surface_size, std::move(frame)); - gl_surface_->CommitOverlayPlanesAsync(std::move(callback), - std::move(feedback), data); - } else { - gfx::SwapResult result = - gl_surface_->CommitOverlayPlanes(std::move(feedback), data); - DoFinishSwapBuffers(surface_size, std::move(frame), - gfx::SwapCompletionResult(result)); - } -} - -void SkiaOutputDeviceDComp::DoFinishSwapBuffersAsync( - const gfx::Size& size, - OutputSurfaceFrame frame, - gfx::SwapCompletionResult result) { - DCHECK(result.release_fence.is_null()); - FinishSwapBuffers(std::move(result), size, std::move(frame)); -} - -void SkiaOutputDeviceDComp::DoFinishSwapBuffers( - const gfx::Size& size, - OutputSurfaceFrame frame, - gfx::SwapCompletionResult result) { - DCHECK(result.release_fence.is_null()); - - // Remove entries from |overlays_| for textures that weren't scheduled as an - // overlay this frame. - if (!overlays_.empty()) { - base::EraseIf(overlays_, [this](auto& entry) { - const gpu::Mailbox& mailbox = entry.first; - return !scheduled_overlay_mailboxes_.contains(mailbox); - }); - scheduled_overlay_mailboxes_.clear(); - // End access for the remaining overlays that were scheduled this frame. - for (auto& kv : overlays_) - kv.second.EndOverlayAccess(); - } - - FinishSwapBuffers(std::move(result), size, std::move(frame)); -} - -bool SkiaOutputDeviceDComp::SetDrawRectangle(const gfx::Rect& draw_rectangle) { +bool SkiaOutputDeviceDCompGLSurface::SetDrawRectangle( + const gfx::Rect& draw_rectangle) { return gl_surface_->SetDrawRectangle(draw_rectangle); } -void SkiaOutputDeviceDComp::SetGpuVSyncEnabled(bool enabled) { - gl_surface_->SetGpuVSyncEnabled(enabled); -} - -void SkiaOutputDeviceDComp::SetEnableDCLayers(bool enable) { +void SkiaOutputDeviceDCompGLSurface::SetEnableDCLayers(bool enable) { gl_surface_->SetEnableDCLayers(enable); } -void SkiaOutputDeviceDComp::ScheduleOverlays( - SkiaOutputSurface::OverlayList overlays) { - for (auto& dc_layer : overlays) { - auto params = std::make_unique<ui::DCRendererLayerParams>(); - // Get GLImages for DC layer textures. - bool success = true; - for (size_t i = 0; i < DCLayerOverlay::kNumResources; ++i) { - const gpu::Mailbox& mailbox = dc_layer.mailbox[i]; - if (i > 0 && mailbox.IsZero()) - break; - - auto* read_access = BeginOverlayAccess(mailbox); - if (!read_access) { - success = false; - break; - } - - if (auto dcomp_surface_proxy = read_access->GetDCOMPSurfaceProxy()) { - params->dcomp_surface_proxy = std::move(dcomp_surface_proxy); - } else if (auto* image = read_access->gl_image()) { - image->SetColorSpace(dc_layer.color_space); - params->images[i] = std::move(image); - } else { - success = false; - break; - } - - scheduled_overlay_mailboxes_.insert(mailbox); - } - - if (!success) { - DLOG(ERROR) << "Failed to get GLImage for DC layer."; - continue; - } - - params->z_order = dc_layer.z_order; - params->content_rect = dc_layer.content_rect; - params->quad_rect = dc_layer.quad_rect; - DCHECK(dc_layer.transform.IsFlat()); - params->transform = dc_layer.transform; - params->clip_rect = dc_layer.clip_rect; - params->protected_video_type = dc_layer.protected_video_type; - params->hdr_metadata = dc_layer.hdr_metadata; - params->is_video_fullscreen_letterboxing = - dc_layer.is_video_fullscreen_letterboxing; - - // Schedule DC layer overlay to be presented at next SwapBuffers(). - if (!gl_surface_->ScheduleDCLayer(std::move(params))) - DLOG(ERROR) << "ScheduleDCLayer failed"; - } +void SkiaOutputDeviceDCompGLSurface::SetGpuVSyncEnabled(bool enabled) { + gl_surface_->SetGpuVSyncEnabled(enabled); } -void SkiaOutputDeviceDComp::EnsureBackbuffer() { - gl_surface_->SetBackbufferAllocation(true); -} - -void SkiaOutputDeviceDComp::DiscardBackbuffer() { - gl_surface_->SetBackbufferAllocation(false); -} - -SkSurface* SkiaOutputDeviceDComp::BeginPaint( +SkSurface* SkiaOutputDeviceDCompGLSurface::BeginPaint( std::vector<GrBackendSemaphore>* end_semaphores) { DCHECK(sk_surface_); return sk_surface_.get(); } -void SkiaOutputDeviceDComp::EndPaint() {} +void SkiaOutputDeviceDCompGLSurface::EndPaint() {} -gpu::OverlayImageRepresentation::ScopedReadAccess* -SkiaOutputDeviceDComp::BeginOverlayAccess(const gpu::Mailbox& mailbox) { - auto it = overlays_.find(mailbox); - if (it != overlays_.end()) - return it->second.BeginOverlayAccess(); +bool SkiaOutputDeviceDCompGLSurface::ScheduleDCLayer( + std::unique_ptr<ui::DCRendererLayerParams> params) { + return gl_surface_->ScheduleDCLayer(std::move(params)); +} - auto overlay = shared_image_representation_factory_->ProduceOverlay(mailbox); - if (!overlay) - return nullptr; +gfx::Size SkiaOutputDeviceDCompGLSurface::GetRootSurfaceSize() const { + return gl_surface_->GetSize(); +} - std::tie(it, std::ignore) = overlays_.emplace(mailbox, std::move(overlay)); - return it->second.BeginOverlayAccess(); +gfx::SwapResult SkiaOutputDeviceDCompGLSurface::DoPostSubBuffer( + const gfx::Rect& rect, + BufferPresentedCallback feedback, + gl::FrameData data) { + return gl_surface_->PostSubBuffer(rect.x(), rect.y(), rect.width(), + rect.height(), std::move(feedback), data); } } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_dcomp.h b/components/viz/service/display_embedder/skia_output_device_dcomp.h index 3718f500..5aa6fbaf 100644 --- a/components/viz/service/display_embedder/skia_output_device_dcomp.h +++ b/components/viz/service/display_embedder/skia_output_device_dcomp.h
@@ -32,64 +32,49 @@ namespace viz { -class SkiaOutputDeviceDComp final : public SkiaOutputDevice { +// Base class for DComp-backed OutputDevices. +class SkiaOutputDeviceDComp : public SkiaOutputDevice { public: - SkiaOutputDeviceDComp( - gpu::MailboxManager* mailbox_manager, - gpu::SharedImageRepresentationFactory* - shared_image_representation_factory, - gpu::SharedContextState* context_state, - scoped_refptr<gl::GLSurface> gl_surface, - scoped_refptr<gpu::gles2::FeatureInfo> feature_info, - gpu::MemoryTracker* memory_tracker, - DidSwapBufferCompleteCallback did_swap_buffer_complete_callback); - SkiaOutputDeviceDComp(const SkiaOutputDeviceDComp&) = delete; SkiaOutputDeviceDComp& operator=(const SkiaOutputDeviceDComp&) = delete; ~SkiaOutputDeviceDComp() override; // SkiaOutputDevice implementation: - bool Reshape(const SkSurfaceCharacterization& characterization, - const gfx::ColorSpace& color_space, - float device_scale_factor, - gfx::OverlayTransform transform) override; void SwapBuffers(BufferPresentedCallback feedback, OutputSurfaceFrame frame) override; void PostSubBuffer(const gfx::Rect& rect, BufferPresentedCallback feedback, OutputSurfaceFrame frame) override; - void CommitOverlayPlanes(BufferPresentedCallback feedback, - OutputSurfaceFrame frame) override; - bool SetDrawRectangle(const gfx::Rect& draw_rectangle) override; - void SetGpuVSyncEnabled(bool enabled) override; - void SetEnableDCLayers(bool enable) override; void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays) override; - void EnsureBackbuffer() override; - void DiscardBackbuffer() override; - SkSurface* BeginPaint( - std::vector<GrBackendSemaphore>* end_semaphores) override; - void EndPaint() override; - private: + protected: + SkiaOutputDeviceDComp( + gpu::MailboxManager* mailbox_manager, + gpu::SharedImageRepresentationFactory* + shared_image_representation_factory, + gpu::SharedContextState* context_state, + gl::GLSurface* gl_surface, + scoped_refptr<gpu::gles2::FeatureInfo> feature_info, + gpu::MemoryTracker* memory_tracker, + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback); + class OverlayData; - // Use instead of calling FinishSwapBuffers() directly. On Windows this cleans - // up old entries in |overlays_|. - void DoFinishSwapBuffers(const gfx::Size& size, - OutputSurfaceFrame frame, - gfx::SwapCompletionResult result); - // Used as callback for SwapBuffersAsync and PostSubBufferAsync to finish - // operation - void DoFinishSwapBuffersAsync(const gfx::Size& size, - OutputSurfaceFrame frame, - gfx::SwapCompletionResult result); - gpu::OverlayImageRepresentation::ScopedReadAccess* BeginOverlayAccess( const gpu::Mailbox& mailbox); void CreateSkSurface(); + virtual bool ScheduleDCLayer( + std::unique_ptr<ui::DCRendererLayerParams> params) = 0; + + virtual gfx::Size GetRootSurfaceSize() const = 0; + + virtual gfx::SwapResult DoPostSubBuffer(const gfx::Rect& rect, + BufferPresentedCallback feedback, + gl::FrameData data) = 0; + // Mailboxes of overlays scheduled in the current frame. base::flat_set<gpu::Mailbox> scheduled_overlay_mailboxes_; @@ -102,21 +87,57 @@ shared_image_representation_factory_; const raw_ptr<gpu::SharedContextState> context_state_; - scoped_refptr<gl::GLSurface> gl_surface_; - const bool supports_async_swap_; - - uint64_t backbuffer_estimated_size_ = 0; - - gfx::Size size_; - SkColorType color_type_; - gfx::ColorSpace color_space_; - GrGLFramebufferInfo framebuffer_info_ = {}; - int sample_count_ = 1; - sk_sp<SkSurface> sk_surface_; base::WeakPtrFactory<SkiaOutputDeviceDComp> weak_ptr_factory_{this}; }; +// A DComp-backed OutputDevice whose root surface is wrapped in a GLSurface. +class VIZ_SERVICE_EXPORT SkiaOutputDeviceDCompGLSurface final + : public SkiaOutputDeviceDComp { + public: + SkiaOutputDeviceDCompGLSurface( + gpu::MailboxManager* mailbox_manager, + gpu::SharedImageRepresentationFactory* + shared_image_representation_factory, + gpu::SharedContextState* context_state, + scoped_refptr<gl::GLSurface> gl_surface, + scoped_refptr<gpu::gles2::FeatureInfo> feature_info, + gpu::MemoryTracker* memory_tracker, + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback); + + ~SkiaOutputDeviceDCompGLSurface() override; + + // SkiaOutputDevice implementation: + bool Reshape(const SkSurfaceCharacterization& characterization, + const gfx::ColorSpace& color_space, + float device_scale_factor, + gfx::OverlayTransform transform) override; + bool SetDrawRectangle(const gfx::Rect& draw_rectangle) override; + void SetEnableDCLayers(bool enable) override; + void SetGpuVSyncEnabled(bool enabled) override; + SkSurface* BeginPaint( + std::vector<GrBackendSemaphore>* end_semaphores) override; + void EndPaint() override; + + protected: + bool ScheduleDCLayer( + std::unique_ptr<ui::DCRendererLayerParams> params) override; + gfx::Size GetRootSurfaceSize() const override; + gfx::SwapResult DoPostSubBuffer(const gfx::Rect& rect, + BufferPresentedCallback feedback, + gl::FrameData data) override; + + private: + scoped_refptr<gl::GLSurface> gl_surface_; + + gfx::Size size_; + gfx::ColorSpace color_space_; + GrGLFramebufferInfo framebuffer_info_ = {}; + sk_sp<SkSurface> sk_surface_; + + uint64_t backbuffer_estimated_size_ = 0; +}; + } // namespace viz #endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_DCOMP_H_
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc index 11529228..d5da933 100644 --- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -14,7 +14,6 @@ #include "components/viz/common/gpu/vulkan_context_provider.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/config/gpu_finch_features.h" -#include "gpu/ipc/common/gpu_surface_lookup.h" #include "gpu/vulkan/vulkan_fence_helper.h" #include "gpu/vulkan/vulkan_function_pointers.h" #include "gpu/vulkan/vulkan_implementation.h" @@ -28,6 +27,7 @@ #if BUILDFLAG(IS_ANDROID) #include <android/native_window_jni.h> +#include "gpu/ipc/common/gpu_surface_lookup.h" #include "ui/gl/android/scoped_a_native_window.h" #include "ui/gl/android/scoped_java_surface.h" #endif
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 59b7970..394aec6 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -1750,7 +1750,7 @@ } else { #if BUILDFLAG(IS_WIN) if (gl_surface_->SupportsDCLayers()) { - output_device_ = std::make_unique<SkiaOutputDeviceDComp>( + output_device_ = std::make_unique<SkiaOutputDeviceDCompGLSurface>( dependency_->GetMailboxManager(), shared_image_representation_factory_.get(), context_state_.get(), gl_surface_, feature_info_,
diff --git a/components/webxr/android/arcore_java_utils.cc b/components/webxr/android/arcore_java_utils.cc index 028a871..7d41876 100644 --- a/components/webxr/android/arcore_java_utils.cc +++ b/components/webxr/android/arcore_java_utils.cc
@@ -13,6 +13,7 @@ #include "device/vr/android/arcore/arcore_shim.h" #include "gpu/ipc/common/gpu_surface_tracker.h" #include "ui/android/window_android.h" +#include "ui/gl/android/scoped_java_surface.h" using base::android::AttachCurrentThread; using base::android::ScopedJavaLocalRef; @@ -80,7 +81,8 @@ gpu::SurfaceHandle surface_handle = gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget( gpu::GpuSurfaceTracker::SurfaceRecord( - window, surface, /*can_be_used_with_surface_control=*/false)); + gl::ScopedJavaSurface(surface, /*auto_release=*/false), + /*can_be_used_with_surface_control=*/false)); ui::WindowAndroid* root_window = ui::WindowAndroid::FromJavaWindowAndroid(java_root_window); display::Display::Rotation display_rotation =
diff --git a/components/webxr/mailbox_to_surface_bridge_impl.cc b/components/webxr/mailbox_to_surface_bridge_impl.cc index eed2e4b..c54cfae3 100644 --- a/components/webxr/mailbox_to_surface_bridge_impl.cc +++ b/components/webxr/mailbox_to_surface_bridge_impl.cc
@@ -220,10 +220,9 @@ gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get(); ANativeWindow_acquire(window); // Skip ANativeWindow_setBuffersGeometry, the default size appears to work. - surface_ = std::make_unique<gl::ScopedJavaSurface>(surface_texture); surface_handle_ = tracker->AddSurfaceForNativeWidget(gpu::GpuSurfaceTracker::SurfaceRecord( - window, surface_->j_surface(), + gl::ScopedJavaSurface(surface_texture), false /* can_be_used_with_surface_control */)); // Unregistering happens in the destructor. ANativeWindow_release(window);
diff --git a/components/webxr/mailbox_to_surface_bridge_impl.h b/components/webxr/mailbox_to_surface_bridge_impl.h index 2eb12c30..fc996c05d 100644 --- a/components/webxr/mailbox_to_surface_bridge_impl.h +++ b/components/webxr/mailbox_to_surface_bridge_impl.h
@@ -88,7 +88,6 @@ void DrawQuad(unsigned int textureHandle, const gfx::Transform& uv_transform); scoped_refptr<viz::ContextProvider> context_provider_; - std::unique_ptr<gl::ScopedJavaSurface> surface_; raw_ptr<gpu::gles2::GLES2Interface> gl_ = nullptr; raw_ptr<gpu::ContextSupport> context_support_ = nullptr; int surface_handle_ = gpu::kNullSurfaceHandle;
diff --git a/content/app/android/content_child_process_service_delegate.cc b/content/app/android/content_child_process_service_delegate.cc index fbdd977..7acb6a65d 100644 --- a/content/app/android/content_child_process_service_delegate.cc +++ b/content/app/android/content_child_process_service_delegate.cc
@@ -76,7 +76,8 @@ return gl::ScopedJavaSurface(); gl::ScopedJavaSurface surface( - content::JNI_SurfaceWrapper_getSurface(env, surface_wrapper)); + content::JNI_SurfaceWrapper_takeSurface(env, surface_wrapper), + /*auto_release=*/true); DCHECK(!surface.j_surface().is_null()); *can_be_used_with_surface_control =
diff --git a/content/browser/android/dialog_overlay_impl.cc b/content/browser/android/dialog_overlay_impl.cc index 379bf3c..9e5a1b7 100644 --- a/content/browser/android/dialog_overlay_impl.cc +++ b/content/browser/android/dialog_overlay_impl.cc
@@ -327,8 +327,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); return gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget( gpu::GpuSurfaceTracker::SurfaceRecord( - gfx::kNullAcceleratedWidget, surface, - false /* can_be_used_with_surface_control */)); + gl::ScopedJavaSurface(surface, /*auto_release=*/false), + /*can_be_used_with_surface_control=*/false)); } static void JNI_DialogOverlayImpl_UnregisterSurface(
diff --git a/content/browser/android/gpu_process_callback.cc b/content/browser/android/gpu_process_callback.cc index aabd7bc..bfafcc1d 100644 --- a/content/browser/android/gpu_process_callback.cc +++ b/content/browser/android/gpu_process_callback.cc
@@ -30,7 +30,7 @@ base::android::ScopedJavaGlobalRef<jobject> jsurface; jsurface.Reset(env, surface); ScopedSurfaceRequestManager::GetInstance()->FulfillScopedSurfaceRequest( - requestToken, gl::ScopedJavaSurface(jsurface)); + requestToken, gl::ScopedJavaSurface(jsurface, /*auto_release=*/true)); } base::android::ScopedJavaLocalRef<jobject>
diff --git a/content/browser/attribution_reporting/attribution_internals.mojom b/content/browser/attribution_reporting/attribution_internals.mojom index dd9fb0c..8d908b6 100644 --- a/content/browser/attribution_reporting/attribution_internals.mojom +++ b/content/browser/attribution_reporting/attribution_internals.mojom
@@ -89,8 +89,9 @@ DebugReportStatus status; }; -struct DebugKey { - uint64 value; +union SourceDebugKey { + uint64 debug_key; + uint64 cleared_debug_key; }; // Struct representing a stored attribution source that will be displayed by WebUI. @@ -106,7 +107,7 @@ double aggregatable_report_window_time; attribution_reporting.mojom.SourceType source_type; int64 priority; - DebugKey? debug_key; + SourceDebugKey? debug_key; array<uint64> dedup_keys; map<string, array<string>> filter_data; // The value is a hex-encoded unsigned 128-bit integer. @@ -130,6 +131,10 @@ Attributability attributability; }; +struct TriggerDebugKey { + uint64 value; +}; + struct WebUITrigger { double trigger_time; url.mojom.Origin destination_origin; @@ -137,6 +142,7 @@ // String instead of mojo_base.mojom.DictionaryValue because the value is // simply displayed in the UI, never inspected. string registration_json; + TriggerDebugKey? cleared_debug_key; enum Status { // Shared statuses: @@ -176,21 +182,6 @@ attribution_reporting.mojom.SourceRegistrationError error; }; -// Struct containing details for a debug key that was removed from a source or -// trigger due to a missing cookie to be displayed as a log by WebUI -struct ClearedDebugKey { - double time; - url.mojom.Origin reporting_origin; - DebugKey cleared_debug_key; - - enum Type { - kTrigger, - kSource, - }; - - Type cleared_from; -}; - // Observer for events relevant to the attribution internals WebUI. interface Observer { // Called when the sources in storage changed, indicating that the observer @@ -219,9 +210,6 @@ // Called when the source header registration JSON parser fails. OnFailedSourceRegistration(FailedSourceRegistration failure); - - // Called when a debug key was removed from a source or trigger due to a missing cookie. - OnDebugKeyCleared(ClearedDebugKey notification); }; // Mojo interface for the attribution internals WebUI to communicate with the
diff --git a/content/browser/attribution_reporting/attribution_internals_browsertest.cc b/content/browser/attribution_reporting/attribution_internals_browsertest.cc index abe25398..d95e016 100644 --- a/content/browser/attribution_reporting/attribution_internals_browsertest.cc +++ b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
@@ -299,7 +299,8 @@ manager()->NotifySourceHandled( SourceBuilder(now + base::Hours(5)).Build(), - StorableSource::Result::kInsufficientSourceCapacity); + StorableSource::Result::kInsufficientSourceCapacity, + /*cleared_debug_key=*/987); manager()->NotifySourceHandled( SourceBuilder(now + base::Hours(6)).Build(), @@ -327,6 +328,7 @@ table.children[1].children[13]?.innerText === "1300 / 65536" && table.children[0].children[14]?.innerText === "19" && table.children[1].children[14]?.innerText === "" && + table.children[4].children[14]?.innerText === 'Cleared (was 987)' && table.children[0].children[15]?.innerText === "" && table.children[1].children[15]?.innerText === "13, 17" && table.children[0].children[16]?.innerText === "" && @@ -392,89 +394,6 @@ } IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, - ClearedDebugKeyFromSource_LogShown) { - ASSERT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); - - static constexpr char wait_script[] = R"( - const table = document.querySelector('#logTable') - .shadowRoot.querySelector('tbody'); - - const description = '<a href="https://github.com/WICG/attribution-report' + - 'ing-api/blob/main/EVENT.md#attribution-success-debugging-' + - 'reports" target="_blank">Cleared Debug Key</a>'; - const metadata = '<dl><dt>Cleared Debug Key</dt><dd>1234</dd>' + - '<dt>From</dt><dd>Source</dd>'+ - '<dt>Reporting Origin</dt><dd>https://report.test</dd></dl>'; - - let obs = new MutationObserver((_, obs) => { - if (table.children.length === 1 && - table.children[0].children[1]?.innerHTML === description && - table.children[0].children[2]?.innerHTML === metadata - ) { - obs.disconnect(); - document.title = $1; - } - }); - obs.observe(table, {childList: true, subtree: true, characterData: true});)"; - - ASSERT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle))); - - TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle); - - manager()->NotifySourceHandled(SourceBuilder().Build(), - StorableSource::Result::kSuccess, - /*cleared_debug_key=*/1234); - - EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); -} - -IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, - ClearedDebugKeyFromTrigger_LogShown) { - ASSERT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); - - static constexpr char wait_script[] = R"( - const table = document.querySelector('#logTable') - .shadowRoot.querySelector('tbody'); - - const description = '<a href="https://github.com/WICG/attribution-report' + - 'ing-api/blob/main/EVENT.md#attribution-success-debugging-' + - 'reports" target="_blank">Cleared Debug Key</a>'; - const metadata = '<dl><dt>Cleared Debug Key</dt><dd>1234</dd>' + - '<dt>From</dt><dd>Trigger</dd>'+ - '<dt>Reporting Origin</dt><dd>https://report.test</dd></dl>'; - - let obs = new MutationObserver((_, obs) => { - if (table.children.length === 1 && - table.children[0].children[1]?.innerHTML === description && - table.children[0].children[2]?.innerHTML === metadata - ) { - obs.disconnect(); - document.title = $1; - } - }); - obs.observe(table, {childList: true, subtree: true, characterData: true});)"; - - ASSERT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle))); - - TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle); - - manager()->NotifyTriggerHandled( - DefaultTrigger(), - CreateReportResult( - /*trigger_time=*/base::Time::Now(), - /*event_level_status=*/AttributionTrigger::EventLevelResult::kSuccess, - /*aggregatable_status=*/ - AttributionTrigger::AggregatableResult::kSuccess, - /*replaced_event_level_report=*/absl::nullopt, - /*new_event_level_report=*/IrreleventEventLevelReport(), - /*new_aggregatable_report=*/IrreleventAggregatableReport(), - /*source=*/SourceBuilder().BuildStored()), - /*cleared_debug_key=*/1234); - - EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); -} - -IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIShownWithNoReports_NoReportsDisplayed) { ASSERT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); @@ -1091,12 +1010,14 @@ let table = document.querySelector('#triggerTable') .shadowRoot.querySelector('tbody'); let obs = new MutationObserver((_, obs) => { - if (table.children.length === 1 && + if (table.children.length === 2 && table.children[0].children[1]?.innerText === "Success: Report stored" && table.children[0].children[2]?.innerText === "Success: Report stored" && table.children[0].children[3]?.innerText === "https://d.test" && table.children[0].children[4]?.innerText === "https://r.test" && - table.children[0].children[5]?.innerText.includes('{')) { + table.children[0].children[5]?.innerText.includes('{') && + table.children[0].children[6]?.innerText === '' && + table.children[1].children[6]?.innerText === '123') { obs.disconnect(); document.title = $1; } @@ -1106,7 +1027,8 @@ auto notify_trigger_handled = [&](AttributionTrigger::EventLevelResult event_status, - AttributionTrigger::AggregatableResult aggregatable_status) { + AttributionTrigger::AggregatableResult aggregatable_status, + absl::optional<uint64_t> cleared_debug_key = absl::nullopt) { static int offset_hours = 0; manager()->NotifyTriggerHandled( trigger, @@ -1116,12 +1038,17 @@ /*replaced_event_level_report=*/absl::nullopt, /*new_event_level_report=*/IrreleventEventLevelReport(), /*new_aggregatable_report=*/IrreleventAggregatableReport(), - /*source=*/SourceBuilder().BuildStored())); + /*source=*/SourceBuilder().BuildStored()), + cleared_debug_key); }; notify_trigger_handled(AttributionTrigger::EventLevelResult::kSuccess, AttributionTrigger::AggregatableResult::kSuccess); + notify_trigger_handled(AttributionTrigger::EventLevelResult::kSuccess, + AttributionTrigger::AggregatableResult::kSuccess, + /*cleared_debug_key=*/123); + // TODO(apaseltiner): Add tests for other statuses. TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc index 1896281..f0b6bf0 100644 --- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc +++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -54,34 +54,38 @@ using Attributability = ::attribution_internals::mojom::WebUISource::Attributability; -using SourceOrTrigger = ::attribution_internals::mojom::ClearedDebugKey::Type; using Empty = ::attribution_internals::mojom::Empty; using ReportStatus = ::attribution_internals::mojom::ReportStatus; using ReportStatusPtr = ::attribution_internals::mojom::ReportStatusPtr; using ::attribution_internals::mojom::WebUIDebugReport; -attribution_internals::mojom::DebugKeyPtr WebUIDebugKey( - absl::optional<uint64_t> debug_key) { - return debug_key ? attribution_internals::mojom::DebugKey::New(*debug_key) - : nullptr; -} - attribution_internals::mojom::WebUISourcePtr WebUISource( const CommonSourceInfo& source, Attributability attributability, const std::vector<uint64_t>& dedup_keys, int64_t aggregatable_budget_consumed, const std::vector<uint64_t>& aggregatable_dedup_keys, - bool debug_reporting_enabled) { + bool debug_reporting_enabled, + absl::optional<uint64_t> cleared_debug_key) { DCHECK_GE(aggregatable_budget_consumed, 0); + + attribution_internals::mojom::SourceDebugKeyPtr debug_key = + cleared_debug_key + ? attribution_internals::mojom::SourceDebugKey::NewClearedDebugKey( + *cleared_debug_key) + : (source.debug_key() + ? attribution_internals::mojom::SourceDebugKey::NewDebugKey( + *source.debug_key()) + : nullptr); + return attribution_internals::mojom::WebUISource::New( source.source_event_id(), source.source_origin(), source.DestinationSite().Serialize(), source.reporting_origin(), source.source_time().ToJsTime(), source.expiry_time().ToJsTime(), source.event_report_window_time().ToJsTime(), source.aggregatable_report_window_time().ToJsTime(), source.source_type(), - source.priority(), WebUIDebugKey(source.debug_key()), dedup_keys, + source.priority(), std::move(debug_key), dedup_keys, source.filter_data().filter_values(), base::MakeFlatMap<std::string, std::string>( source.aggregation_keys().keys(), {}, @@ -125,7 +129,8 @@ web_ui_sources.push_back(WebUISource( source.common_info(), attributability, source.dedup_keys(), source.aggregatable_budget_consumed(), source.aggregatable_dedup_keys(), - /*debug_reporting_enabled=*/false)); + /*debug_reporting_enabled=*/false, + /*cleared_debug_key=*/absl::nullopt)); } std::move(web_ui_callback).Run(std::move(web_ui_sources)); @@ -298,18 +303,6 @@ absl::optional<uint64_t> cleared_debug_key, StorableSource::Result result) { Attributability attributability; - if (cleared_debug_key.has_value()) { - auto web_ui_log = attribution_internals::mojom::ClearedDebugKey::New(); - web_ui_log->cleared_debug_key = WebUIDebugKey(cleared_debug_key.value()); - web_ui_log->time = source.common_info().source_time().ToJsTime(); - web_ui_log->reporting_origin = source.common_info().reporting_origin(); - web_ui_log->cleared_from = SourceOrTrigger::kSource; - - for (auto& observer : observers_) { - observer->OnDebugKeyCleared(web_ui_log.Clone()); - } - } - switch (result) { case StorableSource::Result::kSuccess: // TODO(linnan): Consider displaying source noised in internals UI. @@ -335,7 +328,8 @@ auto web_ui_source = WebUISource(source.common_info(), attributability, /*dedup_keys=*/{}, /*aggregatable_budget_consumed=*/0, - /*aggregatable_dedup_keys=*/{}, source.debug_reporting()); + /*aggregatable_dedup_keys=*/{}, source.debug_reporting(), + cleared_debug_key); for (auto& observer : observers_) { observer->OnSourceRejected(web_ui_source.Clone()); @@ -496,17 +490,6 @@ const attribution_reporting::TriggerRegistration& registration = trigger.registration(); - if (cleared_debug_key.has_value()) { - auto web_ui_log = attribution_internals::mojom::ClearedDebugKey::New(); - web_ui_log->cleared_debug_key = WebUIDebugKey(cleared_debug_key.value()); - web_ui_log->time = result.trigger_time().ToJsTime(); - web_ui_log->reporting_origin = trigger.reporting_origin(); - web_ui_log->cleared_from = SourceOrTrigger::kTrigger; - - for (auto& observer : observers_) { - observer->OnDebugKeyCleared(web_ui_log.Clone()); - } - } auto web_ui_trigger = attribution_internals::mojom::WebUITrigger::New(); web_ui_trigger->trigger_time = result.trigger_time().ToJsTime(); web_ui_trigger->destination_origin = trigger.destination_origin(); @@ -514,6 +497,10 @@ web_ui_trigger->registration_json = SerializeAttributionJson(registration.ToJson(), /*pretty_print=*/true); + web_ui_trigger->cleared_debug_key = + cleared_debug_key ? attribution_internals::mojom::TriggerDebugKey::New( + *cleared_debug_key) + : nullptr; web_ui_trigger->event_level_status = GetWebUITriggerStatus(result.event_level_status()); web_ui_trigger->aggregatable_status =
diff --git a/content/browser/back_forward_cache_no_store_browsertest.cc b/content/browser/back_forward_cache_no_store_browsertest.cc index 3262bdcc..194674c 100644 --- a/content/browser/back_forward_cache_no_store_browsertest.cc +++ b/content/browser/back_forward_cache_no_store_browsertest.cc
@@ -750,12 +750,12 @@ namespace { // Causes a fetch using the "Authorization" header to start and complete in the // target frame. -void UseAuthorizationHeaderFetch(const ToRenderFrameHost& execution_target, - const GURL& url) { +void UseAuthorizationHeader(const ToRenderFrameHost& execution_target, + GURL url) { ASSERT_EQ(42, EvalJs(execution_target, JsReplace( R"( fetch($1, {headers: {Authorization: 'foo'}}) - .then(p => { + .then(p => { // Ensure that we drain the pipe to avoid blocking on network // activity. p.text(); @@ -765,23 +765,6 @@ url))); } -// Causes an XHR using the "Authorization" header to start and complete in the -// target frame. -void UseAuthorizationHeaderXhr(const ToRenderFrameHost& execution_target, - const GURL& url) { - ASSERT_EQ(42, EvalJs(execution_target, JsReplace( - R"( - const xhr = new XMLHttpRequest(); - xhr.open('GET', $1); - xhr.setRequestHeader('Authorization', 'foo'); - xhr.send(); - new Promise(resolve => { - xhr.onload = () => {resolve(42)}; - }); - )", - url))); -} - // Creates an iframe in the target frame with this url. It waits until the frame // has loaded. void CreateIframe(const ToRenderFrameHost& execution_target, GURL url) { @@ -798,49 +781,9 @@ } } // namespace -enum class RequestType { - kFetch, - kXhr, -}; - -class BackForwardCacheAuthorizationHeaderBrowserTest - : public BackForwardCacheBrowserTest, - public ::testing::WithParamInterface<RequestType> { - public: - // Provides meaningful param names instead of /0 and /1. - static std::string DescribeParams( - const ::testing::TestParamInfo<ParamType>& info) { - switch (info.param) { - case RequestType::kFetch: - return "Fetch"; - case RequestType::kXhr: - return "XHR"; - } - } - - protected: - // Make a request using the appropriate method. - void UseAuthorizationHeader(const ToRenderFrameHost& execution_target, - GURL url) { - switch (GetParam()) { - case RequestType::kFetch: - UseAuthorizationHeaderFetch(execution_target, url); - break; - case RequestType::kXhr: - UseAuthorizationHeaderXhr(execution_target, url); - break; - } - } -}; -INSTANTIATE_TEST_SUITE_P( - All, - BackForwardCacheAuthorizationHeaderBrowserTest, - ::testing::Values(RequestType::kFetch, RequestType::kXhr), - &BackForwardCacheAuthorizationHeaderBrowserTest::DescribeParams); - -// Test that a page without CCNS that makes a request with the "Authorization" +// Test that a page without CCNS that makes a fetch with the "Authorization" // header does not log the header. -IN_PROC_BROWSER_TEST_P(BackForwardCacheAuthorizationHeaderBrowserTest, +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, AuthorizationHeaderNotLogged) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -851,7 +794,7 @@ ASSERT_TRUE(NavigateToURL(shell(), url_a)); RenderFrameHostImplWrapper rfh_a(current_frame_host()); - // Make a request with the "Authorization" header in the main frame. + // Do a fetch with the "Authorization" header in the main frame. UseAuthorizationHeader(shell(), url_a); // Navigate away. @@ -865,9 +808,9 @@ ExpectRestored(FROM_HERE); } -// Test that a page with CCNS that makes a request with the "Authorization" -// header logs the header. -IN_PROC_BROWSER_TEST_P(BackForwardCacheAuthorizationHeaderBrowserTest, +// Test that a page with CCNS that makes a fetch with the "Authorization" header +// logs the header. +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, AuthorizationHeaderLoggedMainFrame) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -880,7 +823,7 @@ ASSERT_TRUE(NavigateToURL(shell(), url_a_no_store)); RenderFrameHostImplWrapper rfh_a(current_frame_host()); - // Make a request with the "Authorization" header in the main frame. + // Do a fetch with the "Authorization" header in the main frame. UseAuthorizationHeader(shell(), url_a_2); // Navigate away. @@ -897,10 +840,9 @@ {}, {}, {}, FROM_HERE); } -// Test that a page with CCNS that makes a request with the "Authorization" -// header in a same-as-root-origin subframe of a cross-origin subframe logs the -// header. -IN_PROC_BROWSER_TEST_P(BackForwardCacheAuthorizationHeaderBrowserTest, +// Test that a page with CCNS that makes a fetch with the "Authorization" header +// in a same-as-root-origin subframe of a cross-origin subframe logs the header. +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, AuthorizationHeaderSameOriginSubFrameLogged) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -914,8 +856,7 @@ RenderFrameHostImplWrapper rfh_a(current_frame_host()); // Create a cross-origin iframe with same-as-root-origin iframe inside that - // and make a request with the "Authorization" header in that grand-child - // iframe. + // and do a fetch with the "Authorization" header in that grand-child iframe. CreateIframe(rfh_a.get(), url_b); CreateIframe(DescendantRenderFrameHostImplAt(rfh_a.get(), {0}), url_a_2); @@ -936,10 +877,10 @@ {}, {}, {}, FROM_HERE); } -// Test that a page with CCNS that makes a request with the "Authorization" -// header in a same-origin subframe logs the header in the correct place in the -// tree of reasons. -IN_PROC_BROWSER_TEST_P(BackForwardCacheAuthorizationHeaderBrowserTest, +// Test that a page with CCNS that makes a fetch with the "Authorization" header +// in a same-origin subframe logs the header in the correct place in the tree of +// reasons. +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, AuthorizationHeaderSubFrameTree) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -952,7 +893,7 @@ ASSERT_TRUE(NavigateToURL(shell(), url_a_no_store)); RenderFrameHostImplWrapper rfh_a(current_frame_host()); - // Create a same-origin iframe make a request with the "Authorization" header. + // Create a same-origin iframe do a fetch with the "Authorization" header. CreateIframe(rfh_a.get(), url_a_2); UseAuthorizationHeader(DescendantRenderFrameHostImplAt(rfh_a.get(), {0}), @@ -989,9 +930,9 @@ {subframe_result}))); } -// Test that a page with CCNS that makes a request with the "Authorization" -// header in a cross-origin subframe does not log the header. -IN_PROC_BROWSER_TEST_P(BackForwardCacheAuthorizationHeaderBrowserTest, +// Test that a page with CCNS that makes a fetch with the "Authorization" header +// in a cross-origin subframe does not log the header. +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, AuthorizationHeaderCrossOriginSubFrameNotLogged) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -1004,8 +945,8 @@ ASSERT_TRUE(NavigateToURL(shell(), url_a_no_store)); RenderFrameHostImplWrapper rfh_a(current_frame_host()); - // Create an same-origin iframe and make a request with the "Authorization" - // header in that iframe. + // Create an same-origin iframe and do a fetch with the "Authorization" header + // in that iframe. CreateIframe(rfh_a.get(), url_b); UseAuthorizationHeader(DescendantRenderFrameHostImplAt(rfh_a.get(), {0}), @@ -1069,9 +1010,7 @@ } // Test that a page with CCNS that makes a fetch with the "Authorization" header -// is blocked even when CCNS pages are allowed to be restored. This only tests -// fetch, the blocking mechanism is the same for all kinds of requests, so if it -// works for one it will work for all. +// is blocked even when CCNS pages are allowed to be restored. IN_PROC_BROWSER_TEST_F( BackForwardCacheBrowserTestRestoreCacheControlNoStoreUnlessCookieChange, AuthorizationHeaderBlocks) { @@ -1086,8 +1025,8 @@ ASSERT_TRUE(NavigateToURL(shell(), url_a_no_store)); RenderFrameHostImplWrapper rfh_a(current_frame_host()); - // Make a request with the "Authorization" header in the main frame. - UseAuthorizationHeaderFetch(shell(), url_a_2); + // Do a fetch with the "Authorization" header in the main frame. + UseAuthorizationHeader(shell(), url_a_2); // Navigate away. ASSERT_TRUE(NavigateToURL(shell(), url_b));
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc index 25d1eaf..12805d2 100644 --- a/content/browser/child_process_security_policy_unittest.cc +++ b/content/browser/child_process_security_policy_unittest.cc
@@ -3221,6 +3221,9 @@ ProcessLock::FromSiteInfo(bar_instance->GetSiteInfo())); }, "Cannot lock an already used process to .*bar\\.com"); + + // We need to remove it otherwise other tests may fail. + p->Remove(kRendererID); } } // namespace content
diff --git a/content/browser/file_system/file_system_manager_impl.cc b/content/browser/file_system/file_system_manager_impl.cc index cf6639ba..21cd61d 100644 --- a/content/browser/file_system/file_system_manager_impl.cc +++ b/content/browser/file_system/file_system_manager_impl.cc
@@ -993,6 +993,28 @@ RegisterBlobCallback callback) { storage::FileSystemURL crack_url = context_->CrackURL(url, receivers_.current_context()); + + content::GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult( + FROM_HERE, + // security_policy_ is a singleton so refcounting is unnecessary + base::BindOnce(&ChildProcessSecurityPolicyImpl::CanReadFileSystemFile, + base::Unretained(security_policy_), process_id_, + crack_url), + base::BindOnce(&FileSystemManagerImpl::ContinueRegisterBlob, + weak_factory_.GetWeakPtr(), content_type, url, length, + expected_modification_time, std::move(callback), + crack_url)); +} + +void FileSystemManagerImpl::ContinueRegisterBlob( + const std::string& content_type, + const GURL& url, + uint64_t length, + absl::optional<base::Time> expected_modification_time, + RegisterBlobCallback callback, + storage::FileSystemURL crack_url, + bool security_check_success) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); std::string uuid = base::GenerateGUID(); mojo::PendingRemote<blink::mojom::Blob> blob_remote; mojo::PendingReceiver<blink::mojom::Blob> blob_receiver = @@ -1000,7 +1022,7 @@ if (crack_url.is_valid() && context_->GetFileSystemBackend(crack_url.type()) && - security_policy_->CanReadFileSystemFile(process_id_, crack_url)) { + security_check_success) { blob_storage_context_->CreateFileSystemBlob( context_, std::move(blob_receiver), crack_url, uuid, content_type, length, expected_modification_time.value_or(base::Time()));
diff --git a/content/browser/file_system/file_system_manager_impl.h b/content/browser/file_system/file_system_manager_impl.h index 4e84e97..d89a708 100644 --- a/content/browser/file_system/file_system_manager_impl.h +++ b/content/browser/file_system/file_system_manager_impl.h
@@ -209,6 +209,15 @@ void ContinueCreateSnapshotFile(const storage::FileSystemURL& url, CreateSnapshotFileCallback callback, bool security_check_success); + void ContinueRegisterBlob( + const std::string& content_type, + const GURL& url, + uint64_t length, + absl::optional<base::Time> expected_modification_time, + RegisterBlobCallback callback, + storage::FileSystemURL crack_url, + bool security_check_success); + void Cancel( OperationID op_id, blink::mojom::FileSystemCancellableOperation::CancelCallback callback);
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 63f23b3..de753e5 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -111,10 +111,6 @@ #include "content/common/zygote/zygote_handle_impl_linux.h" #endif -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) -#include "gpu/ipc/common/gpu_surface_tracker.h" -#endif - #if BUILDFLAG(IS_MAC) #include "content/browser/gpu/ca_transaction_gpu_coordinator.h" #endif
diff --git a/content/browser/loader/web_transport_browsertest.cc b/content/browser/loader/web_transport_browsertest.cc index 72730c9a..a198023 100644 --- a/content/browser/loader/web_transport_browsertest.cc +++ b/content/browser/loader/web_transport_browsertest.cc
@@ -108,5 +108,44 @@ ASSERT_TRUE(WaitForTitle(u"PASS", {u"FAIL"})); } +// A test that aims to reproduce https://crbug.com/1369030 -- note that since +// the bug in question is a race condition, this test will probably be flaky if +// this is actually broken. +IN_PROC_BROWSER_TEST_F(WebTransportBrowserTest, EchoLargeBidirectionalStreams) { + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"))); + + ASSERT_TRUE(WaitForTitle(u"Title Of Awesomeness")); + + ASSERT_TRUE( + ExecJs(shell(), base::StringPrintf(R"JS( + async function run() { + const transport = new WebTransport('https://localhost:%d/echo'); + await transport.ready; + + const numBytes = 1024 * 1024; + const numStreams = 5; + for (let i = 0; i < numStreams; i++) { + const stream = await transport.createBidirectionalStream(); + const writer = stream.writable.getWriter(); + await writer.write(new Uint8Array(numBytes)); + await writer.close(); + let response = await (new Response(stream.readable).arrayBuffer()); + if (response.byteLength != numBytes) { + throw Error('Size mismatch, received size: ' + + response.byteLength.toString()); + } + } + } + + run().then(() => { document.title = 'PASS'; }, + (e) => { console.log(e); document.title = 'FAIL'; }); +)JS", + server_.server_address().port()))); + + ASSERT_TRUE(WaitForTitle(u"PASS", {u"FAIL"})); +} + } // namespace } // namespace content
diff --git a/content/browser/media/cdm_registry_impl.cc b/content/browser/media/cdm_registry_impl.cc index 3dc2047..d577857d 100644 --- a/content/browser/media/cdm_registry_impl.cc +++ b/content/browser/media/cdm_registry_impl.cc
@@ -188,29 +188,6 @@ {media::CdmSessionType::kTemporary}); } -// Software secure capability can be obtained synchronously in all supported -// cases. If needed, this can be easily converted to an asynchronous call. -absl::optional<media::CdmCapability> GetSoftwareSecureCapability( - const CdmRegistryImpl& cdm_registry_impl, - const std::string& key_system) { - auto cdm_info = cdm_registry_impl.GetCdmInfo( - key_system, CdmInfo::Robustness::kSoftwareSecure); - if (!cdm_info) { - ReportSoftwareSecureCdmAvailableUMA(key_system, false); - return absl::nullopt; - } - - ReportSoftwareSecureCdmAvailableUMA(key_system, true); - - if (!cdm_info->capability) { - DVLOG(1) << "Lazy initialization of SoftwareSecure CdmCapability not " - "supported!"; - return absl::nullopt; - } - - return cdm_info->capability; -} - #if BUILDFLAG(IS_WIN) bool IsMediaFoundationHardwareSecurityDisabledByGpuFeature() { auto* gpu_data_manager = GpuDataManagerImpl::GetInstance(); @@ -226,71 +203,6 @@ } #endif // BUILDFLAG(IS_WIN) -// Trying to get hardware secure capability synchronously. If lazy -// initialization is needed, set `lazy_initialize` to true. -std::tuple<absl::optional<media::CdmCapability>, CdmInfo::Status> -GetHardwareSecureCapability(const CdmRegistryImpl& cdm_registry_impl, - const std::string& key_system) { - using Status = CdmInfo::Status; - -#if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kLacrosUseChromeosProtectedMedia)) { - return {absl::nullopt, Status::kHardwareSecureDecryptionDisabled}; - } -#elif !BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) - if (!media::IsHardwareSecureDecryptionEnabled()) { - DVLOG(1) << "Hardware secure decryption disabled"; - return {absl::nullopt, Status::kHardwareSecureDecryptionDisabled}; - } -#endif // !BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) - - // Secure codecs override takes precedence over other checks. - auto overridden_capability = - GetHardwareSecureCapabilityOverriddenFromCommandLine(); - if (overridden_capability) { - DVLOG(1) << "Hardware secure codecs overridden from command line"; - return {overridden_capability, Status::kCommandLineOverridden}; - } - - // Hardware secure video codecs need hardware video decoder support. - // TODO(xhwang): Make sure this check is as close as possible to the check - // in the render process. For example, also check check GPU features like - // GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE. - auto* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line && - command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { - DVLOG(1) << "Hardware security not supported because accelerated video " - "decode disabled"; - return {absl::nullopt, Status::kAcceleratedVideoDecodeDisabled}; - } - -#if BUILDFLAG(IS_WIN) - if (IsMediaFoundationHardwareSecurityDisabledByGpuFeature()) { - DVLOG(1) << "Hardware security not supported: GPU workarounds"; - return {absl::nullopt, Status::kGpuFeatureDisabled}; - } - - if (IsGpuHardwareCompositionDisabled()) { - DVLOG(1) << "Hardware security not supported: GPU composition disabled"; - return {absl::nullopt, Status::kGpuCompositionDisabled}; - } -#endif // BUILDFLAG(IS_WIN) - - auto cdm_info = cdm_registry_impl.GetCdmInfo( - key_system, CdmInfo::Robustness::kHardwareSecure); - if (!cdm_info) { - DVLOG(1) << "No Hardware secure decryption CDM registered"; - return {absl::nullopt, Status::kEnabled}; - } - - DCHECK(!(cdm_info->status == CdmInfo::Status::kUninitialized && - cdm_info->capability)) - << "Capability should not have value if uninitialized."; - - return {cdm_info->capability, cdm_info->status}; -} - } // namespace // static @@ -326,7 +238,7 @@ void CdmRegistryImpl::RegisterCdm(const CdmInfo& info) { DVLOG(1) << __func__ << ": key_system=" << info.key_system - << ", robustness=" << static_cast<int>(info.robustness) + << ", robustness=" << info.robustness << ", status=" << static_cast<int>(info.status); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -399,7 +311,8 @@ std::unique_ptr<CdmInfo> CdmRegistryImpl::GetCdmInfo( const std::string& key_system, CdmInfo::Robustness robustness) const { - DVLOG(2) << __func__; + DVLOG(2) << __func__ << ": key_system=" << key_system + << ", robustness=" << robustness; DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (const auto& cdm : cdms_) { @@ -417,7 +330,7 @@ key_system_capabilities_update_callbacks_.AddUnsafe(cb); - if (!pending_lazy_initialize_key_systems_.empty()) { + if (!pending_lazy_initializations_.empty()) { // Lazy initializing some key systems. All callbacks will be notified when // that's finished. return; @@ -431,6 +344,84 @@ FinalizeKeySystemCapabilities(); } +std::pair<absl::optional<media::CdmCapability>, CdmInfo::Status> +CdmRegistryImpl::GetCapability(const std::string& key_system, + CdmInfo::Robustness robustness) { + DVLOG(2) << __func__ << ": key_system=" << key_system + << ", robustness=" << robustness; + using Status = CdmInfo::Status; + + if (robustness == CdmInfo::Robustness::kHardwareSecure) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kLacrosUseChromeosProtectedMedia)) { + return {absl::nullopt, Status::kHardwareSecureDecryptionDisabled}; + } +#elif !BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) + if (!media::IsHardwareSecureDecryptionEnabled()) { + DVLOG(1) << "Hardware secure decryption disabled"; + return {absl::nullopt, Status::kHardwareSecureDecryptionDisabled}; + } +#endif // !BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) + + // Secure codecs override takes precedence over other checks. + auto overridden_capability = + GetHardwareSecureCapabilityOverriddenFromCommandLine(); + if (overridden_capability) { + DVLOG(1) << "Hardware secure codecs overridden from command line"; + return {overridden_capability, Status::kCommandLineOverridden}; + } + + // Hardware secure video codecs need hardware video decoder support. + // TODO(xhwang): Make sure this check is as close as possible to the check + // in the render process. For example, also check check GPU features like + // GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE. + auto* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line && + command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { + DVLOG(1) << "Hardware security not supported because accelerated video " + "decode disabled"; + return {absl::nullopt, Status::kAcceleratedVideoDecodeDisabled}; + } + +#if BUILDFLAG(IS_WIN) + if (IsMediaFoundationHardwareSecurityDisabledByGpuFeature()) { + DVLOG(1) << "Hardware security not supported: GPU workarounds"; + return {absl::nullopt, Status::kGpuFeatureDisabled}; + } + + if (IsGpuHardwareCompositionDisabled()) { + DVLOG(1) << "Hardware security not supported: GPU composition disabled"; + return {absl::nullopt, Status::kGpuCompositionDisabled}; + } +#endif // BUILDFLAG(IS_WIN) + } + + auto cdm_info = GetCdmInfo(key_system, robustness); + if (!cdm_info) { + DVLOG(1) << "No " << robustness << " decryption CDM registered for " + << key_system; + return {absl::nullopt, Status::kEnabled}; + } + + DCHECK(!(cdm_info->status == Status::kUninitialized && cdm_info->capability)) + << "Capability for " << robustness << " " << key_system + << " should not have value if uninitialized."; + + return {cdm_info->capability, cdm_info->status}; +} + +std::pair<absl::optional<media::CdmCapability>, CdmInfo::Status> +CdmRegistryImpl::GetFinalCapability(const std::string& key_system, + CdmInfo::Robustness robustness) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + const auto [capability, status] = GetCapability(key_system, robustness); + DCHECK(status != CdmInfo::Status::kUninitialized); + + return {IsEnabled(status) ? capability : absl::nullopt, status}; +} + void CdmRegistryImpl::FinalizeKeySystemCapabilities() { DVLOG(2) << __func__; DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -438,7 +429,7 @@ // Abort existing pending LazyInitializeHardwareSecureCapability() operations // to avoid updating the observer twice. - pending_lazy_initialize_key_systems_.clear(); + pending_lazy_initializations_.clear(); weak_ptr_factory_.InvalidateWeakPtrs(); // Get the set of supported key systems in case two CDMs are registered with @@ -446,87 +437,100 @@ // while iterating through it. std::set<std::string> supported_key_systems = GetSupportedKeySystems(); - // Finalize hardware secure capabilities for all key systems. (Assumes - // software secure capabilities are always already finalized.) + // Finalize software secure capabilities for all key systems. for (const auto& key_system : supported_key_systems) { - auto cdm_info = - GetCdmInfo(key_system, CdmInfo::Robustness::kHardwareSecure); - if (!cdm_info) { - DVLOG(1) << "No Hardware secure CDM registered"; - continue; + for (const auto robustness : {CdmInfo::Robustness::kSoftwareSecure, + CdmInfo::Robustness::kHardwareSecure}) { + AttemptToFinalizeKeySystemCapability(key_system, robustness); } - - if (cdm_info->status != CdmInfo::Status::kUninitialized) { - DVLOG(1) << "Hardware secure capability already finalized"; - continue; - } - - absl::optional<media::CdmCapability> hw_secure_capability; - CdmInfo::Status status; - std::tie(hw_secure_capability, status) = - GetHardwareSecureCapability(*this, key_system); - if (status != CdmInfo::Status::kUninitialized) { - FinalizeHardwareSecureCapability(key_system, hw_secure_capability, - status); - continue; - } - - // Needs lazy initialize. Use BindToCurrentLoop() to force a post. - pending_lazy_initialize_key_systems_.insert(key_system); - LazyInitializeHardwareSecureCapability( - key_system, media::BindToCurrentLoop(base::BindOnce( - &CdmRegistryImpl::OnHardwareSecureCapabilityInitialized, - weak_ptr_factory_.GetWeakPtr(), key_system))); } - // If not empty, we'll handle it in OnHardwareSecureCapabilityInitialized(). - if (pending_lazy_initialize_key_systems_.empty()) + // If not empty, we'll handle it in OnCapabilityInitialized(). + if (pending_lazy_initializations_.empty()) UpdateAndNotifyKeySystemCapabilities(); } +void CdmRegistryImpl::AttemptToFinalizeKeySystemCapability( + const std::string& key_system, + CdmInfo::Robustness robustness) { + auto cdm_info = GetCdmInfo(key_system, robustness); + if (!cdm_info) { + DVLOG(1) << "No " << robustness << " CDM registered for " << key_system; + return; + } + + if (cdm_info->status != CdmInfo::Status::kUninitialized) { + DVLOG(1) << robustness << " capability already finalized for " + << key_system; + return; + } + + const auto [capability, status] = GetCapability(key_system, robustness); + if (status != CdmInfo::Status::kUninitialized) { + FinalizeCapability(key_system, robustness, capability, status); + return; + } + + // Needs lazy initialize. Use BindToCurrentLoop() to force a post. + pending_lazy_initializations_.insert({key_system, robustness}); + LazyInitializeCapability( + key_system, robustness, + media::BindToCurrentLoop(base::BindOnce( + &CdmRegistryImpl::OnCapabilityInitialized, + weak_ptr_factory_.GetWeakPtr(), key_system, robustness))); +} + // TODO(xhwang): Find a way to register this as callbacks so we don't have to // hardcode platform-specific logic here. -// TODO(jrummell): Support Android query. -void CdmRegistryImpl::LazyInitializeHardwareSecureCapability( +// TODO(crbug.com/853336): Support Android query. +void CdmRegistryImpl::LazyInitializeCapability( const std::string& key_system, + CdmInfo::Robustness robustness, CdmCapabilityCB cdm_capability_cb) { DVLOG(2) << __func__; DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (hw_secure_capability_cb_for_testing_) { - hw_secure_capability_cb_for_testing_.Run(key_system, - std::move(cdm_capability_cb)); + if (capability_cb_for_testing_) { + capability_cb_for_testing_.Run(key_system, robustness, + std::move(cdm_capability_cb)); return; } #if BUILDFLAG(IS_WIN) - auto cdm_info = GetCdmInfo(key_system, CdmInfo::Robustness::kHardwareSecure); - DCHECK(cdm_info && !cdm_info->capability); - GetMediaFoundationServiceHardwareSecureCdmCapability( - key_system, cdm_info->path, std::move(cdm_capability_cb)); -#else - std::move(cdm_capability_cb).Run(absl::nullopt); + if (robustness == CdmInfo::Robustness::kHardwareSecure) { + auto cdm_info = + GetCdmInfo(key_system, CdmInfo::Robustness::kHardwareSecure); + DCHECK(cdm_info && !cdm_info->capability); + GetMediaFoundationServiceHardwareSecureCdmCapability( + key_system, cdm_info->path, std::move(cdm_capability_cb)); + return; + } #endif // BUILDFLAG(IS_WIN) + + std::move(cdm_capability_cb).Run(absl::nullopt); } -void CdmRegistryImpl::OnHardwareSecureCapabilityInitialized( +void CdmRegistryImpl::OnCapabilityInitialized( const std::string& key_system, + const CdmInfo::Robustness robustness, absl::optional<media::CdmCapability> cdm_capability) { DVLOG(1) << __func__ << ": key_system=" << key_system + << ", robustness=" << robustness << ", cdm_capability=" << (cdm_capability ? "yes" : "no"); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(pending_lazy_initialize_key_systems_.count(key_system)); + DCHECK(pending_lazy_initializations_.count({key_system, robustness})); - FinalizeHardwareSecureCapability(key_system, std::move(cdm_capability), - CdmInfo::Status::kEnabled); + FinalizeCapability(key_system, robustness, std::move(cdm_capability), + CdmInfo::Status::kEnabled); - pending_lazy_initialize_key_systems_.erase(key_system); - if (pending_lazy_initialize_key_systems_.empty()) + pending_lazy_initializations_.erase({key_system, robustness}); + if (pending_lazy_initializations_.empty()) UpdateAndNotifyKeySystemCapabilities(); } -void CdmRegistryImpl::FinalizeHardwareSecureCapability( +void CdmRegistryImpl::FinalizeCapability( const std::string& key_system, + const CdmInfo::Robustness robustness, absl::optional<media::CdmCapability> cdm_capability, CdmInfo::Status status) { DVLOG(2) << __func__; @@ -535,19 +539,20 @@ auto itr = cdms_.begin(); for (; itr != cdms_.end(); itr++) { - if (itr->robustness == CdmInfo::Robustness::kHardwareSecure && - MatchKeySystem(*itr, key_system)) { + if (itr->robustness == robustness && MatchKeySystem(*itr, key_system)) { break; } } if (itr == cdms_.end()) { - DLOG(ERROR) << __func__ << ": Cannot find CdmInfo to finalize"; + DLOG(ERROR) << __func__ << ": Cannot find CdmInfo to finalize for " + << key_system << " with robustness " << robustness; return; } if (itr->status != CdmInfo::Status::kUninitialized) { - DLOG(ERROR) << __func__ << ": CdmCapability already finalized"; + DLOG(ERROR) << __func__ << ": CdmCapability already finalized for " + << key_system << " with robustness " << robustness; return; } @@ -588,22 +593,21 @@ std::set<std::string> supported_key_systems = GetSupportedKeySystems(); for (const auto& key_system : supported_key_systems) { + CdmInfo::Status status; media::mojom::KeySystemCapability capability; - // Software secure capability - capability.sw_secure_capability = - GetSoftwareSecureCapability(*this, key_system); + // Software secure capability. + std::tie(capability.sw_secure_capability, status) = + GetFinalCapability(key_system, CdmInfo::Robustness::kSoftwareSecure); + ReportSoftwareSecureCdmAvailableUMA( + key_system, capability.sw_secure_capability != absl::nullopt); - // Hardware secure capability - absl::optional<media::CdmCapability> hw_secure_capability; - CdmInfo::Status status; - std::tie(hw_secure_capability, status) = - GetHardwareSecureCapability(*this, key_system); - DCHECK(status != CdmInfo::Status::kUninitialized); + // Hardware secure capability. + std::tie(capability.hw_secure_capability, status) = + GetFinalCapability(key_system, CdmInfo::Robustness::kHardwareSecure); ReportHardwareSecureCapabilityStatusUMA( - key_system, status, base::OptionalToPtr(hw_secure_capability)); - capability.hw_secure_capability = - IsEnabled(status) ? hw_secure_capability : absl::nullopt; + key_system, status, + base::OptionalToPtr(capability.hw_secure_capability)); if (capability.sw_secure_capability || capability.hw_secure_capability) key_system_capabilities[key_system] = std::move(capability); @@ -612,9 +616,8 @@ return key_system_capabilities; } -void CdmRegistryImpl::SetHardwareSecureCapabilityCBForTesting( - HardwareSecureCapabilityCB cb) { - hw_secure_capability_cb_for_testing_ = std::move(cb); +void CdmRegistryImpl::SetCapabilityCBForTesting(CapabilityCB cb) { + capability_cb_for_testing_ = std::move(cb); } } // namespace content
diff --git a/content/browser/media/cdm_registry_impl.h b/content/browser/media/cdm_registry_impl.h index e4d6d4c..6616e7d9 100644 --- a/content/browser/media/cdm_registry_impl.h +++ b/content/browser/media/cdm_registry_impl.h
@@ -72,18 +72,45 @@ CdmRegistryImpl(); ~CdmRegistryImpl() override; + // Get the capability for `key_system` with robustness `robustness` + // synchronously. If lazy initialization is needed, return + // Status::kUninitialized. + std::pair<absl::optional<media::CdmCapability>, CdmInfo::Status> + GetCapability(const std::string& key_system, CdmInfo::Robustness robustness); + + // Get the capability for `key_system` with robustness `robustness` + // synchronously. All initialization should have been completed. + std::pair<absl::optional<media::CdmCapability>, CdmInfo::Status> + GetFinalCapability(const std::string& key_system, + CdmInfo::Robustness robustness); + // Finalizes KeySystemCapabilities. May lazy initialize CDM capabilities // asynchronously if needed. void FinalizeKeySystemCapabilities(); + // Attempt to finalize KeySystemCapability for `key_system` with robustness + // `robustness`. May lazy initialize it asynchronously if needed. + void AttemptToFinalizeKeySystemCapability(const std::string& key_system, + CdmInfo::Robustness robustness); + + // Callback for when a key system is initialized if lazy initialization + // required. using CdmCapabilityCB = base::OnceCallback<void(absl::optional<media::CdmCapability>)>; - void LazyInitializeHardwareSecureCapability( - const std::string& key_system, - CdmCapabilityCB cdm_capability_cb); - void OnHardwareSecureCapabilityInitialized( + // Lazily initialize `key_system` with robustness `robustness`, calling + // `cdm_capability_cb`. Callback may be called synchronously + // or asynchronously. + void LazyInitializeCapability(const std::string& key_system, + CdmInfo::Robustness robustness, + CdmCapabilityCB cdm_capability_cb); + + // Called when initialization of `key_system` with robustness `robustness` + // is complete. `cdm_capability` will be absl::nullopt if the key system + // with specified robustness isn't supported. + void OnCapabilityInitialized( const std::string& key_system, + const CdmInfo::Robustness robustness, absl::optional<media::CdmCapability> cdm_capability); // Finalizes the CdmInfo corresponding to `key_system` and `robustness` if its @@ -91,21 +118,28 @@ // exist, or if the CdmInfo's CdmCapability is not null. The CdmInfo will be // removed if `cdm_capability` is null, since the CDM does not support any // capability. - void FinalizeHardwareSecureCapability( - const std::string& key_system, - absl::optional<media::CdmCapability> cdm_capability, - CdmInfo::Status status); + void FinalizeCapability(const std::string& key_system, + const CdmInfo::Robustness robustness, + absl::optional<media::CdmCapability> cdm_capability, + CdmInfo::Status status); + // When capabilities for all registered key systems have been determined, + // notify all observers with the updated values. No notification is done + // if the capabilities have not changed. void UpdateAndNotifyKeySystemCapabilities(); + // Returns the set of all registered key systems. std::set<std::string> GetSupportedKeySystems() const; + // Returns the capabailities for all registered key systems. KeySystemCapabilities GetKeySystemCapabilities(); - // Sets a callback to query for hardware secure capability for testing. - using HardwareSecureCapabilityCB = - base::RepeatingCallback<void(const std::string&, CdmCapabilityCB)>; - void SetHardwareSecureCapabilityCBForTesting(HardwareSecureCapabilityCB cb); + // Sets callbacks to query for secure capability for testing. + using CapabilityCB = + base::RepeatingCallback<void(const std::string&, + const CdmInfo::Robustness robustness, + CdmCapabilityCB)>; + void SetCapabilityCBForTesting(CapabilityCB cb); std::vector<CdmInfo> cdms_ GUARDED_BY_CONTEXT(sequence_checker_); @@ -116,11 +150,12 @@ // Cached current KeySystemCapabilities value. absl::optional<KeySystemCapabilities> key_system_capabilities_; - // Key systems pending CdmCapability lazy initialization. - std::set<std::string> pending_lazy_initialize_key_systems_; + // Key system and robustness pairs pending CdmCapability lazy initialization. + std::set<std::pair<std::string, CdmInfo::Robustness>> + pending_lazy_initializations_; - // A callback for testing to avoid hardware dependency. - HardwareSecureCapabilityCB hw_secure_capability_cb_for_testing_; + // Callback for testing to avoid device dependency. + CapabilityCB capability_cb_for_testing_; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/content/browser/media/cdm_registry_impl_unittest.cc b/content/browser/media/cdm_registry_impl_unittest.cc index 59a4ad2..b375511b 100644 --- a/content/browser/media/cdm_registry_impl_unittest.cc +++ b/content/browser/media/cdm_registry_impl_unittest.cc
@@ -111,14 +111,14 @@ gpu_data_manager->UpdateGpuInfo(gpu_info, absl::nullopt); #endif // BUILDFLAG(IS_WIN) - cdm_registry_.SetHardwareSecureCapabilityCBForTesting( - hw_secure_capability_cb_.Get()); + cdm_registry_.SetCapabilityCBForTesting(capability_cb_.Get()); } void OnKeySystemCapabilitiesUpdated( int observer_id, base::OnceClosure done_cb, KeySystemCapabilities key_system_capabilities) { + DVLOG(1) << __func__; results_[observer_id].push_back(std::move(key_system_capabilities)); std::move(done_cb).Run(); } @@ -159,7 +159,17 @@ base::FilePath::FromUTF8Unsafe(kTestPath))); } - void RegisterForLazyInitialization() { + void RegisterForLazySoftwareSecureInitialization() { + // Register a CdmInfo without CdmCapability to allow lazy initialization. + Register(CdmInfo(kTestKeySystem, CdmInfo::Robustness::kSoftwareSecure, + absl::nullopt, kTestCdmType)); + auto cdm_info = cdm_registry_.GetCdmInfo( + kTestKeySystem, CdmInfo::Robustness::kSoftwareSecure); + ASSERT_TRUE(cdm_info); + ASSERT_FALSE(cdm_info->capability); + } + + void RegisterForLazyHardwareSecureInitialization() { // Register a CdmInfo without CdmCapability to allow lazy initialization. Register(CdmInfo(kTestKeySystem, CdmInfo::Robustness::kHardwareSecure, absl::nullopt, kTestCdmType)); @@ -187,6 +197,7 @@ } void GetKeySystemCapabilities() { + DVLOG(1) << __func__; base::RunLoop run_loop; cdm_registry_.ObserveKeySystemCapabilities(base::BindRepeating( &CdmRegistryImplTest::OnKeySystemCapabilitiesUpdated, @@ -229,10 +240,9 @@ BrowserTaskEnvironment task_environment_; CdmRegistryImpl cdm_registry_; - base::MockCallback<CdmRegistryImpl::HardwareSecureCapabilityCB> - hw_secure_capability_cb_; + base::MockCallback<CdmRegistryImpl::CapabilityCB> capability_cb_; - // Map of "obserber ID" to the list of updated KeySystemCapabilities. + // Map of "observer ID" to the list of updated KeySystemCapabilities. std::map<int, std::vector<KeySystemCapabilities>> results_; }; @@ -397,12 +407,34 @@ ASSERT_EQ(support.hw_secure_capability.value(), GetTestCdmCapability()); } -TEST_F(CdmRegistryImplTest, KeySystemCapabilities_LazyInitialize_Supported) { - RegisterForLazyInitialization(); +TEST_F(CdmRegistryImplTest, + KeySystemCapabilities_LazySoftwareSecureInitialize_Supported) { + RegisterForLazySoftwareSecureInitialization(); SelectHardwareSecureDecryption(true); - EXPECT_CALL(hw_secure_capability_cb_, Run(kTestKeySystem, _)) - .WillOnce(RunOnceCallback<1>(GetTestCdmCapability())); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kSoftwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetTestCdmCapability())); + GetKeySystemCapabilities(); + + ASSERT_TRUE(results_.count(kObserver1)); + ASSERT_EQ(results_[kObserver1].size(), 1u); + auto& key_system_capabilities = results_[kObserver1][0]; + ASSERT_EQ(key_system_capabilities.size(), 1u); + ASSERT_TRUE(key_system_capabilities.count(kTestKeySystem)); + const auto& support = key_system_capabilities[kTestKeySystem]; + ASSERT_EQ(support.sw_secure_capability.value(), GetTestCdmCapability()); + ASSERT_FALSE(support.hw_secure_capability); +} + +TEST_F(CdmRegistryImplTest, + KeySystemCapabilities_LazyHardwareSecureInitialize_Supported) { + RegisterForLazyHardwareSecureInitialization(); + SelectHardwareSecureDecryption(true); + + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetTestCdmCapability())); GetKeySystemCapabilities(); ASSERT_TRUE(results_.count(kObserver1)); @@ -415,12 +447,35 @@ ASSERT_EQ(support.hw_secure_capability.value(), GetTestCdmCapability()); } -TEST_F(CdmRegistryImplTest, KeySystemCapabilities_LazyInitialize_NotSupported) { - RegisterForLazyInitialization(); +TEST_F(CdmRegistryImplTest, + KeySystemCapabilities_LazySoftwareSecureInitialize_NotSupported) { + RegisterForLazySoftwareSecureInitialization(); SelectHardwareSecureDecryption(true); - EXPECT_CALL(hw_secure_capability_cb_, Run(kTestKeySystem, _)) - .WillOnce(RunOnceCallback<1>(absl::nullopt)); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kSoftwareSecure, _)) + .WillOnce(RunOnceCallback<2>(absl::nullopt)); + GetKeySystemCapabilities(); + + ASSERT_TRUE(results_.count(kObserver1)); + ASSERT_EQ(results_[kObserver1].size(), 1u); + auto& key_system_capabilities = results_[kObserver1][0]; + ASSERT_TRUE(key_system_capabilities.empty()); + + auto cdm_info = cdm_registry_.GetCdmInfo( + kTestKeySystem, CdmInfo::Robustness::kSoftwareSecure); + ASSERT_EQ(cdm_info->status, CdmInfo::Status::kEnabled); + ASSERT_FALSE(cdm_info->capability); +} + +TEST_F(CdmRegistryImplTest, + KeySystemCapabilities_LazyHardwareSecureInitialize_NotSupported) { + RegisterForLazyHardwareSecureInitialization(); + SelectHardwareSecureDecryption(true); + + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(RunOnceCallback<2>(absl::nullopt)); GetKeySystemCapabilities(); ASSERT_TRUE(results_.count(kObserver1)); @@ -435,7 +490,7 @@ } TEST_F(CdmRegistryImplTest, KeySystemCapabilities_HardwareSecureDisabled) { - RegisterForLazyInitialization(); + RegisterForLazyHardwareSecureInitialization(); SelectHardwareSecureDecryption(false); GetKeySystemCapabilities(); @@ -452,12 +507,16 @@ } TEST_F(CdmRegistryImplTest, KeySystemCapabilities_SoftwareAndHardwareSecure) { - Register(GetTestCdmInfo()); - RegisterForLazyInitialization(); + RegisterForLazySoftwareSecureInitialization(); + RegisterForLazyHardwareSecureInitialization(); SelectHardwareSecureDecryption(true); - EXPECT_CALL(hw_secure_capability_cb_, Run(kTestKeySystem, _)) - .WillOnce(RunOnceCallback<1>(GetTestCdmCapability())); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kSoftwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetTestCdmCapability())); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetOtherCdmCapability())); GetKeySystemCapabilities(); ASSERT_TRUE(results_.count(kObserver1)); @@ -467,7 +526,7 @@ ASSERT_TRUE(key_system_capabilities.count(kTestKeySystem)); const auto& support = key_system_capabilities[kTestKeySystem]; ASSERT_EQ(support.sw_secure_capability.value(), GetTestCdmCapability()); - ASSERT_EQ(support.hw_secure_capability.value(), GetTestCdmCapability()); + ASSERT_EQ(support.hw_secure_capability.value(), GetOtherCdmCapability()); } TEST_F(CdmRegistryImplTest, KeySystemCapabilities_MultipleObservers) { @@ -495,14 +554,49 @@ ASSERT_EQ(key_system_capabilities, results_[kObserver2][0]); } -TEST_F(CdmRegistryImplTest, - KeySystemCapabilities_MultipleObservers_PendingLazyInitialize) { +TEST_F( + CdmRegistryImplTest, + KeySystemCapabilities_MultipleObservers_PendingLazySoftwareSecureInitialize) { + RegisterForLazySoftwareSecureInitialization(); + SelectHardwareSecureDecryption(false); + + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kSoftwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetTestCdmCapability())); + + base::RunLoop run_loop; + cdm_registry_.ObserveKeySystemCapabilities(base::BindRepeating( + &CdmRegistryImplTest::OnKeySystemCapabilitiesUpdated, + base::Unretained(this), kObserver1, base::DoNothing())); + cdm_registry_.ObserveKeySystemCapabilities(base::BindRepeating( + &CdmRegistryImplTest::OnKeySystemCapabilitiesUpdated, + base::Unretained(this), kObserver2, run_loop.QuitClosure())); + run_loop.Run(); + + ASSERT_TRUE(results_.count(kObserver1)); + ASSERT_EQ(results_[kObserver1].size(), 1u); + auto& key_system_capabilities = results_[kObserver1][0]; + ASSERT_EQ(key_system_capabilities.size(), 1u); + ASSERT_TRUE(key_system_capabilities.count(kTestKeySystem)); + const auto& support = key_system_capabilities[kTestKeySystem]; + ASSERT_EQ(support.sw_secure_capability.value(), GetTestCdmCapability()); + ASSERT_FALSE(support.hw_secure_capability); + + ASSERT_TRUE(results_.count(kObserver2)); + ASSERT_EQ(results_[kObserver2].size(), 1u); + ASSERT_EQ(key_system_capabilities, results_[kObserver2][0]); +} + +TEST_F( + CdmRegistryImplTest, + KeySystemCapabilities_MultipleObservers_PendingLazyHardwareSecureInitialize) { Register(GetTestCdmInfo()); - RegisterForLazyInitialization(); + RegisterForLazyHardwareSecureInitialization(); SelectHardwareSecureDecryption(true); - EXPECT_CALL(hw_secure_capability_cb_, Run(kTestKeySystem, _)) - .WillOnce(RunOnceCallback<1>(GetTestCdmCapability())); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetTestCdmCapability())); base::RunLoop run_loop; cdm_registry_.ObserveKeySystemCapabilities(base::BindRepeating( @@ -527,14 +621,16 @@ ASSERT_EQ(key_system_capabilities, results_[kObserver2][0]); } -TEST_F(CdmRegistryImplTest, - KeySystemCapabilities_MultipleObservers_AfterLazyInitialize) { +TEST_F( + CdmRegistryImplTest, + KeySystemCapabilities_MultipleObservers_AfterLazyHardwareSecureInitialize) { Register(GetTestCdmInfo()); - RegisterForLazyInitialization(); + RegisterForLazyHardwareSecureInitialization(); SelectHardwareSecureDecryption(true); - EXPECT_CALL(hw_secure_capability_cb_, Run(kTestKeySystem, _)) - .WillOnce(RunOnceCallback<1>(GetTestCdmCapability())); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetTestCdmCapability())); { base::RunLoop run_loop; @@ -589,9 +685,10 @@ { base::RunLoop run_loop; - EXPECT_CALL(hw_secure_capability_cb_, Run(kTestKeySystem, _)) - .WillOnce(RunOnceCallback<1>(GetOtherCdmCapability())); - RegisterForLazyInitialization(); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(RunOnceCallback<2>(GetOtherCdmCapability())); + RegisterForLazyHardwareSecureInitialization(); run_loop.RunUntilIdle(); } @@ -613,11 +710,13 @@ // Save the callbacks so we can control when and how they are fired. base::OnceCallback<void(absl::optional<media::CdmCapability>)> callback_1, callback_2, callback_3; - EXPECT_CALL(hw_secure_capability_cb_, Run(kTestKeySystem, _)) - .WillOnce(MoveArg<1>(&callback_1)) - .WillOnce(MoveArg<1>(&callback_2)); - EXPECT_CALL(hw_secure_capability_cb_, Run(kOtherKeySystem, _)) - .WillOnce(MoveArg<1>(&callback_3)); + EXPECT_CALL(capability_cb_, + Run(kTestKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(MoveArg<2>(&callback_1)) + .WillOnce(MoveArg<2>(&callback_2)); + EXPECT_CALL(capability_cb_, + Run(kOtherKeySystem, Robustness::kHardwareSecure, _)) + .WillOnce(MoveArg<2>(&callback_3)); // Register CdmInfo for lazy initialization. { @@ -705,7 +804,7 @@ gpu_info.overlay_info.direct_composition = false; GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info, absl::nullopt); - RegisterForLazyInitialization(); + RegisterForLazyHardwareSecureInitialization(); SelectHardwareSecureDecryption(true); GetKeySystemCapabilities();
diff --git a/content/browser/media/media_internals_cdm_helper.cc b/content/browser/media/media_internals_cdm_helper.cc index e1c6dd4..9b7e9b2 100644 --- a/content/browser/media/media_internals_cdm_helper.cc +++ b/content/browser/media/media_internals_cdm_helper.cc
@@ -19,15 +19,6 @@ namespace { -std::string GetCdmInfoRobustnessName(CdmInfo::Robustness robustness) { - switch (robustness) { - case CdmInfo::Robustness::kHardwareSecure: - return "Hardware Secure"; - case CdmInfo::Robustness::kSoftwareSecure: - return "Software Secure"; - } -} - std::string GetCdmInfoCapabilityStatusName(CdmInfo::Status status) { switch (status) { case CdmInfo::Status::kUninitialized:
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager.cc b/content/browser/preloading/prefetch/prefetch_document_manager.cc index 15e248e..5dbbafd9 100644 --- a/content/browser/preloading/prefetch/prefetch_document_manager.cc +++ b/content/browser/preloading/prefetch/prefetch_document_manager.cc
@@ -81,7 +81,8 @@ // No-Vary-Search equivalence. If there is not then stop. auto prefetch_iter = all_prefetches_.find(navigation_handle->GetURL()); if (prefetch_iter == all_prefetches_.end() || !prefetch_iter->second) { - if (!base::FeatureList::IsEnabled( + if (!no_vary_search_support_enabled_ || + !base::FeatureList::IsEnabled( network::features::kPrefetchNoVarySearch)) { return; } @@ -299,7 +300,8 @@ } void PrefetchDocumentManager::OnPrefetchedHeadReceived(const GURL& url) { - if (!base::FeatureList::IsEnabled(network::features::kPrefetchNoVarySearch)) { + if (!no_vary_search_support_enabled_ || + !base::FeatureList::IsEnabled(network::features::kPrefetchNoVarySearch)) { return; } // Find the PrefetchContainer associated with |url|. @@ -317,6 +319,10 @@ referring_page_metrics_.prefetch_successful_count++; } +void PrefetchDocumentManager::EnableNoVarySearchSupport() { + no_vary_search_support_enabled_ = true; +} + DOCUMENT_USER_DATA_KEY_IMPL(PrefetchDocumentManager); } // namespace content
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager.h b/content/browser/preloading/prefetch/prefetch_document_manager.h index aa0a13f..21a4ac8d 100644 --- a/content/browser/preloading/prefetch/prefetch_document_manager.h +++ b/content/browser/preloading/prefetch/prefetch_document_manager.h
@@ -96,6 +96,8 @@ // Helper function to get the |NoVarySearchHelper| associated with |this|. const NoVarySearchHelper& GetNoVarySearchHelper() const; + void EnableNoVarySearchSupport(); + static void SetPrefetchServiceForTesting(PrefetchService* prefetch_service); private: @@ -129,6 +131,8 @@ // Used through the getter GetNoVarySearchHelper NoVarySearchHelper no_vary_search_helper_; + bool no_vary_search_support_enabled_ = false; + base::WeakPtrFactory<PrefetchDocumentManager> weak_method_factory_{this}; DOCUMENT_USER_DATA_KEY_DECL();
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc index 718b3fbd..0ed7ae5b 100644 --- a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc
@@ -129,6 +129,7 @@ auto* prefetch_document_manager = PrefetchDocumentManager::GetOrCreateForCurrentDocument( &GetPrimaryMainFrame()); + prefetch_document_manager->EnableNoVarySearchSupport(); { // Create list of SpeculationCandidatePtrs. std::vector<blink::mojom::SpeculationCandidatePtr> candidates; @@ -245,6 +246,9 @@ } TEST_F(PrefetchDocumentManagerTest, ProcessSpeculationCandidates) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + network::features::kPrefetchNoVarySearch); // Create list of SpeculationCandidatePtrs. std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc index 6ae34239..11d5c942 100644 --- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -261,10 +261,11 @@ } virtual void InitScopedFeatureList() { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - content::features::kPrefetchUseContentRefactor, - {{"ineligible_decoy_request_probability", "0"}, - {"prefetch_container_lifetime_s", "-1"}}); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "0"}, + {"prefetch_container_lifetime_s", "-1"}}}}, + {network::features::kPrefetchNoVarySearch}); } void MakePrefetchService(std::unique_ptr<MockPrefetchServiceDelegate> @@ -280,9 +281,12 @@ // Creates a prefetch request for |url| on the current main frame. void MakePrefetchOnMainFrame(const GURL& url, - const PrefetchType& prefetch_type) { + const PrefetchType& prefetch_type, + bool enable_no_vary_search_header = false) { PrefetchDocumentManager* prefetch_document_manager = PrefetchDocumentManager::GetOrCreateForCurrentDocument(main_rfh()); + if (enable_no_vary_search_header) + prefetch_document_manager->EnableNoVarySearchSupport(); prefetch_document_manager->PrefetchUrl(url, prefetch_type, blink::mojom::Referrer(), nullptr); } @@ -587,8 +591,9 @@ // Enable feature, which means that we should be able to create a // PrefetchService instance. base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - content::features::kPrefetchUseContentRefactor); + scoped_feature_list.InitWithFeatures( + {content::features::kPrefetchUseContentRefactor}, + {network::features::kPrefetchNoVarySearch}); EXPECT_TRUE(PrefetchService::CreateIfPossible(browser_context())); } @@ -597,8 +602,9 @@ // Disable feature, which means that we shouldn't be able to create a // PrefetchService instance. base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - content::features::kPrefetchUseContentRefactor); + scoped_feature_list.InitWithFeatures( + {}, {content::features::kPrefetchUseContentRefactor, + network::features::kPrefetchNoVarySearch}); EXPECT_FALSE(PrefetchService::CreateIfPossible(browser_context())); } @@ -791,11 +797,12 @@ class PrefetchServiceAllowAllDomainsTest : public PrefetchServiceTest { public: void InitScopedFeatureList() override { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - content::features::kPrefetchUseContentRefactor, - {{"ineligible_decoy_request_probability", "0"}, - {"prefetch_container_lifetime_s", "-1"}, - {"allow_all_domains", "true"}}); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "0"}, + {"prefetch_container_lifetime_s", "-1"}, + {"allow_all_domains", "true"}}}}, + {network::features::kPrefetchNoVarySearch}); } }; @@ -874,11 +881,12 @@ : public PrefetchServiceTest { public: void InitScopedFeatureList() override { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - content::features::kPrefetchUseContentRefactor, - {{"ineligible_decoy_request_probability", "0"}, - {"prefetch_container_lifetime_s", "-1"}, - {"allow_all_domains_for_extended_preloading", "true"}}); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "0"}, + {"prefetch_container_lifetime_s", "-1"}, + {"allow_all_domains_for_extended_preloading", "true"}}}}, + {network::features::kPrefetchNoVarySearch}); } }; @@ -2263,11 +2271,12 @@ class PrefetchServiceLimitedPrefetchesTest : public PrefetchServiceTest { public: void InitScopedFeatureList() override { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - content::features::kPrefetchUseContentRefactor, - {{"ineligible_decoy_request_probability", "0"}, - {"prefetch_container_lifetime_s", "-1"}, - {"max_srp_prefetches", "2"}}); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "0"}, + {"prefetch_container_lifetime_s", "-1"}, + {"max_srp_prefetches", "2"}}}}, + {network::features::kPrefetchNoVarySearch}); } }; @@ -2425,11 +2434,12 @@ class PrefetchServiceWithHTMLOnlyTest : public PrefetchServiceTest { public: void InitScopedFeatureList() override { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - content::features::kPrefetchUseContentRefactor, - {{"ineligible_decoy_request_probability", "0"}, - {"prefetch_container_lifetime_s", "-1"}, - {"html_only", "true"}}); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "0"}, + {"prefetch_container_lifetime_s", "-1"}, + {"html_only", "true"}}}}, + {network::features::kPrefetchNoVarySearch}); } }; @@ -2497,10 +2507,11 @@ class PrefetchServiceAlwaysMakeDecoyRequestTest : public PrefetchServiceTest { public: void InitScopedFeatureList() override { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - content::features::kPrefetchUseContentRefactor, - {{"ineligible_decoy_request_probability", "1"}, - {"prefetch_container_lifetime_s", "-1"}}); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "1"}, + {"prefetch_container_lifetime_s", "-1"}}}}, + {network::features::kPrefetchNoVarySearch}); } }; @@ -2971,7 +2982,8 @@ MakePrefetchOnMainFrame(GURL("https://example.com/?a=1"), PrefetchType(/*use_isolated_network_context=*/true, - /*use_prefetch_proxy=*/true)); + /*use_prefetch_proxy=*/true), + /*enable_no_vary_search_header*/ true); base::RunLoop().RunUntilIdle(); VerifyCommonRequestState(GURL("https://example.com/?a=1"),
diff --git a/content/browser/preloading/speculation_rules/speculation_host_impl.cc b/content/browser/preloading/speculation_rules/speculation_host_impl.cc index c42b2be..0bbc49d 100644 --- a/content/browser/preloading/speculation_rules/speculation_host_impl.cc +++ b/content/browser/preloading/speculation_rules/speculation_host_impl.cc
@@ -6,6 +6,7 @@ #include <functional> +#include "content/browser/preloading/prefetch/prefetch_document_manager.h" #include "content/browser/preloading/preloading_decider.h" #include "third_party/blink/public/common/features.h" @@ -72,4 +73,12 @@ preloading_decider->UpdateSpeculationCandidates(candidates); } +void SpeculationHostImpl::EnableNoVarySearchSupport() { + auto* prefetch_document_manager = + PrefetchDocumentManager::GetOrCreateForCurrentDocument( + &render_frame_host()); + DCHECK(prefetch_document_manager); + prefetch_document_manager->EnableNoVarySearchSupport(); +} + } // namespace content
diff --git a/content/browser/preloading/speculation_rules/speculation_host_impl.h b/content/browser/preloading/speculation_rules/speculation_host_impl.h index 96acce3..d95679c 100644 --- a/content/browser/preloading/speculation_rules/speculation_host_impl.h +++ b/content/browser/preloading/speculation_rules/speculation_host_impl.h
@@ -37,6 +37,7 @@ void UpdateSpeculationCandidates( std::vector<blink::mojom::SpeculationCandidatePtr> candidates) override; + void EnableNoVarySearchSupport() override; }; } // namespace content
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index b6d7893..1d0859f2 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -654,8 +654,8 @@ const RenderFrameHostImpl& rfh, const BackForwardCacheCanStoreDocumentResult& flattened_result, const perfetto::StaticString& caller) { - LOG(ERROR) << caller.value << ": " << rfh.GetLastCommittedURL() << " : " - << flattened_result.ToString(); + VLOG(1) << caller.value << ": " << rfh.GetLastCommittedURL() << " : " + << flattened_result.ToString(); TRACE_EVENT("navigation", caller, ChromeTrackEvent::kBackForwardCacheCanStoreDocumentResult, flattened_result);
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 96b3bf25..b48bb7c 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -433,36 +433,26 @@ void CompositorImpl::SetSurface(const base::android::JavaRef<jobject>& surface, bool can_be_used_with_surface_control) { - JNIEnv* env = base::android::AttachCurrentThread(); gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get(); if (window_) { // Shut down GL context before unregistering surface. SetVisible(false); tracker->RemoveSurface(surface_handle_); - ANativeWindow_release(window_); window_ = nullptr; surface_handle_ = gpu::kNullSurfaceHandle; } - ANativeWindow* window = nullptr; - if (surface) { - // Note: This ensures that any local references used by - // ANativeWindow_fromSurface are released immediately. This is needed as a - // workaround for https://code.google.com/p/android/issues/detail?id=68174 - base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env); - window = ANativeWindow_fromSurface(env, surface.obj()); - } + gl::ScopedJavaSurface scoped_surface(surface, /*auto_release=*/false); + gl::ScopedANativeWindow window(scoped_surface); if (window) { - window_ = window; - ANativeWindow_acquire(window); + window_ = std::move(window); // Register first, SetVisible() might create a LayerTreeFrameSink. surface_handle_ = tracker->AddSurfaceForNativeWidget( gpu::GpuSurfaceTracker::SurfaceRecord( - window, surface, can_be_used_with_surface_control)); + std::move(scoped_surface), can_be_used_with_surface_control)); SetVisible(true); - ANativeWindow_release(window); } }
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h index 6992231..40d5e6f 100644 --- a/content/browser/renderer_host/compositor_impl_android.h +++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -40,8 +40,7 @@ #include "ui/android/window_android_compositor.h" #include "ui/compositor/compositor_lock.h" #include "ui/display/display_observer.h" - -struct ANativeWindow; +#include "ui/gl/android/scoped_a_native_window.h" namespace cc { class AnimationHost; @@ -263,7 +262,7 @@ gfx::Size size_; bool requires_alpha_channel_ = false; - raw_ptr<ANativeWindow> window_; + gl::ScopedANativeWindow window_; gpu::SurfaceHandle surface_handle_; std::unique_ptr<ScopedCachedBackBuffer> cached_back_buffer_;
diff --git a/content/browser/resources/attribution_reporting/attribution_internals.ts b/content/browser/resources/attribution_reporting/attribution_internals.ts index 9ddde4a..e3e86d5 100644 --- a/content/browser/resources/attribution_reporting/attribution_internals.ts +++ b/content/browser/resources/attribution_reporting/attribution_internals.ts
@@ -9,7 +9,7 @@ import {getTrustedHTML} from 'chrome://resources/js/static_types.js'; import {Origin} from 'chrome://resources/mojo/url/mojom/origin.mojom-webui.js'; -import {ClearedDebugKey, ClearedDebugKey_Type, FailedSourceRegistration, Handler as AttributionInternalsHandler, HandlerRemote as AttributionInternalsHandlerRemote, ObserverInterface, ObserverReceiver, ReportID, WebUIDebugReport, WebUIReport, WebUISource, WebUISource_Attributability, WebUITrigger, WebUITrigger_Status} from './attribution_internals.mojom-webui.js'; +import {FailedSourceRegistration, Handler as AttributionInternalsHandler, HandlerRemote as AttributionInternalsHandlerRemote, ObserverInterface, ObserverReceiver, ReportID, WebUIDebugReport, WebUIReport, WebUISource, WebUISource_Attributability, WebUITrigger, WebUITrigger_Status} from './attribution_internals.mojom-webui.js'; import {AttributionInternalsTableElement} from './attribution_internals_table.js'; import {ReportType, SourceType} from './attribution_reporting.mojom-webui.js'; import {SourceRegistrationError} from './source_registration_error.mojom-webui.js'; @@ -258,7 +258,15 @@ this.filterData = JSON.stringify(mojo.filterData, null, ' '); this.aggregationKeys = JSON.stringify(mojo.aggregationKeys, bigintReplacer, ' '); - this.debugKey = mojo.debugKey ? mojo.debugKey.value.toString() : ''; + + if (mojo.debugKey?.debugKey !== undefined) { + this.debugKey = mojo.debugKey.debugKey.toString(); + } else if (mojo.debugKey?.clearedDebugKey !== undefined) { + this.debugKey = `Cleared (was ${mojo.debugKey.clearedDebugKey})`; + } else { + this.debugKey = ''; + } + this.dedupKeys = mojo.dedupKeys.join(', '); this.aggregatableBudgetConsumed = mojo.aggregatableBudgetConsumed; this.aggregatableDedupKeys = mojo.aggregatableDedupKeys.join(', '); @@ -343,6 +351,7 @@ destinationOrigin: string; reportingOrigin: string; registrationJson: string; + clearedDebugKey: string; eventLevelStatus: string; aggregatableStatus: string; @@ -351,6 +360,8 @@ this.destinationOrigin = originToText(mojo.destinationOrigin); this.reportingOrigin = originToText(mojo.reportingOrigin); this.registrationJson = mojo.registrationJson; + this.clearedDebugKey = + mojo.clearedDebugKey ? `${mojo.clearedDebugKey.value}` : ''; this.eventLevelStatus = triggerStatusToText(mojo.eventLevelStatus); this.aggregatableStatus = triggerStatusToText(mojo.aggregatableStatus); } @@ -373,6 +384,8 @@ 'Reporting Origin', (e) => e.reportingOrigin), new CodeColumn<Trigger>( 'Registration JSON', (e) => e.registrationJson), + new ValueColumn<Trigger, string>( + 'Cleared Debug Key', (e) => e.clearedDebugKey), ], 0, // Sort by trigger time by default. 'No triggers.', @@ -717,49 +730,6 @@ abstract renderMetadata(td: HTMLElement): void; } -const CLEARED_DEBUG_KEY_COLS: Array<Column<ClearedDebugKeyLog>> = [ - new ValueColumn<ClearedDebugKeyLog, string>( - 'Cleared Debug Key', e => e.clearedDebugKey), - new ValueColumn<ClearedDebugKeyLog, string>('From', e => e.clearedFrom), - new ValueColumn<ClearedDebugKeyLog, string>( - 'Reporting Origin', e => e.reportingOrigin), -]; - -class ClearedDebugKeyLog extends Log { - readonly clearedFrom: string; - readonly clearedDebugKey: string; - - constructor(mojo: ClearedDebugKey) { - super(mojo); - - this.clearedDebugKey = `${mojo.clearedDebugKey.value}`; - - switch (mojo.clearedFrom) { - case (ClearedDebugKey_Type.kSource): - this.clearedFrom = 'Source'; - break; - case (ClearedDebugKey_Type.kTrigger): - this.clearedFrom = 'Trigger'; - break; - default: - this.clearedFrom = 'Unknown type'; - break; - } - } - - renderDescription(td: HTMLElement): void { - renderA( - td, - 'Cleared Debug Key', - 'https://github.com/WICG/attribution-reporting-api/blob/main/EVENT.md#attribution-success-debugging-reports', - ); - } - - renderMetadata(td: HTMLElement) { - renderDL(td, this, CLEARED_DEBUG_KEY_COLS); - } -} - const FAILED_SOURCE_REGISTRATION_COLS: Array<Column<FailedSourceRegistrationLog>> = [ new ValueColumn<FailedSourceRegistrationLog, string>( @@ -1151,11 +1121,6 @@ assert(logTableModel); logTableModel.addLog(new FailedSourceRegistrationLog(mojo)); } - - onDebugKeyCleared(mojo: ClearedDebugKey) { - assert(logTableModel); - logTableModel.addLog(new ClearedDebugKeyLog(mojo)); - } } function installUnreadIndicator(model: TableModel<any>, tab: HTMLElement|null) {
diff --git a/content/browser/shared_storage/shared_storage_document_service_impl.cc b/content/browser/shared_storage/shared_storage_document_service_impl.cc index 9af47aa8..9eb65f2e 100644 --- a/content/browser/shared_storage/shared_storage_document_service_impl.cc +++ b/content/browser/shared_storage/shared_storage_document_service_impl.cc
@@ -344,8 +344,8 @@ return true; return GetContentClient()->browser()->IsSharedStorageAllowed( - &render_frame_host(), main_frame_origin_, - render_frame_host().GetLastCommittedOrigin()); + render_frame_host().GetBrowserContext(), &render_frame_host(), + main_frame_origin_, render_frame_host().GetLastCommittedOrigin()); } std::string SharedStorageDocumentServiceImpl::SerializeLastCommittedOrigin()
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc index ed6958d..ecce4f40 100644 --- a/content/browser/shared_storage/shared_storage_worklet_host.cc +++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -864,9 +864,10 @@ } bool SharedStorageWorkletHost::IsSharedStorageAllowed() { + RenderFrameHost* rfh = + document_service_ ? &(document_service_->render_frame_host()) : nullptr; return GetContentClient()->browser()->IsSharedStorageAllowed( - &(document_service_->render_frame_host()), main_frame_origin_, - shared_storage_origin_); + browser_context_, rfh, main_frame_origin_, shared_storage_origin_); } } // namespace content
diff --git a/content/common/android/surface_wrapper.cc b/content/common/android/surface_wrapper.cc index fed61b3..ba00294 100644 --- a/content/common/android/surface_wrapper.cc +++ b/content/common/android/surface_wrapper.cc
@@ -21,10 +21,10 @@ return Java_SurfaceWrapper_canBeUsedWithSurfaceControl(env, obj); } -base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_getSurface( +base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_takeSurface( JNIEnv* env, const base::android::JavaRef<jobject>& obj) { - return Java_SurfaceWrapper_getSurface(env, obj); + return Java_SurfaceWrapper_takeSurface(env, obj); } } // namespace content.
diff --git a/content/common/android/surface_wrapper.h b/content/common/android/surface_wrapper.h index 0dde535..c6223dcc 100644 --- a/content/common/android/surface_wrapper.h +++ b/content/common/android/surface_wrapper.h
@@ -18,7 +18,7 @@ JNIEnv* env, const base::android::JavaRef<jobject>& obj); -base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_getSurface( +base::android::ScopedJavaLocalRef<jobject> JNI_SurfaceWrapper_takeSurface( JNIEnv* env, const base::android::JavaRef<jobject>& obj);
diff --git a/content/public/android/java/src/org/chromium/content/common/SurfaceWrapper.java b/content/public/android/java/src/org/chromium/content/common/SurfaceWrapper.java index 44818a0..ed896228 100644 --- a/content/public/android/java/src/org/chromium/content/common/SurfaceWrapper.java +++ b/content/public/android/java/src/org/chromium/content/common/SurfaceWrapper.java
@@ -18,21 +18,23 @@ @JNINamespace("content") @MainDex public class SurfaceWrapper implements Parcelable { - private final Surface mSurface; + private Surface mSurface; private final boolean mCanBeUsedWithSurfaceControl; - public SurfaceWrapper(Surface surface, boolean canBeUsedWithSurfaceControl) { + private SurfaceWrapper(Surface surface, boolean canBeUsedWithSurfaceControl) { mSurface = surface; mCanBeUsedWithSurfaceControl = canBeUsedWithSurfaceControl; } @CalledByNative - public Surface getSurface() { - return mSurface; + private Surface takeSurface() { + Surface surface = mSurface; + mSurface = null; + return surface; } @CalledByNative - public boolean canBeUsedWithSurfaceControl() { + private boolean canBeUsedWithSurfaceControl() { return mCanBeUsedWithSurfaceControl; }
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 110e353..b075b996 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -511,6 +511,7 @@ } bool ContentBrowserClient::IsSharedStorageAllowed( + content::BrowserContext* browser_context, content::RenderFrameHost* rfh, const url::Origin& top_frame_origin, const url::Origin& accessing_origin) {
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 99f1c92..450b57f 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -882,7 +882,10 @@ // Allows the embedder to control if Shared Storage API operations can happen // in a given context. - virtual bool IsSharedStorageAllowed(content::RenderFrameHost* rfh, + // + // Note that `rfh` can be nullptr. + virtual bool IsSharedStorageAllowed(content::BrowserContext* browser_context, + content::RenderFrameHost* rfh, const url::Origin& top_frame_origin, const url::Origin& accessing_origin);
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index 80c8aa2..292a43ab 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -153,6 +153,7 @@ sources = [ "bindings_policy.h", + "cdm_info.cc", "cdm_info.h", "child_process_host.h", "child_process_host_delegate.h",
diff --git a/content/public/common/cdm_info.cc b/content/public/common/cdm_info.cc new file mode 100644 index 0000000..36e73b2 --- /dev/null +++ b/content/public/common/cdm_info.cc
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <iostream> + +#include "cdm_info.h" + +#include "base/notreached.h" + +namespace content { + +std::string GetCdmInfoRobustnessName(CdmInfo::Robustness robustness) { + switch (robustness) { + case CdmInfo::Robustness::kHardwareSecure: + return "Hardware Secure"; + case CdmInfo::Robustness::kSoftwareSecure: + return "Software Secure"; + } + NOTREACHED(); +} + +} // namespace content \ No newline at end of file
diff --git a/content/public/common/cdm_info.h b/content/public/common/cdm_info.h index 80a08df..2733702b 100644 --- a/content/public/common/cdm_info.h +++ b/content/public/common/cdm_info.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_PUBLIC_COMMON_CDM_INFO_H_ #define CONTENT_PUBLIC_COMMON_CDM_INFO_H_ +#include <iosfwd> #include <string> #include <vector> @@ -104,6 +105,14 @@ base::FilePath path; }; +CONTENT_EXPORT std::string GetCdmInfoRobustnessName( + CdmInfo::Robustness robustness); + +inline std::ostream& operator<<(std::ostream& os, + CdmInfo::Robustness robustness) { + return os << GetCdmInfoRobustnessName(robustness); +} + } // namespace content #endif // CONTENT_PUBLIC_COMMON_CDM_INFO_H_
diff --git a/device/fido/features.cc b/device/fido/features.cc index 69d89d34..361f2dc 100644 --- a/device/fido/features.cc +++ b/device/fido/features.cc
@@ -52,4 +52,8 @@ "DisableWebAuthnWithBrokenCerts", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kWebAuthnNoPasskeysError, + "WebAuthenticationNoPasskeysError", + base::FEATURE_ENABLED_BY_DEFAULT); + } // namespace device
diff --git a/device/fido/features.h b/device/fido/features.h index c8a846c1..7ba3470 100644 --- a/device/fido/features.h +++ b/device/fido/features.h
@@ -53,6 +53,10 @@ COMPONENT_EXPORT(DEVICE_FIDO) BASE_DECLARE_FEATURE(kDisableWebAuthnWithBrokenCerts); +// Enable a special-case dialog for when there are no internal credentials. +COMPONENT_EXPORT(DEVICE_FIDO) +BASE_DECLARE_FEATURE(kWebAuthnNoPasskeysError); + } // namespace device #endif // DEVICE_FIDO_FEATURES_H_
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h index 66566100..b6f57a5 100644 --- a/device/fido/fido_request_handler_base.h +++ b/device/fido/fido_request_handler_base.h
@@ -123,6 +123,18 @@ // authenticator and thus have privacy implications. ResidentKeyRequirement resident_key_requirement = ResidentKeyRequirement::kDiscouraged; + + // transport_list_did_include_internal is set to true during a getAssertion + // request if at least one element of the allowList included the "internal" + // transport, or didn't have any transports. + // + // An embedder may use this to show a more precise UI when no transports + // are available. If the lack of transports is because the allowList only + // contained NFC-based credentials, and there's no NFC support, then that + // might be meaningfully different from the case where the allowList + // contained credentials that could have been on the local device but + // weren't. + bool transport_list_did_include_internal = false; }; class COMPONENT_EXPORT(DEVICE_FIDO) Observer {
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index 393f8d6..7780b113 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -10,6 +10,7 @@ #include <vector> #include "base/bind.h" +#include "base/containers/contains.h" #include "base/containers/cxx20_erase.h" #include "base/metrics/histogram_functions.h" #include "base/ranges/algorithm.h" @@ -322,6 +323,13 @@ request_.allow_list.empty(); transport_availability_info().is_off_the_record_context = request_.is_off_the_record_context; + transport_availability_info().transport_list_did_include_internal = + std::any_of(request_.allow_list.begin(), request_.allow_list.end(), + [](const PublicKeyCredentialDescriptor& cred) { + return cred.transports.empty() || + base::Contains(cred.transports, + FidoTransportProtocol::kInternal); + }); if (request_.allow_list.empty()) { // Resident credential requests always involve user verification.
diff --git a/docs/adding_to_third_party.md b/docs/adding_to_third_party.md index 98531ca1..1ee92840 100644 --- a/docs/adding_to_third_party.md +++ b/docs/adding_to_third_party.md
@@ -27,9 +27,29 @@ * Motivation of your project * Design docs * Additional checkout size + * If the increase is significant (e.g., 20+ MB), can we consider limiting the + files to be checked in? * Build time increase -* Binary size increase on Android ([official](https://www.chromium.org/developers/gn-build-configuration) builds) + * If the increase is significant (e.g., 30+ seconds), can we consider making + this an optional build target? +* Binary size increase on Android ([official](https://www.chromium.org/developers/gn-build-configuration) builds) + * Any 16 KB increase on Android is flagged on the build bots and + justification is needed. * Binary size increase on Windows +* Is this library maintained on all platforms that we will use it on? + * If not, will the Chrome org be expected to maintain this for some or all + platforms? +* Does it have any performance / memory implications (esp. on Android)? Was the +library designed with intended use on Android? +* Do we really need the library? Is there any alternative such as an existing +library already in Chromium? If introducing a library with similar functionality +as existing, will it be easy for another developer to understand which should be +used where? Will you commit to consolidating uses in Chromium and remove the +alternative libraries? +* For desktop (Win/Mac/Linux/ChromeOS), does the dependency introduce closed +source components (e.g., binaries, WASM binaries, obfuscated code)? If yes, +please reach out to Chrome ATLs. + Googlers can access [go/chrome-atls](https://goto.google.com/chrome-atls) and review existing topics in g/chrome-atls, and can also come to office hours to ask
diff --git a/docs/speed/perf_lab_platforms.md b/docs/speed/perf_lab_platforms.md index 908a401..f49c865 100644 --- a/docs/speed/perf_lab_platforms.md +++ b/docs/speed/perf_lab_platforms.md
@@ -8,7 +8,7 @@ * [android-go-perf](https://ci.chromium.org/p/chrome/builders/ci/android-go-perf): Android O (gobo). * [android-go-perf-pgo](https://ci.chromium.org/p/chrome/builders/ci/android-go-perf-pgo): Android O (gobo). - * [android-go-wembley-perf](https://ci.chromium.org/p/chrome/builders/ci/android-go-wembley-perf): Android M | MASTER. + * [android-go-wembley-perf](https://ci.chromium.org/p/chrome/builders/ci/android-go-wembley-perf): Android 9131443. * [android-go_webview-perf](https://ci.chromium.org/p/chrome/builders/ci/android-go_webview-perf): Android OPM1.171019.021 (gobo). * [android-pixel2-perf](https://ci.chromium.org/p/chrome/builders/ci/android-pixel2-perf): Android OPM1.171019.021. * [android-pixel2-perf-calibration](https://ci.chromium.org/p/chrome/builders/ci/android-pixel2-perf-calibration): Android OPM1.171019.021.
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc index b4427c47..9a4ea8c 100644 --- a/extensions/browser/api/management/management_api.cc +++ b/extensions/browser/api/management/management_api.cc
@@ -360,8 +360,7 @@ std::string error; scoped_refptr<Extension> extension = Extension::Create(base::FilePath(), ManifestLocation::kInvalidLocation, - base::DictAdapterForMigration(*parsed_manifest), - Extension::NO_FLAGS, &error); + *parsed_manifest, Extension::NO_FLAGS, &error); // TODO(lazyboy): Do we need to use |error|? if (!extension) { Respond(Error(keys::kExtensionCreateError));
diff --git a/extensions/browser/image_loader_unittest.cc b/extensions/browser/image_loader_unittest.cc index 30b1c04..e2177ce 100644 --- a/extensions/browser/image_loader_unittest.cc +++ b/extensions/browser/image_loader_unittest.cc
@@ -79,19 +79,20 @@ std::string error; JSONFileValueDeserializer deserializer( extension_dir.AppendASCII("manifest.json")); - std::unique_ptr<base::DictionaryValue> valid_value = - base::DictionaryValue::From( - deserializer.Deserialize(&error_code, &error)); + std::unique_ptr<base::Value> valid_value = + deserializer.Deserialize(&error_code, &error); EXPECT_EQ(0, error_code) << error; if (error_code != 0) return nullptr; EXPECT_TRUE(valid_value.get()); - if (!valid_value) + EXPECT_TRUE(valid_value->is_dict()); + if (!valid_value || !valid_value->is_dict()) { return nullptr; + } - return Extension::Create( - extension_dir, location, *valid_value, Extension::NO_FLAGS, &error); + return Extension::Create(extension_dir, location, valid_value->GetDict(), + Extension::NO_FLAGS, &error); } gfx::Image image_;
diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc index 182ba5bd..e478f9f 100644 --- a/extensions/browser/sandboxed_unpacker.cc +++ b/extensions/browser/sandboxed_unpacker.cc
@@ -538,8 +538,7 @@ std::string error_msg; scoped_refptr<Extension> extension( - Extension::Create(extension_root_, location_, - base::Value::AsDictionaryValue(manifest.value()), + Extension::Create(extension_root_, location_, manifest->GetDict(), creation_flags_, extension_id_, &error_msg)); if (!extension) { ReportUnpackExtensionFailed(error_msg);
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index 9cdcae6..df8bc5b 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc
@@ -140,7 +140,7 @@ // Computes the |extension_id| from the given parameters. On success, returns // true. On failure, populates |error| and returns false. -bool ComputeExtensionID(const base::DictAdapterForMigration& manifest, +bool ComputeExtensionID(const base::Value::Dict& manifest, const base::FilePath& path, int creation_flags, std::u16string* error, @@ -221,12 +221,11 @@ } // static -scoped_refptr<Extension> Extension::Create( - const base::FilePath& path, - ManifestLocation location, - const base::DictAdapterForMigration& value, - int flags, - std::string* utf8_error) { +scoped_refptr<Extension> Extension::Create(const base::FilePath& path, + ManifestLocation location, + const base::Value::Dict& value, + int flags, + std::string* utf8_error) { return Extension::Create(path, location, value, @@ -237,13 +236,12 @@ // TODO(sungguk): Continue removing std::string errors and replacing // with std::u16string. See http://crbug.com/71980. -scoped_refptr<Extension> Extension::Create( - const base::FilePath& path, - ManifestLocation location, - const base::DictAdapterForMigration& value, - int flags, - const std::string& explicit_id, - std::string* utf8_error) { +scoped_refptr<Extension> Extension::Create(const base::FilePath& path, + ManifestLocation location, + const base::Value::Dict& value, + int flags, + const std::string& explicit_id, + std::string* utf8_error) { base::ElapsedTimer timer; DCHECK(utf8_error); std::u16string error;
diff --git a/extensions/common/extension.h b/extensions/common/extension.h index 0862216d..91698320 100644 --- a/extensions/common/extension.h +++ b/extensions/common/extension.h
@@ -32,10 +32,6 @@ #error "Extensions must be enabled" #endif -namespace base { -class DictAdapterForMigration; -} - namespace extensions { class HashedExtensionId; class PermissionsData; @@ -156,22 +152,20 @@ Extension(const Extension&) = delete; Extension& operator=(const Extension&) = delete; - static scoped_refptr<Extension> Create( - const base::FilePath& path, - mojom::ManifestLocation location, - const base::DictAdapterForMigration& value, - int flags, - std::string* error); + static scoped_refptr<Extension> Create(const base::FilePath& path, + mojom::ManifestLocation location, + const base::Value::Dict& value, + int flags, + std::string* error); // In a few special circumstances, we want to create an Extension and give it // an explicit id. Most consumers should just use the other Create() method. - static scoped_refptr<Extension> Create( - const base::FilePath& path, - mojom::ManifestLocation location, - const base::DictAdapterForMigration& value, - int flags, - const ExtensionId& explicit_id, - std::string* error); + static scoped_refptr<Extension> Create(const base::FilePath& path, + mojom::ManifestLocation location, + const base::Value::Dict& value, + int flags, + const ExtensionId& explicit_id, + std::string* error); // Valid schemes for web extent URLPatterns. static const int kValidWebExtentSchemes; @@ -307,9 +301,7 @@ const std::vector<InstallWarning>& install_warnings() const { return install_warnings_; } - const extensions::Manifest* manifest() const { - return manifest_.get(); - } + const extensions::Manifest* manifest() const { return manifest_.get(); } bool wants_file_access() const { return wants_file_access_; } // TODO(rdevlin.cronin): This is needed for ContentScriptsHandler, and should // be moved out as part of crbug.com/159265. This should not be used anywhere @@ -344,7 +336,7 @@ bool is_extension() const; // Regular browser extension, not an app bool is_shared_module() const; // Shared module bool is_theme() const; // Theme - bool is_login_screen_extension() const; // Extension on login screen. + bool is_login_screen_extension() const; // Extension on login screen. bool is_chromeos_system_extension() const; // ChromeOS System Extension. // True if this is a platform app, hosted app, or legacy packaged app. @@ -493,7 +485,7 @@ base::GUID guid_; }; -typedef std::vector<scoped_refptr<const Extension> > ExtensionList; +typedef std::vector<scoped_refptr<const Extension>> ExtensionList; // Handy struct to pass core extension info around. struct ExtensionInfo {
diff --git a/extensions/common/extension_builder.cc b/extensions/common/extension_builder.cc index 9207b4d5..bc9b698 100644 --- a/extensions/common/extension_builder.cc +++ b/extensions/common/extension_builder.cc
@@ -144,11 +144,17 @@ id_ = crx_file::id_util::GenerateId(manifest_data_->name); std::string error; + + // This allows `*manifest_value` to be passed as a reference instead of + // needing to be cloned. + absl::optional<base::Value::Dict> manifest_data_value; + if (manifest_data_) { + manifest_data_value = manifest_data_->GetValue(); + } scoped_refptr<const Extension> extension = Extension::Create( path_, location_, - manifest_data_ ? base::DictAdapterForMigration(manifest_data_->GetValue()) - : *manifest_value_, - flags_, id_, &error); + manifest_data_value ? *manifest_data_value : *manifest_value_, flags_, + id_, &error); CHECK(error.empty()) << error; CHECK(extension);
diff --git a/extensions/common/features/simple_feature_unittest.cc b/extensions/common/features/simple_feature_unittest.cc index 8894dbb..520a8f2 100644 --- a/extensions/common/features/simple_feature_unittest.cc +++ b/extensions/common/features/simple_feature_unittest.cc
@@ -338,11 +338,11 @@ feature.set_min_manifest_version(21); feature.set_max_manifest_version(25); - base::DictionaryValue manifest; - manifest.SetStringKey("name", "test"); - manifest.SetStringKey("version", "1"); - manifest.SetIntKey("manifest_version", 21); - manifest.SetStringPath("app.launch.local_path", "foo.html"); + base::Value::Dict manifest; + manifest.Set("name", "test"); + manifest.Set("version", "1"); + manifest.Set("manifest_version", 21); + manifest.SetByDottedPath("app.launch.local_path", "foo.html"); std::string error; scoped_refptr<const Extension> extension( @@ -456,11 +456,11 @@ } TEST_F(SimpleFeatureTest, SessionType) { - base::DictionaryValue manifest; - manifest.SetStringKey("name", "test"); - manifest.SetStringKey("version", "1"); - manifest.SetIntKey("manifest_version", 2); - manifest.SetStringPath("app.launch.local_path", "foo.html"); + base::Value::Dict manifest; + manifest.Set("name", "test"); + manifest.Set("version", "1"); + manifest.Set("manifest_version", 2); + manifest.SetByDottedPath("app.launch.local_path", "foo.html"); std::string error; scoped_refptr<const Extension> extension(
diff --git a/extensions/common/manifest_handler_unittest.cc b/extensions/common/manifest_handler_unittest.cc index 47661eab..ba85545 100644 --- a/extensions/common/manifest_handler_unittest.cc +++ b/extensions/common/manifest_handler_unittest.cc
@@ -213,18 +213,17 @@ ScopedTestingManifestHandlerRegistry scoped_registry; // Can't use ExtensionBuilder, because this extension will fail to // be parsed. - std::unique_ptr<base::DictionaryValue> manifest_a( - DictionaryBuilder() - .Set("name", "no name") - .Set("version", "0") - .Set("manifest_version", 2) - .Set("a", 1) - .Build()); + base::Value::Dict manifest_a(DictionaryBuilder() + .Set("name", "no name") + .Set("version", "0") + .Set("manifest_version", 2) + .Set("a", 1) + .BuildDict()); // Succeeds when "a" is not recognized. std::string error; scoped_refptr<Extension> extension = Extension::Create( - base::FilePath(), mojom::ManifestLocation::kInvalidLocation, *manifest_a, + base::FilePath(), mojom::ManifestLocation::kInvalidLocation, manifest_a, Extension::NO_FLAGS, &error); EXPECT_TRUE(extension.get()); @@ -237,7 +236,7 @@ extension = Extension::Create(base::FilePath(), mojom::ManifestLocation::kInvalidLocation, - *manifest_a, Extension::NO_FLAGS, &error); + manifest_a, Extension::NO_FLAGS, &error); EXPECT_FALSE(extension.get()); EXPECT_EQ("A", error); }
diff --git a/extensions/common/manifest_test.cc b/extensions/common/manifest_test.cc index dd15eb4..74a8527 100644 --- a/extensions/common/manifest_test.cc +++ b/extensions/common/manifest_test.cc
@@ -126,8 +126,7 @@ const base::Value& value = manifest.GetManifest(test_data_dir, error); if (value.is_none()) return nullptr; - return Extension::Create(test_data_dir.DirName(), location, - base::DictAdapterForMigration(value.GetDict()), + return Extension::Create(test_data_dir.DirName(), location, value.GetDict(), flags, GetTestExtensionID(), error); }
diff --git a/extensions/common/mojom/permission_set_mojom_traits_unittest.cc b/extensions/common/mojom/permission_set_mojom_traits_unittest.cc index 2ae2422..a75a2e4 100644 --- a/extensions/common/mojom/permission_set_mojom_traits_unittest.cc +++ b/extensions/common/mojom/permission_set_mojom_traits_unittest.cc
@@ -47,8 +47,7 @@ value.Append("tcp-connect:*.example.com:80"); value.Append("udp-bind::8080"); value.Append("udp-send-to::8888"); - ASSERT_TRUE( - input->FromValue(&base::Value::AsListValue(value), nullptr, nullptr)); + ASSERT_TRUE(input->FromValue(&value, nullptr, nullptr)); } std::unique_ptr<APIPermission> output = nullptr; @@ -67,8 +66,7 @@ value.Append("tcp-connect:*.example.com:80"); value.Append("udp-bind::8080"); value.Append("udp-send-to::8888"); - ASSERT_TRUE(permission->FromValue(&base::Value::AsListValue(value), nullptr, - nullptr)); + ASSERT_TRUE(permission->FromValue(&value, nullptr, nullptr)); } APIPermissionSet input; @@ -135,8 +133,7 @@ value.Append("tcp-connect:*.example.com:80"); value.Append("udp-bind::8080"); value.Append("udp-send-to::8888"); - ASSERT_TRUE(permission->FromValue(&base::Value::AsListValue(value), nullptr, - nullptr)); + ASSERT_TRUE(permission->FromValue(&value, nullptr, nullptr)); } APIPermissionSet apis;
diff --git a/gpu/command_buffer/service/image_reader_gl_owner.cc b/gpu/command_buffer/service/image_reader_gl_owner.cc index 4b6fb13..2497c096 100644 --- a/gpu/command_buffer/service/image_reader_gl_owner.cc +++ b/gpu/command_buffer/service/image_reader_gl_owner.cc
@@ -226,14 +226,14 @@ // If we've already lost the texture, then do nothing. if (!image_reader_) { DLOG(ERROR) << "Already lost texture / image reader"; - return gl::ScopedJavaSurface::AcquireExternalSurface(nullptr); + return nullptr; } // Get the android native window from the image reader. ANativeWindow* window = nullptr; if (loader_->AImageReader_getWindow(image_reader_, &window) != AMEDIA_OK) { DLOG(ERROR) << "unable to get a window from image reader."; - return gl::ScopedJavaSurface::AcquireExternalSurface(nullptr); + return nullptr; } // Get the java surface object from the Android native window. @@ -243,7 +243,7 @@ DCHECK(j_surface); // Get the scoped java surface that will call release() on destruction. - return gl::ScopedJavaSurface(j_surface); + return gl::ScopedJavaSurface(j_surface, /*auto_release=*/true); } void ImageReaderGLOwner::UpdateTexImage() {
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.cc b/gpu/command_buffer/service/shared_image/compound_image_backing.cc index 79550ab9..9e94f8bb 100644 --- a/gpu/command_buffer/service/shared_image/compound_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
@@ -309,39 +309,33 @@ bool allow_shm_overlays, const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, - gfx::BufferFormat buffer_format, + gfx::BufferFormat format, gfx::BufferPlane plane, const gfx::Size& size, const gfx::ColorSpace& color_space, GrSurfaceOrigin surface_origin, SkAlphaType alpha_type, uint32_t usage) { - DCHECK(IsValidSharedMemoryBufferFormat(size, buffer_format, plane)); - - const gfx::Size plane_size = GetPlaneSize(plane, size); - const viz::ResourceFormat plane_format = - viz::GetResourceFormat(GetPlaneBufferFormat(plane, buffer_format)); - - const size_t plane_index = GetPlaneIndex(plane, buffer_format); - handle.offset += - gfx::BufferOffsetForBufferFormat(size, buffer_format, plane_index); + DCHECK(IsValidSharedMemoryBufferFormat(size, format, plane)); SharedMemoryRegionWrapper shm_wrapper; - if (!shm_wrapper.Initialize(handle, plane_size, plane_format)) { + if (!shm_wrapper.Initialize(handle, size, format, plane)) { DLOG(ERROR) << "Failed to create SharedMemoryRegionWrapper"; return nullptr; } - auto si_format = viz::SharedImageFormat::SinglePlane(plane_format); + const gfx::Size plane_size = GetPlaneSize(plane, size); + const auto plane_format = viz::SharedImageFormat::SinglePlane( + viz::GetResourceFormat(GetPlaneBufferFormat(plane, format))); auto shm_backing = std::make_unique<SharedMemoryImageBacking>( - mailbox, si_format, plane_size, color_space, surface_origin, alpha_type, - SHARED_IMAGE_USAGE_CPU_WRITE, std::move(shm_wrapper)); + mailbox, plane_format, plane_size, color_space, surface_origin, + alpha_type, SHARED_IMAGE_USAGE_CPU_WRITE, std::move(shm_wrapper)); shm_backing->SetNotRefCounted(); return base::WrapUnique(new CompoundImageBacking( - mailbox, si_format, plane_size, color_space, surface_origin, alpha_type, - usage, allow_shm_overlays, std::move(shm_backing), + mailbox, plane_format, plane_size, color_space, surface_origin, + alpha_type, usage, allow_shm_overlays, std::move(shm_backing), gpu_backing_factory->GetWeakPtr())); }
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing.cc b/gpu/command_buffer/service/shared_image/egl_image_backing.cc index 2fd05b2f..ca0e2bc 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/egl_image_backing.cc
@@ -485,12 +485,6 @@ return base::MakeRefCounted<TextureHolder>(std::move(texture)); } -void EGLImageBacking::SetEndReadFence( - scoped_refptr<gl::SharedGLFenceEGL> shared_egl_fence) { - AutoLock auto_lock(this); - read_fences_[gl::g_current_gl_context] = std::move(shared_egl_fence); -} - void EGLImageBacking::MarkForDestruction() { AutoLock auto_lock(this); DCHECK(!have_context() || created_on_context_ == gl::g_current_gl_context);
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing.h b/gpu/command_buffer/service/shared_image/egl_image_backing.h index 3ddf2da9..86e8d60e 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing.h +++ b/gpu/command_buffer/service/shared_image/egl_image_backing.h
@@ -90,8 +90,6 @@ scoped_refptr<TextureHolder> GenEGLImageSibling( base::span<const uint8_t> pixel_data); - void SetEndReadFence(scoped_refptr<gl::SharedGLFenceEGL> shared_egl_fence); - const GLCommonImageBackingFactory::FormatInfo format_info_; scoped_refptr<TextureHolder> source_texture_holder_; raw_ptr<gl::GLApi> created_on_context_;
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc index b8dff58..340359e 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
@@ -469,10 +469,8 @@ SharedContextState* shared_context_state = factory()->GetSharedContextState(); ui::ScopedMakeCurrent smc(shared_context_state->context(), shared_context_state->surface()); - auto image_np = base::MakeRefCounted<gl::GLImageNativePixmap>( - size(), ToBufferFormat(format())); - image_np->InitializeFromTexture(GetGLServiceId()); - image_egl_ = image_np; + image_egl_ = gl::GLImageNativePixmap::CreateFromTexture( + size(), ToBufferFormat(format()), GetGLServiceId()); if (passthrough_texture_) { passthrough_texture_->SetLevelImage(passthrough_texture_->target(), 0, image_egl_.get());
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.cc b/gpu/command_buffer/service/shared_image/shared_image_factory.cc index aa2b9eb02..0c5e3f8 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
@@ -449,10 +449,12 @@ std::unique_ptr<SharedImageBacking> backing; if (use_compound) { + // Only allow shmem overlays for NV12 on Windows. #if BUILDFLAG(IS_WIN) - constexpr bool allow_shm_overlays = true; + const bool allow_shm_overlays = + format == gfx::BufferFormat::YUV_420_BIPLANAR; #else - constexpr bool allow_shm_overlays = false; + const bool allow_shm_overlays = false; #endif backing = CompoundImageBacking::CreateSharedMemory( factory, allow_shm_overlays, mailbox, std::move(handle), format, plane,
diff --git a/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc index 1d88dd89..261fdc0 100644 --- a/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc
@@ -60,12 +60,11 @@ SkAlphaType alpha_type, uint32_t usage) { DCHECK(handle.type == gfx::SHARED_MEMORY_BUFFER); - viz::ResourceFormat format = viz::GetResourceFormat(buffer_format); SharedMemoryRegionWrapper shm_wrapper; - if (!shm_wrapper.Initialize(handle, size, format)) { + if (!shm_wrapper.Initialize(handle, size, buffer_format, plane)) { return nullptr; } - + const auto format = viz::GetResourceFormat(buffer_format); auto backing = std::make_unique<SharedMemoryImageBacking>( mailbox, viz::SharedImageFormat::SinglePlane(format), size, color_space, surface_origin, alpha_type, usage, std::move(shm_wrapper));
diff --git a/gpu/command_buffer/service/shared_memory_region_wrapper.cc b/gpu/command_buffer/service/shared_memory_region_wrapper.cc index 11c93282..91fa8ce 100644 --- a/gpu/command_buffer/service/shared_memory_region_wrapper.cc +++ b/gpu/command_buffer/service/shared_memory_region_wrapper.cc
@@ -7,8 +7,8 @@ #include "base/logging.h" #include "base/numerics/checked_math.h" #include "base/system/sys_info.h" -#include "components/viz/common/resources/resource_format_utils.h" -#include "components/viz/common/resources/resource_sizes.h" +#include "gpu/command_buffer/common/gpu_memory_buffer_support.h" +#include "ui/gfx/buffer_format_util.h" #include "ui/gfx/gpu_memory_buffer.h" namespace gpu { @@ -16,39 +16,25 @@ // Validate that |stride| will work for pixels with |size| and |format|. bool ValidateStride(const gfx::Size size, - viz::ResourceFormat format, + gfx::BufferFormat format, uint32_t stride) { if (!base::IsValueInRangeForNumericType<size_t>(stride)) return false; - uint32_t min_width_in_bytes = 0; - if (!viz::ResourceSizes::MaybeWidthInBytes(size.width(), format, - &min_width_in_bytes)) { + // Use plane index 0 since we can't handle different plane strides anyway. + size_t alignment = gfx::RowByteAlignmentForBufferFormat(format, /*plane=*/0); + if (stride % alignment != 0) + return false; + + size_t min_width_in_bytes = 0; + if (!gfx::RowSizeForBufferFormatChecked(size.width(), format, /*plane=*/0, + &min_width_in_bytes)) { return false; } if (stride < min_width_in_bytes) return false; - // Check that stride is a multiple of pixel byte size. - int bits_per_pixel = viz::BitsPerPixel(format); - switch (bits_per_pixel) { - case 64: - case 32: - case 16: - if (stride % (bits_per_pixel / 8) != 0) - return false; - break; - case 8: - case 4: - break; - default: - // YVU420, YUV_420_BIPLANAR, and YUVA_420_TRIPLANAR format aren't - // supported. - NOTREACHED(); - return false; - } - return true; } @@ -64,7 +50,8 @@ bool SharedMemoryRegionWrapper::Initialize( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, - viz::ResourceFormat format) { + gfx::BufferFormat format, + gfx::BufferPlane plane) { DCHECK(!mapping_.IsValid()); if (!handle.region.IsValid()) { @@ -77,30 +64,49 @@ return false; } - // Minimize the amount of address space we use but make sure offset is a - // multiple of page size as required by MapAt(). - size_t allocation_granularity = base::SysInfo::VMAllocationGranularity(); - size_t memory_offset = handle.offset % allocation_granularity; - size_t map_offset = - allocation_granularity * (handle.offset / allocation_granularity); - - base::CheckedNumeric<size_t> checked_size = handle.stride; - checked_size *= size.height(); - checked_size += memory_offset; - if (!checked_size.IsValid()) { + size_t buffer_size; + if (!gfx::BufferSizeForBufferFormatChecked(size, format, &buffer_size)) { DLOG(ERROR) << "Invalid GMB size."; return false; } - mapping_ = handle.region.MapAt(static_cast<off_t>(map_offset), - checked_size.ValueOrDie()); + // Minimize the amount of address space we use but make sure offset is a + // multiple of page size as required by MapAt(). + // TODO(sunnyps): This doesn't seem to be a requirement of MapAt() anymore. + const size_t allocation_granularity = + base::SysInfo::VMAllocationGranularity(); + const size_t memory_offset = handle.offset % allocation_granularity; + const size_t map_offset = + allocation_granularity * (handle.offset / allocation_granularity); + base::CheckedNumeric<size_t> checked_size = buffer_size; + checked_size += memory_offset; + if (!checked_size.IsValid()) { + DLOG(ERROR) << "Invalid shared memory region map size."; + return false; + } + + const size_t map_size = checked_size.ValueOrDie(); + mapping_ = handle.region.MapAt(static_cast<off_t>(map_offset), map_size); if (!mapping_.IsValid()) { DLOG(ERROR) << "Failed to map shared memory."; return false; } - offset_ = memory_offset; + // Add plane offset separately so that we map the entire buffer even if we're + // accessing an individual plane - this helps with shared memory overlays on + // Windows by allowing access via the Y plane shared image only. + const size_t plane_index = GetPlaneIndex(plane, format); + const size_t plane_offset = + gfx::BufferOffsetForBufferFormat(size, format, plane_index); +#if DCHECK_IS_ON() + const gfx::Size plane_size = GetPlaneSize(plane, size); + const size_t plane_size_bytes = + gfx::PlaneSizeForBufferFormat(plane_size, format, plane_index); + DCHECK_LE(memory_offset + plane_offset + plane_size_bytes, map_size); +#endif + + offset_ = memory_offset + plane_offset; stride_ = handle.stride; return true;
diff --git a/gpu/command_buffer/service/shared_memory_region_wrapper.h b/gpu/command_buffer/service/shared_memory_region_wrapper.h index 19ee638..d8ace07 100644 --- a/gpu/command_buffer/service/shared_memory_region_wrapper.h +++ b/gpu/command_buffer/service/shared_memory_region_wrapper.h
@@ -8,7 +8,7 @@ #include "base/containers/span.h" #include "base/memory/shared_memory_mapping.h" #include "base/unguessable_token.h" -#include "components/viz/common/resources/resource_format.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/size.h" namespace gfx { @@ -31,7 +31,8 @@ // until destruction. bool Initialize(const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, - viz::ResourceFormat format); + gfx::BufferFormat format, + gfx::BufferPlane plane); bool IsValid() const; uint8_t* GetMemory() const;
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc index a3108c9c..686c482 100644 --- a/gpu/command_buffer/tests/gl_test_utils.cc +++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -484,9 +484,9 @@ EXPECT_NE(0u, tex_service_id); // Create an EGLImage from the real texture id. - auto image = base::MakeRefCounted<gl::GLImageNativePixmap>(size, format); - bool result = image->InitializeFromTexture(tex_service_id); - DCHECK(result); + auto image = + gl::GLImageNativePixmap::CreateFromTexture(size, format, tex_service_id); + DCHECK(image); // The test will own the EGLImage no need to keep a reference on the GL // texture after returning from this function. This is covered by the
diff --git a/gpu/ipc/common/gpu_surface_lookup.h b/gpu/ipc/common/gpu_surface_lookup.h index f7b3a4e..ac1cddc 100644 --- a/gpu/ipc/common/gpu_surface_lookup.h +++ b/gpu/ipc/common/gpu_surface_lookup.h
@@ -5,14 +5,10 @@ #ifndef GPU_IPC_COMMON_GPU_SURFACE_LOOKUP_H_ #define GPU_IPC_COMMON_GPU_SURFACE_LOOKUP_H_ -#include "build/build_config.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/surface_handle.h" #include "ui/gfx/native_widget_types.h" - -#if BUILDFLAG(IS_ANDROID) #include "ui/gl/android/scoped_java_surface.h" -#endif namespace gpu { @@ -30,11 +26,9 @@ static GpuSurfaceLookup* GetInstance(); static void InitInstance(GpuSurfaceLookup* lookup); -#if BUILDFLAG(IS_ANDROID) virtual gl::ScopedJavaSurface AcquireJavaSurface( int surface_id, bool* can_be_used_with_surface_control) = 0; -#endif }; } // namespace gpu
diff --git a/gpu/ipc/common/gpu_surface_tracker.cc b/gpu/ipc/common/gpu_surface_tracker.cc index 84921d2..0d28aec 100644 --- a/gpu/ipc/common/gpu_surface_tracker.cc +++ b/gpu/ipc/common/gpu_surface_tracker.cc
@@ -6,31 +6,15 @@ #include "base/check.h" #include "build/build_config.h" - -#if BUILDFLAG(IS_ANDROID) -#include <android/native_window_jni.h> #include "ui/gl/android/scoped_java_surface.h" -#endif // BUILDFLAG(IS_ANDROID) namespace gpu { -#if BUILDFLAG(IS_ANDROID) GpuSurfaceTracker::SurfaceRecord::SurfaceRecord( - gfx::AcceleratedWidget widget, - const base::android::JavaRef<jobject>& j_surface, + gl::ScopedJavaSurface surface, bool can_be_used_with_surface_control) - : widget(widget), - can_be_used_with_surface_control(can_be_used_with_surface_control) { - // TODO(liberato): It would be nice to assert |surface|, but we - // can't. in_process_context_factory.cc (for tests) actually calls us without - // a Surface from java. Presumably, nobody uses it. crbug.com/712717 . - if (j_surface) - surface = gl::ScopedJavaSurface::AcquireExternalSurface(j_surface); -} -#else // BUILDFLAG(IS_ANDROID) -GpuSurfaceTracker::SurfaceRecord::SurfaceRecord(gfx::AcceleratedWidget widget) - : widget(widget) {} -#endif // !BUILDFLAG(IS_ANDROID) + : surface(std::move(surface)), + can_be_used_with_surface_control(can_be_used_with_surface_control) {} GpuSurfaceTracker::SurfaceRecord::SurfaceRecord(SurfaceRecord&&) = default; @@ -66,7 +50,6 @@ surface_map_.erase(surface_handle); } -#if BUILDFLAG(IS_ANDROID) gl::ScopedJavaSurface GpuSurfaceTracker::AcquireJavaSurface( gpu::SurfaceHandle surface_handle, bool* can_be_used_with_surface_control) { @@ -80,9 +63,8 @@ *can_be_used_with_surface_control = it->second.can_be_used_with_surface_control; - return gl::ScopedJavaSurface::AcquireExternalSurface(j_surface.j_surface()); + return j_surface.CopyRetainOwnership(); } -#endif std::size_t GpuSurfaceTracker::GetSurfaceCount() { base::AutoLock lock(surface_map_lock_);
diff --git a/gpu/ipc/common/gpu_surface_tracker.h b/gpu/ipc/common/gpu_surface_tracker.h index 3b245fa..9281127 100644 --- a/gpu/ipc/common/gpu_surface_tracker.h +++ b/gpu/ipc/common/gpu_surface_tracker.h
@@ -9,60 +9,41 @@ #include <map> +#include "base/android/scoped_java_ref.h" #include "base/memory/singleton.h" #include "base/synchronization/lock.h" -#include "build/build_config.h" #include "gpu/gpu_export.h" #include "gpu/ipc/common/gpu_surface_lookup.h" #include "gpu/ipc/common/surface_handle.h" -#include "ui/gfx/native_widget_types.h" - -#if BUILDFLAG(IS_ANDROID) -#include "base/android/scoped_java_ref.h" -#endif +#include "ui/gl/android/scoped_java_surface.h" namespace gpu { -// This class is used on Android and Mac, and is responsible for tracking native +// This class is used on Android, and is responsible for tracking native // window surfaces exposed to the GPU process. Every surface gets registered to // this class, and gets a handle. The handle can be passed to // CommandBufferProxyImpl::Create or to // GpuMemoryBufferManager::CreateGpuMemoryBuffer. // On Android, the handle is used in the GPU process to get a reference to the -// ANativeWindow, using GpuSurfaceLookup (implemented by -// ChildProcessSurfaceManager). We require that an Android Surface is provided -// with the ANativeWindow, so one must provide an explicit GpuSurfaceTracker:: -// SurfaceRecord when adding it. -// On Mac, the handle just passes through the GPU process, and is sent back via -// GpuCommandBufferMsg_SwapBuffersCompleted to reference the surface. +// ScopedJavaSurface, using GpuSurfaceLookup (implemented by +// ChildProcessSurfaceManager). // This class is thread safe. class GPU_EXPORT GpuSurfaceTracker : public gpu::GpuSurfaceLookup { public: struct SurfaceRecord { -#if BUILDFLAG(IS_ANDROID) - SurfaceRecord(gfx::AcceleratedWidget widget, - const base::android::JavaRef<jobject>& j_surface, + SurfaceRecord(gl::ScopedJavaSurface surface, bool can_be_used_with_surface_control); -#else // BUILDFLAG(IS_ANDROID) - explicit SurfaceRecord(gfx::AcceleratedWidget widget); -#endif // !BUILDFLAG(IS_ANDROID) SurfaceRecord(SurfaceRecord&&); SurfaceRecord(const SurfaceRecord&) = delete; - // TODO(crbug.com/1399516): Make this non-android. - gfx::AcceleratedWidget widget; -#if BUILDFLAG(IS_ANDROID) gl::ScopedJavaSurface surface; bool can_be_used_with_surface_control; -#endif }; -#if BUILDFLAG(IS_ANDROID) gl::ScopedJavaSurface AcquireJavaSurface( gpu::SurfaceHandle surface_handle, bool* can_be_used_with_surface_control) override; -#endif // Gets the global instance of the surface tracker. static GpuSurfaceTracker* Get() { return GetInstance(); }
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc index 84dd4215..a581c3de 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc
@@ -116,8 +116,8 @@ << gfx::BufferUsageToString(usage); return nullptr; } - auto image = base::MakeRefCounted<gl::GLImageNativePixmap>(size, format); - if (!image->Initialize(std::move(pixmap))) { + auto image = gl::GLImageNativePixmap::Create(size, format, std::move(pixmap)); + if (!image) { LOG(ERROR) << "Failed to create GLImage " << size.ToString() << ", " << gfx::BufferFormatToString(format) << ", usage " << gfx::BufferUsageToString(usage);
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index c227453..2225f2e 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -311,7 +311,6 @@ "public/headless_browser.cc", "public/headless_browser.h", "public/headless_export.h", - "public/internal/headless_devtools_client_impl.h", "public/internal/message_dispatcher.h", "public/internal/value_conversions.h", "public/util/error_reporter.cc", @@ -386,7 +385,6 @@ "lib/browser/headless_devtools.h", "lib/browser/headless_devtools_agent_host_client.cc", "lib/browser/headless_devtools_agent_host_client.h", - "lib/browser/headless_devtools_client_impl.cc", "lib/browser/headless_devtools_manager_delegate.cc", "lib/browser/headless_devtools_manager_delegate.h", "lib/browser/headless_permission_manager.cc", @@ -715,7 +713,6 @@ deps = [ ":headless_browsertests", - ":headless_example", ":headless_unittests", ] } @@ -1062,22 +1059,3 @@ ] output = "$target_gen_dir/public/version.h" } - -executable("headless_example") { - sources = [ "app/headless_example.cc" ] - defines = [] - - deps = [ - ":headless_shell_lib", - "//content", - "//sandbox", - "//skia", # we need this to override font render hinting in headless build - "//ui/gfx/geometry", - ] - - if (is_win) { - deps += [ "//content/public/app" ] - } - - configs += [ ":headless_defines_config" ] -}
diff --git a/headless/app/headless_example.cc b/headless/app/headless_example.cc deleted file mode 100644 index 3a9ea309..0000000 --- a/headless/app/headless_example.cc +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// A small example application showing the use of the C++ Headless Chrome -// library. It navigates to a web site given on the command line, waits for it -// to load and prints out the DOM. -// -// Tip: start reading from the main() function below. - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "build/build_config.h" -#include "headless/public/devtools/domains/page.h" -#include "headless/public/devtools/domains/runtime.h" -#include "headless/public/headless_browser.h" -#include "headless/public/headless_devtools_client.h" -#include "headless/public/headless_devtools_target.h" -#include "headless/public/headless_web_contents.h" -#include "ui/gfx/geometry/size.h" - -#if BUILDFLAG(IS_WIN) -#include "base/strings/utf_string_conversions.h" -#include "content/public/app/sandbox_helper_win.h" -#include "sandbox/win/src/sandbox_types.h" -#endif - -// This class contains the main application logic, i.e., waiting for a page to -// load and printing its DOM. Note that browser initialization happens outside -// this class. -class HeadlessExample : public headless::HeadlessWebContents::Observer, - public headless::page::Observer { - public: - HeadlessExample(headless::HeadlessBrowser* browser, - headless::HeadlessWebContents* web_contents); - ~HeadlessExample() override; - - // headless::HeadlessWebContents::Observer implementation: - void DevToolsTargetReady() override; - - // headless::page::Observer implementation: - void OnLoadEventFired( - const headless::page::LoadEventFiredParams& params) override; - - // Tip: Observe headless::inspector::ExperimentalObserver::OnTargetCrashed to - // be notified of renderer crashes. - - void OnDomFetched(std::unique_ptr<headless::runtime::EvaluateResult> result); - - private: - // The headless browser instance. Owned by the headless library. See main(). - raw_ptr<headless::HeadlessBrowser> browser_; - // Our tab. Owned by |browser_|. - raw_ptr<headless::HeadlessWebContents> web_contents_; - // The DevTools client used to control the tab. - std::unique_ptr<headless::HeadlessDevToolsClient> devtools_client_; - // A helper for creating weak pointers to this class. - base::WeakPtrFactory<HeadlessExample> weak_factory_{this}; -}; - -namespace { -HeadlessExample* g_example; -} - -HeadlessExample::HeadlessExample(headless::HeadlessBrowser* browser, - headless::HeadlessWebContents* web_contents) - : browser_(browser), - web_contents_(web_contents), - devtools_client_(headless::HeadlessDevToolsClient::Create()) { - web_contents_->AddObserver(this); -} - -HeadlessExample::~HeadlessExample() { - // Note that we shut down the browser last, because it owns objects such as - // the web contents which can no longer be accessed after the browser is gone. - devtools_client_->GetPage()->RemoveObserver(this); - web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get()); - web_contents_->RemoveObserver(this); - browser_->Shutdown(); -} - -// This method is called when the tab is ready for DevTools inspection. -void HeadlessExample::DevToolsTargetReady() { - // Attach our DevTools client to the tab so that we can send commands to it - // and observe events. - web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get()); - - // Start observing events from DevTools's page domain. This lets us get - // notified when the page has finished loading. Note that it is possible - // the page has already finished loading by now. See - // HeadlessShell::DevToolTargetReady for how to handle that case correctly. - devtools_client_->GetPage()->AddObserver(this); - devtools_client_->GetPage()->Enable(); -} - -void HeadlessExample::OnLoadEventFired( - const headless::page::LoadEventFiredParams& params) { - // The page has now finished loading. Let's grab a snapshot of the DOM by - // evaluating the innerHTML property on the document element. - devtools_client_->GetRuntime()->Evaluate( - "(document.doctype ? new " - "XMLSerializer().serializeToString(document.doctype) + '\\n' : '') + " - "document.documentElement.outerHTML", - base::BindOnce(&HeadlessExample::OnDomFetched, - weak_factory_.GetWeakPtr())); -} - -void HeadlessExample::OnDomFetched( - std::unique_ptr<headless::runtime::EvaluateResult> result) { - // Make sure the evaluation succeeded before reading the result. - if (result->HasExceptionDetails()) { - LOG(ERROR) << "Failed to serialize document: " - << result->GetExceptionDetails()->GetText(); - } else { - printf("%s\n", result->GetResult()->GetValue()->GetString().c_str()); - } - - // Shut down the browser (see ~HeadlessExample). - delete g_example; - g_example = nullptr; -} - -// This function is called by the headless library after the browser has been -// initialized. It runs on the UI thread. -void OnHeadlessBrowserStarted(headless::HeadlessBrowser* browser) { - // In order to open tabs, we first need a browser context. It corresponds to a - // user profile and contains things like the user's cookies, local storage, - // cache, etc. - headless::HeadlessBrowserContext::Builder context_builder = - browser->CreateBrowserContextBuilder(); - - // Here we can set options for the browser context. As an example we enable - // incognito mode, which makes sure profile data is not written to disk. - context_builder.SetIncognitoMode(true); - - // Construct the context and set it as the default. The default browser - // context is used by the Target.createTarget() DevTools command when no other - // context is given. - headless::HeadlessBrowserContext* browser_context = context_builder.Build(); - browser->SetDefaultBrowserContext(browser_context); - - // Get the URL from the command line. - base::CommandLine::StringVector args = - base::CommandLine::ForCurrentProcess()->GetArgs(); - if (args.empty()) { - LOG(ERROR) << "No URL to load"; - browser->Shutdown(); - return; - } -#if BUILDFLAG(IS_WIN) - GURL url(base::WideToUTF16(args[0])); -#else - GURL url(args[0]); -#endif - - // Open a tab (i.e., HeadlessWebContents) in the newly created browser - // context. - headless::HeadlessWebContents::Builder tab_builder( - browser_context->CreateWebContentsBuilder()); - - // We can set options for the opened tab here. In this example we are just - // setting the initial URL to navigate to. - tab_builder.SetInitialURL(url); - - // Create an instance of the example app, which will wait for the page to load - // and print its DOM. - headless::HeadlessWebContents* web_contents = tab_builder.Build(); - g_example = new HeadlessExample(browser, web_contents); -} - -int main(int argc, const char** argv) { -#if !BUILDFLAG(IS_WIN) - // This function must be the first thing we call to make sure child processes - // such as the renderer are started properly. The headless library starts - // child processes by forking and exec'ing the main application. - headless::RunChildProcessIfNeeded(argc, argv); -#endif - - // Create a headless browser instance. There can be one of these per process - // and it can only be initialized once. - headless::HeadlessBrowser::Options::Builder builder(argc, argv); - -#if BUILDFLAG(IS_WIN) - // In windows, you must initialize and set the sandbox, or pass it along - // if it has already been initialized. - sandbox::SandboxInterfaceInfo sandbox_info = {nullptr}; - content::InitializeSandboxInfo(&sandbox_info); - builder.SetSandboxInfo(&sandbox_info); -#endif - // Here you can customize browser options. As an example we set the window - // size. - builder.SetWindowSize(gfx::Size(800, 600)); - - // Pass control to the headless library. It will bring up the browser and - // invoke the given callback on the browser UI thread. Note: if you need to - // pass more parameters to the callback, you can add them to the Bind() call - // below. - return headless::HeadlessBrowserMain( - builder.Build(), base::BindOnce(&OnHeadlessBrowserStarted)); -}
diff --git a/headless/lib/browser/headless_devtools_client_impl.cc b/headless/lib/browser/headless_devtools_client_impl.cc deleted file mode 100644 index b1902338a..0000000 --- a/headless/lib/browser/headless_devtools_client_impl.cc +++ /dev/null
@@ -1,524 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "headless/public/internal/headless_devtools_client_impl.h" - -#include <memory> - -#include "base/bind.h" -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "base/values.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "headless/public/headless_devtools_target.h" - -namespace headless { - -namespace { -int g_next_message_id = 0; -int g_next_raw_message_id = 1; -} // namespace - -// static -std::unique_ptr<HeadlessDevToolsClient> HeadlessDevToolsClient::Create() { - auto result = std::make_unique<HeadlessDevToolsClientImpl>(); - result->InitBrowserMainThread(); - return result; -} - -// static -std::unique_ptr<HeadlessDevToolsClient> -HeadlessDevToolsClient::CreateWithExternalHost(ExternalHost* external_host) { - auto result = std::make_unique<HeadlessDevToolsClientImpl>(); - result->AttachToExternalHost(external_host); - return result; -} - -HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl() - : accessibility_domain_(this), - animation_domain_(this), - browser_domain_(this), - cache_storage_domain_(this), - console_domain_(this), - css_domain_(this), - database_domain_(this), - debugger_domain_(this), - device_orientation_domain_(this), - dom_domain_(this), - dom_debugger_domain_(this), - dom_snapshot_domain_(this), - dom_storage_domain_(this), - emulation_domain_(this), - fetch_domain_(this), - headless_experimental_domain_(this), - heap_profiler_domain_(this), - indexeddb_domain_(this), - input_domain_(this), - inspector_domain_(this), - io_domain_(this), - layer_tree_domain_(this), - log_domain_(this), - memory_domain_(this), - network_domain_(this), - page_domain_(this), - performance_domain_(this), - profiler_domain_(this), - runtime_domain_(this), - security_domain_(this), - service_worker_domain_(this), - target_domain_(this), - tracing_domain_(this) {} - -HeadlessDevToolsClientImpl::~HeadlessDevToolsClientImpl() { - if (parent_client_) - parent_client_->sessions_.erase(session_id_); -} - -void HeadlessDevToolsClientImpl::AttachToExternalHost( - ExternalHost* external_host) { - DCHECK(!channel_ && !external_host_); - external_host_ = external_host; -} - -void HeadlessDevToolsClientImpl::InitBrowserMainThread() { - browser_main_thread_ = content::GetUIThreadTaskRunner({}); -} - -void HeadlessDevToolsClientImpl::ChannelClosed() { - pending_messages_.clear(); - channel_ = nullptr; -} - -void HeadlessDevToolsClientImpl::AttachToChannel( - std::unique_ptr<HeadlessDevToolsChannel> channel) { - DCHECK(!channel_ && !external_host_); - channel_ = std::move(channel); - channel_->SetClient(this); -} - -void HeadlessDevToolsClientImpl::DetachFromChannel() { - pending_messages_.clear(); - channel_ = nullptr; -} - -void HeadlessDevToolsClientImpl::SetRawProtocolListener( - RawProtocolListener* raw_protocol_listener) { - raw_protocol_listener_ = raw_protocol_listener; -} - -std::unique_ptr<HeadlessDevToolsClient> -HeadlessDevToolsClientImpl::CreateSession(const std::string& session_id) { - std::unique_ptr<HeadlessDevToolsClientImpl> client = - std::make_unique<HeadlessDevToolsClientImpl>(); - client->parent_client_ = this; - client->session_id_ = session_id; - client->browser_main_thread_ = browser_main_thread_; - sessions_[session_id] = client.get(); - return client; -} - -int HeadlessDevToolsClientImpl::GetNextRawDevToolsMessageId() { - int id = g_next_raw_message_id; - g_next_raw_message_id += 2; - return id; -} - -void HeadlessDevToolsClientImpl::SendRawDevToolsMessage( - const std::string& json_message) { - std::unique_ptr<base::Value> message = - base::JSONReader::ReadDeprecated(json_message); - if (!message || !message->is_dict()) { - LOG(ERROR) << "Malformed raw message"; - return; - } - if (!session_id_.empty()) - message->GetDict().Set("sessionId", session_id_); - SendProtocolMessage(message->GetDict()); -} - -void HeadlessDevToolsClientImpl::DispatchMessageFromExternalHost( - base::span<const uint8_t> json_message) { - DCHECK(external_host_); - ReceiveProtocolMessage(json_message); -} - -void HeadlessDevToolsClientImpl::ReceiveProtocolMessage( - base::span<const uint8_t> json_message) { - base::StringPiece message_str( - reinterpret_cast<const char*>(json_message.data()), json_message.size()); - // LOG(ERROR) << "[RECV] " << message_str; - std::unique_ptr<base::Value> message = - base::JSONReader::ReadDeprecated(message_str, base::JSON_PARSE_RFC); - if (!message || !message->is_dict()) { - NOTREACHED() << "Badly formed reply " << message_str; - return; - } - std::unique_ptr<base::DictionaryValue> message_dict = - base::DictionaryValue::From(std::move(message)); - - const std::string* session_id = message_dict->FindStringKey("sessionId"); - if (session_id) { - auto it = sessions_.find(*session_id); - if (it != sessions_.end()) { - it->second->ReceiveProtocolMessage(json_message, std::move(message_dict)); - return; - } - } - ReceiveProtocolMessage(json_message, std::move(message_dict)); -} - -void HeadlessDevToolsClientImpl::ReceiveProtocolMessage( - base::span<const uint8_t> json_message, - std::unique_ptr<base::DictionaryValue> message) { - base::StringPiece message_str( - reinterpret_cast<const char*>(json_message.data()), json_message.size()); - const base::DictionaryValue* message_dict; - if (!message || !message->GetAsDictionary(&message_dict)) { - NOTREACHED() << "Badly formed reply " << message_str; - return; - } - - if (raw_protocol_listener_ && - raw_protocol_listener_->OnProtocolMessage(json_message, *message_dict)) { - return; - } - - bool success = false; - if (message_dict->FindKey("id")) - success = DispatchMessageReply(std::move(message), *message_dict); - else - success = DispatchEvent(std::move(message), *message_dict); - if (!success) - DLOG(ERROR) << "Unhandled protocol message: " << message_str; -} - -bool HeadlessDevToolsClientImpl::DispatchMessageReply( - std::unique_ptr<base::Value> owning_message, - const base::DictionaryValue& message_dict) { - const base::Value* id_value = message_dict.FindKey("id"); - if (!id_value) { - NOTREACHED() << "ID must be specified."; - return false; - } - auto it = pending_messages_.find(id_value->GetInt()); - if (it == pending_messages_.end()) { - NOTREACHED() << "Unexpected reply"; - return false; - } - Callback callback = std::move(it->second); - pending_messages_.erase(it); - if (!callback.callback_with_result.is_null()) { - const base::DictionaryValue* result_dict; - if (message_dict.GetDictionary("result", &result_dict)) { - if (browser_main_thread_) { - browser_main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - &HeadlessDevToolsClientImpl::DispatchMessageReplyWithResultTask, - weak_ptr_factory_.GetWeakPtr(), std::move(owning_message), - std::move(callback.callback_with_result), result_dict)); - } else { - std::move(callback.callback_with_result).Run(*result_dict); - } - } else if (message_dict.GetDictionary("error", &result_dict)) { - auto null_value = std::make_unique<base::Value>(); - base::Value* null_value_ptr = null_value.get(); - DLOG(ERROR) << "Error in method call result: " << *result_dict; - if (browser_main_thread_) { - browser_main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - &HeadlessDevToolsClientImpl::DispatchMessageReplyWithResultTask, - weak_ptr_factory_.GetWeakPtr(), std::move(null_value), - std::move(callback.callback_with_result), null_value_ptr)); - } else { - std::move(callback.callback_with_result).Run(*null_value); - } - } else { - NOTREACHED() << "Reply has neither result nor error"; - return false; - } - } else if (!callback.callback.is_null()) { - if (browser_main_thread_) { - browser_main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - [](base::WeakPtr<HeadlessDevToolsClientImpl> self, - base::OnceClosure callback) { - if (self) - std::move(callback).Run(); - }, - weak_ptr_factory_.GetWeakPtr(), std::move(callback.callback))); - } else { - std::move(callback.callback).Run(); - } - } - return true; -} - -void HeadlessDevToolsClientImpl::DispatchMessageReplyWithResultTask( - std::unique_ptr<base::Value> owning_message, - base::OnceCallback<void(const base::Value&)> callback, - const base::Value* result_dict) { - std::move(callback).Run(*result_dict); -} - -bool HeadlessDevToolsClientImpl::DispatchEvent( - std::unique_ptr<base::Value> owning_message, - const base::DictionaryValue& message_dict) { - const base::Value* method_value = message_dict.FindKey("method"); - if (!method_value) - return false; - const std::string& method = method_value->GetString(); - if (method == "Inspector.targetCrashed") - renderer_crashed_ = true; - EventHandlerMap::const_iterator it = event_handlers_.find(method); - if (it == event_handlers_.end()) { - if (method != "Inspector.targetCrashed") - NOTREACHED() << "Unknown event: " << method; - return false; - } - if (!it->second.is_null()) { - const base::DictionaryValue* result_dict; - if (!message_dict.GetDictionary("params", &result_dict)) { - NOTREACHED() << "Badly formed event parameters"; - return false; - } - if (browser_main_thread_) { - // DevTools assumes event handling is async so we must post a task here or - // we risk breaking things. - browser_main_thread_->PostTask( - FROM_HERE, - base::BindOnce(&HeadlessDevToolsClientImpl::DispatchEventTask, - weak_ptr_factory_.GetWeakPtr(), - std::move(owning_message), &it->second, result_dict)); - } else { - DispatchEventTask(std::move(owning_message), &it->second, result_dict); - } - } - return true; -} - -void HeadlessDevToolsClientImpl::DispatchEventTask( - std::unique_ptr<base::Value> owning_message, - const EventHandler* event_handler, - const base::DictionaryValue* result_dict) { - event_handler->Run(*result_dict); -} - -accessibility::Domain* HeadlessDevToolsClientImpl::GetAccessibility() { - return &accessibility_domain_; -} - -animation::Domain* HeadlessDevToolsClientImpl::GetAnimation() { - return &animation_domain_; -} - -browser::Domain* HeadlessDevToolsClientImpl::GetBrowser() { - return &browser_domain_; -} - -cache_storage::Domain* HeadlessDevToolsClientImpl::GetCacheStorage() { - return &cache_storage_domain_; -} - -console::Domain* HeadlessDevToolsClientImpl::GetConsole() { - return &console_domain_; -} - -css::Domain* HeadlessDevToolsClientImpl::GetCSS() { - return &css_domain_; -} - -database::Domain* HeadlessDevToolsClientImpl::GetDatabase() { - return &database_domain_; -} - -debugger::Domain* HeadlessDevToolsClientImpl::GetDebugger() { - return &debugger_domain_; -} - -device_orientation::Domain* HeadlessDevToolsClientImpl::GetDeviceOrientation() { - return &device_orientation_domain_; -} - -dom::Domain* HeadlessDevToolsClientImpl::GetDOM() { - return &dom_domain_; -} - -dom_debugger::Domain* HeadlessDevToolsClientImpl::GetDOMDebugger() { - return &dom_debugger_domain_; -} - -dom_snapshot::Domain* HeadlessDevToolsClientImpl::GetDOMSnapshot() { - return &dom_snapshot_domain_; -} - -dom_storage::Domain* HeadlessDevToolsClientImpl::GetDOMStorage() { - return &dom_storage_domain_; -} - -emulation::Domain* HeadlessDevToolsClientImpl::GetEmulation() { - return &emulation_domain_; -} - -fetch::Domain* HeadlessDevToolsClientImpl::GetFetch() { - return &fetch_domain_; -} - -headless_experimental::Domain* -HeadlessDevToolsClientImpl::GetHeadlessExperimental() { - return &headless_experimental_domain_; -} - -heap_profiler::Domain* HeadlessDevToolsClientImpl::GetHeapProfiler() { - return &heap_profiler_domain_; -} - -indexeddb::Domain* HeadlessDevToolsClientImpl::GetIndexedDB() { - return &indexeddb_domain_; -} - -input::Domain* HeadlessDevToolsClientImpl::GetInput() { - return &input_domain_; -} - -inspector::Domain* HeadlessDevToolsClientImpl::GetInspector() { - return &inspector_domain_; -} - -io::Domain* HeadlessDevToolsClientImpl::GetIO() { - return &io_domain_; -} - -layer_tree::Domain* HeadlessDevToolsClientImpl::GetLayerTree() { - return &layer_tree_domain_; -} - -log::Domain* HeadlessDevToolsClientImpl::GetLog() { - return &log_domain_; -} - -memory::Domain* HeadlessDevToolsClientImpl::GetMemory() { - return &memory_domain_; -} - -network::Domain* HeadlessDevToolsClientImpl::GetNetwork() { - return &network_domain_; -} - -page::Domain* HeadlessDevToolsClientImpl::GetPage() { - return &page_domain_; -} - -performance::Domain* HeadlessDevToolsClientImpl::GetPerformance() { - return &performance_domain_; -} - -profiler::Domain* HeadlessDevToolsClientImpl::GetProfiler() { - return &profiler_domain_; -} - -runtime::Domain* HeadlessDevToolsClientImpl::GetRuntime() { - return &runtime_domain_; -} - -security::Domain* HeadlessDevToolsClientImpl::GetSecurity() { - return &security_domain_; -} - -service_worker::Domain* HeadlessDevToolsClientImpl::GetServiceWorker() { - return &service_worker_domain_; -} - -target::Domain* HeadlessDevToolsClientImpl::GetTarget() { - return &target_domain_; -} - -tracing::Domain* HeadlessDevToolsClientImpl::GetTracing() { - return &tracing_domain_; -} - -template <typename CallbackType> -void HeadlessDevToolsClientImpl::FinalizeAndSendMessage( - base::Value::Dict message, - CallbackType callback) { - if (renderer_crashed_) - return; - int id = g_next_message_id; - g_next_message_id += 2; // We only send even numbered messages. - message.Set("id", id); - if (!session_id_.empty()) - message.Set("sessionId", session_id_); - pending_messages_[id] = Callback(std::move(callback)); - SendProtocolMessage(message); -} - -void HeadlessDevToolsClientImpl::SendProtocolMessage( - const base::Value::Dict& message) { - if (parent_client_) { - parent_client_->SendProtocolMessage(message); - return; - } - - std::string json_message; - base::JSONWriter::Write(message, &json_message); - // LOG(ERROR) << "[SEND] " << json_message; - auto bytes_message = base::as_bytes(base::make_span(json_message)); - if (channel_) - channel_->SendProtocolMessage(bytes_message); - else - external_host_->SendProtocolMessage(bytes_message); -} - -template <typename CallbackType> -void HeadlessDevToolsClientImpl::SendMessageWithParams(const char* method, - base::Value params, - CallbackType callback) { - base::Value::Dict message; - message.Set("method", method); - message.Set("params", std::move(params)); - FinalizeAndSendMessage(std::move(message), std::move(callback)); -} - -void HeadlessDevToolsClientImpl::SendMessage( - const char* method, - base::Value params, - base::OnceCallback<void(const base::Value&)> callback) { - SendMessageWithParams(method, std::move(params), std::move(callback)); -} - -void HeadlessDevToolsClientImpl::SendMessage(const char* method, - base::Value params, - base::OnceClosure callback) { - SendMessageWithParams(method, std::move(params), std::move(callback)); -} - -void HeadlessDevToolsClientImpl::RegisterEventHandler( - const char* method, - base::RepeatingCallback<void(const base::Value&)> callback) { - DCHECK(event_handlers_.find(method) == event_handlers_.end()); - event_handlers_[method] = std::move(callback); -} - -HeadlessDevToolsClientImpl::Callback::Callback() = default; - -HeadlessDevToolsClientImpl::Callback::Callback(Callback&& other) = default; - -HeadlessDevToolsClientImpl::Callback::Callback(base::OnceClosure callback) - : callback(std::move(callback)) {} - -HeadlessDevToolsClientImpl::Callback::Callback( - base::OnceCallback<void(const base::Value&)> callback) - : callback_with_result(std::move(callback)) {} - -HeadlessDevToolsClientImpl::Callback::~Callback() = default; - -HeadlessDevToolsClientImpl::Callback& -HeadlessDevToolsClientImpl::Callback::operator=(Callback&& other) = default; - -} // namespace headless
diff --git a/headless/public/internal/headless_devtools_client_impl.h b/headless/public/internal/headless_devtools_client_impl.h deleted file mode 100644 index 56bfd36..0000000 --- a/headless/public/internal/headless_devtools_client_impl.h +++ /dev/null
@@ -1,235 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef HEADLESS_PUBLIC_INTERNAL_HEADLESS_DEVTOOLS_CLIENT_IMPL_H_ -#define HEADLESS_PUBLIC_INTERNAL_HEADLESS_DEVTOOLS_CLIENT_IMPL_H_ - -#include <unordered_map> - -#include "base/containers/flat_map.h" -#include "base/containers/span.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/task/sequenced_task_runner.h" -#include "headless/public/devtools/domains/accessibility.h" -#include "headless/public/devtools/domains/animation.h" -#include "headless/public/devtools/domains/browser.h" -#include "headless/public/devtools/domains/cache_storage.h" -#include "headless/public/devtools/domains/console.h" -#include "headless/public/devtools/domains/css.h" -#include "headless/public/devtools/domains/database.h" -#include "headless/public/devtools/domains/debugger.h" -#include "headless/public/devtools/domains/device_orientation.h" -#include "headless/public/devtools/domains/dom.h" -#include "headless/public/devtools/domains/dom_debugger.h" -#include "headless/public/devtools/domains/dom_snapshot.h" -#include "headless/public/devtools/domains/dom_storage.h" -#include "headless/public/devtools/domains/emulation.h" -#include "headless/public/devtools/domains/fetch.h" -#include "headless/public/devtools/domains/headless_experimental.h" -#include "headless/public/devtools/domains/heap_profiler.h" -#include "headless/public/devtools/domains/indexeddb.h" -#include "headless/public/devtools/domains/input.h" -#include "headless/public/devtools/domains/inspector.h" -#include "headless/public/devtools/domains/io.h" -#include "headless/public/devtools/domains/layer_tree.h" -#include "headless/public/devtools/domains/log.h" -#include "headless/public/devtools/domains/memory.h" -#include "headless/public/devtools/domains/network.h" -#include "headless/public/devtools/domains/page.h" -#include "headless/public/devtools/domains/performance.h" -#include "headless/public/devtools/domains/profiler.h" -#include "headless/public/devtools/domains/runtime.h" -#include "headless/public/devtools/domains/security.h" -#include "headless/public/devtools/domains/service_worker.h" -#include "headless/public/devtools/domains/target.h" -#include "headless/public/devtools/domains/tracing.h" -#include "headless/public/headless_devtools_client.h" -#include "headless/public/headless_export.h" -#include "headless/public/internal/message_dispatcher.h" - -namespace base { -class DictionaryValue; -} - -namespace headless { - -class HEADLESS_EXPORT HeadlessDevToolsClientImpl - : public HeadlessDevToolsClient, - public HeadlessDevToolsChannel::Client, - public internal::MessageDispatcher { - public: - HeadlessDevToolsClientImpl(); - - HeadlessDevToolsClientImpl(const HeadlessDevToolsClientImpl&) = delete; - HeadlessDevToolsClientImpl& operator=(const HeadlessDevToolsClientImpl&) = - delete; - - ~HeadlessDevToolsClientImpl() override; - - // HeadlessDevToolsClient implementation: - accessibility::Domain* GetAccessibility() override; - animation::Domain* GetAnimation() override; - browser::Domain* GetBrowser() override; - cache_storage::Domain* GetCacheStorage() override; - console::Domain* GetConsole() override; - css::Domain* GetCSS() override; - database::Domain* GetDatabase() override; - debugger::Domain* GetDebugger() override; - device_orientation::Domain* GetDeviceOrientation() override; - dom::Domain* GetDOM() override; - dom_debugger::Domain* GetDOMDebugger() override; - dom_snapshot::Domain* GetDOMSnapshot() override; - dom_storage::Domain* GetDOMStorage() override; - emulation::Domain* GetEmulation() override; - fetch::Domain* GetFetch() override; - headless_experimental::Domain* GetHeadlessExperimental() override; - heap_profiler::Domain* GetHeapProfiler() override; - indexeddb::Domain* GetIndexedDB() override; - input::Domain* GetInput() override; - inspector::Domain* GetInspector() override; - io::Domain* GetIO() override; - layer_tree::Domain* GetLayerTree() override; - log::Domain* GetLog() override; - memory::Domain* GetMemory() override; - network::Domain* GetNetwork() override; - page::Domain* GetPage() override; - performance::Domain* GetPerformance() override; - profiler::Domain* GetProfiler() override; - runtime::Domain* GetRuntime() override; - security::Domain* GetSecurity() override; - service_worker::Domain* GetServiceWorker() override; - target::Domain* GetTarget() override; - tracing::Domain* GetTracing() override; - void SetRawProtocolListener( - RawProtocolListener* raw_protocol_listener) override; - std::unique_ptr<HeadlessDevToolsClient> CreateSession( - const std::string& session_id) override; - int GetNextRawDevToolsMessageId() override; - void SendRawDevToolsMessage(const std::string& json_message) override; - void DispatchMessageFromExternalHost( - base::span<const uint8_t> json_message) override; - void AttachToChannel( - std::unique_ptr<HeadlessDevToolsChannel> channel) override; - void DetachFromChannel() override; - - // HeadlessDevToolsChannel::Client implementation. - void ReceiveProtocolMessage(base::span<const uint8_t> message) override; - void ChannelClosed() override; - - // internal::MessageDispatcher implementation: - void SendMessage( - const char* method, - base::Value params, - base::OnceCallback<void(const base::Value&)> callback) override; - void SendMessage(const char* method, - base::Value params, - base::OnceClosure callback) override; - void RegisterEventHandler( - const char* method, - base::RepeatingCallback<void(const base::Value&)> callback) override; - - // TODO(dgozman): remove with ExternalHost. - void AttachToExternalHost(ExternalHost* external_host); - void InitBrowserMainThread(); - - void SetTaskRunnerForTests( - scoped_refptr<base::SequencedTaskRunner> task_runner) { - browser_main_thread_ = task_runner; - } - - private: - // Contains a callback with or without a result parameter depending on the - // message type. - struct Callback { - Callback(); - Callback(Callback&& other); - explicit Callback(base::OnceClosure callback); - explicit Callback(base::OnceCallback<void(const base::Value&)> callback); - ~Callback(); - - Callback& operator=(Callback&& other); - - base::OnceClosure callback; - base::OnceCallback<void(const base::Value&)> callback_with_result; - }; - - template <typename CallbackType> - void FinalizeAndSendMessage(base::Value::Dict message, CallbackType callback); - - template <typename CallbackType> - void SendMessageWithParams(const char* method, - base::Value params, - CallbackType callback); - - bool DispatchMessageReply(std::unique_ptr<base::Value> owning_message, - const base::DictionaryValue& message_dict); - void DispatchMessageReplyWithResultTask( - std::unique_ptr<base::Value> owning_message, - base::OnceCallback<void(const base::Value&)> callback, - const base::Value* result_dict); - using EventHandler = base::RepeatingCallback<void(const base::Value&)>; - using EventHandlerMap = std::unordered_map<std::string, EventHandler>; - - bool DispatchEvent(std::unique_ptr<base::Value> owning_message, - const base::DictionaryValue& message_dict); - void DispatchEventTask(std::unique_ptr<base::Value> owning_message, - const EventHandler* event_handler, - const base::DictionaryValue* result_dict); - - void ReceiveProtocolMessage(base::span<const uint8_t> json_message, - std::unique_ptr<base::DictionaryValue> message); - void SendProtocolMessage(const base::Value::Dict& message); - - std::unique_ptr<HeadlessDevToolsChannel> channel_; - raw_ptr<ExternalHost> external_host_ = nullptr; - raw_ptr<RawProtocolListener> raw_protocol_listener_ = nullptr; - - std::unordered_map<int, Callback> pending_messages_; - EventHandlerMap event_handlers_; - std::string session_id_; - raw_ptr<HeadlessDevToolsClientImpl> parent_client_ = nullptr; - base::flat_map<std::string, HeadlessDevToolsClientImpl*> sessions_; - bool renderer_crashed_ = false; - - accessibility::ExperimentalDomain accessibility_domain_; - animation::ExperimentalDomain animation_domain_; - browser::ExperimentalDomain browser_domain_; - cache_storage::ExperimentalDomain cache_storage_domain_; - console::ExperimentalDomain console_domain_; - css::ExperimentalDomain css_domain_; - database::ExperimentalDomain database_domain_; - debugger::ExperimentalDomain debugger_domain_; - device_orientation::ExperimentalDomain device_orientation_domain_; - dom::ExperimentalDomain dom_domain_; - dom_debugger::ExperimentalDomain dom_debugger_domain_; - dom_snapshot::ExperimentalDomain dom_snapshot_domain_; - dom_storage::ExperimentalDomain dom_storage_domain_; - emulation::ExperimentalDomain emulation_domain_; - fetch::ExperimentalDomain fetch_domain_; - headless_experimental::ExperimentalDomain headless_experimental_domain_; - heap_profiler::ExperimentalDomain heap_profiler_domain_; - indexeddb::ExperimentalDomain indexeddb_domain_; - input::ExperimentalDomain input_domain_; - inspector::ExperimentalDomain inspector_domain_; - io::ExperimentalDomain io_domain_; - layer_tree::ExperimentalDomain layer_tree_domain_; - log::ExperimentalDomain log_domain_; - memory::ExperimentalDomain memory_domain_; - network::ExperimentalDomain network_domain_; - page::ExperimentalDomain page_domain_; - performance::ExperimentalDomain performance_domain_; - profiler::ExperimentalDomain profiler_domain_; - runtime::ExperimentalDomain runtime_domain_; - security::ExperimentalDomain security_domain_; - service_worker::ExperimentalDomain service_worker_domain_; - target::ExperimentalDomain target_domain_; - tracing::ExperimentalDomain tracing_domain_; - scoped_refptr<base::SequencedTaskRunner> browser_main_thread_; - base::WeakPtrFactory<HeadlessDevToolsClientImpl> weak_ptr_factory_{this}; -}; - -} // namespace headless - -#endif // HEADLESS_PUBLIC_INTERNAL_HEADLESS_DEVTOOLS_CLIENT_IMPL_H_
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json index 99652c55..67b06f7 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json
@@ -46,14 +46,15 @@ "$build/reclient": { "bootstrap_env": { "GLOG_vmodule": "bridge*=2", - "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", + "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s" }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", - "profiler_service": "reclient-mac" + "profiler_service": "reclient-mac", + "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json index 3bb4e9d..40dc381 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json
@@ -46,14 +46,15 @@ "$build/reclient": { "bootstrap_env": { "GLOG_vmodule": "bridge*=2", - "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", + "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s" }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", - "profiler_service": "reclient-mac" + "profiler_service": "reclient-mac", + "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json index 905b8a1f..f79200e5 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json
@@ -46,13 +46,14 @@ "$build/reclient": { "bootstrap_env": { "GLOG_vmodule": "bridge*=2", - "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", + "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s" }, "instance": "rbe-chromium-untrusted-test", - "metrics_project": "chromium-reclient-metrics" + "metrics_project": "chromium-reclient-metrics", + "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json index 1ec5bf8..6fccaa3b 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json
@@ -46,13 +46,14 @@ "$build/reclient": { "bootstrap_env": { "GLOG_vmodule": "bridge*=2", - "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", + "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s" }, "instance": "rbe-chromium-trusted-test", - "metrics_project": "chromium-reclient-metrics" + "metrics_project": "chromium-reclient-metrics", + "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json index 6cc4d63..6a3f71d 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json
@@ -45,13 +45,14 @@ "$build/reclient": { "bootstrap_env": { "GLOG_vmodule": "bridge*=2", - "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", + "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s" }, "instance": "rbe-chromium-untrusted-test", - "metrics_project": "chromium-reclient-metrics" + "metrics_project": "chromium-reclient-metrics", + "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json index 111024b..4ca7f05c 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json
@@ -45,13 +45,14 @@ "$build/reclient": { "bootstrap_env": { "GLOG_vmodule": "bridge*=2", - "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", + "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s" }, "instance": "rbe-chromium-trusted-test", - "metrics_project": "chromium-reclient-metrics" + "metrics_project": "chromium-reclient-metrics", + "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star index cfdc647..52b61ed 100644 --- a/infra/config/lib/builders.star +++ b/infra/config/lib/builders.star
@@ -289,7 +289,7 @@ _VALID_REPROXY_ENV_PREFIX_LIST = ["RBE_", "GLOG_", "GOMA_"] -def _reclient_property(*, instance, service, jobs, rewrapper_env, profiler_service, publish_trace, cache_silo, ensure_verified, bootstrap_env): +def _reclient_property(*, instance, service, jobs, rewrapper_env, profiler_service, publish_trace, cache_silo, ensure_verified, bootstrap_env, scandeps_server): reclient = {} instance = defaults.get_value("reclient_instance", instance) if not instance: @@ -317,6 +317,9 @@ ", ".join(_VALID_REPROXY_ENV_PREFIX_LIST) + "), got '%s'" % k) reclient["bootstrap_env"] = bootstrap_env + scandeps_server = defaults.get_value("reclient_scandeps_server", scandeps_server) + if scandeps_server: + reclient["scandeps_server"] = scandeps_server profiler_service = defaults.get_value("reclient_profiler_service", profiler_service) if profiler_service: reclient["profiler_service"] = profiler_service @@ -400,6 +403,7 @@ reclient_bootstrap_env = None, reclient_profiler_service = None, reclient_publish_trace = None, + reclient_scandeps_server = False, reclient_cache_silo = None, reclient_ensure_verified = None, @@ -465,6 +469,7 @@ reclient_bootstrap_env = args.DEFAULT, reclient_profiler_service = args.DEFAULT, reclient_publish_trace = args.DEFAULT, + reclient_scandeps_server = args.DEFAULT, reclient_cache_silo = None, reclient_ensure_verified = None, omit_python2 = args.DEFAULT, @@ -642,6 +647,7 @@ not set. reclient_publish_trace: If True, it publish trace by rpl2cloudtrace. Has no effect if reclient_instance is not set. + reclient_scandeps_server: If true, reproxy should start its own scandeps_server reclient_cache_silo: A string indicating a cache siling key to use for remote caching. Has no effect if reclient_instance is not set. reclient_ensure_verified: If True, it verifies build artifacts. Has no @@ -797,6 +803,7 @@ bootstrap_env = reclient_bootstrap_env, profiler_service = reclient_profiler_service, publish_trace = reclient_publish_trace, + scandeps_server = reclient_scandeps_server, cache_silo = reclient_cache_silo, ensure_verified = reclient_ensure_verified, )
diff --git a/infra/config/subprojects/reclient/reclient.star b/infra/config/subprojects/reclient/reclient.star index 5a95839..546abd8 100644 --- a/infra/config/subprojects/reclient/reclient.star +++ b/infra/config/subprojects/reclient/reclient.star
@@ -60,6 +60,7 @@ "chromium-cq-staging-builder@chops-service-accounts.iam.gserviceaccount.com" ), reclient_version = "staging", + enable_crash_dump = "false", **kwargs): trusted_instance = reclient_instance % "trusted" unstrusted_instance = reclient_instance % "untrusted" @@ -71,7 +72,7 @@ "RBE_ip_reset_min_delay": "-1s", "RBE_deps_cache_mode": "reproxy", # TODO(b/258210757) remove once long term breakpad plans are dertermined - "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", + "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": enable_crash_dump, }) return [ ci.builder( @@ -193,6 +194,7 @@ build_gs_bucket = "chromium-fyi-archive", ), ), + enable_crash_dump = "true", builderless = True, cores = None, os = os.MAC_DEFAULT, @@ -202,6 +204,7 @@ "GLOG_vmodule": "bridge*=2", }, reclient_profiler_service = "reclient-mac", + reclient_scandeps_server = True, ) fyi_reclient_staging_builder( @@ -308,12 +311,14 @@ builderless = True, cores = None, os = os.MAC_DEFAULT, + enable_crash_dump = "true", xcode = xcode.x14main, console_view_category = "ios", priority = 35, reclient_bootstrap_env = { "GLOG_vmodule": "bridge*=2", }, + reclient_scandeps_server = True, ) fyi_reclient_staging_builder( @@ -386,10 +391,12 @@ cores = None, os = os.MAC_DEFAULT, console_view_category = "mac", + enable_crash_dump = "true", priority = 35, reclient_bootstrap_env = { "GLOG_vmodule": "bridge*=2", }, + reclient_scandeps_server = True, ) ci.builder(
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index f430897..25f9cfe 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -498,6 +498,7 @@ "//ios/chrome/browser/screenshot", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/search_engines:extension_search_engine_data_updater", + "//ios/chrome/browser/search_engines:search_engines_util", "//ios/chrome/browser/sessions:scene_util", "//ios/chrome/browser/sessions:session_service", "//ios/chrome/browser/share_extension",
diff --git a/ios/chrome/browser/providers/push_notification/chromium_push_notification.mm b/ios/chrome/browser/providers/push_notification/chromium_push_notification.mm index 6428d39..86299fa3 100644 --- a/ios/chrome/browser/providers/push_notification/chromium_push_notification.mm +++ b/ios/chrome/browser/providers/push_notification/chromium_push_notification.mm
@@ -24,6 +24,12 @@ void RegisterDevice(PushNotificationConfiguration* config, void (^completion_handler)(NSError* error)) final; void UnregisterDevice(void (^completion_handler)(NSError* error)) final; + bool DeviceTokenIsSet() const final; + + protected: + // PushNotificationService implementation. + void SetAccountsToDevice(NSArray<NSString*>* account_ids, + CompletionHandler completion_handler) final; }; void ChromiumPushNotificationService::RegisterDevice( @@ -58,6 +64,27 @@ })); } +bool ChromiumPushNotificationService::DeviceTokenIsSet() const { + return false; +} + +void ChromiumPushNotificationService::SetAccountsToDevice( + NSArray<NSString*>* account_ids, + void (^completion_handler)(NSError* error)) { + // Chromium does not initialize the device's connection to the push + // notification server. As a result, the `completion_handler` is called with + // a NSFeatureUnsupportedError. + + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(^() { + NSError* error = + [NSError errorWithDomain:kChromiumPushNotificationErrorDomain + code:NSFeatureUnsupportedError + userInfo:nil]; + completion_handler(error); + })); +} + } // namespace std::unique_ptr<PushNotificationService> CreatePushNotificationService() {
diff --git a/ios/chrome/browser/push_notification/BUILD.gn b/ios/chrome/browser/push_notification/BUILD.gn index bc7b2aa8..20637ac 100644 --- a/ios/chrome/browser/push_notification/BUILD.gn +++ b/ios/chrome/browser/push_notification/BUILD.gn
@@ -5,6 +5,8 @@ source_set("push_notification_service") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "push_notification_account_context_manager.h", + "push_notification_account_context_manager.mm", "push_notification_client_manager.h", "push_notification_client_manager.mm", "push_notification_configuration.h", @@ -37,3 +39,29 @@ ] deps = [ "//base" ] } + +source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + sources = [ "push_notification_client_manager_unittest.mm" ] + deps = [ + ":push_notification_client", + ":push_notification_service", + ":test_support", + "//testing/gtest", + ] +} + +source_set("test_support") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "test_push_notification_client.h", + "test_push_notification_client.mm", + ] + + deps = [ + ":push_notification_client", + ":push_notification_service", + "//base", + ] +}
diff --git a/ios/chrome/browser/push_notification/push_notification_account_context_manager.h b/ios/chrome/browser/push_notification/push_notification_account_context_manager.h new file mode 100644 index 0000000..397386e --- /dev/null +++ b/ios/chrome/browser/push_notification/push_notification_account_context_manager.h
@@ -0,0 +1,60 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_ACCOUNT_CONTEXT_MANAGER_H_ +#define IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_ACCOUNT_CONTEXT_MANAGER_H_ + +#import <Foundation/Foundation.h> + +#import "ios/chrome/browser/browser_state/chrome_browser_state_manager.h" + +class BrowserStateInfoCache; + +namespace ios { +class ChromeBrowserStateManager; + +} + +// This class is intended to store the permissions for each push notification +// enabled feature for a given account and the number of times the account is +// signed in across BrowserStates. +@interface PushNotificationAccountContext : NSObject +// A dictionary that maps the string value of a push notification client id to +// the perf service value for that push notification enable feature. +@property(nonatomic, copy) NSDictionary<NSString*, NSNumber*>* preferenceMap; +// A counter that stores the number of times a given account is used across +// BrowserStates. +@property(nonatomic, readonly) NSUInteger occurrencesAcrossBrowserStates; +@end + +// The purpose of this class is to manage the mapping between GaiaIDs and its +// context data related to push notifications. +@interface PushNotificationAccountContextManager : NSObject + +// The designated initializer. `BrowserStateInfoCache` must not be nil. +- (instancetype)initWithChromeBrowserStateManager: + (ios::ChromeBrowserStateManager*)manager NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +// Adds the account to the manager if the account is not signed into the device +// in any BrowserState. This function returns a BOOL value indicating whether +// the account was added to the manager. +- (BOOL)addAccount:(NSString*)gaiaID; + +// Removes the account from the manager if the account is not signed into the +// device in any BrowserState. This function returns a BOOL value indicating +// whether the account was removed from the maanger. +- (BOOL)removeAccount:(NSString*)gaiaID; + +// A dictionary that maps a user's GAIA ID to an object containing the account's +// preferences for all push notification enabled features and an number +// representing the number of times the account is signed in across +// BrowserStates. +@property(nonatomic, readonly) + NSDictionary<NSString*, PushNotificationAccountContext*>* contextMap; + +@end + +#endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_ACCOUNT_CONTEXT_MANAGER_H_
diff --git a/ios/chrome/browser/push_notification/push_notification_account_context_manager.mm b/ios/chrome/browser/push_notification/push_notification_account_context_manager.mm new file mode 100644 index 0000000..4c28430d --- /dev/null +++ b/ios/chrome/browser/push_notification/push_notification_account_context_manager.mm
@@ -0,0 +1,145 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/push_notification/push_notification_account_context_manager.h" + +#import "base/strings/sys_string_conversions.h" +#import "components/prefs/pref_service.h" +#import "ios/chrome/browser/browser_state/browser_state_info_cache.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state_manager.h" +#import "ios/chrome/browser/prefs/pref_names.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface PushNotificationAccountContext () + +@property(nonatomic, assign) NSUInteger occurrencesAcrossBrowserStates; + +@end + +@implementation PushNotificationAccountContext +@end + +@implementation PushNotificationAccountContextManager { + // Used to retrieve BrowserStates located at a given path. + ios::ChromeBrowserStateManager* _chromeBrowserStateManager; + // Maps a GaiaID to the given account's AccountContext object. + NSMutableDictionary<NSString*, PushNotificationAccountContext*>* _contextMap; +} + +- (instancetype)initWithChromeBrowserStateManager: + (ios::ChromeBrowserStateManager*)manager { + self = [super init]; + + if (self) { + _contextMap = [[NSMutableDictionary alloc] init]; + _chromeBrowserStateManager = manager; + BrowserStateInfoCache* infoCache = manager->GetBrowserStateInfoCache(); + + const size_t numberOfBrowserStates = infoCache->GetNumberOfBrowserStates(); + for (size_t i = 0; i < numberOfBrowserStates; i++) { + NSString* gaiaID = + base::SysUTF8ToNSString(infoCache->GetGAIAIdOfBrowserStateAtIndex(i)); + base::FilePath path = infoCache->GetPathOfBrowserStateAtIndex(i); + ChromeBrowserState* chromeBrowserState = + _chromeBrowserStateManager->GetBrowserState(path); + [self addAccount:gaiaID withBrowserState:chromeBrowserState]; + } + } + + return self; +} + +- (BOOL)addAccount:(NSString*)gaiaID { + ChromeBrowserState* chromeBrowserState = [self chromeBrowserStateFrom:gaiaID]; + if (!chromeBrowserState) + return NO; + + return [self addAccount:gaiaID + withBrowserState:[self chromeBrowserStateFrom:gaiaID]]; +} + +- (BOOL)removeAccount:(NSString*)gaiaID { + PushNotificationAccountContext* context = _contextMap[gaiaID]; + DCHECK(context); + + context.occurrencesAcrossBrowserStates--; + if (context.occurrencesAcrossBrowserStates > 0) + return NO; + + [_contextMap removeObjectForKey:gaiaID]; + return YES; +} + +#pragma mark - Properties + +- (NSDictionary<NSString*, PushNotificationAccountContext*>*)contextMap { + return _contextMap; +} + +#pragma mark - Private + +// Create a new AccountContext object for the given gaiaID, if the gaia id does +// not already exist in the dictionary, and maps the gaiaID to the new context +// object. +- (BOOL)addAccount:(NSString*)gaiaID + withBrowserState:(ChromeBrowserState*)browserState { + DCHECK(browserState); + + if (!gaiaID.length) + return NO; + + PushNotificationAccountContext* context = _contextMap[gaiaID]; + if (context) { + context.occurrencesAcrossBrowserStates++; + return NO; + } + + PrefService* prefService = browserState->GetPrefs(); + NSMutableDictionary<NSString*, NSNumber*>* preferenceMap = + [[NSMutableDictionary alloc] init]; + const base::Value::Dict& permissions = + prefService->GetDict(prefs::kFeaturePushNotificationPermissions); + + for (const auto pair : permissions) { + preferenceMap[base::SysUTF8ToNSString(pair.first)] = + [NSNumber numberWithBool:pair.second.GetBool()]; + } + + context = [[PushNotificationAccountContext alloc] init]; + context.preferenceMap = preferenceMap; + context.occurrencesAcrossBrowserStates = 1; + _contextMap[gaiaID] = context; + + return YES; +} + +// Returns the ChromeBrowserState that has the given gaiaID set as the primary +// account. TODO(crbug.com/1400732) Implement policy that computes correct +// permission set. This function naively chooses the first ChromeBrowserState +// that is associated with the given gaiaID. In a multi-profile environment +// where the given gaiaID is signed into multiple profiles, it is possible that +// the push notification enabled features' permissions may be incorrectly +// applied. +- (ChromeBrowserState*)chromeBrowserStateFrom:(NSString*)gaiaID { + BrowserStateInfoCache* infoCache = + _chromeBrowserStateManager->GetBrowserStateInfoCache(); + const size_t numberOfBrowserStates = infoCache->GetNumberOfBrowserStates(); + for (size_t i = 0; i < numberOfBrowserStates; i++) { + NSString* browserStateGaiaID = + base::SysUTF8ToNSString(infoCache->GetGAIAIdOfBrowserStateAtIndex(i)); + + if (gaiaID == browserStateGaiaID) { + base::FilePath path = infoCache->GetPathOfBrowserStateAtIndex(i); + return _chromeBrowserStateManager->GetBrowserState(path); + } + } + + return nil; +} + +@end
diff --git a/ios/chrome/browser/push_notification/push_notification_client_id.h b/ios/chrome/browser/push_notification/push_notification_client_id.h index 249dfd6..e85417b 100644 --- a/ios/chrome/browser/push_notification/push_notification_client_id.h +++ b/ios/chrome/browser/push_notification/push_notification_client_id.h
@@ -16,7 +16,7 @@ enum class PushNotificationClientId { // TODO(crbug.com/1353801): Once Chrome has a push notification enabled // feature, add that feature's identifier to this class. - kCommerce = 1, + kCommerce = 1 }; #endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_CLIENT_ID_H_
diff --git a/ios/chrome/browser/push_notification/push_notification_client_manager.h b/ios/chrome/browser/push_notification/push_notification_client_manager.h index aebd6e8..8547bf2 100644 --- a/ios/chrome/browser/push_notification/push_notification_client_manager.h +++ b/ios/chrome/browser/push_notification/push_notification_client_manager.h
@@ -31,6 +31,14 @@ void AddPushNotificationClient( std::unique_ptr<PushNotificationClient> client); + // This function removes the mapping between a PushNotificationClientId and a + // PushNotificationClient from the manager. + void RemovePushNotificationClient(PushNotificationClientId client_id); + + // This function returns a list of the PushNotificationClients stored by the + // manager. + std::vector<const PushNotificationClient*> GetPushNotificationClients(); + // This function is called when the user interacts with the delivered // notification. This function identifies and delegates the interacted with // notification to the appropriate PushNotificationClient. @@ -58,11 +66,10 @@ static std::vector<PushNotificationClientId> GetClients(); private: - // A list of features that support push notifications. - std::unordered_map<PushNotificationClientId, - std::unique_ptr<PushNotificationClient>> - clients_ = std::unordered_map<PushNotificationClientId, - std::unique_ptr<PushNotificationClient>>(); + using ClientMap = std::unordered_map<PushNotificationClientId, + std::unique_ptr<PushNotificationClient>>; + // A map of client ids to the features that support push notifications. + ClientMap clients_; }; -#endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_CLIENT_MANAGER_H_ \ No newline at end of file +#endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_CLIENT_MANAGER_H_
diff --git a/ios/chrome/browser/push_notification/push_notification_client_manager.mm b/ios/chrome/browser/push_notification/push_notification_client_manager.mm index 46c15df..38cad88 100644 --- a/ios/chrome/browser/push_notification/push_notification_client_manager.mm +++ b/ios/chrome/browser/push_notification/push_notification_client_manager.mm
@@ -15,11 +15,6 @@ #error "This file requires ARC support." #endif -namespace { -NSString* kClientIdPushNotificationDictionaryKey = - @"push_notification_client_id"; -} // namespace - PushNotificationClientManager::PushNotificationClientManager() { if (IsPriceNotificationsEnabled()) { AddPushNotificationClient( @@ -33,34 +28,44 @@ clients_.insert(std::make_pair(client->GetClientId(), std::move(client))); } +void PushNotificationClientManager::RemovePushNotificationClient( + PushNotificationClientId client_id) { + clients_.erase(client_id); +} + +std::vector<const PushNotificationClient*> +PushNotificationClientManager::GetPushNotificationClients() { + std::vector<const PushNotificationClient*> manager_clients; + + for (auto& client : clients_) { + manager_clients.push_back(std::move(client.second.get())); + } + + return manager_clients; +} + void PushNotificationClientManager::HandleNotificationInteraction( UNNotificationResponse* notification_response) { - NSDictionary* user_info = - notification_response.notification.request.content.userInfo; - - PushNotificationClientId client_id = - static_cast<PushNotificationClientId>([[user_info - objectForKey:kClientIdPushNotificationDictionaryKey] integerValue]); - - auto it = clients_.find(client_id); - if (it != clients_.end()) { - it->second->HandleNotificationInteraction(notification_response); + for (auto& client : clients_) { + client.second->HandleNotificationInteraction(notification_response); } } UIBackgroundFetchResult PushNotificationClientManager::HandleNotificationReception( NSDictionary<NSString*, id>* user_info) { - PushNotificationClientId client_id = - static_cast<PushNotificationClientId>([[user_info - objectForKey:kClientIdPushNotificationDictionaryKey] integerValue]); - - auto it = clients_.find(client_id); - if (it != clients_.end()) { - return it->second->HandleNotificationReception(user_info); + UIBackgroundFetchResult result = UIBackgroundFetchResultNoData; + for (auto& client : clients_) { + UIBackgroundFetchResult client_result = + client.second->HandleNotificationReception(user_info); + if (client_result == UIBackgroundFetchResultNewData) { + return UIBackgroundFetchResultNewData; + } else if (client_result == UIBackgroundFetchResultFailed) { + result = client_result; + } } - return UIBackgroundFetchResultNoData; + return result; } void PushNotificationClientManager::RegisterActionableNotifications() {
diff --git a/ios/chrome/browser/push_notification/push_notification_client_manager_unittest.mm b/ios/chrome/browser/push_notification/push_notification_client_manager_unittest.mm new file mode 100644 index 0000000..183629a --- /dev/null +++ b/ios/chrome/browser/push_notification/push_notification_client_manager_unittest.mm
@@ -0,0 +1,123 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <UserNotifications/UserNotifications.h> + +#import "ios/chrome/browser/push_notification/push_notification_client.h" +#import "ios/chrome/browser/push_notification/push_notification_client_manager.h" +#import "ios/chrome/browser/push_notification/test_push_notification_client.h" +#import "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +void GenerateClients(std::unique_ptr<PushNotificationClientManager>& manager, + size_t number_of_clients) { + for (size_t i = 0; i < number_of_clients; i++) { + std::unique_ptr<PushNotificationClient> client = + std::make_unique<TestPushNotificationClient>(i + 1); + manager->AddPushNotificationClient(std::move(client)); + } +} + +TestPushNotificationClient* GetClient( + std::unique_ptr<PushNotificationClientManager>& manager, + size_t index) { + return const_cast<TestPushNotificationClient*>( + static_cast<const TestPushNotificationClient*>( + manager->GetPushNotificationClients()[index])); +} + +} // namespace + +class PushNotificationClientManagerTest : public PlatformTest { + protected: + PushNotificationClientManagerTest() { + size_t number_of_clients = manager->GetPushNotificationClients().size(); + + for (size_t i = 0; i < number_of_clients; i++) { + manager->RemovePushNotificationClient( + GetClient(manager, i)->GetClientId()); + } + } + std::unique_ptr<PushNotificationClientManager> manager = + std::make_unique<PushNotificationClientManager>(); +}; + +TEST_F(PushNotificationClientManagerTest, AddClient) { + const unsigned long number_of_clients = 1; + GenerateClients(manager, number_of_clients); + + ASSERT_EQ(number_of_clients, manager->GetPushNotificationClients().size()); +} + +TEST_F(PushNotificationClientManagerTest, AddMultipleClients) { + const unsigned long number_of_clients = 5; + GenerateClients(manager, number_of_clients); + + ASSERT_EQ(number_of_clients, manager->GetPushNotificationClients().size()); +} + +TEST_F(PushNotificationClientManagerTest, HandleNotificationReception) { + GenerateClients(manager, 1); + ASSERT_EQ(UIBackgroundFetchResultNoData, + manager->HandleNotificationReception(nil)); +} + +TEST_F(PushNotificationClientManagerTest, + HandleNotificationReceptionWithNewData) { + const unsigned long number_of_clients = 5; + GenerateClients(manager, number_of_clients); + + TestPushNotificationClient* client = GetClient(manager, 0); + client->SetBackgroundFetchResult(UIBackgroundFetchResultNewData); + ASSERT_EQ(UIBackgroundFetchResultNewData, + manager->HandleNotificationReception(nil)); +} + +TEST_F(PushNotificationClientManagerTest, + HandleNotificationReceptionWithFailure) { + const unsigned long number_of_clients = 5; + GenerateClients(manager, number_of_clients); + + TestPushNotificationClient* client = GetClient(manager, 0); + client->SetBackgroundFetchResult(UIBackgroundFetchResultFailed); + ASSERT_EQ(UIBackgroundFetchResultFailed, + manager->HandleNotificationReception(nil)); +} + +TEST_F(PushNotificationClientManagerTest, + HandleNotificationReceptionWithNewDataAndFailure) { + const unsigned long number_of_clients = 5; + GenerateClients(manager, number_of_clients); + + GetClient(manager, 0) + ->SetBackgroundFetchResult(UIBackgroundFetchResultNewData); + GetClient(manager, 1) + ->SetBackgroundFetchResult(UIBackgroundFetchResultFailed); + ASSERT_EQ(UIBackgroundFetchResultNewData, + manager->HandleNotificationReception(nil)); +} + +TEST_F(PushNotificationClientManagerTest, HandleNotificationInteraction) { + const unsigned long number_of_clients = 1; + GenerateClients(manager, number_of_clients); + + manager->HandleNotificationInteraction(nil); + ASSERT_TRUE(GetClient(manager, 0)->HasNotificationReceivedInteraction()); +} + +TEST_F(PushNotificationClientManagerTest, + HandleNotificationInteractionWithMultipleClients) { + const unsigned long number_of_clients = 5; + GenerateClients(manager, number_of_clients); + + manager->HandleNotificationInteraction(nil); + for (size_t i = 0; i < manager->GetPushNotificationClients().size(); i++) { + ASSERT_TRUE(GetClient(manager, i)->HasNotificationReceivedInteraction()); + } +}
diff --git a/ios/chrome/browser/push_notification/push_notification_configuration.h b/ios/chrome/browser/push_notification/push_notification_configuration.h index aa38d51..ed3f3503 100644 --- a/ios/chrome/browser/push_notification/push_notification_configuration.h +++ b/ios/chrome/browser/push_notification/push_notification_configuration.h
@@ -7,6 +7,7 @@ #import <Foundation/Foundation.h> +@class PushNotificationAccountContextManager; @protocol SingleSignOnService; using GaiaIdToPushNotificationPreferenceMap = @@ -28,10 +29,18 @@ // SingleSignOnService used by PushNotificationService. @property(nonatomic, strong) id<SingleSignOnService> ssoService; -// A dictionary that maps a user's GAIA ID to its preferences for all push -// notification enabled features. +// DEPRECATED. Please use the `contextManager.contextMap` instead. A dictionary +// that maps a user's GAIA ID to its preferences for all push notification +// enabled features. @property(nonatomic, copy) GaiaIdToPushNotificationPreferenceMap* preferenceMap; +// A dictionary that maps a user's GAIA ID to an object containing the account's +// preferences for all push notification enabled features and an number +// representing the number of times the account is signed in across +// BrowserStates. +@property(nonatomic, copy) + PushNotificationAccountContextManager* contextManager; + @end -#endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_CONFIGURATION_H_ \ No newline at end of file +#endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_CONFIGURATION_H_
diff --git a/ios/chrome/browser/push_notification/push_notification_service.h b/ios/chrome/browser/push_notification/push_notification_service.h index c5aaa0e8..09e64dc 100644 --- a/ios/chrome/browser/push_notification/push_notification_service.h +++ b/ios/chrome/browser/push_notification/push_notification_service.h
@@ -12,6 +12,10 @@ namespace user_prefs { class PrefRegistrySyncable; } // namespace user_prefs +namespace ios { +class ChromeBrowserStateManager; +} +@class PushNotificationAccountContextManager; class PushNotificationClientManager; // Service responsible for establishing connection and interacting @@ -35,6 +39,21 @@ // the operation successfully or unsuccessfully completes. virtual void UnregisterDevice(CompletionHandler completion_handler) = 0; + // Returns whether the device has retrieved and stored its APNS device token. + virtual bool DeviceTokenIsSet() const; + + // Registers the new account to the push notification server. In a multi + // BrowserState environment, the PushNotificationService tracks the signed in + // account across BrowserStates. + void RegisterAccount(NSString* account_id, + CompletionHandler completion_handler); + + // Unregisters the account from the push notification server. In a multi + // BrowserState environment, the account will not be signed out until it's + // signed out across BrowserStates. + void UnregisterAccount(NSString* account_id, + CompletionHandler completion_handler); + // Updates the current user's push notification preferences with the push // notification server. void UpdateFeaturePushNotificationPreferences( @@ -51,10 +70,30 @@ // Returns PushNotificationService's PushNotificationClientManager. PushNotificationClientManager* GetPushNotificationClientManager(); + protected: + PushNotificationService(ios::ChromeBrowserStateManager* manager); + // Registers the device with the push notification server. By supplying a list + // of the GAIA IDs currently logged into Chrome on the device and the device's + // APNS token, the server associates the GAIA IDs to the device, which allows + // the server to begin sending push notifications to that device. When this + // method is called, the server overwrites the accountIDs that are associated + // with the device token with the given array of accountIDs. Thus, to + // unregister an account from receiving push notifications on the device, this + // method should be called with an array of accountIDs that omits the account + // that is intended to be unregistered. + virtual void SetAccountsToDevice(NSArray<NSString*>* account_ids, + CompletionHandler completion_handler) {} + private: // The PushNotificationClientManager manages all interactions between the // system and push notification enabled features. std::unique_ptr<PushNotificationClientManager> client_manager_; + + // Stores a mapping of each account's GAIA ID signed into the device to its + // context object. This object contains the account's pref service values + // pertaining to push notification supported features and the number of times + // the given account is signed in across multiple browser states. + __strong PushNotificationAccountContextManager* context_manager_; }; #endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_SERVICE_H_
diff --git a/ios/chrome/browser/push_notification/push_notification_service.mm b/ios/chrome/browser/push_notification/push_notification_service.mm index 272baf8..1cc868d 100644 --- a/ios/chrome/browser/push_notification/push_notification_service.mm +++ b/ios/chrome/browser/push_notification/push_notification_service.mm
@@ -7,7 +7,9 @@ #import "base/strings/string_number_conversions.h" #import "base/values.h" #import "components/pref_registry/pref_registry_syncable.h" +#import "ios/chrome/browser/application_context/application_context.h" #import "ios/chrome/browser/prefs/pref_names.h" +#import "ios/chrome/browser/push_notification/push_notification_account_context_manager.h" #import "ios/chrome/browser/push_notification/push_notification_client_id.h" #import "ios/chrome/browser/push_notification/push_notification_client_manager.h" @@ -16,7 +18,15 @@ #endif PushNotificationService::PushNotificationService() - : client_manager_(std::make_unique<PushNotificationClientManager>()) {} + : PushNotificationService( + GetApplicationContext()->GetChromeBrowserStateManager()) {} + +PushNotificationService::PushNotificationService( + ios::ChromeBrowserStateManager* manager) + : client_manager_(std::make_unique<PushNotificationClientManager>()) { + context_manager_ = [[PushNotificationAccountContextManager alloc] + initWithChromeBrowserStateManager:manager]; +} PushNotificationService::~PushNotificationService() = default; @@ -25,6 +35,28 @@ return client_manager_.get(); } +bool PushNotificationService::DeviceTokenIsSet() const { + return false; +} + +void PushNotificationService::RegisterAccount( + NSString* account_id, + CompletionHandler completion_handler) { + if ([context_manager_ addAccount:account_id]) { + SetAccountsToDevice(context_manager_.contextMap.allKeys, + completion_handler); + } +} + +void PushNotificationService::UnregisterAccount( + NSString* account_id, + CompletionHandler completion_handler) { + if ([context_manager_ removeAccount:account_id]) { + SetAccountsToDevice(context_manager_.contextMap.allKeys, + completion_handler); + } +} + void PushNotificationService::RegisterBrowserStatePrefs( user_prefs::PrefRegistrySyncable* registry) { base::Value::Dict feature_push_notification_permission = base::Value::Dict();
diff --git a/ios/chrome/browser/push_notification/test_push_notification_client.h b/ios/chrome/browser/push_notification/test_push_notification_client.h new file mode 100644 index 0000000..2903b4c --- /dev/null +++ b/ios/chrome/browser/push_notification/test_push_notification_client.h
@@ -0,0 +1,31 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_PUSH_NOTIFICATION_TEST_PUSH_NOTIFICATION_CLIENT_H_ +#define IOS_CHROME_BROWSER_PUSH_NOTIFICATION_TEST_PUSH_NOTIFICATION_CLIENT_H_ + +#import "ios/chrome/browser/push_notification/push_notification_client.h" + +class TestPushNotificationClient : public PushNotificationClient { + public: + TestPushNotificationClient(size_t client_id); + ~TestPushNotificationClient() override; + + // Override PushNotificationClient:: + void HandleNotificationInteraction( + UNNotificationResponse* notification_response) override; + UIBackgroundFetchResult HandleNotificationReception( + NSDictionary<NSString*, id>* notification) override; + NSArray<UNNotificationCategory*>* RegisterActionableNotifications() override; + + // Indicates whether the client has been + bool HasNotificationReceivedInteraction(); + // Sets the client's UIBackgroundFetchResult to given FetchResult. + void SetBackgroundFetchResult(UIBackgroundFetchResult result); + + private: + UIBackgroundFetchResult fetch_result_ = UIBackgroundFetchResultNoData; + bool has_notification_received_interaction_ = false; +}; +#endif // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_TEST_PUSH_NOTIFICATION_CLIENT_H_
diff --git a/ios/chrome/browser/push_notification/test_push_notification_client.mm b/ios/chrome/browser/push_notification/test_push_notification_client.mm new file mode 100644 index 0000000..b5992725 --- /dev/null +++ b/ios/chrome/browser/push_notification/test_push_notification_client.mm
@@ -0,0 +1,41 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/push_notification/test_push_notification_client.h" + +#import "ios/chrome/browser/push_notification/push_notification_client_id.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +TestPushNotificationClient::TestPushNotificationClient(size_t client_id) + : PushNotificationClient(static_cast<PushNotificationClientId>(client_id)) { +} +TestPushNotificationClient::~TestPushNotificationClient() = default; + +void TestPushNotificationClient::HandleNotificationInteraction( + UNNotificationResponse* notification) { + has_notification_received_interaction_ = true; +} + +UIBackgroundFetchResult TestPushNotificationClient::HandleNotificationReception( + NSDictionary<NSString*, id>* notification) { + return fetch_result_; +} + +NSArray<UNNotificationCategory*>* +TestPushNotificationClient::RegisterActionableNotifications() { + // Add actional notifications as new notification types are added. + return @[]; +} + +bool TestPushNotificationClient::HasNotificationReceivedInteraction() { + return has_notification_received_interaction_; +} + +void TestPushNotificationClient::SetBackgroundFetchResult( + UIBackgroundFetchResult result) { + fetch_result_ = result; +}
diff --git a/ios/chrome/browser/search_engines/BUILD.gn b/ios/chrome/browser/search_engines/BUILD.gn index 940e83c..58a78c6 100644 --- a/ios/chrome/browser/search_engines/BUILD.gn +++ b/ios/chrome/browser/search_engines/BUILD.gn
@@ -16,8 +16,6 @@ "search_engine_tab_helper.mm", "search_engine_tab_helper_factory.h", "search_engine_tab_helper_factory.mm", - "search_engines_util.cc", - "search_engines_util.h", "template_url_fetcher_factory.cc", "template_url_fetcher_factory.h", "template_url_service_client_impl.cc", @@ -69,7 +67,7 @@ "extension_search_engine_data_updater.mm", ] deps = [ - ":search_engines", + ":search_engines_util", "//base", "//components/search_engines", "//ios/chrome/browser/widget_kit:features", @@ -123,6 +121,20 @@ configs += [ "//build/config/compiler:enable_arc" ] } +source_set("search_engines_util") { + sources = [ + "search_engines_util.cc", + "search_engines_util.h", + ] + deps = [ + "//base", + "//components/country_codes", + "//components/prefs", + "//components/search_engines", + ] + configs += [ "//build/config/compiler:enable_arc" ] +} + optimize_js("search_engine_js") { primary_script = "resources/search_engine.js" sources = [ "resources/search_engine.js" ]
diff --git a/ios/chrome/browser/ui/context_menu/BUILD.gn b/ios/chrome/browser/ui/context_menu/BUILD.gn index ec710165..a73b5459 100644 --- a/ios/chrome/browser/ui/context_menu/BUILD.gn +++ b/ios/chrome/browser/ui/context_menu/BUILD.gn
@@ -18,6 +18,7 @@ "//ios/chrome/browser/policy:policy_util", "//ios/chrome/browser/prefs:pref_names", "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/search_engines:search_engines_util", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/commands",
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h b/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h index f79f7a1bc..5ba4abea 100644 --- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h +++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h
@@ -40,6 +40,11 @@ // The subtitle displayed by this InfobarBanner. - (void)setSubtitleText:(NSString*)subtitleText; +// Applies a custom style (e.g. bold, italic) to a range of the subtitle +// displayed by the InfobarBanner. +- (void)addCustomStyle:(UIFontDescriptorSymbolicTraits)symbolicTraits + toSubtitleRange:(NSRange)range; + // If YES, restricts the number of lines in subtitle to 1. - (void)setRestrictSubtitleTextToSingleLine: (BOOL)restrictSubtitleTextToSingleLine;
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm index 71e2c24..0ba77823 100644 --- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -58,6 +58,21 @@ constexpr base::TimeDelta kLongPressTimeDuration = base::Milliseconds(400); } // namespace +#pragma mark - StyledRange + +// Used to track ranges of a string that should receive custom styling. +@interface StyledRange : NSObject + +@property(nonatomic) UIFontDescriptorSymbolicTraits symbolicTraits; +@property(nonatomic) NSRange range; + +@end + +@implementation StyledRange +@end + +#pragma mark - InfobarBannerViewController + @interface InfobarBannerViewController () // Properties backing the InfobarBannerConsumer protocol. @@ -67,6 +82,7 @@ @property(nonatomic, assign) BOOL presentsModal; @property(nonatomic, copy) NSString* titleText; @property(nonatomic, copy) NSString* subtitleText; +@property(nonatomic, copy) NSMutableArray<StyledRange*>* subtitleStyledRanges; @property(nonatomic, assign) BOOL useIconBackgroundTint; @property(nonatomic, strong) UIColor* iconImageTintColor; @property(nonatomic, strong) UIColor* iconBackgroundColor; @@ -117,6 +133,7 @@ _presentsModal = presentsModal; _useIconBackgroundTint = YES; _restrictSubtitleTextToSingleLine = NO; + _subtitleStyledRanges = [[NSMutableArray alloc] init]; } return self; } @@ -203,11 +220,8 @@ forAxis:UILayoutConstraintAxisVertical]; self.subTitleLabel = [[UILabel alloc] init]; - self.subTitleLabel.text = self.subtitleText; - self.subTitleLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + self.subTitleLabel.attributedText = [self subtitleAttributedText]; self.subTitleLabel.adjustsFontForContentSizeCategory = YES; - self.subTitleLabel.textColor = [UIColor colorNamed:kTextSecondaryColor]; if (_restrictSubtitleTextToSingleLine) { self.subTitleLabel.numberOfLines = 1; } else { @@ -405,7 +419,7 @@ - (void)setSubtitleText:(NSString*)subtitleText { _subtitleText = subtitleText; - self.subTitleLabel.text = _subtitleText; + self.subTitleLabel.attributedText = [self subtitleAttributedText]; self.subTitleLabel.hidden = !self.subtitleText.length; } @@ -435,6 +449,14 @@ _iconBackgroundColor = iconBackgroundColor; } +- (void)addCustomStyle:(UIFontDescriptorSymbolicTraits)symbolicTraits + toSubtitleRange:(NSRange)range { + StyledRange* styledRange = [[StyledRange alloc] init]; + styledRange.symbolicTraits = symbolicTraits; + styledRange.range = range; + [_subtitleStyledRanges addObject:styledRange]; +} + - (void)setRestrictSubtitleTextToSingleLine: (BOOL)restrictSubtitleTextToSingleLine { _restrictSubtitleTextToSingleLine = restrictSubtitleTextToSingleLine; @@ -643,4 +665,33 @@ return self.titleText; } +- (NSMutableAttributedString*)subtitleAttributedText { + if (!self.self.subtitleText) { + return nil; + } + + UIFontDescriptor* defaultDescriptor = [UIFontDescriptor + preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + // Passing 0 defers the size responsibility to the descriptor. + UIFont* defaultFont = [UIFont fontWithDescriptor:defaultDescriptor size:0.0]; + NSMutableAttributedString* attributedText = [[NSMutableAttributedString alloc] + initWithString:self.subtitleText + attributes:@{ + NSFontAttributeName : defaultFont, + NSForegroundColorAttributeName : + [UIColor colorNamed:kTextSecondaryColor] + }]; + + for (StyledRange* styledRange in self.subtitleStyledRanges) { + UIFontDescriptor* customDescriptor = [defaultDescriptor + fontDescriptorWithSymbolicTraits:styledRange.symbolicTraits]; + // Passing 0 defers the size responsibility to the descriptor. + UIFont* customFont = [UIFont fontWithDescriptor:customDescriptor size:0.0]; + [attributedText addAttribute:NSFontAttributeName + value:customFont + range:styledRange.range]; + } + return attributedText; +} + @end
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller_unittest.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller_unittest.mm index d00b2d3e..d0b33aa 100644 --- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller_unittest.mm
@@ -56,9 +56,9 @@ // Add view_controller_ to the UI Hierarchy to make sure views are created and // retained correctly. [scoped_key_window_.Get() setRootViewController:view_controller_]; - ASSERT_EQ(view_controller_.titleLabel.text, kTitle); - ASSERT_EQ(view_controller_.subTitleLabel.text, kSubtitleText); - ASSERT_EQ(view_controller_.infobarButton.titleLabel.text, kButtonText); + ASSERT_NSEQ(view_controller_.titleLabel.text, kTitle); + ASSERT_NSEQ(view_controller_.subTitleLabel.text, kSubtitleText); + ASSERT_NSEQ(view_controller_.infobarButton.titleLabel.text, kButtonText); } TEST_F(InfobarBannerViewControllerTest, TestSubtitleLabelHidden) { @@ -66,6 +66,38 @@ // Add view_controller_ to the UI Hierarchy to make sure views are created and // retained correctly. [scoped_key_window_.Get() setRootViewController:view_controller_]; - ASSERT_EQ(view_controller_.titleLabel.text, @"title"); + ASSERT_NSEQ(view_controller_.titleLabel.text, @"title"); ASSERT_TRUE(view_controller_.subTitleLabel.hidden); } + +TEST_F(InfobarBannerViewControllerTest, TestAddCustomStyleToSubtitleRange) { + NSString* const kSubtitleText = @"BoldItalic"; + NSRange expectedBoldRange = [kSubtitleText rangeOfString:@"Bold"]; + NSRange expectedItalicRange = [kSubtitleText rangeOfString:@"Italic"]; + [view_controller_ setSubtitleText:kSubtitleText]; + + [view_controller_ addCustomStyle:UIFontDescriptorTraitBold + toSubtitleRange:expectedBoldRange]; + [view_controller_ addCustomStyle:UIFontDescriptorTraitItalic + toSubtitleRange:expectedItalicRange]; + [scoped_key_window_.Get() setRootViewController:view_controller_]; + + NSRange maxSearchRange = NSMakeRange(0, [kSubtitleText length]); + NSRange range1; + UIFont* font1 = [view_controller_.subTitleLabel.attributedText + attribute:NSFontAttributeName + atIndex:0 + longestEffectiveRange:&range1 + inRange:maxSearchRange]; + EXPECT_TRUE(NSEqualRanges(range1, expectedBoldRange)); + EXPECT_EQ([[font1 fontDescriptor] symbolicTraits], UIFontDescriptorTraitBold); + NSRange range2; + UIFont* font2 = [view_controller_.subTitleLabel.attributedText + attribute:NSFontAttributeName + atIndex:expectedItalicRange.location + longestEffectiveRange:&range2 + inRange:maxSearchRange]; + EXPECT_TRUE(NSEqualRanges(range2, expectedItalicRange)); + EXPECT_EQ([[font2 fontDescriptor] symbolicTraits], + UIFontDescriptorTraitItalic); +}
diff --git a/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.mm b/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.mm index 5bb7469..f9480c6 100644 --- a/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.mm +++ b/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.mm
@@ -9,4 +9,9 @@ #endif @implementation FakeInfobarBannerConsumer + +- (void)addCustomStyle:(UIFontDescriptorSymbolicTraits)symbolicTraits + toSubtitleRange:(NSRange)range { +} + @end
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn index 8195192f..7bbb4011 100644 --- a/ios/chrome/browser/ui/location_bar/BUILD.gn +++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -51,6 +51,7 @@ "//ios/chrome/browser/overlays", "//ios/chrome/browser/overlays/public/web_content_area", "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/search_engines:search_engines_util", "//ios/chrome/browser/ssl", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/badges",
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn index b901aa74..601f88a 100644 --- a/ios/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -167,6 +167,7 @@ "//ios/chrome/browser/net", "//ios/chrome/browser/prerender", "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/search_engines:search_engines_util", "//ios/chrome/browser/sessions", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands",
diff --git a/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn b/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn index 3f616231..614f3714 100644 --- a/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn
@@ -27,7 +27,8 @@ "//components/search_engines", "//ios/chrome/app/strings", "//ios/chrome/browser/flags:system_flags", - "//ios/chrome/browser/search_engines:search_engines", + "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/search_engines:search_engines_util", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/lens:lens_entrypoint",
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn index 3f848db..e98ebf368 100644 --- a/ios/chrome/browser/ui/popup_menu/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -78,6 +78,7 @@ "//ios/chrome/browser/policy:policy_util", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/search_engines:search_engines_util", "//ios/chrome/browser/translate", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/activity_services",
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn index 60f434c..403aa3b 100644 --- a/ios/chrome/browser/ui/toolbar/BUILD.gn +++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -45,6 +45,7 @@ "//ios/chrome/browser/prerender", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/search_engines:search_engines_util", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/bookmarks:core", "//ios/chrome/browser/ui/broadcaster",
diff --git a/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm b/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm index 24709ae..bd21205 100644 --- a/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm +++ b/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.h" +#import "base/metrics/histogram_functions.h" #import "base/metrics/histogram_macros.h" #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" @@ -85,6 +86,12 @@ bool user_action) { if (metric_collection_paused_) return; + + base::TimeDelta age_at_deletion = + base::Time::Now() - web_state->GetCreationTime(); + base::UmaHistogramCustomTimes("Tab.AgeAtDeletion", age_at_deletion, + base::Minutes(1), base::Days(24), 50); + if (user_action) base::RecordAction(base::UserMetricsAction("MobileTabClosed")); }
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 169f407..b62c4445 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -239,6 +239,7 @@ "//ios/chrome/browser/policy:unit_tests", "//ios/chrome/browser/prerender:unit_tests", "//ios/chrome/browser/promos_manager:unit_tests", + "//ios/chrome/browser/push_notification:unit_tests", "//ios/chrome/browser/reading_list:unit_tests", "//ios/chrome/browser/safe_browsing:unit_tests", "//ios/chrome/browser/safe_browsing/tailored_security:unit_tests",
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 747291c..150177c 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -75,6 +75,7 @@ "//components/password_manager/core/common", "//components/prefs", "//components/safe_browsing/core/common", + "//components/search_engines", "//components/strings", "//components/sync/base", "//components/translate/core/browser", @@ -97,6 +98,8 @@ "//ios/chrome/browser/passwords", "//ios/chrome/browser/passwords:eg_app_support+eg2", "//ios/chrome/browser/policy:eg_app_support+eg2", + "//ios/chrome/browser/search_engines:search_engines_util", + "//ios/chrome/browser/search_engines:template_url_service_factory", "//ios/chrome/browser/signin:fake_system_identity", "//ios/chrome/browser/sync", "//ios/chrome/browser/translate:eg_app_support+eg2",
diff --git a/ios/chrome/test/earl_grey/DEPS b/ios/chrome/test/earl_grey/DEPS index 1f3f327..a564f78 100644 --- a/ios/chrome/test/earl_grey/DEPS +++ b/ios/chrome/test/earl_grey/DEPS
@@ -2,6 +2,7 @@ # To compile base::Feature under EG2 "chrome_earl_grey_app_interface\.mm":[ "+components/autofill/core/common/autofill_features.h", + "+components/search_engines/template_url_service.h", "+components/password_manager/core/common/password_manager_features.h", "+components/payments/core/features.h", "+components/ukm/ios/features.h",
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm index 5105203c..9cc11e7 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -21,6 +21,7 @@ #import "components/metrics/demographics/demographic_metrics_provider.h" #import "components/password_manager/core/common/password_manager_features.h" #import "components/prefs/pref_service.h" +#import "components/search_engines/template_url_service.h" #import "components/sync/base/pref_names.h" #import "components/unified_consent/unified_consent_service.h" #import "components/variations/variations_associated_data.h" @@ -31,6 +32,8 @@ #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/content_settings/host_content_settings_map_factory.h" #import "ios/chrome/browser/ntp/features.h" +#import "ios/chrome/browser/search_engines/search_engines_util.h" +#import "ios/chrome/browser/search_engines/template_url_service_factory.h" #import "ios/chrome/browser/signin/fake_system_identity.h" #import "ios/chrome/browser/sync/sync_service_factory.h" #import "ios/chrome/browser/ui/commands/application_commands.h" @@ -1104,9 +1107,13 @@ } + (BOOL)isUseLensToSearchForImageEnabled { + TemplateURLService* service = + ios::TemplateURLServiceFactory::GetForBrowserState( + chrome_test_util::GetOriginalBrowserState()); return base::FeatureList::IsEnabled(kUseLensToSearchForImage) && ios::provider::IsLensSupported() && - ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_TABLET; + ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_TABLET && + search_engines::SupportsSearchImageWithLens(service); } + (BOOL)isThumbstripEnabledForWindowWithNumber:(int)windowNumber {
diff --git a/ios/chrome/test/providers/push_notification/test_push_notification.mm b/ios/chrome/test/providers/push_notification/test_push_notification.mm index 628ccc7..41661499 100644 --- a/ios/chrome/test/providers/push_notification/test_push_notification.mm +++ b/ios/chrome/test/providers/push_notification/test_push_notification.mm
@@ -27,6 +27,12 @@ void RegisterDevice(PushNotificationConfiguration* config, void (^completion_handler)(NSError* error)) final; void UnregisterDevice(void (^completion_handler)(NSError* error)) final; + bool DeviceTokenIsSet() const final; + + protected: + // PushNotificationService implementation. + void SetAccountsToDevice(NSArray<NSString*>* account_ids, + CompletionHandler completion_handler) final; }; void TestPushNotificationService::RegisterDevice( @@ -59,8 +65,28 @@ })); } +bool TestPushNotificationService::DeviceTokenIsSet() const { + return false; +} + +void TestPushNotificationService::SetAccountsToDevice( + NSArray<NSString*>* account_ids, + void (^completion_handler)(NSError* error)) { + // Test implementation does nothing. As a result, the `completion_handler` is + // called with a NSFeatureUnsupportedError. + + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(^() { + NSError* error = + [NSError errorWithDomain:kTestPushNotificationErrorDomain + code:NSFeatureUnsupportedError + userInfo:nil]; + completion_handler(error); + })); +} + std::unique_ptr<PushNotificationService> CreatePushNotificationService() { return std::make_unique<TestPushNotificationService>(); } } // namespace provider -} // namespace ios \ No newline at end of file +} // namespace ios
diff --git a/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm b/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm index fa433e2..3a7b6c4 100644 --- a/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm +++ b/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm
@@ -192,56 +192,38 @@ + (NSString*)executeAsyncJavaScriptFunction:(NSString*)function inTab:(NSString*)tabID timeout:(base::TimeDelta)timeout { - const std::string kMessageResultKey("result"); - - // Use a distinct messageID value for each invocation of this method to - // distinguish stale messages (from previous script invocations that timed - // out) from a message for the current script. - static NSUInteger messageID = 0; - std::string command = base::StringPrintf("CWTWebDriver%lu", messageID++); - - // Construct a completion handler that takes a single argument and sends a - // message with this argument. - std::string scriptCompletionHandler = - base::StringPrintf("function(value) {" - "__gCrWeb.message.invokeOnHost({command: " - "'%s.result', %s: value}); }", - command.c_str(), kMessageResultKey.c_str()); - - // Construct a script that calls the given `function` with - // `scriptCompletionHandler` as an argument. - std::string scriptFunctionWithCompletionHandler = base::StringPrintf( - "(%s).call(null, %s)", base::SysNSStringToUTF8(function).c_str(), - scriptCompletionHandler.c_str()); - - __block absl::optional<base::Value> messageValue; - const web::WebState::ScriptCommandCallback callback = - base::BindRepeating(^(const base::Value& value, const GURL&, - /*interacted*/ bool, - /*sender_frame*/ web::WebFrame*) { - const base::Value* result = value.FindKey(kMessageResultKey); - - // `result` will be null when the computed result in JavaScript is - // `undefined`. This happens, for example, when injecting a script that - // performs some action (like setting the document's title) but doesn't - // return any value. - if (result) - messageValue = result->Clone(); - else - messageValue = base::Value(); - }); - __block BOOL webStateFound = NO; - __block base::CallbackListSubscription subscription; + __block absl::optional<base::Value> messageValue; DispatchSyncOnMainThread(^{ web::WebState* webState = GetWebStateWithId(tabID); if (!webState) return; + web::WebFrame* mainFrame = web::GetMainFrame(webState); + if (!mainFrame) { + return; + } webStateFound = YES; - subscription = webState->AddScriptCommandCallback(callback, command); - web::WebFrame* main_frame = web::GetMainFrame(webState); - main_frame->ExecuteJavaScript( - base::UTF8ToUTF16(scriptFunctionWithCompletionHandler)); + + NSString* script = + [NSString stringWithFormat:@"var result;" + @"(%@).call(null, (r) => { result = r; } );" + @"result;", + function]; + + mainFrame->ExecuteJavaScript(base::SysNSStringToUTF16(script), + base::BindOnce(^(const base::Value* result) { + // `result` will be null when the computed + // result in JavaScript is `undefined`. This + // happens, for example, when injecting a + // script that performs some action (like + // setting the document's title) but doesn't + // return any value. + if (result) { + messageValue = result->Clone(); + } else { + messageValue = base::Value(); + } + })); }); if (!webStateFound)
diff --git a/media/gpu/chromeos/gl_image_processor_backend.cc b/media/gpu/chromeos/gl_image_processor_backend.cc index 05f3d42..347c6ff 100644 --- a/media/gpu/chromeos/gl_image_processor_backend.cc +++ b/media/gpu/chromeos/gl_image_processor_backend.cc
@@ -83,9 +83,10 @@ DCHECK(native_pixmap->AreDmaBufFdsValid()); // Import the NativePixmap into GL. - auto image = base::MakeRefCounted<gl::GLImageNativePixmap>( - video_frame->coded_size(), gfx::BufferFormat::YUV_420_BIPLANAR); - if (!image->Initialize(std::move(native_pixmap))) { + auto image = gl::GLImageNativePixmap::Create( + video_frame->coded_size(), gfx::BufferFormat::YUV_420_BIPLANAR, + std::move(native_pixmap)); + if (!image) { LOG(ERROR) << "Could not initialize the GL image"; return nullptr; }
diff --git a/media/gpu/test/video_frame_validator.cc b/media/gpu/test/video_frame_validator.cc index c1ccb518..521ea3a 100644 --- a/media/gpu/test/video_frame_validator.cc +++ b/media/gpu/test/video_frame_validator.cc
@@ -20,6 +20,7 @@ #include "media/gpu/buildflags.h" #include "media/gpu/macros.h" #include "media/gpu/test/image_quality_metrics.h" +#include "media/gpu/test/video_frame_helpers.h" #include "media/gpu/test/video_test_helpers.h" #include "media/gpu/video_frame_mapper.h" #include "media/gpu/video_frame_mapper_factory.h" @@ -31,8 +32,10 @@ namespace test { VideoFrameValidator::VideoFrameValidator( - std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor) + std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, + CropHelper crop_helper) : corrupt_frame_processor_(std::move(corrupt_frame_processor)), + crop_helper_(crop_helper), num_frames_validating_(0), frame_validator_thread_("FrameValidatorThread"), frame_validator_cv_(&frame_validator_lock_) { @@ -179,6 +182,9 @@ ASSERT_TRUE(frame->IsMappable()); + if (ShouldCrop()) + frame = CloneAndCropFrame(std::move(frame)); + auto mismatched_info = Validate(frame, frame_index); base::AutoLock auto_lock(frame_validator_lock_); @@ -195,6 +201,36 @@ frame_validator_cv_.Signal(); } +scoped_refptr<VideoFrame> VideoFrameValidator::CloneAndCropFrame( + scoped_refptr<const VideoFrame> frame) const { + const auto crop = crop_helper_.Run(*frame); + const auto& visible = frame->visible_rect(); + auto cloned_frame = CloneVideoFrame(frame.get(), frame->layout()); + // Ensures that the crop is within the previous visible rectangle. + if (!visible.Contains(crop)) { + LOG(ERROR) << "Crop " << crop.ToString() + << "must be contained by the visible area of the input frame: " + << visible.ToString() << "."; + return cloned_frame; + } + return VideoFrame::WrapVideoFrame(cloned_frame, frame->format(), crop, + crop.size()); +} + +gfx::Rect BottomRowCrop(int row_height, const VideoFrame& frame) { + const auto& visible = frame.visible_rect(); + // Performs bounds checking on the row_height to ensure that the returned + // crop is contained by the current visible area. + if (visible.size().height() < row_height) { + LOG(ERROR) << "Could not get a row of height " << row_height + << " from a visible area of height " << visible.size().height(); + return visible; + } + + return gfx::Rect{visible.x(), visible.bottom() - row_height, visible.width(), + row_height}; +} + struct MD5VideoFrameValidator::MD5MismatchedFrameInfo : public VideoFrameValidator::MismatchedFrameInfo { MD5MismatchedFrameInfo(size_t frame_index, @@ -218,10 +254,11 @@ std::unique_ptr<MD5VideoFrameValidator> MD5VideoFrameValidator::Create( const std::vector<std::string>& expected_frame_checksums, VideoPixelFormat validation_format, - std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor) { - auto video_frame_validator = base::WrapUnique( - new MD5VideoFrameValidator(expected_frame_checksums, validation_format, - std::move(corrupt_frame_processor))); + std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, + CropHelper crop_helper) { + auto video_frame_validator = base::WrapUnique(new MD5VideoFrameValidator( + expected_frame_checksums, validation_format, + std::move(corrupt_frame_processor), std::move(crop_helper))); if (!video_frame_validator->Initialize()) { LOG(ERROR) << "Failed to initialize MD5VideoFrameValidator."; return nullptr; @@ -233,8 +270,10 @@ MD5VideoFrameValidator::MD5VideoFrameValidator( const std::vector<std::string>& expected_frame_checksums, VideoPixelFormat validation_format, - std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor) - : VideoFrameValidator(std::move(corrupt_frame_processor)), + std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, + CropHelper crop_helper) + : VideoFrameValidator(std::move(corrupt_frame_processor), + std::move(crop_helper)), expected_frame_checksums_(expected_frame_checksums), validation_format_(validation_format) {} @@ -325,9 +364,11 @@ std::unique_ptr<RawVideoFrameValidator> RawVideoFrameValidator::Create( const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, - uint8_t tolerance) { + uint8_t tolerance, + CropHelper crop_helper) { auto video_frame_validator = base::WrapUnique(new RawVideoFrameValidator( - get_model_frame_cb, std::move(corrupt_frame_processor), tolerance)); + get_model_frame_cb, std::move(corrupt_frame_processor), tolerance, + std::move(crop_helper))); if (!video_frame_validator->Initialize()) { LOG(ERROR) << "Failed to initialize RawVideoFrameValidator."; return nullptr; @@ -339,8 +380,10 @@ RawVideoFrameValidator::RawVideoFrameValidator( const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, - uint8_t tolerance) - : VideoFrameValidator(std::move(corrupt_frame_processor)), + uint8_t tolerance, + CropHelper crop_helper) + : VideoFrameValidator(std::move(corrupt_frame_processor), + std::move(crop_helper)), get_model_frame_cb_(get_model_frame_cb), tolerance_(tolerance) {} @@ -352,6 +395,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(validator_thread_sequence_checker_); auto model_frame = get_model_frame_cb_.Run(frame_index); CHECK(model_frame); + + if (ShouldCrop()) + model_frame = CloneAndCropFrame(std::move(model_frame)); + size_t diff_cnt = CompareFramesWithErrorDiff(*frame, *model_frame, tolerance_); if (diff_cnt > 0) @@ -376,15 +423,15 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, ValidationMode validation_mode, - double tolerance) { + double tolerance, + CropHelper crop_helper) { auto video_frame_validator = base::WrapUnique(new PSNRVideoFrameValidator( get_model_frame_cb, std::move(corrupt_frame_processor), validation_mode, - tolerance)); + tolerance, std::move(crop_helper))); if (!video_frame_validator->Initialize()) { LOG(ERROR) << "Failed to initialize PSNRVideoFrameValidator."; return nullptr; } - return video_frame_validator; } @@ -392,8 +439,10 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, ValidationMode validation_mode, - double tolerance) - : VideoFrameValidator(std::move(corrupt_frame_processor)), + double tolerance, + CropHelper crop_helper) + : VideoFrameValidator(std::move(corrupt_frame_processor), + std::move(crop_helper)), get_model_frame_cb_(get_model_frame_cb), tolerance_(tolerance), validation_mode_(validation_mode) {} @@ -406,6 +455,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(validator_thread_sequence_checker_); auto model_frame = get_model_frame_cb_.Run(frame_index); CHECK(model_frame); + + if (ShouldCrop()) + model_frame = CloneAndCropFrame(std::move(model_frame)); + double psnr = ComputePSNR(*frame, *model_frame); DVLOGF(4) << "frame_index: " << frame_index << ", psnr: " << psnr; psnr_[frame_index] = psnr; @@ -425,6 +478,7 @@ average += psnr.second; } average /= psnr_.size(); + DVLOGF(4) << "Average PSNR: " << average; if (average < tolerance_) { LOG(ERROR) << "Average PSNR is too low: " << average; return false; @@ -449,15 +503,15 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, ValidationMode validation_mode, - double tolerance) { + double tolerance, + CropHelper crop_helper) { auto video_frame_validator = base::WrapUnique(new SSIMVideoFrameValidator( get_model_frame_cb, std::move(corrupt_frame_processor), validation_mode, - tolerance)); + tolerance, std::move(crop_helper))); if (!video_frame_validator->Initialize()) { LOG(ERROR) << "Failed to initialize SSIMVideoFrameValidator."; return nullptr; } - return video_frame_validator; } @@ -465,8 +519,10 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, ValidationMode validation_mode, - double tolerance) - : VideoFrameValidator(std::move(corrupt_frame_processor)), + double tolerance, + CropHelper crop_helper) + : VideoFrameValidator(std::move(corrupt_frame_processor), + std::move(crop_helper)), get_model_frame_cb_(get_model_frame_cb), tolerance_(tolerance), validation_mode_(validation_mode) {} @@ -478,8 +534,11 @@ size_t frame_index) { DCHECK_CALLED_ON_VALID_SEQUENCE(validator_thread_sequence_checker_); auto model_frame = get_model_frame_cb_.Run(frame_index); - CHECK(model_frame); + + if (ShouldCrop()) + model_frame = CloneAndCropFrame(std::move(model_frame)); + double ssim = ComputeSSIM(*frame, *model_frame); DVLOGF(4) << "frame_index: " << frame_index << ", ssim: " << ssim; ssim_[frame_index] = ssim; @@ -499,6 +558,7 @@ average += ssim.second; } average /= ssim_.size(); + DVLOGF(4) << "Average SSIM: " << average; if (average < tolerance_) { LOG(ERROR) << "Average SSIM is too low: " << average; return false;
diff --git a/media/gpu/test/video_frame_validator.h b/media/gpu/test/video_frame_validator.h index 9bd658a..2c504b5a 100644 --- a/media/gpu/test/video_frame_validator.h +++ b/media/gpu/test/video_frame_validator.h
@@ -48,6 +48,9 @@ using GetModelFrameCB = base::RepeatingCallback<scoped_refptr<const VideoFrame>(size_t)>; + using CropHelper = + base::RepeatingCallback<gfx::Rect(const VideoFrame& frame)>; + VideoFrameValidator(const VideoFrameValidator&) = delete; VideoFrameValidator& operator=(const VideoFrameValidator&) = delete; @@ -78,13 +81,22 @@ }; VideoFrameValidator( - std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor); + std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, + CropHelper crop_helper); // Start the frame validation thread. bool Initialize(); SEQUENCE_CHECKER(validator_thread_sequence_checker_); + // Returns true if the processed frame or model frame should be cropped with + // CloneAndCropFrame() or VideoFrame::WrapVideoFrame(). + bool ShouldCrop() const { return static_cast<bool>(crop_helper_); } + + // This can be used by VideoFrameValidators to support cropping. + scoped_refptr<VideoFrame> CloneAndCropFrame( + scoped_refptr<const VideoFrame> frame) const; + private: void CleanUpOnValidatorThread(); @@ -108,6 +120,10 @@ // forwarded to. This can be used to e.g. write corrupted frames to disk. std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor_; + // If |crop_helper_| is runnable, then ShouldCrop() will return true and + // CloneAndCropFrame() can be used. + const CropHelper crop_helper_; + // The number of frames currently queued for validation. size_t num_frames_validating_ GUARDED_BY(frame_validator_lock_); // The results of invalid frame data. @@ -122,6 +138,11 @@ SEQUENCE_CHECKER(validator_sequence_checker_); }; +// Returns a cropping rectangle containing the bottom |row_height| rows of the +// input frame. This can be used by VideoFrameValidator::CropHelper. +gfx::Rect BottomRowCrop(int row_height, const VideoFrame& frame); +constexpr int kDefaultBottomRowCropHeight = 2; + // Validate by converting the frame to be validated to |validation_format| to // resolve pixel format differences on different platforms. Thereafter, it // compares md5 values of the mapped and converted buffer with golden md5 @@ -132,7 +153,8 @@ static std::unique_ptr<MD5VideoFrameValidator> Create( const std::vector<std::string>& expected_frame_checksums, VideoPixelFormat validation_format = PIXEL_FORMAT_I420, - std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor = nullptr); + std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor = nullptr, + CropHelper crop_helper = CropHelper()); ~MD5VideoFrameValidator() override; private: @@ -141,7 +163,8 @@ MD5VideoFrameValidator( const std::vector<std::string>& expected_frame_checksums, VideoPixelFormat validation_format, - std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor); + std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, + CropHelper crop_helper); MD5VideoFrameValidator(const MD5VideoFrameValidator&) = delete; MD5VideoFrameValidator& operator=(const MD5VideoFrameValidator&) = delete; @@ -167,7 +190,8 @@ static std::unique_ptr<RawVideoFrameValidator> Create( const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor = nullptr, - uint8_t tolerance = kDefaultTolerance); + uint8_t tolerance = kDefaultTolerance, + CropHelper crop_helper = CropHelper()); ~RawVideoFrameValidator() override; private: @@ -176,7 +200,8 @@ RawVideoFrameValidator( const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, - uint8_t tolerance); + uint8_t tolerance, + CropHelper crop_helper); std::unique_ptr<MismatchedFrameInfo> Validate( scoped_refptr<const VideoFrame> frame, @@ -186,8 +211,6 @@ const uint8_t tolerance_; }; -// Validate by computing PSNR from the frame to be validated and the model frame -// acquired by |get_model_frame_cb_|. If the PSNR value is equal to or more than // |tolerance_|, the validation on the frame passes. class PSNRVideoFrameValidator : public VideoFrameValidator { public: @@ -197,7 +220,8 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor = nullptr, ValidationMode validation_mode = ValidationMode::kThreshold, - double tolerance = kDefaultTolerance); + double tolerance = kDefaultTolerance, + CropHelper crop_helper = CropHelper()); const std::map<size_t, double>& GetPSNRValues() const { return psnr_; } ~PSNRVideoFrameValidator() override; @@ -208,7 +232,8 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, ValidationMode validation_mode, - double tolerance); + double tolerance, + CropHelper crop_helper); std::unique_ptr<MismatchedFrameInfo> Validate( scoped_refptr<const VideoFrame> frame, @@ -217,6 +242,7 @@ bool Passed() const override; const GetModelFrameCB get_model_frame_cb_; + const CropHelper crop_helper_; const double tolerance_; const ValidationMode validation_mode_; std::map<size_t, double> psnr_; @@ -233,7 +259,8 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor = nullptr, ValidationMode validation_mode = ValidationMode::kThreshold, - double tolerance = kDefaultTolerance); + double tolerance = kDefaultTolerance, + CropHelper crop_helper = CropHelper()); const std::map<size_t, double>& GetSSIMValues() const { return ssim_; } ~SSIMVideoFrameValidator() override; @@ -244,7 +271,8 @@ const GetModelFrameCB& get_model_frame_cb, std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor, ValidationMode validation_mode, - double tolerance); + double tolerance, + CropHelper crop_helper); std::unique_ptr<MismatchedFrameInfo> Validate( scoped_refptr<const VideoFrame> frame,
diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc index fa9a95b..c3c57a0 100644 --- a/media/gpu/v4l2/generic_v4l2_device.cc +++ b/media/gpu/v4l2/generic_v4l2_device.cc
@@ -316,9 +316,8 @@ // TODO(b/220336463): plumb the right color space. auto image = - base::MakeRefCounted<gl::GLImageNativePixmap>(size, buffer_format); - bool ret = image->Initialize(std::move(pixmap)); - DCHECK(ret); + gl::GLImageNativePixmap::Create(size, buffer_format, std::move(pixmap)); + DCHECK(image); return image; }
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc index f739173..4098b3a 100644 --- a/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc
@@ -86,10 +86,10 @@ return VaapiStatus::Codes::kBadContext; // TODO(b/220336463): plumb the right color space. - auto image = - base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format); + auto image = gl::GLImageNativePixmap::CreateFromTexture(visible_size_, format, + texture_id_); // Create an EGLImage from a gl texture - if (!image->InitializeFromTexture(texture_id_)) { + if (!image) { DLOG(ERROR) << "Failed to initialize eglimage from texture id: " << texture_id_; return VaapiStatus::Codes::kFailedToInitializeImage;
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc index 2abb6886..0b646a87f5 100644 --- a/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
@@ -89,13 +89,14 @@ // TODO(b/220336463): plumb the right color space. auto image = - base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format); - if (!image->Initialize(std::move(pixmap))) { + gl::GLImageNativePixmap::Create(visible_size_, format, std::move(pixmap)); + if (!image) { LOG(ERROR) << "Failed to create GLImage"; return VaapiStatus::Codes::kFailedToInitializeImage; } - gl_image_ = image; + gl_image_ = std::move(image); + if (!gl_image_->BindTexImage(texture_target_)) { LOG(ERROR) << "Failed to bind texture to GLImage"; return VaapiStatus::Codes::kFailedToBindTexture;
diff --git a/media/mojo/clients/mojo_android_overlay_unittest.cc b/media/mojo/clients/mojo_android_overlay_unittest.cc index 7e1447a8..aa426a8 100644 --- a/media/mojo/clients/mojo_android_overlay_unittest.cc +++ b/media/mojo/clients/mojo_android_overlay_unittest.cc
@@ -138,7 +138,7 @@ surface_ = gl::ScopedJavaSurface(surface_texture_.get()); surface_key_ = gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget( gpu::GpuSurfaceTracker::SurfaceRecord( - gfx::kNullAcceleratedWidget, surface_.j_surface(), + surface_.CopyRetainOwnership(), false /* can_be_used_with_surface_control */)); mock_provider_.client_->OnSurfaceReady(surface_key_);
diff --git a/mojo/public/tools/bindings/generators/mojom_ts_generator.py b/mojo/public/tools/bindings/generators/mojom_ts_generator.py index 8ee12d63..94296195 100644 --- a/mojo/public/tools/bindings/generators/mojom_ts_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_ts_generator.py
@@ -285,8 +285,7 @@ # names. return False return (mojom.IsIntegralKind(kind) or mojom.IsFloatKind(kind) - or mojom.IsDoubleKind(kind) or mojom.IsStringKind(kind) - or mojom.IsEnumKind(kind)) + or mojom.IsDoubleKind(kind) or mojom.IsStringKind(kind)) def _TypescriptType(self, kind, maybe_nullable=False): def recurse_nullable(kind): @@ -302,10 +301,13 @@ else: return "%s[]" % get_type_name(kind.kind) - if (mojom.IsMapKind(kind) and self._IsStringableKind(kind.key_kind) - and not mojom.IsNullableKind(kind.key_kind)): - return "{[key: %s]: %s}" % (get_type_name( - kind.key_kind), recurse_nullable(kind.value_kind)) + if (mojom.IsMapKind(kind) and not mojom.IsNullableKind(kind.key_kind)): + if mojom.IsEnumKind(kind.key_kind): + return "{[key in %s]?: %s}" % (get_type_name( + kind.key_kind), recurse_nullable(kind.value_kind)) + if self._IsStringableKind(kind.key_kind): + return "{[key: %s]: %s}" % (get_type_name( + kind.key_kind), recurse_nullable(kind.value_kind)) if mojom.IsMapKind(kind): return "Map<%s, %s>" % (recurse_nullable(
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl.cc b/sandbox/linux/bpf_dsl/bpf_dsl.cc index 2173963..87f8323f 100644 --- a/sandbox/linux/bpf_dsl/bpf_dsl.cc +++ b/sandbox/linux/bpf_dsl/bpf_dsl.cc
@@ -52,9 +52,7 @@ class TrapResultExprImpl : public internal::ResultExprImpl { public: TrapResultExprImpl(TrapRegistry::TrapFnc func, const void* arg, bool safe) - : func_(func), arg_(reinterpret_cast<uintptr_t>(arg)), safe_(safe) { - DCHECK(func_); - } + : handler_(func, arg, safe) {} TrapResultExprImpl(const TrapResultExprImpl&) = delete; TrapResultExprImpl& operator=(const TrapResultExprImpl&) = delete; @@ -62,17 +60,14 @@ ~TrapResultExprImpl() override {} CodeGen::Node Compile(PolicyCompiler* pc) const override { - return pc->Trap(func_, reinterpret_cast<const void*>(arg_), safe_); + return pc->Trap(handler_); } - bool HasUnsafeTraps() const override { return safe_ == false; } - + bool HasUnsafeTraps() const override { return !handler_.safe; } bool IsDeny() const override { return true; } private: - TrapRegistry::TrapFnc func_; - uintptr_t arg_; // Usually a pointer, but may be a smuggled int. - bool safe_; + TrapRegistry::Handler handler_; }; class IfThenResultExprImpl : public internal::ResultExprImpl {
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc index d3c42644..b94ec6e 100644 --- a/sandbox/linux/bpf_dsl/policy_compiler.cc +++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -435,17 +435,15 @@ // The performance penalty for this extra round-trip to user-space is not // actually that bad, as we only ever pay it for denied system calls; and a // typical program has very few of these. - return Trap(ReturnErrno, reinterpret_cast<void*>(ret & SECCOMP_RET_DATA), - true); + return Trap( + {ReturnErrno, reinterpret_cast<void*>(ret & SECCOMP_RET_DATA), true}); } return gen_.MakeInstruction(BPF_RET + BPF_K, ret); } -CodeGen::Node PolicyCompiler::Trap(TrapRegistry::TrapFnc fnc, - const void* aux, - bool safe) { - uint16_t trap_id = registry_->Add(fnc, aux, safe); +CodeGen::Node PolicyCompiler::Trap(const TrapRegistry::Handler& handler) { + uint16_t trap_id = registry_->Add(handler); return gen_.MakeInstruction(BPF_RET + BPF_K, SECCOMP_RET_TRAP + trap_id); }
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.h b/sandbox/linux/bpf_dsl/policy_compiler.h index 5439c0a..d35862af 100644 --- a/sandbox/linux/bpf_dsl/policy_compiler.h +++ b/sandbox/linux/bpf_dsl/policy_compiler.h
@@ -60,7 +60,7 @@ // Trap returns a CodeGen::Node to indicate the system call should // instead invoke a trap handler. - CodeGen::Node Trap(TrapRegistry::TrapFnc fnc, const void* aux, bool safe); + CodeGen::Node Trap(const TrapRegistry::Handler& handler); // MaskedEqual returns a CodeGen::Node that represents a conditional branch. // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared
diff --git a/sandbox/linux/bpf_dsl/test_trap_registry.cc b/sandbox/linux/bpf_dsl/test_trap_registry.cc index bf546d3f..2b71fce 100644 --- a/sandbox/linux/bpf_dsl/test_trap_registry.cc +++ b/sandbox/linux/bpf_dsl/test_trap_registry.cc
@@ -11,14 +11,16 @@ namespace sandbox { namespace bpf_dsl { -TestTrapRegistry::TestTrapRegistry() : map_() {} -TestTrapRegistry::~TestTrapRegistry() {} +TestTrapRegistry::TestTrapRegistry() = default; -uint16_t TestTrapRegistry::Add(TrapFnc fnc, const void* aux, bool safe) { - EXPECT_TRUE(safe); +TestTrapRegistry::~TestTrapRegistry() = default; + +uint16_t TestTrapRegistry::Add(const Handler& handler) { + EXPECT_TRUE(handler.safe); const uint16_t next_id = map_.size() + 1; - return map_.insert(std::make_pair(Key(fnc, aux), next_id)).first->second; + auto result = map_.insert({handler, next_id}); + return result.first->second; // Old value if pre-existing handler. } bool TestTrapRegistry::EnableUnsafeTraps() {
diff --git a/sandbox/linux/bpf_dsl/test_trap_registry.h b/sandbox/linux/bpf_dsl/test_trap_registry.h index 5c080bd..e51b440fc 100644 --- a/sandbox/linux/bpf_dsl/test_trap_registry.h +++ b/sandbox/linux/bpf_dsl/test_trap_registry.h
@@ -24,13 +24,11 @@ virtual ~TestTrapRegistry(); - uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override; + uint16_t Add(const Handler& handler) override; bool EnableUnsafeTraps() override; private: - using Key = std::pair<TrapFnc, const void*>; - - std::map<Key, uint16_t> map_; + std::map<Handler, uint16_t> map_; }; } // namespace bpf_dsl
diff --git a/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc b/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc index eaf2657..76ec007 100644 --- a/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc +++ b/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc
@@ -39,7 +39,7 @@ for (int i = 0; i < 2; ++i) { for (size_t j = 0; j < std::size(funcs); ++j) { // Trap IDs start at 1. - EXPECT_EQ(j + 1, traps.Add(funcs[j].fnc, funcs[j].aux, true)); + EXPECT_EQ(j + 1, traps.Add({funcs[j].fnc, funcs[j].aux, true})); } } }
diff --git a/sandbox/linux/bpf_dsl/trap_registry.h b/sandbox/linux/bpf_dsl/trap_registry.h index 00bf79c9..99bd439 100644 --- a/sandbox/linux/bpf_dsl/trap_registry.h +++ b/sandbox/linux/bpf_dsl/trap_registry.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include "base/check.h" #include "sandbox/linux/system_headers/linux_seccomp.h" #include "sandbox/sandbox_export.h" @@ -33,6 +34,22 @@ // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void* aux); + struct Handler { + Handler() = default; + Handler(TrapFnc f, const void* a, bool s) + : fnc(f), aux(reinterpret_cast<uintptr_t>(a)), safe(s) { + DCHECK(fnc); + } + + bool operator<(const Handler& that) const { + return std::tie(fnc, aux, safe) < std::tie(that.fnc, that.aux, that.safe); + } + + TrapFnc fnc = nullptr; + uintptr_t aux = 0; // Usually a pointer, but may be a smuggled int. + bool safe = false; + }; + TrapRegistry(const TrapRegistry&) = delete; TrapRegistry& operator=(const TrapRegistry&) = delete; @@ -40,7 +57,7 @@ // non-zero trap ID that uniquely identifies the tuple for the life // time of the trap registry. If the same tuple is registered // multiple times, the same value will be returned each time. - virtual uint16_t Add(TrapFnc fnc, const void* aux, bool safe) = 0; + virtual uint16_t Add(const Handler& handler) = 0; // EnableUnsafeTraps tries to enable unsafe traps and returns // whether it was successful. This is a one-way operation.
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc index f381216..7f262aa 100644 --- a/sandbox/linux/seccomp-bpf/trap.cc +++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -227,7 +227,7 @@ SECCOMP_PARM6(ctx)); #endif // defined(__mips__) } else { - const TrapKey& trap = trap_array_[info->si_errno - 1]; + const auto& trap = trap_array_[info->si_errno - 1]; if (!trap.safe) { SetIsInSigHandler(); } @@ -260,12 +260,8 @@ return; } -bool Trap::TrapKey::operator<(const TrapKey& o) const { - return std::tie(fnc, aux, safe) < std::tie(o.fnc, o.aux, o.safe); -} - -uint16_t Trap::Add(TrapFnc fnc, const void* aux, bool safe) { - if (!safe && !SandboxDebuggingAllowedByUser()) { +uint16_t Trap::Add(const Handler& handler) { + if (!handler.safe && !SandboxDebuggingAllowedByUser()) { // Unless the user set the CHROME_SANDBOX_DEBUGGING environment variable, // we never return an ErrorCode that is marked as "unsafe". This also // means, the BPF compiler will never emit code that allow unsafe system @@ -282,10 +278,6 @@ "is enabled"); } - // Each unique pair of TrapFnc and auxiliary data make up a distinct instance - // of a SECCOMP_RET_TRAP. - TrapKey key(fnc, aux, safe); - // We return unique identifiers together with SECCOMP_RET_TRAP. This allows // us to associate trap with the appropriate handler. The kernel allows us // identifiers in the range from 0 to SECCOMP_RET_DATA (0xFFFF). We want to @@ -295,7 +287,7 @@ // calls that might be async-signal-unsafe. // In order to do so, we store all of our traps in a C-style trap_array_. - TrapIds::const_iterator iter = trap_ids_.find(key); + auto iter = trap_ids_.find(handler); if (iter != trap_ids_.end()) { // We have seen this pair before. Return the same id that we assigned // earlier. @@ -328,8 +320,8 @@ // events. if (trap_array_size_ >= trap_array_capacity_) { trap_array_capacity_ += kCapacityIncrement; - TrapKey* old_trap_array = trap_array_; - TrapKey* new_trap_array = new TrapKey[trap_array_capacity_]; + auto* old_trap_array = trap_array_; + auto* new_trap_array = new TrapRegistry::Handler[trap_array_capacity_]; std::copy_n(old_trap_array, trap_array_size_, new_trap_array); trap_array_ = new_trap_array; @@ -341,8 +333,8 @@ } uint16_t id = trap_array_size_ + 1; - trap_ids_[key] = id; - trap_array_[trap_array_size_] = key; + trap_ids_[handler] = id; + trap_array_[trap_array_size_] = handler; trap_array_size_++; return id; }
diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h index 67df58c..60a1ead 100644 --- a/sandbox/linux/seccomp-bpf/trap.h +++ b/sandbox/linux/seccomp-bpf/trap.h
@@ -33,8 +33,7 @@ Trap(const Trap&) = delete; Trap& operator=(const Trap&) = delete; - uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override; - + uint16_t Add(const Handler& handler) override; bool EnableUnsafeTraps() override; // Registry returns the trap registry used by Trap's SIGSYS handler, @@ -46,18 +45,7 @@ static bool SandboxDebuggingAllowedByUser(); private: - struct TrapKey { - TrapKey() = default; - TrapKey(TrapFnc f, const void* a, bool s) - : fnc(f), aux(reinterpret_cast<uintptr_t>(a)), safe(s) {} - - bool operator<(const TrapKey&) const; - - TrapFnc fnc = nullptr; - uintptr_t aux = 0; // Usually a pointer, but may be a smuggled int. - bool safe = false; - }; - using TrapIds = std::map<TrapKey, uint16_t>; + using HandlerToIdMap = std::map<TrapRegistry::Handler, uint16_t>; // Our constructor is private. A shared global instance is created // automatically as needed. @@ -73,18 +61,20 @@ // dumps. void SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx) __attribute__((noinline)); + // We have a global singleton that handles all of our SIGSYS traps. This // variable must never be deallocated after it has been set up initially, as // there is no way to reset in-kernel BPF filters that generate SIGSYS // events. static Trap* global_trap_; - TrapIds trap_ids_; // Maps from TrapKeys to numeric ids - // Array of TrapKeys indexed by ids. + HandlerToIdMap trap_ids_; // Maps from Handlers to numeric ids + + // Array of handlers indexed by ids. // - // This is not a raw_ptr as it is an owning pointer anyway, and is meant to be - // used between normal code and signal handlers. - RAW_PTR_EXCLUSION TrapKey* trap_array_ = nullptr; + // This is not a raw_ptr as it is an owning pointer anyway, and needs + // to be safe for signal handlers. + RAW_PTR_EXCLUSION TrapRegistry::Handler* trap_array_ = nullptr; size_t trap_array_size_ = 0; // Currently used size of array size_t trap_array_capacity_ = 0; // Currently allocated capacity of array bool has_unsafe_traps_ = false; // Whether unsafe traps have been enabled
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index de04861b..5ad8138 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -325,7 +325,7 @@ BASE_FEATURE(kPrefetchNoVarySearch, "PrefetchNoVarySearch", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kPrerender2ContentSecurityPolicyExtensions, "Prerender2ContentSecurityPolicyExtensions",
diff --git a/services/network/public/cpp/parsed_headers.cc b/services/network/public/cpp/parsed_headers.cc index f1f24c7..a8fa17e 100644 --- a/services/network/public/cpp/parsed_headers.cc +++ b/services/network/public/cpp/parsed_headers.cc
@@ -101,6 +101,10 @@ } } + // We're not checking that PrefetchNoVarySearch is enabled on the + // renderer side through the Origin Trial, as the network service + // doesn't know anything about blink. + // The code here only parses the No-Vary-Search header if it is present. if (base::FeatureList::IsEnabled(network::features::kPrefetchNoVarySearch)) parsed_headers->no_vary_search = ParseNoVarySearch(*headers);
diff --git a/services/network/public/cpp/parsed_headers_unittest.cc b/services/network/public/cpp/parsed_headers_unittest.cc index 9367be2..63d4e1d 100644 --- a/services/network/public/cpp/parsed_headers_unittest.cc +++ b/services/network/public/cpp/parsed_headers_unittest.cc
@@ -32,7 +32,16 @@ class NoVarySearchPrefetchDisabledTest : public ::testing::Test, - public ::testing::WithParamInterface<base::StringPiece> {}; + public ::testing::WithParamInterface<base::StringPiece> { + public: + NoVarySearchPrefetchDisabledTest() { + scoped_feature_list_.InitAndDisableFeature( + network::features::kPrefetchNoVarySearch); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; TEST_P(NoVarySearchPrefetchDisabledTest, ParsingNVSReturnsDefaultURLVariance) { TestNVSDefaultURLVariance(GetParam());
diff --git a/services/network/web_transport.cc b/services/network/web_transport.cc index a0e1ac53..2ccb558 100644 --- a/services/network/web_transport.cc +++ b/services/network/web_transport.cc
@@ -217,7 +217,7 @@ void Send() { MaySendFin(); - while (outgoing_ && outgoing_->CanWrite()) { + while (readable_ && outgoing_ && outgoing_->CanWrite()) { const void* data = nullptr; uint32_t available = 0; MojoResult result = readable_->BeginReadData( @@ -250,7 +250,7 @@ } void MaySendFin() { - if (!outgoing_) { + if (!readable_ || !outgoing_) { return; } if (!has_seen_end_of_pipe_for_readable_ || !has_received_fin_from_client_) {
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index abc3086..50670b75 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -220,6 +220,9 @@ // skia changes to implement new api is completed. #define SK_USE_LEGACY_VMA_MEMORY_QUERY +// Temporary until web tests can be rebaselined (skbug.com/13752) +#define SK_DISABLE_RASTER_PIPELINE_SAMPLING_FIXES + ///////////////////////// Imported from BUILD.gn and skia_common.gypi /* In some places Skia can use static initializers for global initialization,
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index ad0ef524..33b2164 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -361,9 +361,8 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "device_os": "MASTER", "device_os_flavor": "google", - "device_type": "wembley", + "device_type": "wembley_2GB", "os": "Android", "pool": "chrome.tests.perf" }
diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json index 66122af05..38ffd154 100644 --- a/testing/buildbot/client.v8.fyi.json +++ b/testing/buildbot/client.v8.fyi.json
@@ -514,6 +514,41 @@ }, { "args": [ + "mediapipe", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--stable-jobs", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=passthrough --use-gl=angle" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "mediapipe_passthrough_tests", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ "pixel", "--show-stdout", "--browser=release", @@ -629,13 +664,96 @@ }, { "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--stable-jobs", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-vulkan=native --disable-vulkan-fallback-to-gl-for-testing --enable-features=Vulkan --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough", + "--dont-restore-color-profile-after-test", + "--test-machine-name", + "${buildername}", + "--git-revision=${got_cr_revision}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "vulkan_pixel_skia_gold_test", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl2_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--stable-jobs", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json", + "--jobs=4" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl2_conformance_gl_passthrough_tests", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ "webgl1_conformance", "--show-stdout", "--browser=release", "--passthrough", "-v", "--stable-jobs", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", "--jobs=4" ], @@ -644,7 +762,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "webgl_conformance_tests", + "name": "webgl_conformance_gl_passthrough_tests", "resultdb": { "enable": true, "has_native_resultdb_integration": true
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index f982529..8a4ae8b 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3658,6 +3658,17 @@ 'VR Linux', ], }, + 'vulkan_pixel_skia_gold_test': { + 'replacements': { + # The V8 builders pass the V8 revision for ${got_revision}, so instead + # use ${got_cr_revision}, which is only set on the V8 bots. + 'Linux V8 FYI Release (NVIDIA)': { + 'args': { + '--git-revision': '${got_cr_revision}', + }, + }, + }, + }, 'wayland_client_perftests': { 'remove_from': [ 'linux-chromeos-dbg', # https://crbug.com/859307
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e10483b..eb0efd105 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -6318,7 +6318,7 @@ 'linux_nvidia_gtx_1660_stable', ], 'test_suites': { - 'gpu_telemetry_tests': 'gpu_v8_desktop_passthrough_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_release_vulkan_telemetry_tests', }, }, 'Linux V8 FYI Release - pointer compression (NVIDIA)': {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index efb322c..40e21512 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -775,6 +775,33 @@ "enable_features": [ "AssistMultiWord" ] + }, + { + "name": "EnabledWithGboard_20221213", + "params": { + "group": "gboard" + }, + "enable_features": [ + "AssistMultiWord" + ] + }, + { + "name": "EnabledWithGboardD_20221213", + "params": { + "group": "gboard_d" + }, + "enable_features": [ + "AssistMultiWord" + ] + }, + { + "name": "EnabledWithGboardE_20221213", + "params": { + "group": "gboard_e" + }, + "enable_features": [ + "AssistMultiWord" + ] } ] } @@ -904,6 +931,21 @@ ] } ], + "AutocorrectByDefault": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled_20221208", + "enable_features": [ + "AutocorrectByDefault" + ] + } + ] + } + ], "AutofillAcrossIframes": [ { "platforms": [ @@ -3174,30 +3216,6 @@ ] } ], - "ContextualPageActions": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "action_chip": "true", - "action_chip_time_ms": "6000", - "action_chip_with_different_color": "false", - "enable_ui": "true", - "reader_mode_session_rate_limiting": "true" - }, - "enable_features": [ - "ContextualPageActionPriceTracking", - "ContextualPageActionReaderMode", - "ContextualPageActions" - ] - } - ] - } - ], "CrOSBluetoothLLPrivacy": [ { "platforms": [ @@ -5410,21 +5428,6 @@ ] } ], - "HttpsOnlyMode": [ - { - "platforms": [ - "ios" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "HttpsOnlyMode" - ] - } - ] - } - ], "IOSAutofillBranding": [ { "platforms": [ @@ -7391,7 +7394,7 @@ { "name": "Enabled", "params": { - "omnibox_answer_color_reversal_countries": "zh-CN,zh-TW,ja-JP,ko-KR", + "omnibox_answer_color_reversal_countries": "ja-JP,ko-KR,zh-CN,zh-TW", "omnibox_answer_color_reversal_finance_only": "true" }, "enable_features": [
diff --git a/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom b/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom index 99d0cc2..5acb443 100644 --- a/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom +++ b/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom
@@ -22,6 +22,8 @@ // sent. UpdateSpeculationCandidates( array<SpeculationCandidate> candidates); + // Enables matching prefetches according to No-Vary-Search response headers. + EnableNoVarySearchSupport(); }; // The action that is proposed.
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc index 8de39af4..ae9eb2e50 100644 --- a/third_party/blink/renderer/core/fetch/request.cc +++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -793,6 +793,14 @@ input_request->BodyBuffer()->CloseAndLockAndDisturb(); } + // Back/forward-cache is interested in use of the "Authorization" header. + if (r->getHeaders() && + r->getHeaders()->has("Authorization", exception_state)) { + execution_context->GetScheduler()->RegisterStickyFeature( + SchedulingPolicy::Feature::kAuthorizationHeader, + {SchedulingPolicy::DisableBackForwardCache()}); + } + // "Return |r|." return r; }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc index 0955b9b..f38352a 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -512,9 +512,9 @@ fixedpos_containing_block_offset = converter.ToLogical( multicol_info->fixedpos_containing_block.Offset(), fixedpos_containing_block_fragment->Size()); - fixedpos_containing_block_rel_offset = converter.ToLogical( + fixedpos_containing_block_rel_offset = RelativeInsetToLogical( multicol_info->fixedpos_containing_block.RelativeOffset(), - fixedpos_containing_block_fragment->Size()); + GetWritingDirection()); fixedpos_containing_block_rel_offset += relative_offset; // We want the fixedpos containing block offset to be the offset from // the containing block to the top of the fragmentation context root, @@ -612,9 +612,8 @@ LogicalOffset containing_block_offset = converter.ToLogical(descendant.containing_block.Offset(), containing_block_fragment->Size()); - LogicalOffset containing_block_rel_offset = - converter.ToLogical(descendant.containing_block.RelativeOffset(), - containing_block_fragment->Size()); + LogicalOffset containing_block_rel_offset = RelativeInsetToLogical( + descendant.containing_block.RelativeOffset(), GetWritingDirection()); containing_block_rel_offset += relative_offset; if (!fragment.IsFragmentainerBox()) containing_block_offset += offset; @@ -658,9 +657,9 @@ fixedpos_containing_block_offset = converter.ToLogical(descendant.fixedpos_containing_block.Offset(), fixedpos_containing_block_fragment->Size()); - fixedpos_containing_block_rel_offset = converter.ToLogical( + fixedpos_containing_block_rel_offset = RelativeInsetToLogical( descendant.fixedpos_containing_block.RelativeOffset(), - fixedpos_containing_block_fragment->Size()); + GetWritingDirection()); fixedpos_containing_block_rel_offset += relative_offset; if (!fragment.IsFragmentainerBox()) fixedpos_containing_block_offset += offset;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc index b1e7189..228df94 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -1016,9 +1016,9 @@ fixedpos_containing_block_offset = converter.ToLogical(descendant.fixedpos_containing_block.Offset(), fixedpos_containing_block_fragment->Size()); - fixedpos_containing_block_rel_offset = converter.ToLogical( + fixedpos_containing_block_rel_offset = RelativeInsetToLogical( descendant.fixedpos_containing_block.RelativeOffset(), - fixedpos_containing_block_fragment->Size()); + writing_direction); } NGInlineContainer<LogicalOffset> inline_container(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h index 7295d86..f1ffccc5 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
@@ -380,6 +380,20 @@ MulticolCollection multicols_with_pending_oofs; }; +inline PhysicalOffset RelativeInsetToPhysical( + LogicalOffset relative_inset, + WritingDirectionMode writing_direction) { + return relative_inset.ConvertToPhysical(writing_direction, PhysicalSize(), + PhysicalSize()); +} + +inline LogicalOffset RelativeInsetToLogical( + PhysicalOffset relative_inset, + WritingDirectionMode writing_direction) { + return relative_inset.ConvertToLogical(writing_direction, PhysicalSize(), + PhysicalSize()); +} + } // namespace blink WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index cc03ca42..401c132 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -102,8 +102,8 @@ return NGContainingBlock<PhysicalOffset>( containing_block.Offset().ConvertToPhysical( builder->Style().GetWritingDirection(), outer_size, inner_size), - containing_block.RelativeOffset().ConvertToPhysical( - builder->Style().GetWritingDirection(), outer_size, inner_size), + RelativeInsetToPhysical(containing_block.RelativeOffset(), + builder->Style().GetWritingDirection()), containing_block.Fragment(), containing_block.IsInsideColumnSpanner(), containing_block.RequiresContentBeforeBreaking()); }
diff --git a/third_party/blink/renderer/core/loader/threadable_loader.cc b/third_party/blink/renderer/core/loader/threadable_loader.cc index b56f74b8..b0377b28 100644 --- a/third_party/blink/renderer/core/loader/threadable_loader.cc +++ b/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -112,13 +112,6 @@ } void ThreadableLoader::Start(ResourceRequest request) { - // Back/forward-cache is interested in use of the "Authorization" header. - if (request.HttpHeaderField("Authorization")) { - execution_context_->GetScheduler()->RegisterStickyFeature( - SchedulingPolicy::Feature::kAuthorizationHeader, - {SchedulingPolicy::DisableBackForwardCache()}); - } - const auto request_context = request.GetRequestContext(); if (request.GetMode() == network::mojom::RequestMode::kNoCors) { SECURITY_CHECK(cors::IsNoCorsAllowedContext(request_context));
diff --git a/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc b/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc index b3e7c1c4..ae25b305 100644 --- a/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc +++ b/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
@@ -75,8 +75,6 @@ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeCanvas2DLayerBridge(size); element->SetResourceProviderForTesting(nullptr, std::move(bridge), size); ASSERT_EQ(context, element->RenderingContext()); - ASSERT_TRUE(context->IsComposited()); - ASSERT_TRUE(element->IsAccelerated()); // Force the page to paint. element->PreFinalizeFrame(); @@ -84,6 +82,9 @@ element->PostFinalizeFrame(); UpdateAllLifecyclePhasesForTest(); + ASSERT_TRUE(context->IsComposited()); + ASSERT_TRUE(element->IsAccelerated()); + // Fetch the layer associated with the <canvas>, and check that it was // correctly configured in the layer tree. const cc::Layer* layer = context->CcLayer();
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 9336ba1..b797ed6 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -4240,6 +4240,10 @@ const LayoutObject& object) { DCHECK(CanDoDeferredTransformNodeUpdate(object)); + // GeometryMapper depends on paint properties. This is typically called from + // the PrePaintTreeWalk, but we may skip that for this direct update. + GeometryMapper::ClearCache(); + auto& box = To<LayoutBox>(object); PhysicalSize size = PhysicalSize(box.Size()); FragmentData* fragment_data = &object.GetMutableForPainting().FirstFragment();
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index fb1a0e1f..3c67a49 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -87,12 +87,6 @@ .PaintProperties(); } -const GeometryMapperTransformCache& -PaintPropertyTreeBuilderTest::GetTransformCache( - const TransformPaintPropertyNode& transform) { - return transform.GetTransformCache(); -} - void PaintPropertyTreeBuilderTest::SetUp() { EnableCompositing(); RenderingTest::SetUp(); @@ -7383,30 +7377,4 @@ EXPECT_FALSE(properties->Effect()->OutputClip()); } -TEST_P(PaintPropertyTreeBuilderTest, TransformChangesInvalidateGeometryMapper) { - SetBodyInnerHTML(R"HTML( - <style>#div { width:10px; height:10px; transform:translateX(9px); }</style> - <div id="div" style="transform: translateX(5px);"></div> - )HTML"); - - const auto* properties = PaintPropertiesForElement("div"); - const auto& transform_cache = GetTransformCache(*properties->Transform()); - EXPECT_TRUE(transform_cache.IsValid()); - - // Change the transform and ensure the geometry mapper cache is invalidated. - auto* div = GetDocument().getElementById("div"); - div->removeAttribute(html_names::kStyleAttr); - UpdateAllLifecyclePhasesExceptPaint(); - EXPECT_FALSE(transform_cache.IsValid()); - - UpdateAllLifecyclePhasesForTest(); - EXPECT_TRUE(transform_cache.IsValid()); - - // Make a color change and ensure the geometry mapper cache is not - // invalidated. - div->setAttribute(html_names::kStyleAttr, "background: green;"); - UpdateAllLifecyclePhasesExceptPaint(); - EXPECT_TRUE(transform_cache.IsValid()); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h index 419bcbf..76e25ed2 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
@@ -13,7 +13,6 @@ namespace blink { class ClipPaintPropertyNode; -class GeometryMapperTransformCache; class ScrollPaintPropertyNode; class TransformPaintPropertyNode; struct PhysicalOffset; @@ -42,9 +41,6 @@ const ObjectPaintProperties* PaintPropertiesForElement(const char* name); - const GeometryMapperTransformCache& GetTransformCache( - const TransformPaintPropertyNode&); - static unsigned NumFragments(const LayoutObject* obj) { unsigned count = 0; auto* fragment = &obj->FirstFragment();
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index 6829a72..9d6f47a 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -27,6 +27,7 @@ #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_property_tree_printer.h" +#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -55,10 +56,11 @@ PrePaintTreeWalkContext context; -#if DCHECK_IS_ON() - bool needed_tree_builder_context_update = + // GeometryMapper depends on paint properties. + bool needs_tree_builder_context_update = NeedsTreeBuilderContextUpdate(root_frame_view, context); -#endif + if (needs_tree_builder_context_update) + GeometryMapper::ClearCache(); VisualViewport& visual_viewport = root_frame_view.GetPage()->GetVisualViewport(); @@ -72,7 +74,7 @@ paint_invalidator_.ProcessPendingDelayedPaintInvalidations(); #if DCHECK_IS_ON() - if (needed_tree_builder_context_update && VLOG_IS_ON(1)) + if (needs_tree_builder_context_update && VLOG_IS_ON(1)) ShowAllPropertyTrees(root_frame_view); #endif
diff --git a/third_party/blink/renderer/core/speculation_rules/build.gni b/third_party/blink/renderer/core/speculation_rules/build.gni index 784aa8c..5a40c52 100644 --- a/third_party/blink/renderer/core/speculation_rules/build.gni +++ b/third_party/blink/renderer/core/speculation_rules/build.gni
@@ -18,6 +18,7 @@ ] blink_core_tests_speculation_rules = [ + "no_vary_search_origin_trial_test.cc", "speculation_rule_set_test.cc", "speculation_rules_header_test.cc", "speculation_rules_origin_trial_test.cc",
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc index 53343d46..46920683 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc +++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -313,6 +313,7 @@ auto* execution_context = GetSupplementable()->GetExecutionContext(); if (!execution_context) return; + has_pending_update_ = true; execution_context->GetAgent()->event_loop()->EnqueueMicrotask( WTF::BindOnce(&DocumentSpeculationRules::UpdateSpeculationCandidates, @@ -389,6 +390,11 @@ // Add candidates derived from document rule predicates. AddLinkBasedSpeculationCandidates(candidates); + if (!sent_is_part_of_no_vary_search_trial_ && + RuntimeEnabledFeatures::NoVarySearchPrefetchEnabled(execution_context)) { + sent_is_part_of_no_vary_search_trial_ = true; + host->EnableNoVarySearchSupport(); + } host->UpdateSpeculationCandidates(std::move(candidates)); }
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h index ebe2986..51836fb 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h +++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h
@@ -106,6 +106,7 @@ bool has_pending_update_ = false; bool initialized_ = false; + bool sent_is_part_of_no_vary_search_trial_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/no_vary_search_origin_trial_test.cc b/third_party/blink/renderer/core/speculation_rules/no_vary_search_origin_trial_test.cc new file mode 100644 index 0000000..fe1b2f88 --- /dev/null +++ b/third_party/blink/renderer/core/speculation_rules/no_vary_search_origin_trial_test.cc
@@ -0,0 +1,141 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> + +#include "base/run_loop.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/features_generated.h" +#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h" +#include "third_party/blink/public/platform/web_url_response.h" +#include "third_party/blink/public/web/web_navigation_params.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/core/html/html_head_element.h" +#include "third_party/blink/renderer/core/html/html_script_element.h" +#include "third_party/blink/renderer/core/speculation_rules/stub_speculation_host.h" +#include "third_party/blink/renderer/core/testing/dummy_page_holder.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { +namespace { + +void CommitTestNavigation( + LocalFrame& frame, + const KURL& url, + const Vector<std::pair<String, String>>& response_headers) { + auto navigation_params = std::make_unique<WebNavigationParams>(); + navigation_params->url = url; + WebNavigationParams::FillStaticResponse(navigation_params.get(), "text/html", + "UTF-8", "<!DOCTYPE html>"); + for (const auto& [header, value] : response_headers) + navigation_params->response.AddHttpHeaderField(header, value); + frame.Loader().CommitNavigation(std::move(navigation_params), nullptr); +} + +HTMLScriptElement* InsertSpeculationRules(Document& document, + const String& speculation_script) { + HTMLScriptElement* script = + MakeGarbageCollected<HTMLScriptElement>(document, CreateElementFlags()); + script->setAttribute(html_names::kTypeAttr, "SpEcUlAtIoNrUlEs"); + script->setText(speculation_script); + document.head()->appendChild(script); + return script; +} + +// Generated by: +// tools/origin_trials/generate_token.py --version 3 --expire-days 3650 +// https://speculationrules.test NoVarySearchPrefetch +// Token details: +// Version: 3 +// Origin: https://speculationrules.test:443 +// Is Subdomain: None +// Is Third Party: None +// Usage Restriction: None +// Feature: NoVarySearchPrefetch +// Expiry: 1985830923 (2032-12-05 03:42:03 UTC) +// Signature (Base64): +// fFyfaSvsR9K2Wqm/Nvo3KWQsdLUaEGHZj+La5IUXRK/LdCrvtdggLOtoQiEZwkL8rJJz3S+/Mfa6I/LOY0KOCA== +[[maybe_unused]] constexpr char kNoVarySearchPrefetchToken[] = + "A3xcn2kr7EfStlqpvzb6NylkLHS1GhBh2Y/i2uSFF0Svy3Qq77XYICzraEIhGcJC/" + "KySc90vvzH2uiPyzmNCjggAAABoeyJvcmlnaW4iOiAiaHR0cHM6Ly9zcGVjdWxhdGlvbnJ1bGV" + "zLnRlc3Q6NDQzIiwgImZlYXR1cmUiOiAiTm9WYXJ5U2VhcmNoUHJlZmV0Y2giLCAiZXhwaXJ5I" + "jogMTk4NTgzMDkyM30="; + +TEST(PrefetchNoVarySearchOriginTrialTest, CanEnableFromToken) { + ScopedTestOriginTrialPolicy using_test_keys; + DummyPageHolder page_holder; + LocalFrame& frame = page_holder.GetFrame(); + + CommitTestNavigation(frame, KURL("https://speculationrules.test/"), + {{"Origin-Trial", kNoVarySearchPrefetchToken}}); + + // This should have enabled the origin trial and all its dependent features. + EXPECT_TRUE( + RuntimeEnabledFeatures::NoVarySearchPrefetchEnabled(frame.DomWindow())); + EXPECT_TRUE(RuntimeEnabledFeatures::SpeculationRulesPrefetchProxyEnabled( + frame.DomWindow())); +} + +TEST(PrefetchNoVarySearchOriginTrialTest, DoesNotEnableWithoutToken) { + ScopedTestOriginTrialPolicy using_test_keys; + DummyPageHolder page_holder; + LocalFrame& frame = page_holder.GetFrame(); + + // Do not send the Origin-Trial token. + CommitTestNavigation(frame, KURL("https://speculationrules.test/"), {}); + + // This should not have enabled the origin trial. + EXPECT_FALSE( + RuntimeEnabledFeatures::NoVarySearchPrefetchEnabled(frame.DomWindow())); +} + +void NoVarySearchPrefetchEnabledTest(StubSpeculationHost& speculation_host) { + DummyPageHolder page_holder; + LocalFrame& frame = page_holder.GetFrame(); + frame.GetSettings()->SetScriptEnabled(true); + + auto& broker = frame.DomWindow()->GetBrowserInterfaceBroker(); + broker.SetBinderForTesting( + mojom::blink::SpeculationHost::Name_, + WTF::BindRepeating(&StubSpeculationHost::BindUnsafe, + WTF::Unretained(&speculation_host))); + + base::RunLoop run_loop; + speculation_host.SetDoneClosure(run_loop.QuitClosure()); + + const String speculation_script = + R"({"prefetch": [ + {"source": "list", + "urls": ["https://example.com/foo"], + "requires": ["anonymous-client-ip-when-cross-origin"]} + ]})"; + InsertSpeculationRules(page_holder.GetDocument(), speculation_script); + run_loop.Run(); + + broker.SetBinderForTesting(mojom::blink::SpeculationHost::Name_, {}); +} + +TEST(PrefetchNoVarySearchOriginTrialTest, + EnabledNoVarySearchPrefetchInBrowser) { + ScopedNoVarySearchPrefetchForTest enable_no_vary_search_prefetch_{true}; + StubSpeculationHost speculation_host; + NoVarySearchPrefetchEnabledTest(speculation_host); + EXPECT_TRUE(speculation_host.sent_no_vary_search_support_to_browser()); +} + +TEST(PrefetchNoVarySearchOriginTrialTest, + DoNotEnableNoVarySearchPrefetchInBrowser) { + StubSpeculationHost speculation_host; + NoVarySearchPrefetchEnabledTest(speculation_host); + EXPECT_FALSE(speculation_host.sent_no_vary_search_support_to_browser()); +} + +} // namespace +} // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.cc b/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.cc index 4d6bfdd..21fef772 100644 --- a/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.cc +++ b/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.cc
@@ -32,4 +32,8 @@ std::move(done_closure_).Run(); } +void StubSpeculationHost::EnableNoVarySearchSupport() { + sent_no_vary_search_support_to_browser_ = true; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.h b/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.h index 41c5f4f2..7226199 100644 --- a/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.h +++ b/third_party/blink/renderer/core/speculation_rules/stub_speculation_host.h
@@ -37,13 +37,21 @@ // mojom::blink::SpeculationHost. void UpdateSpeculationCandidates(Candidates candidates) override; + // mojom::blink::SpeculationHost. + void EnableNoVarySearchSupport() override; + void OnConnectionLost(); bool is_bound() const { return receiver_.is_bound(); } + bool sent_no_vary_search_support_to_browser() const { + return sent_no_vary_search_support_to_browser_; + } + private: mojo::Receiver<SpeculationHost> receiver_{this}; Vector<mojom::blink::SpeculationCandidatePtr> candidates_; + bool sent_no_vary_search_support_to_browser_ = false; base::OnceClosure done_closure_; base::RepeatingCallback<void(const Candidates&)> candidates_updated_callback_; };
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc index 0f343820a..f998630 100644 --- a/third_party/blink/renderer/core/timing/performance.cc +++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -483,41 +483,49 @@ if (!window) { return entries; } - LocalFrame* parent_frame = window->GetFrame(); - if (!parent_frame) { + LocalFrame* root_frame = window->GetFrame(); + if (!root_frame) { return entries; } + const SecurityOrigin* root_origin = + ExecutionContext::From(script_state)->GetSecurityOrigin(); HeapDeque<Member<Frame>> queue; - queue.push_back(parent_frame); + queue.push_back(root_frame); while (!queue.empty()) { Frame* current_frame = queue.TakeFirst(); - if (LocalFrame* local_frame = DynamicTo<LocalFrame>(current_frame); - local_frame && !local_frame->IsCrossOriginToNearestMainFrame()) { + if (LocalFrame* local_frame = DynamicTo<LocalFrame>(current_frame)) { // Get the Performance object from the current frame. LocalDOMWindow* current_window = local_frame->DomWindow(); // As we verified that the frame this was called with is not detached when // entring this loop, we can assume that all its children are also not // detached, and hence have a window object. DCHECK(current_window); - WindowPerformance* window_performance = - DOMWindowPerformance::performance(*current_window); - // Get the performance entries based on entry_type input. - PerformanceEntryVector current_entries; - if (entry_type.IsNull()) { - current_entries = window_performance->GetEntriesForCurrentFrame(); - } else { - current_entries = - window_performance->GetEntriesByTypeForCurrentFrame(entry_type); + // Validate that the child frame's origin is the same as the root + // frame. + const SecurityOrigin* current_origin = + current_window->GetSecurityOrigin(); + if (root_origin->IsSameOriginWith(current_origin)) { + WindowPerformance* window_performance = + DOMWindowPerformance::performance(*current_window); + + // Get the performance entries based on entry_type input. + PerformanceEntryVector current_entries; + if (entry_type.IsNull()) { + current_entries = window_performance->GetEntriesForCurrentFrame(); + } else { + current_entries = + window_performance->GetEntriesByTypeForCurrentFrame(entry_type); + } + + entries.AppendVector(current_entries); } - - entries.AppendVector(current_entries); } - // Add both Local and Remote Frames to the queue. + // Add both Local and Remote Frame children to the queue. for (Frame* child = current_frame->FirstChild(); child; child = child->NextSibling()) { queue.push_back(child);
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index 020b4d9..e46a8fcb 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -189,7 +189,10 @@ } bool CanvasRenderingContext2D::IsComposited() const { - return IsAccelerated(); + if (Canvas2DLayerBridge* layer_bridge = canvas()->GetCanvas2DLayerBridge()) { + return layer_bridge->IsComposited(); + } + return false; } void CanvasRenderingContext2D::Stop() {
diff --git a/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc b/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc index 08b2f69a..661b0cea 100644 --- a/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc +++ b/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc
@@ -32,7 +32,6 @@ #include "third_party/blink/renderer/modules/webaudio/audio_buffer.h" #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h" #include "third_party/blink/renderer/platform/audio/audio_bus.h" -#include "third_party/blink/renderer/platform/audio/audio_file_reader.h" #include "third_party/blink/renderer/platform/bindings/cross_thread_copier.h" #include "third_party/blink/renderer/platform/bindings/exception_context.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -79,7 +78,7 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner, const ExceptionContext& exception_context) { DCHECK(!IsMainThread()); - scoped_refptr<AudioBus> bus = CreateBusFromInMemoryAudioFile( + scoped_refptr<AudioBus> bus = AudioBus::CreateBusFromInMemoryAudioFile( audio_data->Data(), audio_data->ByteLength(), false, sample_rate); // Decoding is finished, but we need to do the callbacks on the main thread.
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc index 5933e32..2e03280 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
@@ -33,7 +33,6 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_buffer_options.h" #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h" #include "third_party/blink/renderer/platform/audio/audio_bus.h" -#include "third_party/blink/renderer/platform/audio/audio_file_reader.h" #include "third_party/blink/renderer/platform/audio/audio_utilities.h" #include "third_party/blink/renderer/platform/bindings/exception_messages.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 9c01b81..7c8fc318 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -304,7 +304,6 @@ "audio/audio_dsp_kernel.h", "audio/audio_dsp_kernel_processor.cc", "audio/audio_dsp_kernel_processor.h", - "audio/audio_file_reader.h", "audio/audio_io_callback.h", "audio/audio_processor.cc", "audio/audio_processor.h",
diff --git a/third_party/blink/renderer/platform/audio/audio_bus.cc b/third_party/blink/renderer/platform/audio/audio_bus.cc index 9a4d923..e8a48f1 100644 --- a/third_party/blink/renderer/platform/audio/audio_bus.cc +++ b/third_party/blink/renderer/platform/audio/audio_bus.cc
@@ -37,7 +37,6 @@ #include "base/ranges/algorithm.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_audio_bus.h" -#include "third_party/blink/renderer/platform/audio/audio_file_reader.h" #include "third_party/blink/renderer/platform/audio/denormal_disabler.h" #include "third_party/blink/renderer/platform/audio/sinc_resampler.h" #include "third_party/blink/renderer/platform/audio/vector_math.h" @@ -744,10 +743,11 @@ sample_rate); } -scoped_refptr<AudioBus> CreateBusFromInMemoryAudioFile(const void* data, - size_t data_size, - bool mix_to_mono, - float sample_rate) { +scoped_refptr<AudioBus> AudioBus::CreateBusFromInMemoryAudioFile( + const void* data, + size_t data_size, + bool mix_to_mono, + float sample_rate) { scoped_refptr<AudioBus> audio_bus = DecodeAudioFileData(static_cast<const char*>(data), data_size); if (!audio_bus.get()) {
diff --git a/third_party/blink/renderer/platform/audio/audio_bus.h b/third_party/blink/renderer/platform/audio/audio_bus.h index 3290de3..39c64c0e 100644 --- a/third_party/blink/renderer/platform/audio/audio_bus.h +++ b/third_party/blink/renderer/platform/audio/audio_bus.h
@@ -70,6 +70,16 @@ uint32_t length, bool allocate = true); + // Pass in 0.0 for sampleRate to use the file's sample-rate, otherwise a + // sample-rate conversion to the requested sampleRate will be made (if it + // doesn't already match the file's sample-rate). The created buffer will + // have its sample-rate set correctly to the result. + static scoped_refptr<AudioBus> CreateBusFromInMemoryAudioFile( + const void* data, + size_t data_size, + bool mix_to_mono, + float sample_rate); + AudioBus(const AudioBus&) = delete; AudioBus& operator=(const AudioBus&) = delete;
diff --git a/third_party/blink/renderer/platform/audio/audio_file_reader.h b/third_party/blink/renderer/platform/audio/audio_file_reader.h deleted file mode 100644 index 8a499b79..0000000 --- a/third_party/blink/renderer/platform/audio/audio_file_reader.h +++ /dev/null
@@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_AUDIO_FILE_READER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_AUDIO_FILE_READER_H_ - -#include "base/memory/scoped_refptr.h" -#include "third_party/blink/renderer/platform/platform_export.h" - -namespace blink { - -class AudioBus; - -// For both create functions: -// Pass in 0.0 for sampleRate to use the file's sample-rate, otherwise a -// sample-rate conversion to the requested sampleRate will be made (if it -// doesn't already match the file's sample-rate). The created buffer will have -// its sample-rate set correctly to the result. - -PLATFORM_EXPORT scoped_refptr<AudioBus> CreateBusFromInMemoryAudioFile( - const void* data, - size_t data_size, - bool mix_to_mono, - float sample_rate); - -PLATFORM_EXPORT scoped_refptr<AudioBus> CreateBusFromAudioFile( - const char* file_path, - bool mix_to_mono, - float sample_rate); - -// May pass in 0.0 for sampleRate in which case it will use the AudioBus's -// sampleRate -PLATFORM_EXPORT void WriteBusToAudioFile(AudioBus* bus, - const char* file_path, - double file_sample_rate); - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_AUDIO_FILE_READER_H_
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc index 262d8ac..ceeb6c8 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -152,6 +152,25 @@ return ShouldAccelerate(); } +bool Canvas2DLayerBridge::IsComposited() const { + if (IsHibernating()) { + return false; + } + + if (UNLIKELY(!resource_host_)) { + return false; + } + + CanvasResourceProvider* resource_provider = + resource_host_->ResourceProvider(); + if (UNLIKELY(!resource_provider)) { + return false; + } + + return resource_provider->SupportsDirectCompositing() && + !resource_host_->LowLatencyEnabled(); +} + static void HibernateWrapper(base::WeakPtr<Canvas2DLayerBridge> bridge, base::TimeTicks /*idleDeadline*/) { if (bridge) { @@ -268,14 +287,13 @@ if (resource_provider && resource_provider->IsValid()) { #if DCHECK_IS_ON() - // If resource provider is accelerated, a layer should already exist. + // If resource provider is composited, a layer should already exist. // unless this is a canvas in low latency mode. // If this DCHECK fails, it probably means that // CanvasRenderingContextHost::GetOrCreateCanvasResourceProvider() was // called on a 2D context before this function. - if (IsAccelerated()) { - DCHECK(!!layer_ || - (resource_host_ && resource_host_->LowLatencyEnabled())); + if (IsComposited()) { + DCHECK(!!layer_); } #endif return resource_provider; @@ -310,7 +328,7 @@ // TODO crbug/1090081: Check possibility to move DidDraw inside Clear. DidDraw(); - if (IsAccelerated() && !layer_) { + if (IsComposited() && !layer_) { layer_ = cc::TextureLayer::CreateForMailbox(this); layer_->SetIsDrawable(true); layer_->SetHitTestable(true); @@ -320,6 +338,7 @@ cc::PaintFlags::FilterQuality::kNone); layer_->SetHDRConfiguration(resource_host_->GetHDRMode(), resource_host_->GetHDRMetadata()); + layer_->SetFlipped(!resource_provider->IsOriginTopLeft()); } // After the page becomes visible and successfully restored the canvas // resource provider, set |lose_context_in_background_| to false. @@ -747,7 +766,7 @@ constexpr unsigned kMaxCanvasAnimationBacklog = 2; if (frames_since_last_commit_ >= static_cast<int>(kMaxCanvasAnimationBacklog)) { - if (IsAccelerated() && !rate_limiter_) { + if (IsComposited() && !rate_limiter_) { rate_limiter_ = std::make_unique<SharedContextRateLimiter>( kMaxCanvasAnimationBacklog); } @@ -759,8 +778,9 @@ } void Canvas2DLayerBridge::DoPaintInvalidation(const gfx::Rect& dirty_rect) { - if (layer_ && raster_mode_ == RasterMode::kGPU) + if (layer_ && IsComposited()) { layer_->SetNeedsDisplayRect(dirty_rect); + } } scoped_refptr<StaticBitmapImage> Canvas2DLayerBridge::NewImageSnapshot() {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h index af3cb0fe..66a9272 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -95,6 +95,8 @@ virtual void DidRestoreCanvasMatrixClipStack(cc::PaintCanvas*) {} virtual bool IsAccelerated() const; + bool IsComposited() const; + // This may recreate CanvasResourceProvider cc::PaintCanvas* GetPaintCanvas(); bool IsValid();
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc index d620c77..3160461 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -1019,4 +1019,29 @@ EXPECT_FALSE(bridge->HasRateLimiterForTesting()); } +TEST_F(Canvas2DLayerBridgeTest, SoftwareCanvasIsCompositedIfImageChromium) { + ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform; + ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(true); + const_cast<gpu::Capabilities&>(SharedGpuContext::ContextProviderWrapper() + ->ContextProvider() + ->GetCapabilities()) + .gpu_memory_buffer_formats.Add(gfx::BufferFormat::BGRA_8888); + std::unique_ptr<Canvas2DLayerBridge> bridge = + MakeBridge(gfx::Size(300, 150), RasterMode::kCPU, kNonOpaque); + EXPECT_TRUE(bridge->IsValid()); + DrawSomething(bridge.get()); + EXPECT_FALSE(bridge->IsAccelerated()); + EXPECT_TRUE(bridge->IsComposited()); +} + +TEST_F(Canvas2DLayerBridgeTest, SoftwareCanvasNotCompositedIfNotImageChromium) { + ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(false); + std::unique_ptr<Canvas2DLayerBridge> bridge = + MakeBridge(gfx::Size(300, 150), RasterMode::kCPU, kNonOpaque); + EXPECT_TRUE(bridge->IsValid()); + DrawSomething(bridge.get()); + EXPECT_FALSE(bridge->IsAccelerated()); + EXPECT_FALSE(bridge->IsComposited()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index 2989bd8..f0b976c3 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -130,7 +130,12 @@ scoped_refptr<CanvasResource>&& resource, const gpu::SyncToken& sync_token, bool lost_resource) { - if (!resource) + // If there is a LastUnrefCallback, we need to abort because recycling the + // resource now will prevent the LastUnrefCallback from ever being called. + // In such cases, ReleaseFrameResources will be called again when + // CanvasResourceDispatcher destroys the corresponding FrameResource object, + // at which time this resource will be safely recycled. + if (!resource || resource->HasLastUnrefCallback()) return; resource->WaitSyncToken(sync_token); @@ -144,8 +149,9 @@ if (lost_resource) resource->NotifyResourceLost(); if (resource_provider && !lost_resource && resource->IsRecycleable() && - resource->HasOneRef()) + resource->HasOneRef()) { resource_provider->RecycleResource(std::move(resource)); + } } bool CanvasResource::PrepareTransferableResource( @@ -699,7 +705,10 @@ auto surface = SkSurface::MakeRasterDirect(CreateSkImageInfo(), gpu_memory_buffer_->memory(0), gpu_memory_buffer_->stride(0)); - surface->getCanvas()->drawImage(image, 0, 0); + + SkPixmap pixmap; + image->peekPixels(&pixmap); + surface->writePixels(pixmap, 0, 0); auto* sii = ContextProviderWrapper()->ContextProvider()->SharedImageInterface(); gpu_memory_buffer_->Unmap();
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h index f80baf6..8a74aa78 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -83,6 +83,8 @@ last_unref_callback_ = std::move(callback); } + bool HasLastUnrefCallback() { return !!last_unref_callback_; } + // We perform a lazy copy on write if the canvas content needs to be updated // while its current resource is in use. In order to avoid re-allocating // resources, its preferable to reuse a resource if its no longer in use.
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc index 4c4c7a25..86fb8ec 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
@@ -251,6 +251,44 @@ EXPECT_EQ(original_mailbox, provider->Snapshot()->GetMailboxHolder().mailbox); } +TEST_F(CanvasResourceProviderTest, NoRecycleIfLastRefCallback) { + const SkImageInfo kInfo = SkImageInfo::MakeN32Premul(10, 10); + + const uint32_t shared_image_usage_flags = + gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | gpu::SHARED_IMAGE_USAGE_SCANOUT; + + auto provider = CanvasResourceProvider::CreateSharedImageProvider( + kInfo, cc::PaintFlags::FilterQuality::kMedium, + CanvasResourceProvider::ShouldInitialize::kCallClear, + context_provider_wrapper_, RasterMode::kGPU, true /*is_origin_top_left*/, + shared_image_usage_flags); + + ASSERT_TRUE(provider->IsValid()); + + scoped_refptr<StaticBitmapImage> snapshot1 = provider->Snapshot(); + ASSERT_TRUE(snapshot1); + + // Set up a LastUnrefCallback that recycles the resource asynchronously, + // similarly to what OffscreenCanvasPlaceholder would do. + provider->ProduceCanvasResource()->SetLastUnrefCallback( + base::BindOnce([](scoped_refptr<CanvasResource> resource) {})); + + // Resource updated after draw. + provider->Canvas()->clear(SkColors::kWhite); + provider->FlushCanvas(); + scoped_refptr<StaticBitmapImage> snapshot2 = provider->Snapshot(); + EXPECT_NE(snapshot2->GetMailboxHolder().mailbox, + snapshot1->GetMailboxHolder().mailbox); + + auto snapshot1_mailbox = snapshot1->GetMailboxHolder().mailbox; + snapshot1.reset(); // resource not recycled due to LastUnrefCallback + provider->Canvas()->clear(SkColors::kBlack); + provider->FlushCanvas(); + scoped_refptr<StaticBitmapImage> snapshot3 = provider->Snapshot(); + // confirm resource is not recycled. + EXPECT_NE(snapshot3->GetMailboxHolder().mailbox, snapshot1_mailbox); +} + TEST_F(CanvasResourceProviderTest, CanvasResourceProviderSharedImageCopyOnWriteDisabled) { auto* fake_context = static_cast<FakeWebGraphicsContext3DProvider*>(
diff --git a/third_party/blink/renderer/platform/graphics/gradient.cc b/third_party/blink/renderer/platform/graphics/gradient.cc index 315e111..50f2af1 100644 --- a/third_party/blink/renderer/platform/graphics/gradient.cc +++ b/third_party/blink/renderer/platform/graphics/gradient.cc
@@ -104,7 +104,7 @@ if (stops_.empty()) { // A gradient with no stops must be transparent black. pos.push_back(WebCoreDoubleToSkScalar(0)); - colors.push_back(SK_ColorTRANSPARENT); + colors.push_back(SkColors::kTransparent); } else if (stops_.front().stop > 0) { // Copy the first stop to 0.0. The first stop position may have a slight // rounding error, but we don't care in this float comparison, since @@ -112,20 +112,20 @@ // with a stop at (0 + epsilon). pos.push_back(WebCoreDoubleToSkScalar(0)); if (color_filter_) { - colors.push_back(color_filter_->filterColor( - stops_.front().color.ToSkColorDeprecated())); + colors.push_back(color_filter_->filterColor4f( + stops_.front().color.toSkColor4f(), nullptr, nullptr)); } else { - colors.push_back(stops_.front().color.ToSkColorDeprecated()); + colors.push_back(stops_.front().color.toSkColor4f()); } } for (const auto& stop : stops_) { pos.push_back(WebCoreDoubleToSkScalar(stop.stop)); if (color_filter_) { - colors.push_back( - color_filter_->filterColor(stop.color.ToSkColorDeprecated())); + colors.push_back(color_filter_->filterColor4f(stop.color.toSkColor4f(), + nullptr, nullptr)); } else { - colors.push_back(stop.color.ToSkColorDeprecated()); + colors.push_back(stop.color.toSkColor4f()); } } @@ -232,10 +232,8 @@ if (is_dark_mode_enabled_) { for (auto& color : colors) { - color = EnsureDarkModeFilter() - .InvertColorIfNeeded(SkColor4f::FromColor(color), - DarkModeFilter::ElementRole::kBackground) - .toSkColor(); + color = EnsureDarkModeFilter().InvertColorIfNeeded( + color, DarkModeFilter::ElementRole::kBackground); } } // The matrix type is mutable and set lazily. Force it to be computed here to @@ -298,23 +296,16 @@ SkTileMode tile_mode, SkGradientShader::Interpolation interpolation, const SkMatrix& local_matrix, - SkColor fallback_color) const override { + SkColor4f fallback_color) const override { if (GetDegenerateHandling() == DegenerateHandling::kDisallow && p0_ == p1_) { return PaintShader::MakeEmpty(); } SkPoint pts[2] = {FloatPointToSkPoint(p0_), FloatPointToSkPoint(p1_)}; - // TODO(crbug/1308932): Remove this helper vector colors4f and make all - // SkColor4f. - std::vector<SkColor4f> colors4f; - colors4f.reserve(colors.size()); - for (auto& color : colors) - colors4f.push_back(SkColor4f::FromColor(color)); return PaintShader::MakeLinearGradient( - pts, colors4f.data(), pos.data(), static_cast<int>(colors4f.size()), - tile_mode, interpolation, 0 /* flags */, &local_matrix, - SkColor4f::FromColor(fallback_color)); + pts, colors.data(), pos.data(), static_cast<int>(colors.size()), + tile_mode, interpolation, 0 /* flags */, &local_matrix, fallback_color); } private: @@ -348,7 +339,7 @@ SkTileMode tile_mode, SkGradientShader::Interpolation interpolation, const SkMatrix& local_matrix, - SkColor fallback_color) const override { + SkColor4f fallback_color) const override { const SkMatrix* matrix = &local_matrix; absl::optional<SkMatrix> adjusted_local_matrix; if (aspect_ratio_ != 1) { @@ -370,17 +361,10 @@ return PaintShader::MakeEmpty(); } - // TODO(crbug/1308932): Remove this helper vector colors4f and make all - // SkColor4f. - std::vector<SkColor4f> colors4f; - colors4f.reserve(colors.size()); - for (auto& color : colors) - colors4f.push_back(SkColor4f::FromColor(color)); return PaintShader::MakeTwoPointConicalGradient( FloatPointToSkPoint(p0_), radius0, FloatPointToSkPoint(p1_), radius1, - colors4f.data(), pos.data(), static_cast<int>(colors4f.size()), - tile_mode, interpolation, 0 /* flags */, matrix, - SkColor4f::FromColor(fallback_color)); + colors.data(), pos.data(), static_cast<int>(colors.size()), tile_mode, + interpolation, 0 /* flags */, matrix, fallback_color); } private: @@ -415,7 +399,7 @@ SkTileMode tile_mode, SkGradientShader::Interpolation interpolation, const SkMatrix& local_matrix, - SkColor fallback_color) const override { + SkColor4f fallback_color) const override { if (GetDegenerateHandling() == DegenerateHandling::kDisallow && start_angle_ == end_angle_) { return PaintShader::MakeEmpty(); @@ -432,17 +416,10 @@ matrix = &*adjusted_local_matrix; } - // TODO(crbug/1308932): Remove this helper vector colors4f and make all - // SkColor4f. - std::vector<SkColor4f> colors4f; - colors4f.reserve(colors.size()); - for (auto& color : colors) - colors4f.push_back(SkColor4f::FromColor(color)); return PaintShader::MakeSweepGradient( - position_.x(), position_.y(), colors4f.data(), pos.data(), - static_cast<int>(colors4f.size()), tile_mode, start_angle_, end_angle_, - interpolation, 0 /* flags */, matrix, - SkColor4f::FromColor(fallback_color)); + position_.x(), position_.y(), colors.data(), pos.data(), + static_cast<int>(colors.size()), tile_mode, start_angle_, end_angle_, + interpolation, 0 /* flags */, matrix, fallback_color); } private:
diff --git a/third_party/blink/renderer/platform/graphics/gradient.h b/third_party/blink/renderer/platform/graphics/gradient.h index 7706f8c6..05e00d6 100644 --- a/third_party/blink/renderer/platform/graphics/gradient.h +++ b/third_party/blink/renderer/platform/graphics/gradient.h
@@ -128,14 +128,14 @@ protected: Gradient(Type, GradientSpreadMethod, ColorInterpolation, DegenerateHandling); - using ColorBuffer = Vector<SkColor, 8>; + using ColorBuffer = Vector<SkColor4f, 8>; using OffsetBuffer = Vector<SkScalar, 8>; virtual sk_sp<PaintShader> CreateShader(const ColorBuffer&, const OffsetBuffer&, SkTileMode, SkGradientShader::Interpolation, const SkMatrix&, - SkColor) const = 0; + SkColor4f) const = 0; DegenerateHandling GetDegenerateHandling() const { return degenerate_handling_;
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h index 2dd3c43..e4f5dba 100644 --- a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h +++ b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
@@ -199,8 +199,14 @@ : ClipPaintPropertyNodeOrAlias(parent), state_(std::move(state)) {} void AddChanged(PaintPropertyChangeType changed) { + // TODO(crbug.com/814815): This is a workaround of the bug. When the bug is + // fixed, change the following condition to + // DCHECK(!clip_cache_ || !clip_cache_->IsValid()); DCHECK_NE(PaintPropertyChangeType::kUnchanged, changed); - GeometryMapperClipCache::ClearCache(); + if (clip_cache_ && clip_cache_->IsValid()) { + DLOG(WARNING) << "Clip tree changed without invalidating the cache."; + GeometryMapperClipCache::ClearCache(); + } PaintPropertyNode::AddChanged(changed); }
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h index a1040d2..30d6776 100644 --- a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h +++ b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
@@ -426,11 +426,15 @@ } void AddChanged(PaintPropertyChangeType changed) { + // TODO(crbug.com/814815): This is a workaround of the bug. When the bug is + // fixed, change the following condition to + // DCHECK(!transform_cache_ || !transform_cache_->IsValid()); DCHECK_NE(PaintPropertyChangeType::kUnchanged, changed); - - GeometryMapperTransformCache::ClearCache(); - GeometryMapperClipCache::ClearCache(); - + if (transform_cache_ && transform_cache_->IsValid()) { + DLOG(WARNING) << "Transform tree changed without invalidating the cache."; + GeometryMapperTransformCache::ClearCache(); + GeometryMapperClipCache::ClearCache(); + } TransformPaintPropertyNodeOrAlias::AddChanged(changed); } @@ -439,7 +443,6 @@ friend class GeometryMapperTest; friend class GeometryMapperTransformCache; friend class GeometryMapperTransformCacheTest; - friend class PaintPropertyTreeBuilderTest; const GeometryMapperTransformCache& GetTransformCache() const { if (!transform_cache_)
diff --git a/third_party/blink/renderer/platform/network/http_parsers_test.cc b/third_party/blink/renderer/platform/network/http_parsers_test.cc index 668c1a57d..ae7d707 100644 --- a/third_party/blink/renderer/platform/network/http_parsers_test.cc +++ b/third_party/blink/renderer/platform/network/http_parsers_test.cc
@@ -860,7 +860,16 @@ class NoVarySearchPrefetchDisabledTest : public ::testing::Test, - public ::testing::WithParamInterface<base::StringPiece> {}; + public ::testing::WithParamInterface<base::StringPiece> { + public: + NoVarySearchPrefetchDisabledTest() { + scoped_feature_list_.InitAndDisableFeature( + network::features::kPrefetchNoVarySearch); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; TEST_P(NoVarySearchPrefetchDisabledTest, ParsingNVSReturnsDefaultURLVariance) { const auto parsed_headers =
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 9489e7b70..a437ceb 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1888,6 +1888,16 @@ origin_trial_feature_name: "NotificationTriggers", status: "experimental", }, + // Origin trial to experiment with No-Vary-Search in Prefetch Cache + // See crbug.com/1378075. Depends on SpeculationRulesPrefetchProxy to be + // enabled. + // On the browser side, the trial needs features::kPrefetchUseContentRefactor + // enabled. If features::kPrefetchUseContentRefactor is disabled, then + // the code will behave as if PrefetchNoVarySearch is disabled. + { + name: "NoVarySearchPrefetch", + origin_trial_feature_name: "NoVarySearchPrefetch", + }, { name: "OffMainThreadCSSPaint", status: "stable", @@ -2617,7 +2627,7 @@ status: "stable", base_feature: "SpeculationRulesPrefetchProxy", copied_from_base_feature_if: "overridden", - implied_by: ["SpeculationRulesPrefetchFuture"], + implied_by: ["SpeculationRulesPrefetchFuture", "NoVarySearchPrefetch"], }, { "name": "SpeculationRulesPrefetchWithSubresources",
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 86583ca..a3de662 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -614,6 +614,13 @@ "args": ["--disable-site-isolation-trials"], "expires": "Jul 1, 2023" }, + { + "prefix": "not-site-per-process-nonexclusive", + "platforms": ["Linux", "Mac", "Win"], + "bases": ["external/wpt/performance-timeline/tentative"], + "args": ["--disable-site-isolation-trials"], + "expires": "Jul 1, 2023" + }, "----------------------- origin-keyed agent clusters --------------------", "Origin-keyed agent clusters web platform tests are for the feature at", @@ -635,7 +642,6 @@ "--reset-browsing-instance-between-tests"], "expires": "Jul 1, 2023" }, - { "prefix": "focusless-spat-nav", "platforms": ["Linux", "Mac", "Win"], @@ -1544,13 +1550,26 @@ ], "exclusive_tests": "ALL", "args": [ - "--enable-blink-features=SpeculationRulesPrefetchProxy,SpeculationRulesFetchFromHeader,SpeculationRulesReferrerPolicyKey,SpeculationRulesDocumentRules", - "--enable-features=SpeculationRulesPrefetchProxy,PrefetchUseContentRefactor,PrefetchNoVarySearch", + "--enable-blink-features=SpeculationRulesPrefetchProxy,SpeculationRulesFetchFromHeader,SpeculationRulesReferrerPolicyKey,SpeculationRulesDocumentRules,NoVarySearchPrefetch", + "--enable-features=SpeculationRulesPrefetchProxy,PrefetchUseContentRefactor", "--bypass-prefetch-proxy-for-host=not-web-platform.test" ], "expires": "Jul 1, 2023" }, { + "prefix": "prefetch-no-vary-search", + "platforms": ["Linux", "Mac", "Win"], + "bases": [ + "external/wpt/speculation-rules/prefetch/no-vary-search" + ], + "exclusive_tests": "ALL", + "args": [ + "--enable-blink-features=NoVarySearchPrefetch", + "--enable-features=PrefetchUseContentRefactor" + ], + "expires": "Jul 1, 2023" + }, + { "prefix": "cookie-reject-domain-non-ascii", "platforms": ["Linux", "Mac", "Win"], "bases": [ "http/tests/inspector-protocol/issues/cookie-domain-non-ascii.js" ],
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-100.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-100.html new file mode 100644 index 0000000..1bf71e83 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-100.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1395581"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:2; column-fill:auto; height:200px;"> + <div style="width:60px; height:60px; direction:rtl; border:20px solid green; background:red;"> + <div style="position:relative;"> + <div style="position:absolute; left:0; top:0; width:60px; height:30px; background:green;"></div> + <div style="position:absolute; right:0; top:30px; width:60px; height:30px; background:green;"></div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-101.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-101.html new file mode 100644 index 0000000..ed7e1e23 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-101.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1395581"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:2; column-fill:auto; gap:0; width:100px; height:100px; background:red;"> + <div style="width:30px; height:180px; direction:rtl; border:10px solid green;"> + <div style="position:relative;"> + <div style="position:absolute; left:0; top:0; width:30px; height:90px; background:green;"></div> + <div style="position:absolute; right:0; top:90px; width:30px; height:90px; background:green;"></div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-102.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-102.html new file mode 100644 index 0000000..45cbc0b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-102.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1395581"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="position:absolute; margin-left:15px; margin-top:15px; width:30px; height:70px; background:green;"></div> +<div style="columns:2; column-fill:auto; height:200px;"> + <div style="width:70px; height:70px; direction:rtl; border:solid 15px green; background:red;"> + <div style="position:relative;"> + <div style="position:absolute; width:40px; height:70px; background:green;"></div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-103.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-103.html new file mode 100644 index 0000000..b54cbcd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-103.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1395581"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="position:absolute; margin-left:10px; margin-top:10px; width:10px; height:90px; background:green;"></div> +<div style="position:absolute; margin-left:60px; width:10px; height:90px; background:green;"></div> +<div style="columns:2; column-fill:auto; gap:0; width:100px; height:100px; background:red;"> + <div style="width:32px; height:180px; direction:rtl; border:solid 10px green; border-right-width:8px;"> + <div style="position:relative;"> + <div style="position:absolute; width:22px; height:180px; background:green;"></div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/gradient/css-color-4-colors-default-to-oklab-gradient.html b/third_party/blink/web_tests/external/wpt/css/css-images/gradient/css-color-4-colors-default-to-oklab-gradient.html index 5be18ac..63fdd6f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/gradient/css-color-4-colors-default-to-oklab-gradient.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/gradient/css-color-4-colors-default-to-oklab-gradient.html
@@ -11,7 +11,7 @@ .test { width: 480px; height: 50px; - background: linear-gradient(to right, rgb(255, 0, 0), color(srgb 0 255 0)); + background: linear-gradient(to right, rgb(255, 0, 0), color(srgb 0 1 0)); } </style> </head>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html index 4fb7f113..0f8195157 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html
@@ -12,6 +12,7 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-contain-png-001-ref.html"> + <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-2000"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html index 738c015a..14834316 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html
@@ -12,6 +12,7 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-contain-png-002-ref.html"> + <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-2000"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html index 36031175..0e2a388 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html
@@ -12,6 +12,7 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-fill-png-001-ref.html"> + <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-3200"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html index a332c37..43bcced 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html
@@ -12,6 +12,7 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-fill-png-002-ref.html"> + <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-3200"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-child.sub.html b/third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-cross-origin-child.sub.html similarity index 67% rename from third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-child.sub.html rename to third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-cross-origin-child.sub.html index 32dd4cb..4be0df87 100644 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-child.sub.html +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-cross-origin-child.sub.html
@@ -2,6 +2,7 @@ <head></head> <body></body> <script> + // Create child frame that is cross-origin with its parent. const childFrame = document.createElement('iframe') childFrame.src = "http://{{hosts[][]}}:{{ports[http][0]}}/performance-timeline/resources/child-frame.html" document.body.appendChild(childFrame) @@ -9,6 +10,7 @@ performance.mark("entry-name") childFrame.addEventListener('load', () => { - window.parent.postMessage("DONE", "*") + const entries = performance.getEntries(true) + window.parent.postMessage(entries.length, "*") }) </script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-same-origin-child.html b/third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-same-origin-child.html new file mode 100644 index 0000000..c9248a4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/resources/parent-frame-with-same-origin-child.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<head></head> +<body></body> +<script> + // Create child frame that is same-origin with its parent. + const childFrame = document.createElement('iframe') + childFrame.src = "child-frame.html" + document.body.appendChild(childFrame) + + performance.mark("entry-name") + + childFrame.addEventListener('load', () => { + const entries = performance.getEntries(true) + window.parent.postMessage(entries.length, "*") + }) +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-from-child-cross-origin-grandchild.sub.html b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-from-child-cross-origin-grandchild.sub.html new file mode 100644 index 0000000..dcd716d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-from-child-cross-origin-grandchild.sub.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +</body> +<script> +promise_test(() => { + return new Promise(resolve => { + performance.clearResourceTimings() + + // Create child iframe with an embedded frame that is same-origin with its parent but cross-origin with the current frame. + const crossOriginChildFrame = document.createElement('iframe') + crossOriginChildFrame.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/performance-timeline/resources/parent-frame-with-same-origin-child.html" + document.body.appendChild(crossOriginChildFrame) + + // Listen for postMessage() from child frame. + window.addEventListener("message", e => { + // 0 entries for parent, 4 for child, 2 for grandchild. + assert_equals(e.data, 6) + + resolve() + }) + }) +}, "GetEntries of a Cross-Origin child frame with one Cross-Origin grandchild frame") +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-from-child-same-origin-grandchild.sub.html b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-from-child-same-origin-grandchild.sub.html new file mode 100644 index 0000000..991715f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-from-child-same-origin-grandchild.sub.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +</body> +<script> +promise_test(() => { + return new Promise(resolve => { + performance.clearResourceTimings() + + // Create child iframe with an embedded frame that is cross-origin with its parent but same-origin with the current frame. + const crossOriginChildFrame = document.createElement('iframe') + crossOriginChildFrame.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/performance-timeline/resources/parent-frame-with-cross-origin-child.sub.html" + document.body.appendChild(crossOriginChildFrame) + + // Listen for postMessage() from child frame. + window.addEventListener("message", e => { + // 0 entries for parent, 4 for child, 0 for grandchild. + assert_equals(e.data, 4) + + resolve() + }) + }) +}, "GetEntries of a Cross-Origin child frame with one Same-Origin grandchild frame") +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-local-child-one-local-grandchild.html b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-local-child-one-local-grandchild.html index ee2dadd..06a13f3 100644 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-local-child-one-local-grandchild.html +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-local-child-one-local-grandchild.html
@@ -10,9 +10,9 @@ return new Promise(resolve => { performance.clearResourceTimings() - // Create child iframe. + // Create child iframe with an embedded frame that is cross-origin with its parent, but same-origin with the current frame. const childFrame = document.createElement('iframe') - childFrame.src = "../resources/parent-frame-with-child.sub.html" + childFrame.src = "../resources/parent-frame-with-cross-origin-child.sub.html" document.body.appendChild(childFrame) // Listen for postMessage() from grandchild frame.
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-remote-child-one-local-grandchild.sub.html b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-remote-child-one-local-grandchild.sub.html index a9efe41..3248d601 100644 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-remote-child-one-local-grandchild.sub.html +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/include-frames-one-remote-child-one-local-grandchild.sub.html
@@ -10,9 +10,9 @@ return new Promise(resolve => { performance.clearResourceTimings() - // Create child iframe. + // Create child iframe with an embedded frame that is cross-origin with its parent, but same-origin with the current frame. const remoteChildFrame = document.createElement('iframe') - remoteChildFrame.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/performance-timeline/resources/parent-frame-with-child.sub.html" + remoteChildFrame.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/performance-timeline/resources/parent-frame-with-cross-origin-child.sub.html" document.body.appendChild(remoteChildFrame) // Listen for postMessage() from grandchild frame.
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/no-vary-search/README.txt b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/no-vary-search/README.txt new file mode 100644 index 0000000..60ac226f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/no-vary-search/README.txt
@@ -0,0 +1 @@ +Web Platform Tests for No-Vary-Search support in prefetch cache.
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/generated-gradients-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/generated-gradients-expected.png index a03c012..7f32aa6f 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/generated-gradients-expected.png +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/generated-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/simple-gradients-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/simple-gradients-expected.png index 61a0d2f..16450ae6 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/simple-gradients-expected.png +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/gradients/simple-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/wicd/test-scalable-background-image2-expected.png index bb0f5b2..be7d1ba 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/svg/batik/text/textEffect-expected.png b/third_party/blink/web_tests/flag-specific/highdpi/svg/batik/text/textEffect-expected.png index b4db6398..6ef1fe26 100644 --- a/third_party/blink/web_tests/flag-specific/highdpi/svg/batik/text/textEffect-expected.png +++ b/third_party/blink/web_tests/flag-specific/highdpi/svg/batik/text/textEffect-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/flag-specific/highdpi/svg/wicd/test-scalable-background-image2-expected.png new file mode 100644 index 0000000..481f4f2 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/highdpi/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/gradients/generated-gradients-expected.png b/third_party/blink/web_tests/platform/linux/fast/gradients/generated-gradients-expected.png index e138595..1481503 100644 --- a/third_party/blink/web_tests/platform/linux/fast/gradients/generated-gradients-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/gradients/generated-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/gradients/simple-gradients-expected.png b/third_party/blink/web_tests/platform/linux/fast/gradients/simple-gradients-expected.png index d916621..99755b1 100644 --- a/third_party/blink/web_tests/platform/linux/fast/gradients/simple-gradients-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/gradients/simple-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png index d76cc76..8226e918 100644 --- a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-3-expected.png b/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-3-expected.png index df70ddad..b95cdbf 100644 --- a/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-3-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-3-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/platform/linux/svg/wicd/test-scalable-background-image2-expected.png index 481f4f2..5c1a25a8 100644 --- a/third_party/blink/web_tests/platform/linux/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/svg/wicd/test-scalable-background-image2-expected.png index 10e1a16..3ab85fb 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.13/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.13/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png index 5f61902..1662057d 100644 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 5d03ab2a..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png deleted file mode 100644 index 9597811..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png deleted file mode 100644 index 2d91917..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png deleted file mode 100644 index ef045b8..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png deleted file mode 100644 index 9597811..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png deleted file mode 100644 index 68e5798..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png deleted file mode 100644 index c8b2b51..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png deleted file mode 100644 index 7a299d1..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png deleted file mode 100644 index 9176a3a1..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png deleted file mode 100644 index 220dc263..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png deleted file mode 100644 index 4090cebd..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png deleted file mode 100644 index 66da85c..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png deleted file mode 100644 index cb7b5b4..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png deleted file mode 100644 index c8acdf4d..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png deleted file mode 100644 index 86aa0df..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png deleted file mode 100644 index 6892e25b..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png deleted file mode 100644 index 450d929c..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png deleted file mode 100644 index ea6faa4..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png deleted file mode 100644 index 3d6f2cb..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png deleted file mode 100644 index 6027fc7..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png deleted file mode 100644 index 36fe0c2..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png deleted file mode 100644 index 92335fbd..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png deleted file mode 100644 index 54909a8..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/conic-gradient-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/conic-gradient-expected.png index c5e3412..ba20a1ca 100644 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/conic-gradient-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/conic-gradient-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/generated-gradients-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/generated-gradients-expected.png new file mode 100644 index 0000000..448329e36 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/generated-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png index ea05f2f..35559e0c 100644 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/media/alpha-video-playback-expected.png deleted file mode 100644 index 7fc316c..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/media/alpha-video-playback-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png deleted file mode 100644 index 2bfe7f7..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/svg/wicd/test-scalable-background-image2-expected.png index 84df5d5..49428ee 100644 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 3d15b57..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 8d0f8d8..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index c231417..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png new file mode 100644 index 0000000..5f61902 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 1344ecc..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/canvas/canvas-incremental-repaint-expected.png new file mode 100644 index 0000000..f0252fb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/platform/mac-mac11/svg/wicd/test-scalable-background-image2-expected.png index 3b37f98ad..4d997c6 100644 --- a/third_party/blink/web_tests/platform/mac-mac11/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png index d9ba88e..66a699e 100644 --- a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png index ba341e1b..5b6ab5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png index 5f61902..1662057d 100644 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 5d03ab2a..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png deleted file mode 100644 index 9597811..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png deleted file mode 100644 index 2d91917..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png deleted file mode 100644 index ef045b8..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png deleted file mode 100644 index 9597811..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png deleted file mode 100644 index 68e5798..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png deleted file mode 100644 index c8b2b51..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png deleted file mode 100644 index 7a299d1..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png deleted file mode 100644 index 9176a3a1..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png deleted file mode 100644 index 220dc263..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png deleted file mode 100644 index 4090cebd..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png deleted file mode 100644 index 66da85c..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png deleted file mode 100644 index cb7b5b4..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png deleted file mode 100644 index c8acdf4d..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png deleted file mode 100644 index 86aa0df..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png deleted file mode 100644 index 6892e25b..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png deleted file mode 100644 index 450d929c..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png deleted file mode 100644 index ea6faa4..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png deleted file mode 100644 index 3d6f2cb..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png deleted file mode 100644 index 6027fc7..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png deleted file mode 100644 index 36fe0c2..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png deleted file mode 100644 index 92335fbd..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png deleted file mode 100644 index 54909a8..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/conic-gradient-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/conic-gradient-expected.png index c5e3412..ba20a1ca 100644 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/conic-gradient-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/conic-gradient-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/generated-gradients-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/generated-gradients-expected.png new file mode 100644 index 0000000..448329e36 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/generated-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png index ea05f2f..35559e0c 100644 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/media/alpha-video-playback-expected.png deleted file mode 100644 index 7fc316c..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/media/alpha-video-playback-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png deleted file mode 100644 index 2bfe7f7..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/svg/wicd/test-scalable-background-image2-expected.png index cd18903b..6f110d15 100644 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 3d15b57..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 8d0f8d8..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index c231417..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png deleted file mode 100644 index ffa89d0..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png new file mode 100644 index 0000000..5f61902 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png deleted file mode 100644 index 1344ecc..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png index 6a9b251..92e03005 100644 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png index aef4be0..f0252fb 100644 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png index ad7239b..28a0a35c 100644 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-webp-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-webp-expected.png new file mode 100644 index 0000000..2159358a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-webp-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/pixelated-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/pixelated-expected.png new file mode 100644 index 0000000..b75d52bc --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/pixelated-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png index 577c247..9e2444f 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png index 6770f89..5210665 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png index 9af4d8d..73668a6 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png index 0d159ed..13b9281 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png index 6770f89..5210665 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png index c824cba..3344e87 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png index bf48c62d..c1d9b25b 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png index 6744078..5bc891c 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png index ba54ccd..867acb27 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png index 16af243d..4e5b644 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png index 02ae9d4..6e61b30 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png index f863fcd..23fe32a 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png index db826b4..f1e886ee 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png index 2f59f7f..0368d30d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png index 574a796..c621520 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png index 4de189f..dd4d416 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png index 42f81d5a..aa13f9c 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png index 42f81d5a..aa13f9c 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png index 3189d77..4dd743b 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png index f75fe963..0476678 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png index a2bc636..2a1980a 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png index 8d82275..a5c05a8 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png index f65ba0d..a095fc9 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png index dec5aeb..63d3411 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png index 9e27acf..0c84723 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png index 777f415b..114e9dc 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png index f400434..ecf3bcc5 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png index 5bb2acd0..dcce6db4 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png index 900f5a7..fe6ecd6d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png index a434e66..0ad74dc 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/gradients/conic-gradient-expected.png b/third_party/blink/web_tests/platform/mac/fast/gradients/conic-gradient-expected.png index 9f4d9b65..114f0cfb 100644 --- a/third_party/blink/web_tests/platform/mac/fast/gradients/conic-gradient-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/gradients/conic-gradient-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/gradients/generated-gradients-expected.png b/third_party/blink/web_tests/platform/mac/fast/gradients/generated-gradients-expected.png index 448329e36..00855abf 100644 --- a/third_party/blink/web_tests/platform/mac/fast/gradients/generated-gradients-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/gradients/generated-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/gradients/simple-gradients-expected.png b/third_party/blink/web_tests/platform/mac/fast/gradients/simple-gradients-expected.png index 1bda305..bc6d9a7 100644 --- a/third_party/blink/web_tests/platform/mac/fast/gradients/simple-gradients-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/gradients/simple-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png b/third_party/blink/web_tests/platform/mac/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png index 7d3b99d5..303e8178 100644 --- a/third_party/blink/web_tests/platform/mac/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png b/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png index 50044ee..ef8cc96 100644 --- a/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/inspector-protocol/overlay/overlay-with-emulation-scale-expected.txt b/third_party/blink/web_tests/platform/mac/inspector-protocol/overlay/overlay-with-emulation-scale-expected.txt new file mode 100644 index 0000000..f546a917 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/inspector-protocol/overlay/overlay-with-emulation-scale-expected.txt
@@ -0,0 +1,4 @@ +Verifies that overlay is correctly rendered with emulation scale > 1. +The test passes if the image URL below is 300x600 image containing a 270x420 brown rectangle, without any green or red. +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAJYCAYAAADYJts/AAAAAXNSR0IArs4c6QAAB9JJREFUeJzt20EKhEAMAMGdxf9/OT5BBUVaqu6BnJpcsmZmfgAB/7cXADhLsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjK2yxNrPbAG8Gk3vSy7sIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8jYLk/MPLAGwDEXFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARk7HLgMrk9KayMAAAAASUVORK5CYII= +
diff --git a/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png index e2872f31..7fc316c 100644 --- a/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png +++ b/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-putImageData-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-putImageData-expected.txt new file mode 100644 index 0000000..9051839 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-putImageData-expected.txt
@@ -0,0 +1,16 @@ +{ + "layers": [ + { + "name": "Scrolling background of LayoutNGView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutHTMLCanvas CANVAS id='canvas'", + "position": [8, 8], + "bounds": [100, 100] + } + ] +} +
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-expected.txt new file mode 100644 index 0000000..dce35520 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-expected.txt
@@ -0,0 +1,16 @@ +{ + "layers": [ + { + "name": "Scrolling background of LayoutNGView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutHTMLCanvas (positioned) CANVAS id='canvas'", + "position": [50, 50], + "bounds": [500, 500] + } + ] +} +
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png index 4359ac3..2bfe7f7 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.txt new file mode 100644 index 0000000..dbfdd46 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.txt
@@ -0,0 +1,20 @@ +{ + "layers": [ + { + "name": "Scrolling background of LayoutNGView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "invalidations": [ + [50, 50, 600, 500] + ] + }, + { + "name": "LayoutHTMLCanvas (positioned) CANVAS id='canvas'", + "position": [50, 50], + "bounds": [500, 500], + "backgroundColor": "#003300" + } + ] +} +
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt index 5598dfc..f5ec0f3 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt
@@ -1,56 +1,235 @@ { "layers": [ { - "name": "Scrolling background of LayoutView #document", + "name": "Scrolling background of LayoutNGView #document", "bounds": [785, 928], "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [569, 562, 133, 42], - [569, 512, 133, 42], - [569, 462, 133, 42], - [569, 412, 133, 42], - [569, 362, 133, 42], - [569, 312, 133, 42], - [569, 262, 133, 42], - [569, 212, 133, 42], - [569, 162, 133, 42], - [569, 112, 133, 42], - [569, 62, 133, 42], - [427, 562, 133, 42], - [427, 512, 133, 42], - [427, 462, 133, 42], - [427, 412, 133, 42], - [427, 362, 133, 42], - [427, 312, 133, 42], - [427, 262, 133, 42], - [427, 212, 133, 42], - [427, 162, 133, 42], - [427, 112, 133, 42], - [427, 62, 133, 42], - [285, 562, 133, 42], - [285, 512, 133, 42], - [285, 462, 133, 42], - [285, 412, 133, 42], - [285, 362, 133, 42], - [285, 312, 133, 42], - [285, 262, 133, 42], - [285, 212, 133, 42], - [285, 162, 133, 42], - [285, 112, 133, 42], - [285, 62, 133, 42], - [143, 562, 133, 42], - [143, 512, 133, 42], - [143, 462, 133, 42], - [143, 412, 133, 42], - [143, 362, 133, 42], - [143, 312, 133, 42], - [143, 262, 133, 42], - [143, 212, 133, 42], - [143, 162, 133, 42], - [143, 112, 133, 42], - [143, 62, 133, 42] - ] + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-oversolid color'", + "position": [145, 63], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-overimage'", + "position": [287, 63], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-overcanvas'", + "position": [429, 63], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-overvideo'", + "position": [571, 63], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-insolid color'", + "position": [145, 113], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-inimage'", + "position": [287, 113], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-incanvas'", + "position": [429, 113], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-invideo'", + "position": [571, 113], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-outsolid color'", + "position": [145, 163], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-outimage'", + "position": [287, 163], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-outcanvas'", + "position": [429, 163], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-outvideo'", + "position": [571, 163], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-atopsolid color'", + "position": [145, 213], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-atopimage'", + "position": [287, 213], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-atopcanvas'", + "position": [429, 213], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-atopvideo'", + "position": [571, 213], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-oversolid color'", + "position": [145, 263], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-overimage'", + "position": [287, 263], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-overcanvas'", + "position": [429, 263], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-overvideo'", + "position": [571, 263], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-insolid color'", + "position": [145, 313], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-inimage'", + "position": [287, 313], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-incanvas'", + "position": [429, 313], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-invideo'", + "position": [571, 313], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-outsolid color'", + "position": [145, 363], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-outimage'", + "position": [287, 363], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-outcanvas'", + "position": [429, 363], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-outvideo'", + "position": [571, 363], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-atopsolid color'", + "position": [145, 413], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-atopimage'", + "position": [287, 413], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-atopcanvas'", + "position": [429, 413], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='destination-atopvideo'", + "position": [571, 413], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='lightersolid color'", + "position": [145, 463], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='lighterimage'", + "position": [287, 463], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='lightercanvas'", + "position": [429, 463], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='lightervideo'", + "position": [571, 463], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='copysolid color'", + "position": [145, 513], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='copyimage'", + "position": [287, 513], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='copycanvas'", + "position": [429, 513], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='copyvideo'", + "position": [571, 513], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='xorsolid color'", + "position": [145, 563], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='xorimage'", + "position": [287, 563], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='xorcanvas'", + "position": [429, 563], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='xorvideo'", + "position": [571, 563], + "bounds": [130, 40] + }, + { + "name": "LayoutHTMLCanvas CANVAS id='source-canvas'", + "position": [16, 751], + "bounds": [150, 60] }, { "name": "LayoutVideo VIDEO id='video'",
diff --git a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png index 82032ccc..d848959 100644 --- a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png +++ b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-3-expected.png b/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-3-expected.png index b662737a..67644339 100644 --- a/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-3-expected.png +++ b/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-3-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/platform/mac/svg/wicd/test-scalable-background-image2-expected.png index b52fb41..b30acc9 100644 --- a/third_party/blink/web_tests/platform/mac/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/platform/mac/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png index e53a7e8..9b27031 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png index 4eb24ef..da2f7b8c 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png index fb5bce8..91c1688 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png index 93ddabe..ddfd164 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png index 183ab2f..13013cb5b 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png index 7606226..0d95b5e3 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png new file mode 100644 index 0000000..1aa13baa --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png new file mode 100644 index 0000000..4b949f6 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-expected.png new file mode 100644 index 0000000..1fca07f0 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-grid-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-grid-expected.png new file mode 100644 index 0000000..f55c833 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-grid-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/pixelated-canvas-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/pixelated-canvas-expected.png new file mode 100644 index 0000000..1021936 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/pixelated-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png new file mode 100644 index 0000000..e2872f31 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png new file mode 100644 index 0000000..e2872f31 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-hidpi-blurry-expected.png new file mode 100644 index 0000000..6a9b251 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-hidpi-blurry-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png b/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png new file mode 100644 index 0000000..ad7239b --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png index fa3bcbc..c0ced16 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/gradients/conic-gradient-expected.png b/third_party/blink/web_tests/platform/win/fast/gradients/conic-gradient-expected.png index cab834f..92291e33 100644 --- a/third_party/blink/web_tests/platform/win/fast/gradients/conic-gradient-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/gradients/conic-gradient-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/gradients/generated-gradients-expected.png b/third_party/blink/web_tests/platform/win/fast/gradients/generated-gradients-expected.png index 5478656..3b7b9f1 100644 --- a/third_party/blink/web_tests/platform/win/fast/gradients/generated-gradients-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/gradients/generated-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/gradients/simple-gradients-expected.png b/third_party/blink/web_tests/platform/win/fast/gradients/simple-gradients-expected.png index 24061be..4cf5a70 100644 --- a/third_party/blink/web_tests/platform/win/fast/gradients/simple-gradients-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/gradients/simple-gradients-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png b/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png index 3970797..b83e74d 100644 --- a/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-linear-gradients-color-hints-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-repeating-gradient-color-hint-expected.png b/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-repeating-gradient-color-hint-expected.png index b784d383..0ebb499 100644 --- a/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-repeating-gradient-color-hint-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/gradients/unprefixed-repeating-gradient-color-hint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png index 922589a..90034c74 100644 --- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/pservers-grad-14-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-3-expected.png b/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-3-expected.png index 524e955..cc57d74 100644 --- a/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-3-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-3-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/wicd/test-scalable-background-image2-expected.png b/third_party/blink/web_tests/platform/win/svg/wicd/test-scalable-background-image2-expected.png index 4bf8691..46ad5fe 100644 --- a/third_party/blink/web_tests/platform/win/svg/wicd/test-scalable-background-image2-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/wicd/test-scalable-background-image2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/svg/as-background-image/svg-as-background-with-relative-size-expected.png b/third_party/blink/web_tests/svg/as-background-image/svg-as-background-with-relative-size-expected.png index c4d42e1..e2e753a 100644 --- a/third_party/blink/web_tests/svg/as-background-image/svg-as-background-with-relative-size-expected.png +++ b/third_party/blink/web_tests/svg/as-background-image/svg-as-background-with-relative-size-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-site-per-process-nonexclusive/README.md b/third_party/blink/web_tests/virtual/not-site-per-process-nonexclusive/README.md new file mode 100644 index 0000000..6481c20 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-site-per-process-nonexclusive/README.md
@@ -0,0 +1,5 @@ +# virtual/not-site-per-process + +## Summary + +See virtual/not-site-per-process. This virtual test suite removes the `exclusive_tests: "ALL"` configuration, and specifies tests that should be run both with and without site isolation enabled. \ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/prefetch-no-vary-search/README.md b/third_party/blink/web_tests/virtual/prefetch-no-vary-search/README.md new file mode 100644 index 0000000..60ac226f --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefetch-no-vary-search/README.md
@@ -0,0 +1 @@ +Web Platform Tests for No-Vary-Search support in prefetch cache.
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index 6e4f2f01..dda6a8b 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: 73c1fba668a86dd003fa2ac6af86ab7d89c09908 +Version: b3f85342261db10bbeb2e5a07c7e54b616309b9e License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/tools/licenses/licenses_test.py b/tools/licenses/licenses_test.py index 4772582..1af0ebe 100755 --- a/tools/licenses/licenses_test.py +++ b/tools/licenses/licenses_test.py
@@ -40,6 +40,16 @@ 'Name': 'lib3', 'License File': os.path.join('third_party', 'lib3', 'LICENSE'), }, + os.path.join('third_party', 'lib3-v1'): { + # Test SPDX license file dedup. (different name, same license file) + 'Name': 'lib3-v1', + 'License File': os.path.join('third_party', 'lib3', 'LICENSE'), + }, + os.path.join('third_party', 'lib3-v2'): { + # Test SPDX id dedup. (same name, different license file) + 'Name': 'lib3', + 'License File': os.path.join('third_party', 'lib3-v2', 'LICENSE'), + }, } def test_get_third_party_deps_from_gn_deps_output(self): @@ -91,6 +101,8 @@ 'lib1 license text\n', 'lib2 license text\n', 'lib3 license text\n', + 'lib3 license text\n', + 'lib3-v2 license text\n', ] license_txt = licenses.GenerateLicenseFilePlainText( @@ -113,6 +125,16 @@ 'lib3', '--------------------', 'lib3 license text', + '', + '--------------------', + 'lib3-v1', + '--------------------', + 'lib3 license text', + '', + '--------------------', + 'lib3-v2', + '--------------------', + 'lib3-v2 license text', ]) + '\n' # extra new line to account for join not adding one to the end self.assertEqual(license_txt, expected) @@ -122,6 +144,7 @@ 'lib1\nlicense text\n', 'lib2\nlicense text\n', 'lib3\nlicense text\n', + 'lib3-v2\nlicense text\n', ] license_txt = licenses.GenerateLicenseFileSpdx( @@ -167,11 +190,21 @@ "SPDXID": "SPDXRef-Package-lib3", "name": "lib3", "licenseConcluded": "LicenseRef-lib3" + }, + { + "SPDXID": "SPDXRef-Package-lib3-v1", + "name": "lib3-v1", + "licenseConcluded": "LicenseRef-lib3" + }, + { + "SPDXID": "SPDXRef-Package-lib3-1", + "name": "lib3", + "licenseConcluded": "LicenseRef-lib3-1" } ], "hasExtractedLicensingInfos": [ { - "name": "Chromium License", + "name": "Chromium", "licenseId": "LicenseRef-Chromium", "extractedText": "root\\nlicense text\\n", "crossRefs": [ @@ -181,7 +214,7 @@ ] }, { - "name": "lib1 License", + "name": "lib1", "licenseId": "LicenseRef-lib1", "extractedText": "lib1\\nlicense text\\n", "crossRefs": [ @@ -191,7 +224,7 @@ ] }, { - "name": "lib2 License", + "name": "lib2", "licenseId": "LicenseRef-lib2", "extractedText": "lib2\\nlicense text\\n", "crossRefs": [ @@ -201,7 +234,7 @@ ] }, { - "name": "lib3 License", + "name": "lib3", "licenseId": "LicenseRef-lib3", "extractedText": "lib3\\nlicense text\\n", "crossRefs": [ @@ -209,6 +242,16 @@ "url": "http://google.com/third_party/lib3/LICENSE" } ] + }, + { + "name": "lib3", + "licenseId": "LicenseRef-lib3-1", + "extractedText": "lib3-v2\\nlicense text\\n", + "crossRefs": [ + { + "url": "http://google.com/third_party/lib3-v2/LICENSE" + } + ] } ], "relationships": [ @@ -226,6 +269,16 @@ "spdxElementId": "SPDXRef-Package-Chromium", "relationshipType": "CONTAINS", "relatedSpdxElement": "SPDXRef-Package-lib3" + }, + { + "spdxElementId": "SPDXRef-Package-Chromium", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Package-lib3-v1" + }, + { + "spdxElementId": "SPDXRef-Package-Chromium", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Package-lib3-1" } ] }'''
diff --git a/tools/licenses/spdx_writer.py b/tools/licenses/spdx_writer.py index 0ede233..c612d18 100644 --- a/tools/licenses/spdx_writer.py +++ b/tools/licenses/spdx_writer.py
@@ -2,12 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import collections import dataclasses import json import os import pathlib import re -from typing import Callable +from typing import Callable, DefaultDict, Tuple class SpdxWriter: @@ -22,7 +23,9 @@ doc_namespace: str = None, read_file=lambda x: pathlib.Path(x).read_text(encoding='utf-8')): self.root_package = _Package(root_package_name, root_license) - self.packages = [self.root_package] + # Use dict to ensure no duplicate pkgs. + # In >=py3.7 dicts are ordered by insertion. + self.packages = {} self.root = root self.link_prefix = link_prefix @@ -35,7 +38,7 @@ def add_package(self, name: str, license_file: str): """Add a package to the SPDX output.""" - self.packages.append(_Package(name, license_file)) + self.packages[_Package(name, license_file)] = None def write_to_file(self, file_path: str): """Writes the content to a file.""" @@ -50,13 +53,10 @@ for pkg in self.packages: writer.add_package(pkg) - for pkg in self.packages: - writer.add_license_file(pkg) - return writer.write() -@dataclasses.dataclass +@dataclasses.dataclass(frozen=True) class _Package: """Stores needed data for a package to output SPDX.""" name: str @@ -118,37 +118,93 @@ 'relationships': [], } + # Used to dedup license files based on file path. + self.existing_license_files = {} # 'file path': 'licenseId' + # Used to make sure that there are no duplicate ids. + self.existing_package_ids = collections.defaultdict(int) # 'packageId': num + self.existing_license_ids = collections.defaultdict(int) # 'licenseId': num + + # Add the root package to make sure that its ID isn't taken. + self.add_package(root_package) + def write(self) -> str: """Returns a JSON string for the current state of the writer.""" return json.dumps(self.content, indent=4) + def _get_dedup_id(self, elem_id: str, id_dict: DefaultDict[str, int]) -> str: + """Returns a unique id given a dictionary with existing ids. + + IDs are case sensitive, so this method ignores casing for uniqueness. + + Args: + elem_id: the requested id to use for the element. + id_dict: dictionary holding already used ids. + + Returns: + When the elem_id is already unique, return elem_id. + When the elem_id has been used, return elem_id + '-[next num]'. + """ + suffix = id_dict[elem_id] + id_dict[elem_id] += 1 + return f'{elem_id}-{suffix}' if suffix > 0 else elem_id + + def _get_package_id(self, pkg: _Package) -> str: + """Makes sure that there are no pkg id duplicates.""" + return self._get_dedup_id(pkg.package_spdx_id, self.existing_package_ids) + + def _get_license_id(self, pkg: _Package) -> Tuple[str, bool]: + """Handles license deduplication. + + If this pkg.file has already been seen, reuse that same id instead. If + there are two packages with the same name but different license files, + handle deduping the names. + + Args: + pkg: The package to get a license id for. + + Returns: + First return value is the id, second is whether the license needs to be + added to the SPDX doc (False if it already exists in the doc). + """ + existing = self.existing_license_files.get(pkg.file) + if existing: + return existing, False + + license_id = self._get_dedup_id(pkg.license_spdx_id, + self.existing_license_ids) + self.existing_license_files[pkg.file] = license_id + return license_id, True + def add_package(self, pkg: _Package): """Writes a package to the file (package metadata).""" + pkg_id = self._get_package_id(pkg) + license_id, need_to_add_license = self._get_license_id(pkg) + self.content['packages'].append({ - 'SPDXID': pkg.package_spdx_id, + 'SPDXID': pkg_id, 'name': pkg.name, - 'licenseConcluded': pkg.license_spdx_id, + 'licenseConcluded': license_id, }) if pkg.package_spdx_id != self.root_package_id: self.content['relationships'].append({ - 'spdxElementId': - self.root_package_id, - 'relationshipType': - 'CONTAINS', - 'relatedSpdxElement': - pkg.package_spdx_id, + 'spdxElementId': self.root_package_id, + 'relationshipType': 'CONTAINS', + 'relatedSpdxElement': pkg_id, }) - def add_license_file(self, pkg: _Package): + if need_to_add_license: + self._add_license_file(pkg, license_id) + + def _add_license_file(self, pkg: _Package, license_id: str): """Writes a license to the file (raw license text).""" spdx_path = _get_spdx_path(self.root, pkg.file) url = f'{self.link_prefix}{spdx_path.replace(os.sep, "/")}' self.content['hasExtractedLicensingInfos'].append({ 'name': - f'{pkg.name} License', + f'{pkg.name}', 'licenseId': - pkg.license_spdx_id, + license_id, 'extractedText': self.read_file(pkg.file), 'crossRefs': [{
diff --git a/tools/licenses/spdx_writer_test.py b/tools/licenses/spdx_writer_test.py index 67746dd..15945c9d 100755 --- a/tools/licenses/spdx_writer_test.py +++ b/tools/licenses/spdx_writer_test.py
@@ -4,6 +4,7 @@ # found in the LICENSE file. """Unit tests for //tools/spdx_writer.py.""" +import collections import os import sys import unittest @@ -13,6 +14,7 @@ from spdx_writer import _get_spdx_path from spdx_writer import _Package +from spdx_writer import _SPDXJSONWriter from test_utils import path_from_root @@ -41,5 +43,38 @@ self.assertEqual(self.p.license_spdx_id, 'LicenseRef-abc-def-ghi') +class SPDXJSONWriterTest(unittest.TestCase): + def setUp(self): + super().setUp() + + root_pkg = _Package('root', path_from_root('src', 'LICENSE')) + self.writer = _SPDXJSONWriter(path_from_root('src'), root_pkg, '', '', + '', lambda _: '') + + def test_get_dedup_id(self): + id_dict = collections.defaultdict(int) + elem_id = 'abc' + + id1 = self.writer._get_dedup_id(elem_id, id_dict) + self.assertEqual(id1, elem_id) + + id2 = self.writer._get_dedup_id(elem_id, id_dict) + self.assertEqual(id2, elem_id + '-1') + + def test_get_license_id(self): + license_path = path_from_root('src', 'p1', 'LICENSE') + p1 = _Package('p1', license_path) + + p1_id, need_license = self.writer._get_license_id(p1) + self.assertEqual(p1_id, p1.license_spdx_id) + self.assertTrue(need_license) + + # Try a new package with the same license path. + p2 = _Package('p2', license_path) + p2_id, need_license = self.writer._get_license_id(p2) + self.assertEqual(p2_id, p1.license_spdx_id) + self.assertFalse(need_license) + + if __name__ == '__main__': unittest.main()
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 040a599..65dd903f 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -29430,6 +29430,18 @@ <int value="9" label="WMV"/> </enum> +<enum name="DownloadWarningAction"> + <int value="0" label="SHOWN"/> + <int value="1" label="PROCEED"/> + <int value="2" label="DISCARD"/> + <int value="3" label="KEEP"/> + <int value="4" label="CLOSE"/> + <int value="5" label="CANCEL"/> + <int value="6" label="DISMISS"/> + <int value="7" label="BACK"/> + <int value="8" label="OPEN_SUBPAGE"/> +</enum> + <enum name="DownloadWarningSurface"> <int value="1" label="BUBBLE_MAINPAGE"/> <int value="2" label="BUBBLE_SUBPAGE"/> @@ -32315,6 +32327,7 @@ <int value="1042" label="ShowCastSessionsStartedByOtherDevices"/> <int value="1043" label="CloudAPAuthEnabled"/> <int value="1044" label="UsbDetectorNotificationEnabled"/> + <int value="1045" label="LacrosSelection"/> </enum> <enum name="EnterprisePoliciesSources"> @@ -51322,6 +51335,7 @@ <int value="9" label="Text node sibling (includes <b>, etc)"/> <int value="10" label="value attribute"/> <int value="11" label="<label> for attribute"/> + <int value="12" label="Succeeding DOM node overlaying the input"/> </enum> <enum name="InfoBarClosingStates">
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index dcc63339..fde8bad 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -1335,6 +1335,21 @@ </summary> </histogram> +<histogram + name="Android.FamilyLinkUser.LocalWebApprovalParentAuthenticationError" + units="Status error codes raised in GMS Core" expires_after="2023-03-26"> + <owner>anthie@google.com</owner> + <owner>ljjlee@google.com</owner> + <owner>chrome-kids-eng@google.com</owner> + <owner>cros-families-eng@google.com</owner> + <summary> + The different GMS error status codes that a user may encounter during the + parent authentication step in the local web approval flow. Recorded on + Android only. See go/chrome-local-web-approval-parent-auth-error-codes + (Googlers only) for the error code definitions. + </summary> +</histogram> + <histogram base="true" name="Android.FeatureModules.AvailabilityStatus" enum="FeatureModuleAvailabilityStatus" expires_after="2023-10-16"> <!-- Name completed by histogram_suffixes
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml index 6907b1e..faab4f5 100644 --- a/tools/metrics/histograms/metadata/arc/histograms.xml +++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -498,7 +498,7 @@ </histogram> <histogram name="Arc.AppShortcutSearchResult.ShortcutStatus" - enum="ArcAppShortcutStatus" expires_after="2022-12-04"> + enum="ArcAppShortcutStatus" expires_after="2023-06-10"> <owner>batoon@google.com</owner> <owner>arc-core@google.com</owner> <summary> @@ -509,7 +509,7 @@ </histogram> <histogram name="Arc.AppShortcutsRequest.ShortcutStatus" - enum="ArcAppShortcutStatus" expires_after="2022-12-04"> + enum="ArcAppShortcutStatus" expires_after="2023-06-10"> <owner>batoon@google.com</owner> <owner>arc-core@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 7f72314..1a8060f 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -346,6 +346,22 @@ </summary> </histogram> +<histogram name="Ash.ArcAppInitialAppsInstallDuration" units="ms" + expires_after="2023-12-01"> + <owner>alemate@chromium.org</owner> + <owner>khmel@chromium.org</owner> + <owner>arc-performance@google.com</owner> + <owner>chromeos-perfmetrics-eng@google.com</owner> + <summary> + For each user after they opted-in into ARC++, records the duration of + initial apps installation. Duration is measured as an interval between the + opt-in and the moment when all default apps become either "ready" + or "update error". This is only reported within the same opt-in + session, and is not reported if default apps were not installed within the + session. + </summary> +</histogram> + <histogram name="Ash.Assistant.AnimationSmoothness{AshAssistantAnimationSmoothness}" units="%" expires_after="2021-11-21"> @@ -3323,6 +3339,25 @@ </summary> </histogram> +<histogram name="Ash.NotifierFramework.Nudge.TimeToAction.{TimeRange}" + enum="NudgeCatalogName" expires_after="2023-02-10"> + <owner>kradtke@google.com</owner> + <owner>cros-status-area-eng@google.com</owner> + <summary> + Tracks the time from when a specific educational nudge is shown to when it's + interacted with. Starts measuring time when the nudge is shown and records + the Nudge catalog name in one of the time buckets available if the user + performs the expected action that the nudge is informing about. This metric + can be compared with `Ash.NotifierFramework.Nudge.ShownCount` to infer the + nudge action wasn't taken within that session. + </summary> + <token key="TimeRange"> + <variant name="Within1h"/> + <variant name="Within1m"/> + <variant name="WithinSession"/> + </token> +</histogram> + <histogram name="Ash.NotifierFramework.Toast.Dismissed.{TimeRange}" enum="ToastCatalogName" expires_after="2023-02-10"> <owner>kradtke@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/download/histograms.xml b/tools/metrics/histograms/metadata/download/histograms.xml index 54d1cf78..04f8ca9 100644 --- a/tools/metrics/histograms/metadata/download/histograms.xml +++ b/tools/metrics/histograms/metadata/download/histograms.xml
@@ -1447,6 +1447,19 @@ <summary>Records events for local video thumbnail retrieval.</summary> </histogram> +<histogram name="Download.WarningData.ActionAdded" enum="DownloadWarningAction" + expires_after="2023-06-07"> + <owner>xinghuilu@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records the warning action that is successfully added in warning action + event. Logged each time an action is taken on the download warning. For the + SHOWN action, only logged for the first time. Not logged if the action is + not added because the first warning is missing or the events have exceeded + the max length. + </summary> +</histogram> + <histogram name="Download.WarningData.AddWarningActionEventOutcome" enum="DownloadAddWarningActionEventOutcome" expires_after="2023-05-22"> <owner>xinghuilu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml index df5966a..7bcca37 100644 --- a/tools/metrics/histograms/metadata/gpu/histograms.xml +++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -1129,7 +1129,7 @@ </histogram> <histogram name="GPU.PaintOpReader.DeserializationError" - enum="PaintOpDeserializationError" expires_after="2023-01-22"> + enum="PaintOpDeserializationError" expires_after="2024-01-22"> <owner>junov@chromium.org</owner> <owner>graphics-dev@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index ed3fac18c..7fff9a1 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1353,6 +1353,27 @@ </token> </histogram> +<histogram name="History.Clusters.UpdateClusters.TimeBetweenTasks" units="ms" + expires_after="2023-10-01"> + <owner>manukh@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + The time elapsed between subsequent cluster update tasks + (HistoryClustersServiceTaskUpdateClusters). Depending on finch params, this + occurs either: + + 1) Never (e.g. if updating and persisting clusters is disabled). + + 2) OR N time after startup in addition to every M time; where N is typically + 5-60 minutes, and M is typically 1-12 hours. + + 3) OR on keyword refresh request bounded to at most every M time, where M is + typically 1-12 hours. Keyword refresh requests occur when the omnibox input + looks like a search query and journeys in the omnibox is enabled. + </summary> +</histogram> + <histogram name="History.Clusters.WebUISessionDuration" units="ms" expires_after="2023-04-16"> <owner>tommycli@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index fa42a9a..b59c6ed 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -7983,7 +7983,7 @@ </histogram> <histogram base="true" name="LoadingPredictor.PreconnectLearningPrecision" - units="%" expires_after="2022-12-19"> + units="%" expires_after="2023-12-12"> <owner>spelchat@chromium.org</owner> <owner>chrome-brapp-loading@chromium.org</owner> <summary> @@ -8018,7 +8018,7 @@ </histogram> <histogram name="LoadingPredictor.PreresolveCount" units="hosts" - expires_after="2022-12-19"> + expires_after="2023-12-12"> <owner>spelchat@chromium.org</owner> <owner>chrome-brapp-loading@chromium.org</owner> <summary> @@ -8029,7 +8029,7 @@ </histogram> <histogram name="LoadingPredictor.PreresolveHitsPercentage" units="%" - expires_after="2022-12-19"> + expires_after="2023-12-12"> <owner>spelchat@chromium.org</owner> <owner>chrome-brapp-loading@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml index 0fb01294..f4c76d3 100644 --- a/tools/metrics/histograms/metadata/startup/histograms.xml +++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -219,7 +219,7 @@ </histogram> <histogram name="Startup.Android.FeedsLoadingPlaceholderShown.Instant" - units="ms" expires_after="2023-01-15"> + units="ms" expires_after="2023-06-30"> <owner>hanxi@chromium.org</owner> <owner>wychen@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml index c69d0ec..65db5f3 100644 --- a/tools/metrics/histograms/metadata/tab/histograms.xml +++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -266,6 +266,16 @@ </summary> </histogram> +<histogram name="Tab.AgeAtDeletion" units="ms" expires_after="2023-12-13"> + <owner>ewannpv@chromium.org</owner> + <owner>gambard@chromium.org</owner> + <owner>bling-team@google.com</owner> + <summary> + The age of a Tab when closed (Time between creation time on the current + device and closure time). + </summary> +</histogram> + <histogram name="Tab.AgeUponRestoreFromColdStart" units="minutes" expires_after="M88"> <owner>dtrainor@chromium.org</owner>
diff --git a/tools/metrics/structured/structured.xml b/tools/metrics/structured/structured.xml index 33930cc8..7c449c5 100644 --- a/tools/metrics/structured/structured.xml +++ b/tools/metrics/structured/structured.xml
@@ -416,6 +416,13 @@ Project used to record a sequence of events that are related to each other. </summary> + <event name="UserLogin"> + <summary> + An event to signify a user is using the system. + </summary> + + </event> + <event name="Test1"> <summary> Test event used for unit tests to ensure that the code-gen for the event
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py index d83fe216..3a45dcbb 100644 --- a/tools/perf/core/bot_platforms.py +++ b/tools/perf/core/bot_platforms.py
@@ -681,7 +681,7 @@ 'android-pixel4a_power-perf-pgo', 'Android QD4A.200102.001.A1', _ANDROID_PIXEL4A_POWER_BENCHMARK_CONFIGS, 12, 'android') ANDROID_GO_WEMBLEY = PerfPlatform('android-go-wembley-perf', - 'Android M | MASTER', + 'Android 9131443', _ANDROID_GO_WEMBLEY_BENCHMARK_CONFIGS, 2, 'android') ANDROID_NEW_PIXEL = PerfPlatform('android-new-pixel-perf',
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 888e428d..8bde4a9 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -904,8 +904,7 @@ 'dimension': { 'pool': 'chrome.tests.perf', 'os': 'Android', - 'device_type': 'wembley', - 'device_os': 'MASTER', + 'device_type': 'wembley_2GB', 'device_os_flavor': 'google', }, },
diff --git a/tools/perf/core/perf_json_config_validator.py b/tools/perf/core/perf_json_config_validator.py index 3a88d3e..907c3bd 100644 --- a/tools/perf/core/perf_json_config_validator.py +++ b/tools/perf/core/perf_json_config_validator.py
@@ -68,7 +68,6 @@ raise ValueError('Invalid perf pool %s in %s' % (v, builder_name)) if k == 'os' and v == 'Android': if (not 'device_type' in dimension.keys() or - not 'device_os' in dimension.keys() or not 'device_os_flavor' in dimension.keys()): raise ValueError( 'Invalid android dimensions %s in %s' % (v, builder_name))
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 0d90eae..24101be 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/v31.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "ecbfa1398bd09e5a57bc5218aa9c7aec691cce25", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/ae7f044c460c89dac35657f618549998d665d7eb/trace_processor_shell.exe" + "hash": "cc817f9c3998e1c2dea11752c61456413c98f1f6", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/aa7e493dcf9bf77707735b98723b916e08561bbe/trace_processor_shell.exe" }, "linux_arm": { "hash": "6373f26144aad58f230d11d6a91efda5a09c9873", @@ -21,8 +21,8 @@ "full_remote_path": "perfetto-luci-artifacts/v31.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "47d0feffdbcd8c0dfe7650dd0874b4c7a291153f", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/ae7f044c460c89dac35657f618549998d665d7eb/trace_processor_shell" + "hash": "375e45389f78aec067a6df88497229d65190aa06", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/aa7e493dcf9bf77707735b98723b916e08561bbe/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/core/shard_maps/android-go-wembley-perf_map.json b/tools/perf/core/shard_maps/android-go-wembley-perf_map.json index 89006ec..b0494fa 100644 --- a/tools/perf/core/shard_maps/android-go-wembley-perf_map.json +++ b/tools/perf/core/shard_maps/android-go-wembley-perf_map.json
@@ -3,23 +3,28 @@ "benchmarks": { "speedometer2": { "abridged": false + }, + "startup.mobile": { + "end": 2, + "abridged": false } } }, "1": { "benchmarks": { "startup.mobile": { + "begin": 2, "abridged": false } } }, "extra_infos": { "num_stories": 5, - "predicted_min_shard_time": 40, + "predicted_min_shard_time": 20, "predicted_min_shard_index": 1, - "predicted_max_shard_time": 140.0, + "predicted_max_shard_time": 30, "predicted_max_shard_index": 0, - "shard #0": 140.0, - "shard #1": 40 + "shard #0": 30, + "shard #1": 20 } } \ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/android-go-wembley-perf_timing.json b/tools/perf/core/shard_maps/timing_data/android-go-wembley-perf_timing.json index 08f2d08..0637a08 100644 --- a/tools/perf/core/shard_maps/timing_data/android-go-wembley-perf_timing.json +++ b/tools/perf/core/shard_maps/timing_data/android-go-wembley-perf_timing.json
@@ -1,6 +1 @@ -[ - { - "duration": "140.0", - "name": "speedometer2/Speedometer2" - } -] \ No newline at end of file +[] \ No newline at end of file
diff --git a/tools/traffic_annotation/auditor/chromeos/safe_list.txt b/tools/traffic_annotation/auditor/chromeos/safe_list.txt index 96fc26073..e79f113 100644 --- a/tools/traffic_annotation/auditor/chromeos/safe_list.txt +++ b/tools/traffic_annotation/auditor/chromeos/safe_list.txt
@@ -11,7 +11,6 @@ all,chromeos/ash/services/device_sync/cryptauth_client_impl.cc all,chrome/browser/supervised_user/kids_chrome_management/kids_chrome_management_client.cc all,chrome/browser/ash/net/network_diagnostics/network_diagnostics_util.cc -all,chrome/browser/ash/net/network_diagnostics/http_request_manager.cc all,chrome/browser/ash/net/network_diagnostics/tls_prober.cc all,ash/quick_pair/repository/fast_pair/fast_pair_image_decoder.cc all,chrome/browser/search/background/ntp_background_service.cc
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index ca60eed2..f637e36 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -405,4 +405,5 @@ <item id="projector_xhr_loader" added_in_milestone="110" content_hash_code="071c4ac5" os_list="chromeos" file_path="ash/webui/projector_app/projector_xhr_sender.cc" /> <item id="bruschetta_installer_download" added_in_milestone="110" content_hash_code="01b953f4" os_list="chromeos" file_path="chrome/browser/ash/bruschetta/bruschetta_installer.cc" /> <item id="quick_start_session_auth_requester" added_in_milestone="110" content_hash_code="08353e70" os_list="chromeos" file_path="chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.cc" /> + <item id="network_diagnostics_routines" added_in_milestone="110" content_hash_code="0007b237" os_list="chromeos" file_path="chrome/browser/ash/net/network_diagnostics/http_request_manager.cc" /> </annotations>
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index 62326cd..64aa0f0a 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -272,6 +272,7 @@ <annotation id="projector_xhr_loader"/> <annotation id="bruschetta_installer_download"/> <annotation id="quick_start_session_auth_requester"/> + <annotation id="network_diagnostics_routines"/> </sender> </group> <group name="Admin Features" hidden="true">
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 67289b87..8f6206c 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -131,6 +131,14 @@ android_resources("ui_java_resources") { sources = [ + "java/res/anim/menu_enter.xml", + "java/res/anim/menu_enter_from_bottom.xml", + "java/res/anim/menu_enter_from_bottom_left.xml", + "java/res/anim/menu_enter_from_top_left.xml", + "java/res/anim/menu_exit.xml", + "java/res/anim/menu_exit_from_bottom.xml", + "java/res/anim/menu_exit_from_bottom_left.xml", + "java/res/anim/menu_exit_from_top_left.xml", "java/res/color/blue_when_enabled_dark.xml", "java/res/color/blue_when_enabled_list.xml", "java/res/color/default_text_color_light_list.xml", @@ -179,6 +187,7 @@ "java/res/values-ldrtl/values.xml", "java/res/values-night/colors.xml", "java/res/values-night/dimens.xml", + "java/res/values-sw600dp/dimens.xml", "java/res/values-sw600dp/values.xml", "java/res/values-sw720dp-v17/values.xml", "java/res/values-v17/styles.xml", @@ -193,6 +202,7 @@ "java/res/values/semantic_colors_adaptive.xml", "java/res/values/semantic_colors_non_adaptive.xml", "java/res/values/strings.xml", + "java/res/values/styles.xml", "java/res/values/values.xml", ]
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_enter.xml b/ui/android/java/res/anim/menu_enter.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_enter.xml rename to ui/android/java/res/anim/menu_enter.xml
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_enter_from_bottom.xml b/ui/android/java/res/anim/menu_enter_from_bottom.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_enter_from_bottom.xml rename to ui/android/java/res/anim/menu_enter_from_bottom.xml
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_enter_from_bottom_left.xml b/ui/android/java/res/anim/menu_enter_from_bottom_left.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_enter_from_bottom_left.xml rename to ui/android/java/res/anim/menu_enter_from_bottom_left.xml
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_enter_from_top_left.xml b/ui/android/java/res/anim/menu_enter_from_top_left.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_enter_from_top_left.xml rename to ui/android/java/res/anim/menu_enter_from_top_left.xml
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_exit.xml b/ui/android/java/res/anim/menu_exit.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_exit.xml rename to ui/android/java/res/anim/menu_exit.xml
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_exit_from_bottom.xml b/ui/android/java/res/anim/menu_exit_from_bottom.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_exit_from_bottom.xml rename to ui/android/java/res/anim/menu_exit_from_bottom.xml
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_exit_from_bottom_left.xml b/ui/android/java/res/anim/menu_exit_from_bottom_left.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_exit_from_bottom_left.xml rename to ui/android/java/res/anim/menu_exit_from_bottom_left.xml
diff --git a/components/browser_ui/widget/android/java/res/anim/menu_exit_from_top_left.xml b/ui/android/java/res/anim/menu_exit_from_top_left.xml similarity index 100% rename from components/browser_ui/widget/android/java/res/anim/menu_exit_from_top_left.xml rename to ui/android/java/res/anim/menu_exit_from_top_left.xml
diff --git a/ui/android/java/res/values-ldrtl/values.xml b/ui/android/java/res/values-ldrtl/values.xml index 913ceb9..6e02d750 100644 --- a/ui/android/java/res/values-ldrtl/values.xml +++ b/ui/android/java/res/values-ldrtl/values.xml
@@ -9,4 +9,8 @@ <!-- Expand more --> <integer name="expand_more_horizontal_rotation_degree" tools:ignore="UnusedResources">90</integer> + + <!-- Menu Animation Constants --> + <item type="fraction" format="fraction" name="menu_animation_pivot_x">5%</item> + <item type="fraction" format="fraction" name="menu_start_animation_pivot_x">95%</item> </resources>
diff --git a/ui/android/java/res/values-sw600dp/dimens.xml b/ui/android/java/res/values-sw600dp/dimens.xml new file mode 100644 index 0000000..26cc88c --- /dev/null +++ b/ui/android/java/res/values-sw600dp/dimens.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2019 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<resources> + <!-- Menu Dimensions --> + <!-- Necessary to align the menu icon with the actual button. --> + <dimen name="menu_negative_software_vertical_offset">6dp</dimen> +</resources> \ No newline at end of file
diff --git a/ui/android/java/res/values/dimens.xml b/ui/android/java/res/values/dimens.xml index afa55dc..7746c7d 100644 --- a/ui/android/java/res/values/dimens.xml +++ b/ui/android/java/res/values/dimens.xml
@@ -40,6 +40,9 @@ <dimen name="menu_footer_chip_icon_size">16dp</dimen> <dimen name="menu_footer_chip_vertical_inset">8dp</dimen> + <!-- Custom menu--> + <dimen name="menu_negative_software_vertical_offset">0dp</dimen> + <!-- Dropdown default measures --> <dimen name="dropdown_item_height">50dp</dimen> <dimen name="dropdown_item_divider_height">1px</dimen>
diff --git a/ui/android/java/res/values/styles.xml b/ui/android/java/res/values/styles.xml new file mode 100644 index 0000000..37042d7 --- /dev/null +++ b/ui/android/java/res/values/styles.xml
@@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2022 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<resources xmlns:tools="http://schemas.android.com/tools"> + <!-- AnchoredPopupAnimationStyle --> + <style name="AnchoredPopupAnimEndTop"> + <item name="android:windowEnterAnimation">@anim/menu_enter</item> + <item name="android:windowExitAnimation">@anim/menu_exit</item> + </style> + <style name="AnchoredPopupAnimEndBottom"> + <item name="android:windowEnterAnimation">@anim/menu_enter_from_bottom</item> + <item name="android:windowExitAnimation">@anim/menu_exit_from_bottom</item> + </style> + <style name="AnchoredPopupAnimStartTop"> + <item name="android:windowEnterAnimation">@anim/menu_enter_from_top_left</item> + <item name="android:windowExitAnimation">@anim/menu_exit_from_top_left</item> + </style> + <style name="AnchoredPopupAnimStartBottom"> + <item name="android:windowEnterAnimation">@anim/menu_enter_from_bottom_left</item> + <item name="android:windowExitAnimation">@anim/menu_exit_from_bottom_left</item> + </style> +</resources>
diff --git a/ui/android/java/res/values/values.xml b/ui/android/java/res/values/values.xml index e86eec9..6de551e 100644 --- a/ui/android/java/res/values/values.xml +++ b/ui/android/java/res/values/values.xml
@@ -16,4 +16,8 @@ <!-- Drag shadow resize ratio --> <item name="drag_shadow_resize_ratio" format="float" type="dimen">0.6</item> <item name="drag_shadow_max_size_to_window_ratio" format="float" type="dimen">0.35</item> + + <!-- Menu Animation Constants --> + <item type="fraction" format="fraction" name="menu_animation_pivot_x">95%</item> + <item type="fraction" format="fraction" name="menu_start_animation_pivot_x">5%</item> </resources>
diff --git a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java index a2d5e54..ff7a961 100644 --- a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java +++ b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
@@ -22,10 +22,12 @@ import android.widget.PopupWindow.OnDismissListener; import androidx.annotation.IntDef; +import androidx.annotation.StyleRes; import androidx.annotation.VisibleForTesting; import org.chromium.base.ObserverList; import org.chromium.base.metrics.RecordUserAction; +import org.chromium.ui.R; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -186,6 +188,9 @@ private boolean mUpdateOrientationOnChange; private boolean mSmartAnchorWithMaxWidth; + private @StyleRes int mAnimationStyleId; + private boolean mAnimateFromAnchor; + /** * Constructs an {@link AnchoredPopupWindow} instance. * @param context Context to draw resources from. @@ -313,15 +318,27 @@ } /** - * Sets the animation style for the popup. This should be called before the popup is shown. + * Sets the animation style for the popup. This should be called before the popup is shown. + * Setting this style will take precedence over {@link #setAnimateFromAnchor(boolean)}. * @param animationStyleId The id of the animation style. */ public void setAnimationStyle(int animationStyleId) { + mAnimationStyleId = animationStyleId; mPopupWindow.setAnimationStyle(animationStyleId); } /** - * If set to true, orientation will be updated everytime that the {@link OnRectChanged} is + * Set whether the popup should enter from / exit to the anchor point. This should be + * called before the popup is shown. If an animation style is specified by + * {@link #setAnimationStyle(int)}, this method will have no effect. + * @param animateFromAnchor Whether the popup should animator from anchor point. + */ + public void setAnimateFromAnchor(boolean animateFromAnchor) { + mAnimateFromAnchor = animateFromAnchor; + } + + /** + * If set to true, orientation will be updated every time that the {@link OnRectChanged} is * called. */ public void setUpdateOrientationOnChange(boolean updateOrientationOnChange) { @@ -728,7 +745,35 @@ return value; } - private void showPopupWindow() { + /** + * Calculate the style Id to use when showing the popup window, + * when {@link #setAnimateFromAnchor(true)}. + * @param isPositionBelow Whether the popup is positioned below the anchor rect. + * @param isPositionToLeft Whether the popup is positioned below the anchor rect. + * @return The style resource Id to use for {@link PopupWindow#setAnimationStyle} + */ + @VisibleForTesting + static @StyleRes int calculateAnimationStyle( + boolean isPositionBelow, boolean isPositionToLeft) { + if (isPositionToLeft) { + return isPositionBelow + ? R.style.AnchoredPopupAnimEndTop // Left + below -> enter top right (end) + : R.style.AnchoredPopupAnimEndBottom; // Left + above -> enter bottom right + // (end) + } + return isPositionBelow + ? R.style.AnchoredPopupAnimStartTop // Right & below -> enter top left (start) + : R.style.AnchoredPopupAnimStartBottom; // Right & above -> enter bottom left + // (start) + } + + @VisibleForTesting + void showPopupWindow() { + if (mAnimateFromAnchor && mAnimationStyleId == 0) { + int animationStyle = calculateAnimationStyle( + mPopupSpec.isPositionBelow, mPopupSpec.isPositionToLeft); + mPopupWindow.setAnimationStyle(animationStyle); + } try { mPopupWindow.showAtLocation(mRootView, Gravity.TOP | Gravity.START, mPopupSpec.popupRect.left, mPopupSpec.popupRect.top);
diff --git a/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java b/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java index 7ac05767..e038de1 100644 --- a/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java +++ b/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java
@@ -7,11 +7,20 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import android.app.Activity; import android.graphics.Rect; +import android.view.View; import android.widget.FrameLayout; +import android.widget.PopupWindow; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -21,6 +30,7 @@ import org.robolectric.shadows.ShadowView; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.ui.R; import org.chromium.ui.widget.AnchoredPopupWindow.HorizontalOrientation; import org.chromium.ui.widget.AnchoredPopupWindow.PopupSpec; import org.chromium.ui.widget.AnchoredPopupWindow.VerticalOrientation; @@ -53,6 +63,7 @@ private boolean mSmartAnchorWithMaxWidth; private FrameLayout mContentView; + private Activity mActivity; @Before public void setUp() { @@ -62,14 +73,21 @@ mPopupHeight = 300; mWindowRect = new Rect(0, 0, mRootWidth, mRootHeight); - final Activity activity = Robolectric.buildActivity(Activity.class).get(); - mContentView = new FrameLayout(activity); + mActivity = Robolectric.buildActivity(Activity.class).get(); + + mContentView = new FrameLayout(mActivity); mContentView.setMinimumWidth(mPopupWidth); mContentView.setMinimumHeight(mPopupHeight); setDefaultValueForAnchoredPopup(); } + @After + public void tearDown() { + mActivity.finish(); + UiWidgetFactory.setInstance(null); + } + @Test public void testGetPopupPosition_BelowRight() { Rect anchorRect = new Rect(10, 10, 20, 20); @@ -600,6 +618,71 @@ /*expectedPopupRect*/ new Rect(350, 800, 500, 1000)); } + @Test + public void calculateAnimationStyleStartTop() { + assertEquals("Position below right -> animate from start top.", + R.style.AnchoredPopupAnimStartTop, + AnchoredPopupWindow.calculateAnimationStyle(/*isPositionBelow*/ true, + /*isPositionToLeft*/ false)); + } + + @Test + public void calculateAnimationStyleStartBottom() { + assertEquals("Position above right -> animate from start bottom.", + R.style.AnchoredPopupAnimStartBottom, + AnchoredPopupWindow.calculateAnimationStyle(/*isPositionBelow*/ false, + /*isPositionToLeft*/ false)); + } + + @Test + public void calculateAnimationStyleEndTop() { + assertEquals("Position below left -> animate from end top.", + R.style.AnchoredPopupAnimEndTop, + AnchoredPopupWindow.calculateAnimationStyle(/*isPositionBelow*/ true, + /*isPositionToLeft*/ true)); + } + + @Test + public void calculateAnimationStyleEndBottom() { + assertEquals("Position above left -> animate from end bottom.", + R.style.AnchoredPopupAnimEndBottom, + AnchoredPopupWindow.calculateAnimationStyle(/*isPositionBelow*/ false, + /*isPositionToLeft*/ true)); + } + + @Test + public void setAnimateFromAnchor() { + // Set up for test case, so we have a mock popup window. + UiWidgetFactory mockFactory = mock(UiWidgetFactory.class); + UiWidgetFactory.setInstance(mockFactory); + + PopupWindow mockPopup = mock(PopupWindow.class); + doReturn(mockPopup).when(mockFactory).createPopupWindow(any()); + + AnchoredPopupWindow popupWindow = createAnchorPopupWindow(); + popupWindow.setAnimateFromAnchor(true); + popupWindow.showPopupWindow(); + verify(mockPopup).setAnimationStyle(anyInt()); + } + + @Test + public void setAnimationStyleNotOverrideByAnimateFromAnchor() { + // Set up for test case, so we have a mock popup window. + UiWidgetFactory mockFactory = mock(UiWidgetFactory.class); + UiWidgetFactory.setInstance(mockFactory); + PopupWindow mockPopup = mock(PopupWindow.class); + doReturn(mockPopup).when(mockFactory).createPopupWindow(any()); + + AnchoredPopupWindow popupWindow = createAnchorPopupWindow(); + popupWindow.setAnimationStyle(R.style.Animation_AppCompat_Dialog); + verify(mockPopup).setAnimationStyle(R.style.Animation_AppCompat_Dialog); + + popupWindow.setAnimateFromAnchor(true); + popupWindow.showPopupWindow(); + // setAnimationStyle should only called once, since #setAnimateFromAnchor is no-op. + verify(mockPopup, times(1)).setAnimationStyle(anyInt()); + } + private void setDefaultValueForAnchoredPopup() { mPaddingX = 0; mPaddingY = 0; @@ -632,4 +715,10 @@ String.format("PopupRect does not match expected Rect. Test case:<%s>", testCase), expectedRect, popupRect); } + + private AnchoredPopupWindow createAnchorPopupWindow() { + View rootView = mock(View.class); + RectProvider provider = new RectProvider(new Rect(0, 0, 0, 0)); + return new AnchoredPopupWindow(mActivity, rootView, null, mContentView, provider); + } }
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm index e554874..532fdfb 100644 --- a/ui/base/clipboard/clipboard_mac.mm +++ b/ui/base/clipboard/clipboard_mac.mm
@@ -135,8 +135,8 @@ // Safari only places RTF on the pasteboard, never HTML. We can convert RTF // to HTML, so the presence of either indicates success when looking for HTML. if (format == ClipboardFormatType::HtmlType()) { - return [types containsObject:NSHTMLPboardType] || - [types containsObject:NSRTFPboardType]; + return [types containsObject:NSPasteboardTypeHTML] || + [types containsObject:NSPasteboardTypeRTF]; } // Chrome can retrieve an image from the clipboard as either a bitmap or PNG. if (format == ClipboardFormatType::PngType() || @@ -266,14 +266,15 @@ NSPasteboard* pb = GetPasteboard(); NSArray* supportedTypes = - @[ NSHTMLPboardType, NSRTFPboardType, NSPasteboardTypeString ]; + @[ NSPasteboardTypeHTML, NSPasteboardTypeRTF, NSPasteboardTypeString ]; NSString* bestType = [pb availableTypeFromArray:supportedTypes]; if (bestType) { NSString* contents; - if ([bestType isEqualToString:NSRTFPboardType]) + if ([bestType isEqualToString:NSPasteboardTypeRTF]) { contents = ClipboardUtil::GetHTMLFromRTFOnPasteboard(pb); - else + } else { contents = [pb stringForType:bestType]; + } *markup = base::SysNSStringToUTF16(contents); } @@ -417,7 +418,7 @@ NSString* html_fragment = base::SysUTF8ToNSString(html_fragment_str); // TODO(avi): url_data? - [GetPasteboard() setString:html_fragment forType:NSHTMLPboardType]; + [GetPasteboard() setString:html_fragment forType:NSPasteboardTypeHTML]; } void ClipboardMac::WriteSvg(const char* markup_data, size_t markup_len) {
diff --git a/ui/base/dragdrop/os_exchange_data_provider_mac.mm b/ui/base/dragdrop/os_exchange_data_provider_mac.mm index 7f583d5..b5b03f0 100644 --- a/ui/base/dragdrop/os_exchange_data_provider_mac.mm +++ b/ui/base/dragdrop/os_exchange_data_provider_mac.mm
@@ -364,10 +364,9 @@ // static NSArray* OSExchangeDataProviderMac::SupportedPasteboardTypes() { return @[ - kUTTypeChromiumWebCustomData, kUTTypeWebKitWebURLsWithTitles, - NSURLPboardType, NSFilenamesPboardType, kUTTypeChromiumInitiatedDrag, - NSStringPboardType, NSHTMLPboardType, NSRTFPboardType, - NSFilenamesPboardType, kUTTypeChromiumWebCustomData, NSPasteboardTypeString + kUTTypeChromiumInitiatedDrag, kUTTypeChromiumWebCustomData, + kUTTypeWebKitWebURLsWithTitles, NSFilenamesPboardType, NSPasteboardTypeHTML, + NSPasteboardTypeRTF, NSPasteboardTypeString, NSPasteboardTypeURL ]; }
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 36483ab..77501b9 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -55,10 +55,6 @@ #include "ui/accelerated_widget_mac/ca_transaction_observer.h" #endif -#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) -#include "gpu/ipc/common/gpu_surface_tracker.h" -#endif - namespace ui { namespace { @@ -318,10 +314,6 @@ PerCompositorData* data = it->second.get(); frame_sink_manager_->UnregisterBeginFrameSource(data->begin_frame_source()); DCHECK(data); -#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) - if (data->surface_handle()) - gpu::GpuSurfaceTracker::Get()->RemoveSurface(data->surface_handle()); -#endif per_compositor_data_.erase(it); } @@ -399,20 +391,6 @@ } else { #if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) data->SetSurfaceHandle(widget); -#else - gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get(); - data->SetSurfaceHandle(tracker->AddSurfaceForNativeWidget( - gpu::GpuSurfaceTracker::SurfaceRecord( - widget -#if BUILDFLAG(IS_ANDROID) - // We have to provide a surface too, but we don't have one. For - // now, we don't proide it, since nobody should ask anyway. - // If we ever provide a valid surface here, then GpuSurfaceTracker - // can be more strict about enforcing it. - , - nullptr, false /* can_be_used_with_surface_control */ -#endif - ))); #endif }
diff --git a/ui/gfx/buffer_format_util.h b/ui/gfx/buffer_format_util.h index 01f17f55..35f4592f 100644 --- a/ui/gfx/buffer_format_util.h +++ b/ui/gfx/buffer_format_util.h
@@ -29,6 +29,11 @@ GFX_EXPORT size_t SubsamplingFactorForBufferFormat(BufferFormat format, size_t plane); +// Returns the alignment requirement to store a row of the given zero-indexed +// |plane| of |format|. +GFX_EXPORT size_t RowByteAlignmentForBufferFormat(BufferFormat format, + size_t plane); + // Returns the number of bytes used to store a row of the given zero-indexed // |plane| of |format|. GFX_EXPORT size_t RowSizeForBufferFormat(size_t width,
diff --git a/ui/gl/android/scoped_a_native_window.cc b/ui/gl/android/scoped_a_native_window.cc index 8e93462..a73ea62 100644 --- a/ui/gl/android/scoped_a_native_window.cc +++ b/ui/gl/android/scoped_a_native_window.cc
@@ -16,6 +16,9 @@ return ScopedANativeWindow(a_native_window); } +ScopedANativeWindow::ScopedANativeWindow() = default; +ScopedANativeWindow::ScopedANativeWindow(std::nullptr_t) {} + ScopedANativeWindow::ScopedANativeWindow(const ScopedJavaSurface& surface) { if (!surface.j_surface()) { return;
diff --git a/ui/gl/android/scoped_a_native_window.h b/ui/gl/android/scoped_a_native_window.h index 339f384..a5e5785 100644 --- a/ui/gl/android/scoped_a_native_window.h +++ b/ui/gl/android/scoped_a_native_window.h
@@ -5,6 +5,8 @@ #ifndef UI_GL_ANDROID_SCOPED_A_NATIVE_WINDOW_H_ #define UI_GL_ANDROID_SCOPED_A_NATIVE_WINDOW_H_ +#include <cstddef> + #include "ui/gl/gl_export.h" struct ANativeWindow; @@ -16,6 +18,8 @@ class GL_EXPORT ScopedANativeWindow { public: static ScopedANativeWindow Wrap(ANativeWindow* a_native_window); + ScopedANativeWindow(); + ScopedANativeWindow(std::nullptr_t); explicit ScopedANativeWindow(const ScopedJavaSurface& surface); ~ScopedANativeWindow();
diff --git a/ui/gl/android/scoped_java_surface.cc b/ui/gl/android/scoped_java_surface.cc index 8ac2f58c..d3bf54a 100644 --- a/ui/gl/android/scoped_java_surface.cc +++ b/ui/gl/android/scoped_java_surface.cc
@@ -14,14 +14,15 @@ namespace gl { -ScopedJavaSurface::ScopedJavaSurface() { -} +ScopedJavaSurface::ScopedJavaSurface() = default; +ScopedJavaSurface::ScopedJavaSurface(std::nullptr_t) {} ScopedJavaSurface::ScopedJavaSurface( - const base::android::JavaRef<jobject>& surface) { + const base::android::JavaRef<jobject>& surface, + bool auto_release) + : auto_release_(auto_release), j_surface_(surface) { JNIEnv* env = base::android::AttachCurrentThread(); DCHECK(env->IsInstanceOf(surface.obj(), android_view_Surface_clazz(env))); - j_surface_.Reset(surface); } ScopedJavaSurface::ScopedJavaSurface(const SurfaceTexture* surface_texture) { @@ -45,6 +46,10 @@ ReleaseSurfaceIfNeeded(); } +ScopedJavaSurface ScopedJavaSurface::CopyRetainOwnership() const { + return ScopedJavaSurface(j_surface_, /*auto_release=*/false); +} + void ScopedJavaSurface::ReleaseSurfaceIfNeeded() { if (auto_release_ && !j_surface_.is_null()) { JNIEnv* env = base::android::AttachCurrentThread(); @@ -56,7 +61,6 @@ ReleaseSurfaceIfNeeded(); j_surface_ = std::move(other.j_surface_); auto_release_ = other.auto_release_; - is_protected_ = other.is_protected_; } bool ScopedJavaSurface::IsEmpty() const { @@ -68,13 +72,4 @@ return !IsEmpty() && JNI_Surface::Java_Surface_isValidZ(env, j_surface_); } -// static -ScopedJavaSurface ScopedJavaSurface::AcquireExternalSurface( - const base::android::JavaRef<jobject>& surface) { - ScopedJavaSurface scoped_surface(surface); - scoped_surface.auto_release_ = false; - scoped_surface.is_protected_ = true; - return scoped_surface; -} - } // namespace gl
diff --git a/ui/gl/android/scoped_java_surface.h b/ui/gl/android/scoped_java_surface.h index b04b0a0..d11c73b5 100644 --- a/ui/gl/android/scoped_java_surface.h +++ b/ui/gl/android/scoped_java_surface.h
@@ -6,6 +6,7 @@ #define UI_GL_ANDROID_SCOPED_JAVA_SURFACE_H_ #include <jni.h> +#include <cstddef> #include "base/android/scoped_java_ref.h" #include "ui/gl/gl_export.h" @@ -20,9 +21,11 @@ class GL_EXPORT ScopedJavaSurface { public: ScopedJavaSurface(); + ScopedJavaSurface(std::nullptr_t); // Wraps an existing Java Surface object in a ScopedJavaSurface. - explicit ScopedJavaSurface(const base::android::JavaRef<jobject>& surface); + ScopedJavaSurface(const base::android::JavaRef<jobject>& surface, + bool auto_release); // Creates a Java Surface from a SurfaceTexture and wraps it in a // ScopedJavaSurface. @@ -33,26 +36,21 @@ ScopedJavaSurface(ScopedJavaSurface&& rvalue); ScopedJavaSurface& operator=(ScopedJavaSurface&& rhs); - // Creates a ScopedJavaSurface that is owned externally, i.e., - // someone else is responsible to call Surface.release(). - static ScopedJavaSurface AcquireExternalSurface( - const base::android::JavaRef<jobject>& surface); - ScopedJavaSurface(const ScopedJavaSurface&) = delete; ScopedJavaSurface& operator=(const ScopedJavaSurface&) = delete; ~ScopedJavaSurface(); + // Make a copy that does not retain ownership. Client is responsible for not + // using the copy after this is destroyed. + ScopedJavaSurface CopyRetainOwnership() const; + // Checks whether the surface is an empty one. bool IsEmpty() const; // Checks whether this object references a valid surface. bool IsValid() const; - // Checks whether the surface is hardware protected so that no readback is - // possible. - bool is_protected() const { return is_protected_; } - const base::android::JavaRef<jobject>& j_surface() const { return j_surface_; } @@ -63,7 +61,6 @@ void ReleaseSurfaceIfNeeded(); bool auto_release_ = true; - bool is_protected_ = false; base::android::ScopedJavaGlobalRef<jobject> j_surface_; };
diff --git a/ui/gl/gl_image_egl.h b/ui/gl/gl_image_egl.h index c5e6bcbc..4e4e1df 100644 --- a/ui/gl/gl_image_egl.h +++ b/ui/gl/gl_image_egl.h
@@ -17,8 +17,6 @@ // Abstract base class for EGL-based images. class GL_EXPORT GLImageEGL : public GLImage { public: - explicit GLImageEGL(const gfx::Size& size); - GLImageEGL(const GLImageEGL&) = delete; GLImageEGL& operator=(const GLImageEGL&) = delete; @@ -30,6 +28,7 @@ void ReleaseTexImage(unsigned target) override {} protected: + explicit GLImageEGL(const gfx::Size& size); ~GLImageEGL() override; // Same semantic as specified for eglCreateImageKHR. There two main usages:
diff --git a/ui/gl/gl_image_native_pixmap.cc b/ui/gl/gl_image_native_pixmap.cc index d492ad8f..68d0c7c 100644 --- a/ui/gl/gl_image_native_pixmap.cc +++ b/ui/gl/gl_image_native_pixmap.cc
@@ -126,6 +126,39 @@ } // namespace +scoped_refptr<GLImageNativePixmap> GLImageNativePixmap::Create( + const gfx::Size& size, + gfx::BufferFormat format, + scoped_refptr<gfx::NativePixmap> pixmap) { + return CreateForPlane(size, format, gfx::BufferPlane::DEFAULT, + std::move(pixmap)); +} + +scoped_refptr<GLImageNativePixmap> GLImageNativePixmap::CreateForPlane( + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferPlane plane, + scoped_refptr<gfx::NativePixmap> pixmap) { + auto image = + base::WrapRefCounted(new GLImageNativePixmap(size, format, plane)); + if (!image->Initialize(std::move(pixmap))) { + return nullptr; + } + return image; +} + +scoped_refptr<GLImageNativePixmap> GLImageNativePixmap::CreateFromTexture( + const gfx::Size& size, + gfx::BufferFormat format, + uint32_t texture_id) { + auto image = base::WrapRefCounted( + new GLImageNativePixmap(size, format, gfx::BufferPlane::DEFAULT)); + if (!image->InitializeFromTexture(texture_id)) { + return nullptr; + } + return image; +} + GLImageNativePixmap::GLImageNativePixmap(const gfx::Size& size, gfx::BufferFormat format, gfx::BufferPlane plane) @@ -238,7 +271,6 @@ &attrs[0])) { return false; } - did_initialize_ = true; } pixmap_ = pixmap; @@ -265,7 +297,6 @@ nullptr)) { return false; } - did_initialize_ = true; return true; } @@ -361,12 +392,10 @@ } bool GLImageNativePixmap::BindTexImage(unsigned target) { - DCHECK(did_initialize_); return GLImageEGL::BindTexImage(target); } bool GLImageNativePixmap::CopyTexImage(unsigned target) { - DCHECK(did_initialize_); if (egl_image_ != EGL_NO_IMAGE_KHR) return false;
diff --git a/ui/gl/gl_image_native_pixmap.h b/ui/gl/gl_image_native_pixmap.h index 59bd313..c54afe9 100644 --- a/ui/gl/gl_image_native_pixmap.h +++ b/ui/gl/gl_image_native_pixmap.h
@@ -17,14 +17,24 @@ class GL_EXPORT GLImageNativePixmap : public gl::GLImageEGL { public: - GLImageNativePixmap(const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferPlane plane = gfx::BufferPlane::DEFAULT); - // Create an EGLImage from a given NativePixmap. - bool Initialize(scoped_refptr<gfx::NativePixmap> pixmap); + static scoped_refptr<GLImageNativePixmap> Create( + const gfx::Size& size, + gfx::BufferFormat format, + scoped_refptr<gfx::NativePixmap> pixmap); + + // Create an EGLImage from a given NativePixmap and plane. + static scoped_refptr<GLImageNativePixmap> CreateForPlane( + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferPlane plane, + scoped_refptr<gfx::NativePixmap> pixmap); // Create an EGLImage from a given GL texture. - bool InitializeFromTexture(uint32_t texture_id); + static scoped_refptr<GLImageNativePixmap> CreateFromTexture( + const gfx::Size& size, + gfx::BufferFormat format, + uint32_t texture_id); + // Export the wrapped EGLImage to dmabuf fds. gfx::NativePixmapHandle ExportHandle(); @@ -45,11 +55,18 @@ ~GLImageNativePixmap() override; private: + GLImageNativePixmap(const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferPlane plane); + // Create an EGLImage from a given NativePixmap. + bool Initialize(scoped_refptr<gfx::NativePixmap> pixmap); + // Create an EGLImage from a given GL texture. + bool InitializeFromTexture(uint32_t texture_id); + gfx::BufferFormat format_; scoped_refptr<gfx::NativePixmap> pixmap_; gfx::BufferPlane plane_; bool has_image_dma_buf_export_; - bool did_initialize_; }; } // namespace gl
diff --git a/ui/gl/gl_image_native_pixmap_unittest.cc b/ui/gl/gl_image_native_pixmap_unittest.cc index dc65e52..aafe748 100644 --- a/ui/gl/gl_image_native_pixmap_unittest.cc +++ b/ui/gl/gl_image_native_pixmap_unittest.cc
@@ -59,8 +59,9 @@ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); - auto image = base::MakeRefCounted<gl::GLImageNativePixmap>(size, format); - EXPECT_TRUE(image->InitializeFromTexture(texture_id)); + auto image = + gl::GLImageNativePixmap::CreateFromTexture(size, format, texture_id); + EXPECT_TRUE(image); glDeleteTextures(1, &texture_id); return image;
diff --git a/ui/ozone/common/native_pixmap_egl_binding.cc b/ui/ozone/common/native_pixmap_egl_binding.cc index efb2090..d4c21a6 100644 --- a/ui/ozone/common/native_pixmap_egl_binding.cc +++ b/ui/ozone/common/native_pixmap_egl_binding.cc
@@ -22,15 +22,16 @@ const gfx::ColorSpace& color_space, GLenum target, GLuint texture_id) { - auto gl_image = base::MakeRefCounted<gl::GLImageNativePixmap>( - plane_size, plane_format, plane); - if (color_space.IsValid()) - gl_image->SetColorSpace(color_space); - if (!gl_image->Initialize(std::move(pixmap))) { + auto gl_image = gl::GLImageNativePixmap::CreateForPlane( + plane_size, plane_format, plane, std::move(pixmap)); + if (!gl_image) { LOG(ERROR) << "Unable to initialize GL image from pixmap"; return nullptr; } + if (color_space.IsValid()) + gl_image->SetColorSpace(color_space); + auto binding = std::make_unique<NativePixmapEGLBinding>(); if (!binding->BindTexture(std::move(gl_image), target, texture_id)) { return nullptr;
diff --git a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc index 8e1b4430b..6258cd0 100644 --- a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc +++ b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -122,12 +122,11 @@ ->GetSurfaceFactoryOzone() ->CreateNativePixmap(widget, nullptr, size, format, gfx::BufferUsage::SCANOUT); - auto image = base::MakeRefCounted<gl::GLImageNativePixmap>(size, format); - if (!image->Initialize(std::move(pixmap))) { + image_ = gl::GLImageNativePixmap::Create(size, format, std::move(pixmap)); + if (!image_) { LOG(ERROR) << "Failed to create GLImage"; return false; } - image_ = image; glBindTexture(GL_TEXTURE_2D, gl_tex_); image_->BindTexImage(GL_TEXTURE_2D);
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.cc b/ui/ozone/demo/surfaceless_gl_renderer.cc index f7baedf..d564ef0 100644 --- a/ui/ozone/demo/surfaceless_gl_renderer.cc +++ b/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -93,12 +93,11 @@ ->GetSurfaceFactoryOzone() ->CreateNativePixmap(widget, nullptr, size, format, gfx::BufferUsage::SCANOUT); - auto image = base::MakeRefCounted<gl::GLImageNativePixmap>(size, format); - if (!image->Initialize(std::move(pixmap))) { + image_ = gl::GLImageNativePixmap::Create(size, format, std::move(pixmap)); + if (!image_) { LOG(ERROR) << "Failed to create GLImage"; return false; } - image_ = image; glBindFramebufferEXT(GL_FRAMEBUFFER, gl_fb_); glBindTexture(GL_TEXTURE_2D, gl_tex_);
diff --git a/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc b/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc index 061e5507..425ea8fd 100644 --- a/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc +++ b/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc
@@ -60,8 +60,9 @@ client_pixmap->Unmap(); } - auto image = base::MakeRefCounted<gl::GLImageNativePixmap>(size, format); - EXPECT_TRUE(image->Initialize(pixmap.get())); + auto image = + gl::GLImageNativePixmap::Create(size, format, std::move(pixmap)); + EXPECT_TRUE(image); return image; }
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index 9dfb392f..38934c5e 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -128,8 +128,10 @@ void OnDragDrop(std::unique_ptr<OSExchangeData> data, int modifiers) override { MockOnDragDrop(); - on_drop_closure_.Run(); - on_drop_closure_.Reset(); + if (on_drop_closure_) { + on_drop_closure_.Run(); + on_drop_closure_.Reset(); + } } int OnDragMotion(const gfx::PointF& point, @@ -501,9 +503,21 @@ SendMotionEvent(top_left); } +// Emulating an incoming DnD session, ensures that data drag controller +// fetches all the data for the mime-types offered by the source client. TEST_P(WaylandDataDragControllerTest, DropSeveralMimeTypes) { - EXPECT_CALL(*drop_handler_, MockOnDragEnter()).Times(1); const uint32_t surface_id = window_->root_surface()->get_surface_id(); + + // As data for each offered mime-type is asynchronously read (eg: using + // wl_display.sync callbacks, etc), a nested run loop is used to ensure + // it is reliably done. Furthermore, WmDropHandler::OnDragEnter() is expected + // to be called only once the data is fully fetched, so it's used here as + // condition to quit the loop and verify the expectations, otherwise some + // flakiness may be observed, see https://crbug.com/1395127. + base::RunLoop loop; + EXPECT_CALL(*drop_handler_, MockOnDragEnter()).WillOnce([&loop]() { + loop.Quit(); + }); PostToServerAndWait([surface_id](wl::TestWaylandServerThread* server) { auto* data_offer = server->data_device_manager()->data_device()->CreateAndSendDataOffer(); @@ -522,15 +536,13 @@ 1002, surface->resource(), wl_fixed_from_int(entered_point.x()), wl_fixed_from_int(entered_point.y()), data_offer); }); + loop.Run(); + Mock::VerifyAndClearExpectations(drop_handler_.get()); EXPECT_CALL(*drop_handler_, MockOnDragDrop()).Times(1); - base::RunLoop loop; - drop_handler_->SetOnDropClosure(loop.QuitClosure()); PostToServerAndWait([](wl::TestWaylandServerThread* server) { server->data_device_manager()->data_device()->OnDrop(); }); - - loop.Run(); Mock::VerifyAndClearExpectations(drop_handler_.get()); ASSERT_NE(drop_handler_->dropped_data(), nullptr);
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index bc48ab46..2b0181d 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -605,7 +605,7 @@ Emoji && Symbols </message> </if> - <if expr="chromeos_ash"> + <if expr="is_chromeos"> <message name="IDS_APP_SHOW_CLIPBOARD_HISTORY" desc="The context menu item to show the clipboard history menu."> Clipboard </message>
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index c92b020..e683ccc1 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -596,11 +596,11 @@ } if (is_chromeos) { - sources += [ "controls/menu/menu_config_chromeos.cc" ] - if (!is_chromeos_lacros) { - public += [ "controls/views_text_services_context_menu_chromeos.h" ] - sources += [ "controls/views_text_services_context_menu_chromeos.cc" ] - } + public += [ "controls/views_text_services_context_menu_chromeos.h" ] + sources += [ + "controls/menu/menu_config_chromeos.cc", + "controls/views_text_services_context_menu_chromeos.cc", + ] } if (is_mac) {
diff --git a/ui/views/cocoa/immersive_mode_controller_unittest.mm b/ui/views/cocoa/immersive_mode_controller_unittest.mm index 51aa430a..9579af9 100644 --- a/ui/views/cocoa/immersive_mode_controller_unittest.mm +++ b/ui/views/cocoa/immersive_mode_controller_unittest.mm
@@ -236,11 +236,16 @@ [fullscreen_window.get().contentView addSubview:titlebar_container_view]; [fullscreen_window orderBack:nil]; + auto immersive_mode_controller = std::make_unique<ImmersiveModeController>( + browser(), overlay(), base::DoNothing()); + base::WeakPtrFactory<ImmersiveModeController> weak_ptr_factory( + immersive_mode_controller.get()); + // Create a titlebar observer. This is the class under test. base::scoped_nsobject<ImmersiveModeTitlebarObserver> titlebar_observer( [[ImmersiveModeTitlebarObserver alloc] - initWithOverlayWindow:overlay() - overlayView:overlay_view]); + initWithController:weak_ptr_factory.GetWeakPtr() + overlayView:overlay_view]); // Observer the fake fake titlebar container view. [titlebar_container_view addObserver:titlebar_observer
diff --git a/ui/views/controls/views_text_services_context_menu_base.cc b/ui/views/controls/views_text_services_context_menu_base.cc index 2ec8faa..57d33de 100644 --- a/ui/views/controls/views_text_services_context_menu_base.cc +++ b/ui/views/controls/views_text_services_context_menu_base.cc
@@ -88,7 +88,7 @@ return command_id == IDS_CONTENT_CONTEXT_EMOJI; } -#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_CHROMEOS_ASH) +#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_CHROMEOS) // static std::unique_ptr<ViewsTextServicesContextMenu> ViewsTextServicesContextMenu::Create(ui::SimpleMenuModel* menu,
diff --git a/ui/views/controls/views_text_services_context_menu_base.h b/ui/views/controls/views_text_services_context_menu_base.h index 1bd3aa3..7bdea6d 100644 --- a/ui/views/controls/views_text_services_context_menu_base.h +++ b/ui/views/controls/views_text_services_context_menu_base.h
@@ -35,7 +35,7 @@ bool SupportsCommand(int command_id) const override; protected: -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) Textfield* client() { return client_; } const Textfield* client() const { return client_; } #endif
diff --git a/ui/views/controls/views_text_services_context_menu_chromeos.cc b/ui/views/controls/views_text_services_context_menu_chromeos.cc index 63de8cf..86c09714 100644 --- a/ui/views/controls/views_text_services_context_menu_chromeos.cc +++ b/ui/views/controls/views_text_services_context_menu_chromeos.cc
@@ -34,10 +34,11 @@ // In unit tests, `impl_factory` may not be set. Use // `ViewTextServicesContextMenuBase` in that case. - if (impl_factory) + if (impl_factory) { impl_ = impl_factory.Run(menu, client); - else + } else { impl_ = std::make_unique<ViewsTextServicesContextMenuBase>(menu, client); + } } ViewsTextServicesContextMenuChromeos::~ViewsTextServicesContextMenuChromeos() = @@ -66,7 +67,7 @@ bool ViewsTextServicesContextMenuChromeos::SupportsCommand( int command_id) const { - return impl_->IsCommandIdEnabled(command_id); + return impl_->SupportsCommand(command_id); } // static
diff --git a/ui/views/controls/views_text_services_context_menu_chromeos.h b/ui/views/controls/views_text_services_context_menu_chromeos.h index 9cdd0de..f583a26 100644 --- a/ui/views/controls/views_text_services_context_menu_chromeos.h +++ b/ui/views/controls/views_text_services_context_menu_chromeos.h
@@ -12,8 +12,9 @@ namespace views { -// This class is used to add and handle text service items in the text context -// menu under the CrOS environment. +// This class is used to add and handle text service items in ChromeOS native UI +// textfield context menus. The implementation is specific to the platform (Ash +// or Lacros) where the textfield lives. class VIEWS_EXPORT ViewsTextServicesContextMenuChromeos : public ViewsTextServicesContextMenu { public: @@ -40,9 +41,9 @@ bool SupportsCommand(int command_id) const override; private: - // CrOS functionality must be provided by the embedder, so requests are - // forwarded to this concrete object, whose construction can be controlled by - // `SetImplFactory()`. + // ChromeOS functionality is provided by a platform-specific implementation. + // Function calls are forwarded to this instance, whose construction is + // controlled by `SetImplFactory()`. std::unique_ptr<ViewsTextServicesContextMenu> impl_; };
diff --git a/ui/webui/resources/cr_components/history_clusters/url_visit.html b/ui/webui/resources/cr_components/history_clusters/url_visit.html index d552dbd..86e5985 100644 --- a/ui/webui/resources/cr_components/history_clusters/url_visit.html +++ b/ui/webui/resources/cr_components/history_clusters/url_visit.html
@@ -47,7 +47,7 @@ margin-inline-end: var(--cluster-padding-horizontal); min-width: 0; outline: none; - padding-inline-end: 2px; /* So focus outline does not intersect text */ + padding-inline: 2px; /* So focus outline does not intersect text */ } :host(:hover) #link-container {
diff --git a/ui/webui/resources/js/metrics_reporter/BUILD.gn b/ui/webui/resources/js/metrics_reporter/BUILD.gn index 6fcb00b..487a50b 100644 --- a/ui/webui/resources/js/metrics_reporter/BUILD.gn +++ b/ui/webui/resources/js/metrics_reporter/BUILD.gn
@@ -10,6 +10,7 @@ sources = [ "metrics_reporter.mojom" ] webui_module_path = "chrome://resources/js/metrics_reporter" public_deps = [ "//mojo/public/mojom/base" ] + use_typescript_sources = true } # Output folder used to hold ts_library() output. @@ -20,24 +21,24 @@ root_dir = target_gen_dir out_dir = preprocess_folder composite = true - tsconfig_base = "tsconfig_base.json" in_files = [ "metrics_reporter.ts", "browser_proxy.ts", - "metrics_reporter.mojom-webui.js", + "metrics_reporter.mojom-webui.ts", ] definitions = [ "//tools/typescript/definitions/chrome_timeticks.d.ts" ] deps = [ "//ui/webui/resources:library", "//ui/webui/resources/mojo:library", ] - extra_deps = [ ":copy_src_and_mojom" ] + extra_deps = [ + ":copy_src", + ":mojo_bindings_ts__generator", + ] } -copy("copy_src_and_mojom") { - deps = [ ":mojo_bindings_js__generator" ] +copy("copy_src") { sources = [ - "$root_gen_dir/mojom-webui/ui/webui/resources/js/metrics_reporter/metrics_reporter.mojom-webui.js", "browser_proxy.ts", "metrics_reporter.ts", ]
diff --git a/ui/webui/resources/js/metrics_reporter/tsconfig_base.json b/ui/webui/resources/js/metrics_reporter/tsconfig_base.json deleted file mode 100644 index 5502828..0000000 --- a/ui/webui/resources/js/metrics_reporter/tsconfig_base.json +++ /dev/null
@@ -1,6 +0,0 @@ -{ - "extends": "../../../../../tools/typescript/tsconfig_base.json", - "compilerOptions": { - "allowJs": true - } -}