diff --git a/DEPS b/DEPS index 743a2d4..9904bed 100644 --- a/DEPS +++ b/DEPS
@@ -253,15 +253,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': '3b238ceae9c3381b2333e7bff794a0d88eb3fce9', + 'skia_revision': 'ae5984082b5e7aa4e7c4c8f9201f83bca067f66e', # 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': '19907681704961ae0e5b537cfdcd7ad1b6bc83f1', + 'v8_revision': '119490592b44642f2730b8954002a7268eb04605', # 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': '18c36f8aa629231795c82831a2cf80e8f77f989a', + 'angle_revision': 'cbbf5b5dafeda4191b0f41914127b4ccf14d7a5b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -269,7 +269,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '24a4746f1a4862b3eb86103e555ee5e9bc831a11', + 'pdfium_revision': '7b7976446504d893878fd46514f283275ce90d08', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -320,7 +320,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '72a759f77919cfc8cad63a5c1f670eda3f94c3d1', + 'catapult_revision': 'b2ed43640f35da1fb8e352d8a08f074c70b9bee8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -368,7 +368,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'cbdde604b87f27128185c8f9393f2c3d2211b7fc', + 'dawn_revision': '1e988b417ccb9cce2fa79a04dc942d60a1dccee8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -728,7 +728,7 @@ }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '6d04bede62d40373947a87e6b7dac3033199da83', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '0c6bc2b507d0efe5091094099086de7b9035e924', 'condition': 'checkout_ios', }, @@ -1523,7 +1523,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '8c8fafb6ff4b4a715b868915840fc95040290ef7', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd89b25832b668dcf2d55bccbfb57f9a24723b869', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1814,7 +1814,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f187e24914c62ce9b26be9bd23a548755a0e75ac', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ca7a17a9c855382eae3465f5a846679c5273d47d', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java index 6f09dda..c66ed749 100644 --- a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java +++ b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java
@@ -356,6 +356,15 @@ setUrlBarText(url); setUrlFail(false); loadUrlFromUrlBar(mUrlBar); + + mMultiFileSelector = new MultiFileSelector(); + mFileContents = + registerForActivityResult(mMultiFileSelector, new ActivityResultCallback<Uri[]>() { + @Override + public void onActivityResult(Uri[] result) { + mFilePathCallback.onReceiveValue(result); + } + }); } @Override @@ -493,14 +502,6 @@ } }); - mMultiFileSelector = new MultiFileSelector(); - mFileContents = - registerForActivityResult(mMultiFileSelector, new ActivityResultCallback<Uri[]>() { - @Override - public void onActivityResult(Uri[] result) { - mFilePathCallback.onReceiveValue(result); - } - }); mWebView = webview; getContainer().addView( webview, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
diff --git a/ash/clipboard/clipboard_history_controller_unittest.cc b/ash/clipboard/clipboard_history_controller_unittest.cc index ae064766..2013e58 100644 --- a/ash/clipboard/clipboard_history_controller_unittest.cc +++ b/ash/clipboard/clipboard_history_controller_unittest.cc
@@ -6,7 +6,6 @@ #include <memory> #include <vector> -#include "build/build_config.h" #include "ash/app_list/app_list_controller_impl.h" #include "ash/clipboard/clipboard_history.h" @@ -20,6 +19,7 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/repeating_test_future.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_future.h" #include "base/threading/sequenced_task_runner_handle.h" @@ -46,14 +46,6 @@ run_loop.Run(); } -void WriteToClipboard(const std::string& str) { - { - ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); - scw.WriteText(base::UTF8ToUTF16(str)); - } - FlushMessageLoop(); -} - class MockClipboardImageModelFactory : public ClipboardImageModelFactory { public: MockClipboardImageModelFactory() = default; @@ -113,6 +105,8 @@ chromeos::features::kClipboardHistory); AshTestBase::SetUp(); mock_image_factory_ = std::make_unique<MockClipboardImageModelFactory>(); + GetClipboardHistoryController()->set_confirmed_operation_callback_for_test( + operation_confirmed_future_.GetCallback()); } ClipboardHistoryControllerImpl* GetClipboardHistoryController() { @@ -121,6 +115,26 @@ void ShowMenu() { PressAndReleaseKey(ui::VKEY_V, ui::EF_COMMAND_DOWN); } + void WaitForOperationConfirmed() { + EXPECT_TRUE(operation_confirmed_future_.Take()); + } + + void WriteImageToClipboardAndConfirm(const SkBitmap& bitmap) { + { + ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); + scw.WriteImage(bitmap); + } + WaitForOperationConfirmed(); + } + + void WriteTextToClipboardAndConfirm(const std::u16string& str) { + { + ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); + scw.WriteText(str); + } + WaitForOperationConfirmed(); + } + base::Value::List GetHistoryValues() { base::test::TestFuture<base::Value> future; GetClipboardHistoryController()->GetHistoryValuesForTest( @@ -155,6 +169,9 @@ EXPECT_EQ(0u, locked_before_query_result.size()); } + protected: + base::test::RepeatingTestFuture<bool> operation_confirmed_future_; + private: base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<MockClipboardImageModelFactory> mock_image_factory_; @@ -178,7 +195,7 @@ TEST_F(ClipboardHistoryControllerTest, MultiShowMenu) { base::HistogramTester histogram_tester; // Copy something to enable the clipboard history menu. - WriteToClipboard("test"); + WriteTextToClipboardAndConfirm(u"test"); ShowMenu(); @@ -233,7 +250,7 @@ // menu view should not show (https://crbug.com/1100739). TEST_F(ClipboardHistoryControllerTest, VerifyAvailabilityInUserModes) { // Write one item into the clipboard history. - WriteToClipboard("text"); + WriteTextToClipboardAndConfirm(u"text"); constexpr struct { user_manager::UserType user_type; @@ -258,7 +275,21 @@ Shell::Get()->session_controller()->UpdateUserSession(session); // Write a new item into the clipboard buffer. - WriteToClipboard("test"); + { + ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); + scw.WriteText(u"test"); + } + + if (test_case.is_enabled) { + WaitForOperationConfirmed(); + } else { + FlushMessageLoop(); + // Note: This check might not catch a scenario where a mode expected to be + // disabled actually allows writes to go through, because the operation + // might not have finished yet in that case. The history verification + // below mitigates the chance that such a bug would not be caught. + EXPECT_TRUE(operation_confirmed_future_.IsEmpty()); + } const std::list<ClipboardHistoryItem>& items = Shell::Get()->clipboard_history_controller()->history()->GetItems(); @@ -298,7 +329,7 @@ // Verifies that the clipboard history menu is disabled when the screen for // user adding shows. TEST_F(ClipboardHistoryControllerTest, DisableInUserAddingScreen) { - WriteToClipboard("text"); + WriteTextToClipboardAndConfirm(u"text"); // Emulate that the user adding screen displays. Shell::Get()->session_controller()->ShowMultiProfileLogin(); @@ -330,7 +361,7 @@ // Tests that clearing the clipboard clears ClipboardHistory TEST_F(ClipboardHistoryControllerTest, ClearClipboardClearsHistory) { // Write a single item to ClipboardHistory. - WriteToClipboard("test"); + WriteTextToClipboardAndConfirm(u"test"); // Clear the clipboard. ui::Clipboard::GetForCurrentThread()->Clear(ui::ClipboardBuffer::kCopyPaste); @@ -350,7 +381,7 @@ TEST_F(ClipboardHistoryControllerTest, ClearingClipboardClosesClipboardHistory) { // Write a single item to ClipboardHistory. - WriteToClipboard("test"); + WriteTextToClipboardAndConfirm(u"test"); ASSERT_TRUE(Shell::Get()->cursor_manager()->IsCursorVisible()); @@ -370,15 +401,10 @@ TEST_F(ClipboardHistoryControllerTest, EncodeImage) { // Write a bitmap to ClipboardHistory. SkBitmap test_bitmap = gfx::test::CreateBitmap(3, 2); - { - ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); - scw.WriteImage(test_bitmap); - } - FlushMessageLoop(); + WriteImageToClipboardAndConfirm(test_bitmap); - // The bitmap should be encoded to a PNG once this task completes. Manually - // pry into the contents of the result to confirm that the newly-encoded PNG - // is included. + // The bitmap should be encoded to a PNG. Manually pry into the contents of + // the result to confirm that the newly-encoded PNG is included. auto result = GetHistoryValues(); EXPECT_EQ(1u, result.size()); @@ -391,64 +417,60 @@ test_bitmaps.emplace_back(gfx::test::CreateBitmap(2, 1)); test_bitmaps.emplace_back(gfx::test::CreateBitmap(3, 2)); test_bitmaps.emplace_back(gfx::test::CreateBitmap(4, 3)); - for (const auto& test_bitmap : test_bitmaps) { - ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); - scw.WriteImage(test_bitmap); - FlushMessageLoop(); - } + for (const auto& test_bitmap : test_bitmaps) + WriteImageToClipboardAndConfirm(test_bitmap); - // The bitmaps should be encoded to PNGs once this task completes. Manually - // pry into the contents of the result to confirm that the newly-encoded PNGs - // are included. auto result = GetHistoryValues(); auto num_results = result.size(); EXPECT_EQ(num_results, test_bitmaps.size()); - // History values should be sorted by recency. + // The bitmaps should be encoded to PNGs. Manually pry into the contents of + // the result to confirm that the newly-encoded PNGs are included. History + // values should be sorted by recency. for (uint i = 0; i < num_results; ++i) { ExpectHistoryValueMatchesBitmap(result[i].GetIfDict(), test_bitmaps[num_results - 1 - i]); } } -#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) -#define MAYBE_WriteBitmapWhileEncodingImage \ - DISABLED_WriteBitmapWhileEncodingImage -#else -#define MAYBE_WriteBitmapWhileEncodingImage WriteBitmapWhileEncodingImage -#endif -TEST_F(ClipboardHistoryControllerTest, MAYBE_WriteBitmapWhileEncodingImage) { +TEST_F(ClipboardHistoryControllerTest, WriteBitmapWhileEncodingImage) { // Write a bitmap to ClipboardHistory. std::vector<const SkBitmap> test_bitmaps; test_bitmaps.emplace_back(gfx::test::CreateBitmap(3, 2)); test_bitmaps.emplace_back(gfx::test::CreateBitmap(4, 3)); - { - ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); - scw.WriteImage(test_bitmaps[0]); - } - FlushMessageLoop(); + WriteImageToClipboardAndConfirm(test_bitmaps[0]); // Write another bitmap to the clipboard while encoding the first bitmap. GetClipboardHistoryController() ->set_new_bitmap_to_write_while_encoding_for_test(test_bitmaps[1]); - // Both bitmaps should be encoded to a PNG once this task completes. Manually - // pry into the contents of the result to confirm that the newly-encoded PNGs - // are included. - auto result = GetHistoryValues(); - auto num_results = result.size(); + // Make sure the second bitmap is written to the clipboard before history + // values are returned. + GetClipboardHistoryController()->BlockGetHistoryValuesForTest(); + base::test::TestFuture<base::Value> future; + GetClipboardHistoryController()->GetHistoryValuesForTest( + future.GetCallback()); + EXPECT_FALSE(future.IsReady()); + WaitForOperationConfirmed(); + + GetClipboardHistoryController()->ResumeGetHistoryValuesForTest(); + auto* result = future.Get().GetIfList(); + ASSERT_TRUE(result); + auto num_results = result->size(); EXPECT_EQ(num_results, test_bitmaps.size()); - // History values should be sorted by recency. + // Both bitmaps should be encoded to PNGs. Manually pry into the contents of + // the result to confirm that the newly-encoded PNGs are included. History + // values should be sorted by recency. for (uint i = 0; i < num_results; ++i) { - ExpectHistoryValueMatchesBitmap(result[i].GetIfDict(), + ExpectHistoryValueMatchesBitmap((*result)[i].GetIfDict(), test_bitmaps[num_results - 1 - i]); } } TEST_F(ClipboardHistoryControllerTest, LockedScreenText) { // Write text to ClipboardHistory and verify that it can be retrieved. - WriteToClipboard("test"); + WriteTextToClipboardAndConfirm(u"test"); auto history_list_value = GetHistoryValues(); EXPECT_EQ(1u, history_list_value.size()); auto* history_list_item = history_list_value[0].GetIfDict(); @@ -463,11 +485,7 @@ TEST_F(ClipboardHistoryControllerTest, LockedScreenImage) { // Write a bitmap to ClipboardHistory and verify that it can be returned. SkBitmap test_bitmap = gfx::test::CreateBitmap(3, 2); - { - ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); - scw.WriteImage(test_bitmap); - } - FlushMessageLoop(); + WriteImageToClipboardAndConfirm(test_bitmap); auto result = GetHistoryValues(); EXPECT_EQ(1u, result.size()); ExpectHistoryValueMatchesBitmap(result[0].GetIfDict(), test_bitmap);
diff --git a/ash/components/arc/arc_features.cc b/ash/components/arc/arc_features.cc index 4f9f766d..21a26be 100644 --- a/ash/components/arc/arc_features.cc +++ b/ash/components/arc/arc_features.cc
@@ -93,10 +93,6 @@ const base::Feature kKeyboardShortcutHelperIntegrationFeature{ "ArcKeyboardShortcutHelperIntegration", base::FEATURE_DISABLED_BY_DEFAULT}; -// Controls ARC mouse wheel smooth scroll compatibility feature. -const base::Feature kMouseWheelSmoothScroll{"ArcMouseWheelSmoothScroll", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Controls experimental 64-bit native bridge support for ARC on boards that // have 64-bit native bridge support available but not yet enabled. const base::Feature kNativeBridge64BitSupportExperimentFeature{
diff --git a/ash/components/arc/arc_features.h b/ash/components/arc/arc_features.h index 232b61fd..2f5607bd 100644 --- a/ash/components/arc/arc_features.h +++ b/ash/components/arc/arc_features.h
@@ -31,7 +31,6 @@ extern const base::Feature kLogdConfig; extern const base::FeatureParam<int> kLogdConfigSize; extern const base::Feature kKeyboardShortcutHelperIntegrationFeature; -extern const base::Feature kMouseWheelSmoothScroll; extern const base::Feature kNativeBridge64BitSupportExperimentFeature; extern const base::Feature kNativeBridgeToggleFeature; extern const base::Feature kOutOfProcessVideoDecoding;
diff --git a/ash/components/arc/compat_mode/arc_resize_lock_manager.cc b/ash/components/arc/compat_mode/arc_resize_lock_manager.cc index a834a6b..2675cecb 100644 --- a/ash/components/arc/compat_mode/arc_resize_lock_manager.cc +++ b/ash/components/arc/compat_mode/arc_resize_lock_manager.cc
@@ -181,11 +181,7 @@ ArcBridgeService* arc_bridge_service) : compat_mode_button_controller_( std::make_unique<CompatModeButtonController>()), - touch_mode_mouse_rewriter_( - base::FeatureList::IsEnabled(arc::kRightClickLongPress) || - base::FeatureList::IsEnabled(arc::kMouseWheelSmoothScroll) - ? std::make_unique<TouchModeMouseRewriter>() - : nullptr) { + touch_mode_mouse_rewriter_(std::make_unique<TouchModeMouseRewriter>()) { if (aura::Env::HasInstance()) env_observation.Observe(aura::Env::GetInstance()); }
diff --git a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc index 0b53150..d2e16527 100644 --- a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc +++ b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc
@@ -101,9 +101,6 @@ const bool in_resize_locked = IsInResizeLockedWindow(target); if (event.IsMouseWheelEvent()) { - if (!base::FeatureList::IsEnabled(arc::kMouseWheelSmoothScroll)) - return SendEvent(continuation, &event); - if (!in_resize_locked) return SendEvent(continuation, &event);
diff --git a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter_unittest.cc b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter_unittest.cc index fae80a3b..0551bad6 100644 --- a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter_unittest.cc +++ b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter_unittest.cc
@@ -87,8 +87,7 @@ void SetUp() override { views::ViewsTestBase::SetUp(); - feature_list_.InitWithFeatures( - {arc::kRightClickLongPress, arc::kMouseWheelSmoothScroll}, {}); + feature_list_.InitWithFeatures({arc::kRightClickLongPress}, {}); } base::test::ScopedFeatureList feature_list_;
diff --git a/ash/components/arc/ime/arc_ime_service_unittest.cc b/ash/components/arc/ime/arc_ime_service_unittest.cc index 7610a87..ea2e5c3 100644 --- a/ash/components/arc/ime/arc_ime_service_unittest.cc +++ b/ash/components/arc/ime/arc_ime_service_unittest.cc
@@ -110,7 +110,7 @@ client_ = nullptr; } - void OnTextInputTypeChanged(const ui::TextInputClient* client) override { + void OnTextInputTypeChanged(ui::TextInputClient* client) override { count_on_text_input_type_changed_++; }
diff --git a/ash/components/geolocation/simple_geolocation_request.cc b/ash/components/geolocation/simple_geolocation_request.cc index 52f089d..365ecf195 100644 --- a/ash/components/geolocation/simple_geolocation_request.cc +++ b/ash/components/geolocation/simple_geolocation_request.cc
@@ -308,43 +308,37 @@ } // Helpers to reformat data into dictionaries for conversion to request JSON -std::unique_ptr<base::DictionaryValue> CreateAccessPointDictionary( - WifiAccessPoint access_point) { - auto access_point_dictionary = std::make_unique<base::DictionaryValue>(); +base::Value::Dict CreateAccessPointDictionary( + const WifiAccessPoint& access_point) { + base::Value::Dict access_point_dictionary; - access_point_dictionary->SetKey(kMacAddress, - base::Value(access_point.mac_address)); - access_point_dictionary->SetKey(kSignalStrength, - base::Value(access_point.signal_strength)); + access_point_dictionary.Set(kMacAddress, access_point.mac_address); + access_point_dictionary.Set(kSignalStrength, access_point.signal_strength); if (!access_point.timestamp.is_null()) { - access_point_dictionary->SetKey( + access_point_dictionary.Set( kAge, - base::Value(base::NumberToString( - (base::Time::Now() - access_point.timestamp).InMilliseconds()))); + base::NumberToString( + (base::Time::Now() - access_point.timestamp).InMilliseconds())); } - access_point_dictionary->SetKey(kChannel, base::Value(access_point.channel)); - access_point_dictionary->SetKey(kSignalToNoiseRatio, - base::Value(access_point.signal_to_noise)); + access_point_dictionary.Set(kChannel, access_point.channel); + access_point_dictionary.Set(kSignalToNoiseRatio, + access_point.signal_to_noise); return access_point_dictionary; } -std::unique_ptr<base::DictionaryValue> CreateCellTowerDictionary( - CellTower cell_tower) { - auto cell_tower_dictionary = std::make_unique<base::DictionaryValue>(); - cell_tower_dictionary->SetKey(kCellId, base::Value(cell_tower.ci)); - cell_tower_dictionary->SetKey(kLocationAreaCode, base::Value(cell_tower.lac)); - cell_tower_dictionary->SetKey(kMobileCountryCode, - base::Value(cell_tower.mcc)); - cell_tower_dictionary->SetKey(kMobileNetworkCode, - base::Value(cell_tower.mnc)); +base::Value::Dict CreateCellTowerDictionary(const CellTower& cell_tower) { + base::Value::Dict cell_tower_dictionary; + cell_tower_dictionary.Set(kCellId, cell_tower.ci); + cell_tower_dictionary.Set(kLocationAreaCode, cell_tower.lac); + cell_tower_dictionary.Set(kMobileCountryCode, cell_tower.mcc); + cell_tower_dictionary.Set(kMobileNetworkCode, cell_tower.mnc); if (!cell_tower.timestamp.is_null()) { - cell_tower_dictionary->SetKey( - kAge, - base::Value(base::NumberToString( - (base::Time::Now() - cell_tower.timestamp).InMilliseconds()))); + cell_tower_dictionary.Set( + kAge, base::NumberToString( + (base::Time::Now() - cell_tower.timestamp).InMilliseconds())); } return cell_tower_dictionary; } @@ -391,29 +385,27 @@ if (!cell_tower_data_ && !wifi_data_) return std::string(kSimpleGeolocationRequestBody); - std::unique_ptr<base::DictionaryValue> request(new base::DictionaryValue); - request->SetKey(kConsiderIp, base::Value(true)); + base::Value::Dict request; + request.Set(kConsiderIp, true); if (wifi_data_) { - auto wifi_access_points = std::make_unique<base::ListValue>(); + base::Value::List wifi_access_points; for (const WifiAccessPoint& access_point : *wifi_data_) { - wifi_access_points->Append(CreateAccessPointDictionary(access_point)); + wifi_access_points.Append(CreateAccessPointDictionary(access_point)); } - request->SetKey(kWifiAccessPoints, base::Value::FromUniquePtrValue( - std::move(wifi_access_points))); + request.Set(kWifiAccessPoints, std::move(wifi_access_points)); } if (cell_tower_data_) { - auto cell_towers = std::make_unique<base::ListValue>(); + base::Value::List cell_towers; for (const CellTower& cell_tower : *cell_tower_data_) { - cell_towers->Append(CreateCellTowerDictionary(cell_tower)); + cell_towers.Append(CreateCellTowerDictionary(cell_tower)); } - request->SetKey(kCellTowers, - base::Value::FromUniquePtrValue(std::move(cell_towers))); + request.Set(kCellTowers, std::move(cell_towers)); } std::string result; - if (!base::JSONWriter::Write(*request, &result)) { + if (!base::JSONWriter::Write(request, &result)) { // If there's no data for a network type, we will have already reported // false above if (wifi_data_)
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 2c83ccf..79c1a64 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -659,7 +659,7 @@ base::FEATURE_DISABLED_BY_DEFAULT}; // Enables the System Web App (SWA) version of file manager. -const base::Feature kFilesSWA{"FilesSWA", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kFilesSWA{"FilesSWA", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables partitioning of removable disks in file manager. const base::Feature kFilesSinglePartitionFormat{
diff --git a/ash/public/cpp/desk_template.cc b/ash/public/cpp/desk_template.cc index 0c935816..bd23c3b7 100644 --- a/ash/public/cpp/desk_template.cc +++ b/ash/public/cpp/desk_template.cc
@@ -49,11 +49,6 @@ constexpr char DeskTemplate::kIncognitoWindowIdentifier[]; -DeskTemplate::DeskTemplate() - : uuid_(base::GUID::GenerateRandomV4()), - source_(DeskTemplateSource::kUnknownSource), - created_time_(base::Time::Now()) {} - std::unique_ptr<DeskTemplate> DeskTemplate::Clone() const { std::unique_ptr<DeskTemplate> desk_template = std::make_unique<DeskTemplate>( uuid_.AsLowercaseString(), source_, base::UTF16ToUTF8(template_name_),
diff --git a/ash/public/cpp/desk_template.h b/ash/public/cpp/desk_template.h index d8e1cd5a..fca13a359 100644 --- a/ash/public/cpp/desk_template.h +++ b/ash/public/cpp/desk_template.h
@@ -106,8 +106,6 @@ std::string ToString() const; private: - DeskTemplate(); - const base::GUID uuid_; // We utilize the string based base::GUID to uniquely // identify the template.
diff --git a/ash/rgb_keyboard/rgb_keyboard_manager.cc b/ash/rgb_keyboard/rgb_keyboard_manager.cc index cdab580..24bf509 100644 --- a/ash/rgb_keyboard/rgb_keyboard_manager.cc +++ b/ash/rgb_keyboard/rgb_keyboard_manager.cc
@@ -58,6 +58,10 @@ recently_sent_rgb_for_testing_[2] = 0u; } +void RgbKeyboardManager::SetCapsLockState(bool is_caps_lock_set) { + is_caps_lock_set_ = is_caps_lock_set; +} + // static RgbKeyboardManager* RgbKeyboardManager::Get() { return g_instance;
diff --git a/ash/rgb_keyboard/rgb_keyboard_manager.h b/ash/rgb_keyboard/rgb_keyboard_manager.h index ee21c6b..43a6e2e6 100644 --- a/ash/rgb_keyboard/rgb_keyboard_manager.h +++ b/ash/rgb_keyboard/rgb_keyboard_manager.h
@@ -34,6 +34,7 @@ RgbKeyboardCapabilities GetRgbKeyboardCapabilities() const; void SetStaticBackgroundColor(uint8_t r, uint8_t g, uint8_t b); void SetRainbowMode(); + void SetCapsLockState(bool is_caps_lock_set); // Returns the global instance if initialized. May return null. static RgbKeyboardManager* Get(); @@ -44,11 +45,14 @@ bool is_rainbow_mode_set() const { return is_rainbow_mode_set_for_testing_; } + bool is_caps_lock_set() const { return is_caps_lock_set_; } + private: // TODO(jimmyxgong): Remove the following members after DBus client is // available. std::vector<uint8_t> recently_sent_rgb_for_testing_; bool is_rainbow_mode_set_for_testing_ = false; + bool is_caps_lock_set_ = false; }; } // namespace ash
diff --git a/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc b/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc index 7cc5f94..e42fed2 100644 --- a/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc +++ b/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc
@@ -100,4 +100,12 @@ EXPECT_FALSE(manager_->is_rainbow_mode_set()); } + +TEST_F(RgbKeyboardManagerTest, SetCapsLockState) { + EXPECT_FALSE(manager_->is_caps_lock_set()); + manager_->SetCapsLockState(/*is_caps_lock_set=*/true); + EXPECT_TRUE(manager_->is_caps_lock_set()); + manager_->SetCapsLockState(/*is_caps_lock_set=*/false); + EXPECT_FALSE(manager_->is_caps_lock_set()); +} } // namespace ash \ No newline at end of file
diff --git a/ash/webui/os_feedback_ui/resources/fake_data.js b/ash/webui/os_feedback_ui/resources/fake_data.js index c3e51dc..42fc8ed 100644 --- a/ash/webui/os_feedback_ui/resources/fake_data.js +++ b/ash/webui/os_feedback_ui/resources/fake_data.js
@@ -11,6 +11,20 @@ */ /** @type {!HelpContentList} */ +export const fakePopularHelpContentList = [ + { + title: stringToMojoString16('fake article'), + url: {url: 'https://support.google.com/chromebook/?q=article'}, + contentType: HelpContentType.kArticle + }, + { + title: stringToMojoString16('fake forum'), + url: {url: 'https://support.google.com/chromebook/?q=forum'}, + contentType: HelpContentType.kForum + } +]; + +/** @type {!HelpContentList} */ export const fakeHelpContentList = [ { title: stringToMojoString16('Fix connection problems'),
diff --git a/ash/webui/os_feedback_ui/resources/feedback_types.js b/ash/webui/os_feedback_ui/resources/feedback_types.js index 1790e16..4720aae 100644 --- a/ash/webui/os_feedback_ui/resources/feedback_types.js +++ b/ash/webui/os_feedback_ui/resources/feedback_types.js
@@ -42,6 +42,20 @@ export const SearchResponse = ash.osFeedbackUi.mojom.SearchResponse; /** + * Type alias for search result. When isPopularContent is true, the contentList + * contains top popular help contents, i.e. returned where the search query is + * empty. The isQueryEmpty is true when the current query is empty. The + * isPopularContent is true when the current query is not empty and no matches + * are found. + * @typedef {{ + * contentList: HelpContentList, + * isQueryEmpty: boolean, + * isPopularContent: boolean + * }} + */ +export let SearchResult; + +/** * Type alias for the HelpContentProviderInterface. * @typedef {ash.osFeedbackUi.mojom.HelpContentProviderInterface} */
diff --git a/ash/webui/os_feedback_ui/resources/help_content.html b/ash/webui/os_feedback_ui/resources/help_content.html index 29034ec..c7b09e6 100644 --- a/ash/webui/os_feedback_ui/resources/help_content.html +++ b/ash/webui/os_feedback_ui/resources/help_content.html
@@ -13,9 +13,8 @@ } </style> <div id="helpContentContainer"> - <!--TODO(xiangdongkong): use localized strings --> - <p id="helpContentLabel">Suggested help content:</p> - <dom-repeat items="[[helpContentList]]"> + <p id="helpContentLabel">[[getLabel_(searchResult)]]</p> + <dom-repeat items="[[searchResult.contentList]]"> <template> <div class="help-item"> <a href="[[getUrl_(item)]]" target="_blank">
diff --git a/ash/webui/os_feedback_ui/resources/help_content.js b/ash/webui/os_feedback_ui/resources/help_content.js index f3d0298..7e3ff06 100644 --- a/ash/webui/os_feedback_ui/resources/help_content.js +++ b/ash/webui/os_feedback_ui/resources/help_content.js
@@ -6,7 +6,7 @@ import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; import {mojoString16ToString} from '//resources/ash/common/mojo_utils.js'; import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {HelpContent, HelpContentList, HelpContentType} from './feedback_types.js'; +import {HelpContent, HelpContentList, HelpContentType, SearchResult} from './feedback_types.js'; /** * @const {string} @@ -32,16 +32,40 @@ } static get properties() { - return { - /** - * An implicit array of help contents to be displayed. - * @type {!HelpContentList} - */ - helpContentList: {type: HelpContentList, value: () => []} + return {searchResult: {type: SearchResult}}; + } + + constructor() { + super(); + + /** + * @type {!SearchResult} + */ + this.searchResult = { + contentList: [], + isQueryEmpty: true, + isPopularContent: true }; } /** + * Compute the label to use. + * @param {!SearchResult} searchResult + * @returns {string} + * @protected + */ + getLabel_(searchResult) { + // TODO(xiangdongkong): Use localized strings. + if (!searchResult.isPopularContent) { + return 'Suggested help content'; + } + if (searchResult.isQueryEmpty) { + return 'Popular help content'; + } + return 'No matched results, see popular help content'; + } + + /** * Find the icon name to be used for a help content type. * @param {!HelpContentType} contentType * @return {string}
diff --git a/ash/webui/os_feedback_ui/resources/search_page.js b/ash/webui/os_feedback_ui/resources/search_page.js index e719aeb..6d56f43 100644 --- a/ash/webui/os_feedback_ui/resources/search_page.js +++ b/ash/webui/os_feedback_ui/resources/search_page.js
@@ -10,7 +10,7 @@ import {stringToMojoString16} from 'chrome://resources/ash/common/mojo_utils.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {HelpContentProviderInterface, SearchRequest, SearchResponse} from './feedback_types.js'; +import {HelpContentList, HelpContentProviderInterface, SearchRequest, SearchResponse, SearchResult} from './feedback_types.js'; import {getHelpContentProvider} from './mojo_interface_provider.js'; /** @@ -76,6 +76,12 @@ /** @private {?HTMLIFrameElement} */ this.iframe_ = null; + + /** + * The content list received when query is empty. + * @private {!HelpContentList|undefined} + */ + this.popularHelpContentList_; } ready() { @@ -83,6 +89,8 @@ this.iframe_ = /** @type {HTMLIFrameElement} */ ( this.shadowRoot.querySelector('iframe')); + // Fetch popular help contents with empty query. + this.fetchHelpContent_(/* query= */ ''); } /** * @@ -95,40 +103,60 @@ if (Math.abs(newCharCount - this.lastCharCount_) >= MIN_CHARS_COUNT) { this.lastCharCount_ = newCharCount; - - /** @type {!SearchRequest} */ - const request = { - query: stringToMojoString16(newInput), - maxResults: MAX_RESULTS, - }; - - this.fetchHelpContent_(request); + this.fetchHelpContent_(newInput); } } /** - * @param {!SearchRequest} request + * @param {string} query * @private */ - fetchHelpContent_(request) { - this.helpContentProvider_.getHelpContents(request).then( - /** {{response: !SearchResponse}} */ (response) => { - if (!this.iframe_) { - console.warn('untrusted iframe is not found'); - return; - } + async fetchHelpContent_(query) { + if (!this.iframe_) { + console.warn('untrusted iframe is not found'); + return; + } - const data = { - response: response.response, - }; + /** @type {!SearchRequest} */ + const request = { + query: stringToMojoString16(query), + maxResults: MAX_RESULTS, + }; - // Wait for the iframe to complete loading before postMessage. - this.iframeLoaded_.then(() => { - // TODO(xiangdongkong): Use Mojo to communicate with untrusted page. - this.iframe_.contentWindow.postMessage( - data, OS_FEEDBACK_UNTRUSTED_ORIGIN); - }); - }); + /** @type boolean */ + const isQueryEmpty = (query === ''); + + /** @type boolean */ + let isPopularContent; + + /** @type {{response: !SearchResponse}} */ + let response; + + if (isQueryEmpty) { + // Load popular help content if they are not loaded before. + if (this.popularHelpContentList_ === undefined) { + response = await this.helpContentProvider_.getHelpContents(request); + this.popularHelpContentList_ = response.response.results; + } + isPopularContent = true; + } else { + response = await this.helpContentProvider_.getHelpContents(request); + isPopularContent = (response.response.totalResults === 0); + } + + /** @type {!SearchResult} */ + const data = { + contentList: /** @type {!HelpContentList} */ ( + isPopularContent ? this.popularHelpContentList_ : + response.response.results), + isQueryEmpty: isQueryEmpty, + isPopularContent: isPopularContent + }; + + // Wait for the iframe to complete loading before postMessage. + await this.iframeLoaded_; + // TODO(xiangdongkong): Use Mojo to communicate with untrusted page. + this.iframe_.contentWindow.postMessage(data, OS_FEEDBACK_UNTRUSTED_ORIGIN); } }
diff --git a/ash/webui/os_feedback_ui/untrusted_resources/untrusted_index.js b/ash/webui/os_feedback_ui/untrusted_resources/untrusted_index.js index 9a3e9a2..83e3407 100644 --- a/ash/webui/os_feedback_ui/untrusted_resources/untrusted_index.js +++ b/ash/webui/os_feedback_ui/untrusted_resources/untrusted_index.js
@@ -22,14 +22,14 @@ console.error('Unknown origin: ' + event.origin); return; } - // After receiving help content sent from parent page, display them. - helpContent.helpContentList = event.data.response.results; + // After receiving search result sent from parent page, display them. + helpContent.searchResult = event.data; // Post a message to parent to make testing easier. window.parent.postMessage( { id: 'help-content-received-for-testing', - count: event.data.response.results.length, + count: event.data.contentList.length, }, OS_FEEDBACK_TRUSTED_ORIGIN); });
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc index 4010a1d..499273b 100644 --- a/ash/wm/desks/desks_unittests.cc +++ b/ash/wm/desks/desks_unittests.cc
@@ -2805,6 +2805,24 @@ split_view_controller()->state()); } +// Tests that closing the active desk while in overview does not quit overview. +// Regression test for https://crbug.com/1309175. +TEST_F(TabletModeDesksTest, RemovingActiveDeskDoesNotExitOverview) { + auto* desks_controller = DesksController::Get(); + NewDesk(); + ASSERT_EQ(2u, desks_controller->desks().size()); + Desk* desk_2 = desks_controller->desks()[1].get(); + ActivateDesk(desk_2); + + auto* overview_controller = Shell::Get()->overview_controller(); + EnterOverview(); + ASSERT_TRUE(overview_controller->InOverviewSession()); + + // Remove `desk_2`, which is the active test. We should stay in overview. + RemoveDesk(desk_2); + EXPECT_TRUE(overview_controller->InOverviewSession()); +} + TEST_F(TabletModeDesksTest, BackdropsStacking) { auto* desks_controller = DesksController::Get(); NewDesk();
diff --git a/ash/wm/splitview/split_view_utils.cc b/ash/wm/splitview/split_view_utils.cc index a030085..12e75b6 100644 --- a/ash/wm/splitview/split_view_utils.cc +++ b/ash/wm/splitview/split_view_utils.cc
@@ -373,14 +373,15 @@ } } - // Ensure that overview mode is active if and only if there is a window - // snapped to one side but no window snapped to the other side. + // Ensure that overview mode is active if there is a window snapped to one of + // the sides. Ensure overview mode is not active if there are two snapped + // windows. OverviewController* overview_controller = Shell::Get()->overview_controller(); SplitViewController::State state = split_view_controller->state(); if (state == SplitViewController::State::kLeftSnapped || state == SplitViewController::State::kRightSnapped) { overview_controller->StartOverview(OverviewStartAction::kSplitView); - } else { + } else if (state == SplitViewController::State::kBothSnapped) { overview_controller->EndOverview(OverviewEndAction::kSplitView); } }
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc index a4f3b0c..3b4e2da 100644 --- a/base/metrics/field_trial.cc +++ b/base/metrics/field_trial.cc
@@ -1211,8 +1211,8 @@ HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); if (tokens[1] == "p") { DCHECK(IsCurrentProcessElevated()); - // LaunchElevatedProcess doesn't have a way to duplicate the handle, - // but this process can since by definition it's not sandboxed. + // LaunchProcess doesn't have a way to duplicate the handle, but this + // process can since by definition it's not sandboxed. ProcessId parent_pid = GetParentProcessId(GetCurrentProcess()); HANDLE parent_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, parent_pid); // TODO(https://crbug.com/916461): Duplicating the handle is known to fail
diff --git a/base/process/launch.h b/base/process/launch.h index 1b790c9..c5f1147 100644 --- a/base/process/launch.h +++ b/base/process/launch.h
@@ -94,7 +94,11 @@ #if BUILDFLAG(IS_WIN) bool start_hidden = false; - // Process will be started using a shell helper so that it is elevated. + // Process will be started using ShellExecuteEx instead of CreateProcess so + // that it is elevated. LaunchProcess with this flag will have different + // behaviour due to ShellExecuteEx. Some common operations like OpenProcess + // will fail. Currently the only other supported LaunchOptions are + // |start_hidden| and |wait|. bool elevated = false; // Sets STARTF_FORCEOFFFEEDBACK so that the feedback cursor is forced off @@ -332,7 +336,9 @@ // Windows-specific LaunchProcess that takes the command line as a // string. Useful for situations where you need to control the // command line arguments directly, but prefer the CommandLine version -// if launching Chrome itself. +// if launching Chrome itself. Also prefer the CommandLine version if +// `options.elevated` is set because `cmdline` needs to be parsed for +// ShellExecuteEx. // // The first command line argument should be the path to the process, // and don't forget to quote it. @@ -342,14 +348,6 @@ BASE_EXPORT Process LaunchProcess(const CommandLine::StringType& cmdline, const LaunchOptions& options); -// Launches a process with elevated privileges. This does not behave exactly -// like LaunchProcess as it uses ShellExecuteEx instead of CreateProcess to -// create the process. This means the process will have elevated privileges -// and thus some common operations like OpenProcess will fail. Currently the -// only supported LaunchOptions are |start_hidden| and |wait|. -BASE_EXPORT Process LaunchElevatedProcess(const CommandLine& cmdline, - const LaunchOptions& options); - #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) // A POSIX-specific version of LaunchProcess that takes an argv array // instead of a CommandLine. Useful for situations where you need to
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc index ed48eb48..ebefc18a 100644 --- a/base/process/launch_win.cc +++ b/base/process/launch_win.cc
@@ -137,6 +137,39 @@ status != TERMINATION_STATUS_ABNORMAL_TERMINATION; } +Process LaunchElevatedProcess(const CommandLine& cmdline, + bool start_hidden, + bool wait) { + TRACE_EVENT0("base", "LaunchElevatedProcess"); + const FilePath::StringType file = cmdline.GetProgram().value(); + const CommandLine::StringType arguments = cmdline.GetArgumentsString(); + + SHELLEXECUTEINFO shex_info = {}; + shex_info.cbSize = sizeof(shex_info); + shex_info.fMask = SEE_MASK_NOCLOSEPROCESS; + shex_info.hwnd = GetActiveWindow(); + shex_info.lpVerb = L"runas"; + shex_info.lpFile = file.c_str(); + shex_info.lpParameters = arguments.c_str(); + shex_info.lpDirectory = nullptr; + shex_info.nShow = start_hidden ? SW_HIDE : SW_SHOWNORMAL; + shex_info.hInstApp = nullptr; + + if (!ShellExecuteEx(&shex_info)) { + DPLOG(ERROR); + return Process(); + } + + if (wait) { + ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); + WaitForSingleObject(shex_info.hProcess, INFINITE); + } + + debug::GlobalActivityTracker::RecordProcessLaunchIfEnabled( + GetProcessId(shex_info.hProcess), file, arguments); + return Process(shex_info.hProcess); +} + } // namespace void RouteStdioToConsole(bool create_console_if_not_found) { @@ -210,13 +243,18 @@ Process LaunchProcess(const CommandLine& cmdline, const LaunchOptions& options) { + if (options.elevated) + return LaunchElevatedProcess(cmdline, options.start_hidden, options.wait); return LaunchProcess(cmdline.GetCommandLineString(), options); } Process LaunchProcess(const CommandLine::StringType& cmdline, const LaunchOptions& options) { + if (options.elevated) { + return LaunchElevatedProcess(base::CommandLine::FromString(cmdline), + options.start_hidden, options.wait); + } TRACE_EVENT0("base", "LaunchProcess"); - CHECK(!options.elevated); // Mitigate the issues caused by loading DLLs on a background thread // (http://crbug/973868). SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); @@ -412,39 +450,6 @@ return Process(process_info.TakeProcessHandle()); } -Process LaunchElevatedProcess(const CommandLine& cmdline, - const LaunchOptions& options) { - TRACE_EVENT0("base", "LaunchElevatedProcess"); - CHECK(options.elevated); - const FilePath::StringType file = cmdline.GetProgram().value(); - const CommandLine::StringType arguments = cmdline.GetArgumentsString(); - - SHELLEXECUTEINFO shex_info = {}; - shex_info.cbSize = sizeof(shex_info); - shex_info.fMask = SEE_MASK_NOCLOSEPROCESS; - shex_info.hwnd = GetActiveWindow(); - shex_info.lpVerb = L"runas"; - shex_info.lpFile = file.c_str(); - shex_info.lpParameters = arguments.c_str(); - shex_info.lpDirectory = nullptr; - shex_info.nShow = options.start_hidden ? SW_HIDE : SW_SHOWNORMAL; - shex_info.hInstApp = nullptr; - - if (!ShellExecuteEx(&shex_info)) { - DPLOG(ERROR); - return Process(); - } - - if (options.wait) { - ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); - WaitForSingleObject(shex_info.hProcess, INFINITE); - } - - debug::GlobalActivityTracker::RecordProcessLaunchIfEnabled( - GetProcessId(shex_info.hProcess), file, arguments); - return Process(shex_info.hProcess); -} - bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) { JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {}; limit_info.BasicLimitInformation.LimitFlags = limit_flags;
diff --git a/base/process/process_info.h b/base/process/process_info.h index ac6b963..e6ee787 100644 --- a/base/process/process_info.h +++ b/base/process/process_info.h
@@ -25,7 +25,7 @@ // Determines whether the current process is elevated. Note: in some // configurations this may be true for processes launched without using -// base::LaunchElevatedProcess(). +// LaunchOptions::elevated. BASE_EXPORT bool IsCurrentProcessElevated(); // Determines whether the current process is running within an App Container.
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 3f80868..3dca68a4 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -7.20220324.1.1 +7.20220324.3.1
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 3c7900b6..3dca68a4 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -7.20220324.2.1 +7.20220324.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 3f80868..3dca68a4 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -7.20220324.1.1 +7.20220324.3.1
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index cd3a63fe..f1e0552 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1291,16 +1291,15 @@ outputs = [ "$root_out_dir/{{source_file_part}}-$chrome_version_full.breakpad" ] - args = rebase_path(outputs, root_out_dir) + [ - rebase_path( - get_label_info( - "//third_party/breakpad:dump_syms($host_toolchain)", - "root_out_dir") + "/dump_syms", - root_out_dir), + dump_syms = "//third_party/breakpad:dump_syms($host_toolchain)" + args = rebase_path(outputs, root_build_dir) + [ + rebase_path(get_label_info(dump_syms, "root_out_dir") + "/" + + get_label_info(dump_syms, "name"), + root_build_dir), "-g", rebase_path( "$root_out_dir/{{source_file_part}}.dSYM/Contents/Resources/DWARF/{{source_file_part}}", - root_out_dir), + root_build_dir), "{{source}}", ] @@ -1310,10 +1309,10 @@ "//components/crash/core/app:chrome_crashpad_handler", "//third_party/angle:libEGL", "//third_party/angle:libGLESv2", - "//third_party/breakpad:dump_syms($host_toolchain)", "//third_party/swiftshader/src/OpenGL/libEGL:swiftshader_libEGL", "//third_party/swiftshader/src/OpenGL/libGLESv2:swiftshader_libGLESv2", "//third_party/swiftshader/src/Vulkan:swiftshader_libvulkan", + dump_syms, ] if (build_with_internal_optimization_guide) { deps += [ "//components/optimization_guide/internal:optimization_guide_internal" ]
diff --git a/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java b/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java index 2053aec..6d4495f 100644 --- a/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java +++ b/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java
@@ -761,11 +761,10 @@ settingsButtonVisible = true; break; - // TODO: create a dedicated error message for these cases, which - // result when the client sends a discoverable-credentials - // request that Android cannot handle. - // case ERROR_AUTHENTICATOR_SELECTION_RECEIVED: - // case ERROR_DISCOVERABLE_CREDENTIALS_REQUEST: + case ERROR_AUTHENTICATOR_SELECTION_RECEIVED: + case ERROR_DISCOVERABLE_CREDENTIALS_REQUEST: + desc = getResources().getString(R.string.cablev2_error_disco_cred, packageLabel); + break; default: TextView errorCodeTextView = (TextView) mErrorView.findViewById(R.id.error_code);
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java index d615863..14a3714 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java
@@ -99,7 +99,10 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_AUTOFILL) + .build(); public AccessorySheetRenderTest(boolean nightModeEnabled, boolean useRtlLayout) { FeatureList.setTestFeatures(
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java index 8a29d84..aee0b30 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java
@@ -94,7 +94,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_SHOPPING_PRICE_TRACKING) + .build(); @Before public void setUp() {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java index 5a7bff1..9d481233 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java
@@ -49,7 +49,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_SHOPPING_PRICE_TRACKING) + .build(); public PriceCardViewTest(boolean nightModeEnabled) { NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java index 7af160b8..ecc6504 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java
@@ -88,9 +88,12 @@ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); @Rule - public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() - .setRevision(RENDER_TEST_REVISION) - .build(); + public ChromeRenderTestRule mRenderTestRule = + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(RENDER_TEST_REVISION) + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_SHOPPING_PRICE_TRACKING) + .build(); @Before public void setUp() throws Exception {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java index 3961ed6..c863bca 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -141,7 +141,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_TAB_SWITCHER_GRID) + .build(); @BeforeClass public static void setUpBeforeActivityLaunched() {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java index d795fae..3626839 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
@@ -102,7 +102,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_TAB_SWITCHER_GRID) + .build(); @Before public void setUp() {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java index b39367d6..60dd79f 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java
@@ -97,7 +97,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_TAB_GROUPS) + .build(); @Before public void setUp() {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java index aaa9768..bc4f576 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
@@ -78,7 +78,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_TAB_SWITCHER) + .build(); private TabSelectionEditorTestingRobot mRobot = new TabSelectionEditorTestingRobot();
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java index a6ad7ec..952bf8b9 100644 --- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java
@@ -43,8 +43,8 @@ mVrDialog = new VrDialog(mContext, mVrDialogManager); int style = (model.get(ModalDialogProperties.BUTTON_STYLES) == ModalDialogProperties.ButtonStyles.PRIMARY_FILLED_NEGATIVE_OUTLINE) - ? R.style.Theme_Chromium_ModalDialog_FilledPrimaryButton - : R.style.Theme_Chromium_ModalDialog_TextPrimaryButton; + ? R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledPrimaryButton + : R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton; ModalDialogView dialogView = (ModalDialogView) LayoutInflater.from(new ContextThemeWrapper(mContext, style)) .inflate(R.layout.modal_dialog_view, null);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java index b791bf9..eb94b4f 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java
@@ -150,7 +150,10 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_CONTENT_SUGGESTIONS_FEED) + .build(); public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule(mFakeAccountManagerFacade);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java index 18d6213..4c7bfbb9 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java
@@ -46,9 +46,12 @@ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); @Rule - public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() - .setFailOnUnsupportedConfigs(true) - .build(); + public ChromeRenderTestRule mRenderTestRule = + ChromeRenderTestRule.Builder.withPublicCorpus() + .setFailOnUnsupportedConfigs(true) + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_CONTENT_SUGGESTIONS_FEED) + .build(); @Before public void setUp() {
diff --git a/chrome/android/java/res/values-v21/styles.xml b/chrome/android/java/res/values-v21/styles.xml index 61c625a..fdd8947 100644 --- a/chrome/android/java/res/values-v21/styles.xml +++ b/chrome/android/java/res/values-v21/styles.xml
@@ -12,7 +12,7 @@ <!-- Set android alert dialog attributes because the context menu dialog is OS-dependent. Not setting alertDialogTheme pre-v21 because the window background causes bad visual states with alert dialog list. --> - <item name="android:alertDialogTheme">@style/Theme.Chromium.AlertDialog</item> + <item name="android:alertDialogTheme">@style/ThemeOverlay.BrowserUI.AlertDialog</item> </style> <style name="Base.Theme.Chromium" parent="Base.V21.Theme.Chromium" />
diff --git a/chrome/android/java/res/values/styles.xml b/chrome/android/java/res/values/styles.xml index 0b86d052..f73aac9 100644 --- a/chrome/android/java/res/values/styles.xml +++ b/chrome/android/java/res/values/styles.xml
@@ -86,7 +86,7 @@ <item name="appBarLayoutStyle">@style/Widget.MaterialComponents.AppBarLayout.Surface</item> <item name="toolbarStyle">@style/SettingsToolbarStyle</item> <item name="preferenceTheme">@style/PreferenceTheme</item> - <item name="alertDialogTheme">@style/Theme.Chromium.AlertDialog</item> + <item name="alertDialogTheme">@style/ThemeOverlay.BrowserUI.AlertDialog</item> <item name="searchViewStyle">@style/Widget.AppCompat.SearchView.ActionBar</item> <!-- Text style attributes used by the preference_material.xml layout. -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java index 68e3a59..350fded 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
@@ -127,12 +127,13 @@ @CalledByNative private void confirmDeletion(String title, String body) { - mDeletionDialog = new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog) - .setTitle(title) - .setMessage(body) - .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.ok, this) - .create(); + mDeletionDialog = + new AlertDialog.Builder(mContext, R.style.ThemeOverlay_BrowserUI_AlertDialog) + .setTitle(title) + .setMessage(body) + .setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.ok, this) + .create(); mDeletionDialog.show(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ConfirmImportantSitesDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ConfirmImportantSitesDialogFragment.java index db9bbd97..5e7405f8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ConfirmImportantSitesDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ConfirmImportantSitesDialogFragment.java
@@ -325,7 +325,7 @@ message.setText(messageResource); final AlertDialog.Builder builder = - new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(titleResource) .setPositiveButton( R.string.clear_browsing_data_important_dialog_button, listener)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/OtherFormsOfHistoryDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/OtherFormsOfHistoryDialogFragment.java index 8f20f2e..282881f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/OtherFormsOfHistoryDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/OtherFormsOfHistoryDialogFragment.java
@@ -63,7 +63,7 @@ // Construct the dialog. AlertDialog dialog = - new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setView(view) .setTitle(R.string.clear_browsing_data_history_dialog_title) .setPositiveButton(R.string.ok_got_it, this)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java index 1633ccf7c..e763775 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java
@@ -309,9 +309,9 @@ boolean shouldRemoveScrim = isPopup && ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXT_MENU_POPUP_STYLE); final ContextMenuDialog dialog = new ContextMenuDialog(activity, - R.style.Theme_Chromium_AlertDialog, topMarginPx, bottomMarginPx, layout, view, - isPopup, shouldRemoveScrim, popupMargin, desiredPopupContentWidth, webContentView, - rect, ChromeAccessibilityUtil.get()); + R.style.ThemeOverlay_BrowserUI_AlertDialog, topMarginPx, bottomMarginPx, layout, + view, isPopup, shouldRemoveScrim, popupMargin, desiredPopupContentWidth, + webContentView, rect, ChromeAccessibilityUtil.get()); dialog.setContentView(layout); return dialog;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java index dba335c..cef9eff6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java
@@ -86,7 +86,7 @@ public static void showDialog(Context context) { AlertDialog.Builder builder = - new AlertDialog.Builder(context, R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(context, R.style.ThemeOverlay_BrowserUI_AlertDialog); builder.setView(DistilledPagePrefsView.create(context)); builder.show(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUIUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUIUtils.java index 06cb6e2..b49dbe9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUIUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUIUtils.java
@@ -31,7 +31,7 @@ if (webContents != null && activity != null) { RecordUserAction.record("DomDistiller_DistilledPagePrefsOpened"); AlertDialog.Builder builder = - new AlertDialog.Builder(activity, R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(activity, R.style.ThemeOverlay_BrowserUI_AlertDialog); builder.setView(DistilledPagePrefsView.create(activity)); builder.show(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java index e79de57d..94c662f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java
@@ -552,7 +552,7 @@ }; new AlertDialog .Builder(ApplicationStatus.getLastTrackedFocusedActivity(), - R.style.Theme_Chromium_AlertDialog) + R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.proceed_oma_download_message) .setPositiveButton(R.string.ok, clickListener) .setNegativeButton(R.string.cancel, clickListener) @@ -582,7 +582,7 @@ }; new AlertDialog .Builder(ApplicationStatus.getLastTrackedFocusedActivity(), - R.style.Theme_Chromium_AlertDialog) + R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(titleId) .setPositiveButton(R.string.ok, clickListener) .setCancelable(false)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index cc54a8a..7800f53 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -485,8 +485,6 @@ // Record the timestamp at which the new tab page's construction started. uma.trackTimeToFirstDraw(mFeedSurfaceProvider.getView(), mConstructedTimeNs); - - TrackerFactory.getTrackerForProfile(profile).notifyEvent(EventConstants.NTP_SHOWN); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java index 7f2e84a..2ab613f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java
@@ -196,7 +196,7 @@ } mAdapter = generateAccountsArrayAdapter(mContext, mCredentials); final AlertDialog.Builder builder = - new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(mContext, R.style.ThemeOverlay_BrowserUI_AlertDialog) .setCustomTitle(titleView) .setNegativeButton(R.string.cancel, this) .setAdapter(mAdapter, new DialogInterface.OnClickListener() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java index 512d76c1..336947c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java
@@ -69,7 +69,7 @@ private void show() { final AlertDialog.Builder builder = - new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(mContext, R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(mTitle) .setPositiveButton(mOkButtonText, this) .setNegativeButton(mTurnOffButtonText, this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportErrorDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportErrorDialogFragment.java index b99fcfe..6b57f2dd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportErrorDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportErrorDialogFragment.java
@@ -71,7 +71,7 @@ detailedDescription.setVisibility(View.GONE); } return new AlertDialog - .Builder(getActivity(), R.style.Theme_Chromium_AlertDialog_NoActionBar) + .Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog_NoActionBar) .setView(dialog) .setTitle(R.string.password_settings_export_error_title) .setPositiveButton(mParams.positiveButtonLabelId, mHandler)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragment.java index c0482bc..917ab03d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragment.java
@@ -40,7 +40,7 @@ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog - .Builder(getActivity(), R.style.Theme_Chromium_AlertDialog_NoActionBar) + .Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog_NoActionBar) .setPositiveButton(R.string.password_settings_export_action_title, mHandler) .setNegativeButton(R.string.cancel, mHandler) .setMessage(getActivity().getResources().getString(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ProgressBarDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ProgressBarDialogFragment.java index b84a5688..188d003 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ProgressBarDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ProgressBarDialogFragment.java
@@ -40,7 +40,7 @@ (MaterialProgressBar) dialog.findViewById(R.id.passwords_progress_bar); bar.setIndeterminate(true); return new AlertDialog - .Builder(getActivity(), R.style.Theme_Chromium_AlertDialog_NoActionBar) + .Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog_NoActionBar) .setView(dialog) .setNegativeButton(R.string.cancel, mHandler) .setTitle(getActivity().getResources().getString(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseCreationDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseCreationDialogFragment.java index 38ff5ed..85acef8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseCreationDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseCreationDialogFragment.java
@@ -62,7 +62,7 @@ instructionsView.setText(getInstructionsText()); AlertDialog dialog = - new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setView(view) .setTitle(R.string.sync_passphrase_type_custom_dialog_title) .setPositiveButton(R.string.save, null)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java index 805b25d..c72087b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
@@ -124,7 +124,7 @@ getContext().getColor(R.color.input_underline_error_color), PorterDuff.Mode.SRC_IN); final AlertDialog d = - new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setView(v) .setPositiveButton(R.string.submit, new Dialog.OnClickListener() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java index d4d3bc6..13da09a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java
@@ -97,7 +97,7 @@ } } - return new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + return new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setNegativeButton(R.string.cancel, this) .setTitle(R.string.sync_passphrase_type_title) .setView(dialog)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkOfflineDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkOfflineDialog.java index eb49495..5ce5487 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkOfflineDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkOfflineDialog.java
@@ -30,7 +30,7 @@ */ public void show(final Activity activity, String errorMessage) { AlertDialog.Builder builder = - new AlertDialog.Builder(activity, R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(activity, R.style.ThemeOverlay_BrowserUI_AlertDialog); builder.setMessage(errorMessage) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java index 42cc6426..8ae0650 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java
@@ -67,7 +67,10 @@ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_APP_MENU) + .build(); private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>foo</html>"); private static final String TEST_URL2 = UrlUtils.encodeHtmlDataUri("<html>bar</html>");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedPromoRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedPromoRenderTest.java index c65dbd98e..e0f09ee 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedPromoRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedPromoRenderTest.java
@@ -61,7 +61,10 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(3).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(3) + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SIGN_IN) + .build(); @ParameterAnnotations.UseMethodParameterBefore(NightModeTestUtils.NightModeParams.class) public void setupNightMode(boolean nightModeEnabled) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java index a61defe..22b8865 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java
@@ -65,7 +65,9 @@ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_BOOKMARKS) + .build(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java index 9b89e302..a69e29a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -126,7 +126,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_BOOKMARKS) + .build(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowRenderTest.java index 869e1a33..d4f77f3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowRenderTest.java
@@ -61,7 +61,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_BOOKMARKS) + .build(); @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java index ba48503..95844eb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java
@@ -41,7 +41,9 @@ public class PowerBookmarkTagChipListTest extends BlankUiTestActivityTestCase { @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_BOOKMARKS) + .build(); private ViewGroup mContentView; private PowerBookmarkTagChipList mTagChipList;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java index e2e63ddf..52486f0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java
@@ -65,7 +65,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.PRIVACY) + .build(); @Mock private SyncService mMockSyncService;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java index abf13e7..85baead 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java
@@ -90,7 +90,10 @@ @Rule public final RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE_CUSTOM_TABS) + .build(); @Before public void setUp() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityRenderTest.java index 14f5fc7..867b34b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityRenderTest.java
@@ -64,7 +64,10 @@ public final EmbeddedTestServerRule mEmbeddedTestServerRule = new EmbeddedTestServerRule(); @Rule - public final RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + public final RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE_CUSTOM_TABS) + .build(); @Before public void setUp() throws TimeoutException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java index fdf0b2f..5771ee93 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java
@@ -82,7 +82,9 @@ public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule(); @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_CUSTOM_TABS) + .build(); private static final String PAGE_WITH_TITLE = "<!DOCTYPE html><html><head><title>Example title</title></head></html>";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java index b924b995..213b67f9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
@@ -86,7 +86,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_NEW_TAB_PAGE_EXPLORE_SITES) + .build(); private Tab mTab; private RecyclerView mRecyclerView;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBarTest.java index 3411c17..c9a09dc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBarTest.java
@@ -90,7 +90,10 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(2).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(2) + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SYNC) + .build(); @Before public void setUp() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java index 52a9aa4..3cb4e125 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java
@@ -71,7 +71,10 @@ @Rule public RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE_MESSAGES) + .build(); public ModalDialogViewRenderTest(boolean nightModeEnabled) { // Sets a fake background color to make the screenshots easier to compare with bare eyes. @@ -112,7 +115,7 @@ @MediumTest @Feature({"ModalDialog", "RenderTest"}) public void testRender_TitleAndTitleIcon() throws IOException { - setUpViews(R.style.Theme_Chromium_ModalDialog_TextPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton); final Drawable icon = UiUtils.getTintedDrawable(getActivity(), org.chromium.chrome.R.drawable.ic_add, R.color.default_icon_color_tint_list); createModel(mModelBuilder.with(ModalDialogProperties.TITLE, mResources, R.string.title) @@ -124,7 +127,7 @@ @MediumTest @Feature({"ModalDialog", "RenderTest"}) public void testRender_TitleAndMessage() throws IOException { - setUpViews(R.style.Theme_Chromium_ModalDialog_TextPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton); createModel( mModelBuilder.with(ModalDialogProperties.TITLE, mResources, R.string.title) .with(ModalDialogProperties.MESSAGE, @@ -140,7 +143,7 @@ @MediumTest @Feature({"ModalDialog", "RenderTest"}) public void testRender_FilledPrimaryButton() throws IOException { - setUpViews(R.style.Theme_Chromium_ModalDialog_FilledPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledPrimaryButton); createModel( mModelBuilder.with(ModalDialogProperties.TITLE, mResources, R.string.title) .with(ModalDialogProperties.MESSAGE, @@ -159,7 +162,7 @@ final Drawable icon = UiUtils.getTintedDrawable(getActivity(), org.chromium.chrome.R.drawable.ic_add, R.color.default_icon_color_tint_list); - setUpViews(R.style.Theme_Chromium_ModalDialog_TextPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton); createModel( mModelBuilder.with(ModalDialogProperties.TITLE, mResources, R.string.title) .with(ModalDialogProperties.MESSAGE, "Message") @@ -175,7 +178,7 @@ final Drawable icon = AppCompatResources.getDrawable(getActivity(), R.drawable.ic_add); icon.mutate().setTint(SemanticColorUtils.getDefaultIconColorInverse(getActivity())); - setUpViews(R.style.Theme_Chromium_ModalDialog_FilledPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledPrimaryButton); createModel( mModelBuilder.with(ModalDialogProperties.TITLE, mResources, R.string.title) .with(ModalDialogProperties.MESSAGE, "Message") @@ -190,7 +193,7 @@ @MediumTest @Feature({"ModalDialog", "RenderTest"}) public void testRender_ScrollableTitle() throws IOException { - setUpViews(R.style.Theme_Chromium_ModalDialog_TextPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton); createModel( mModelBuilder.with(ModalDialogProperties.TITLE, mResources, R.string.title) .with(ModalDialogProperties.TITLE_SCROLLABLE, true) @@ -204,7 +207,7 @@ @MediumTest @Feature({"ModalDialog", "RenderTest"}) public void testRender_CustomView() throws IOException { - setUpViews(R.style.Theme_Chromium_ModalDialog_TextPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton); TestThreadUtils.runOnUiThreadBlocking(() -> { mCustomTextView1.setText( TextUtils.join("\n", Collections.nCopies(100, "Custom Message"))); @@ -221,7 +224,7 @@ @MediumTest @Feature({"ModalDialog", "RenderTest"}) public void testRender_FooterMessage() throws IOException { - setUpViews(R.style.Theme_Chromium_ModalDialog_TextPrimaryButton); + setUpViews(R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton); createModel( mModelBuilder.with(ModalDialogProperties.TITLE, mResources, R.string.title) .with(ModalDialogProperties.MESSAGE,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java index 79fbef5..034f566 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java
@@ -40,7 +40,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_INCOGNITO) + .build(); public IncognitoDescriptionViewRenderTest(boolean nightModeEnabled) { NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 4c8a51ef..c3687139b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -116,9 +116,11 @@ public AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule(); @Rule - public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() - .setRevision(RENDER_TEST_REVISION) - .build(); + public ChromeRenderTestRule mRenderTestRule = + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(RENDER_TEST_REVISION) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_NEW_TAB_PAGE) + .build(); @Mock OmniboxStub mOmniboxStub; @Mock
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java index 6378541..1f439667 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java
@@ -56,7 +56,10 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(3).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(3) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_RECENT_TABS) + .build(); private FakeRecentlyClosedTabManager mManager; private Tab mTab;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionViewRenderTest.java index b33d40d..34fa2c9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionViewRenderTest.java
@@ -39,7 +39,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_INCOGNITO) + .build(); public RevampedIncognitoDescriptionViewRenderTest(boolean nightModeEnabled) { NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java index 0631b7f..8e5ffec 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java
@@ -54,7 +54,9 @@ public class StatusViewRenderTest extends BlankUiTestActivityTestCase { @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_OMNIBOX) + .build(); @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java index e020f63..306502c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java
@@ -57,7 +57,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_OMNIBOX) + .build(); @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java index f36d61fe..25bcea02 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java
@@ -31,7 +31,9 @@ public class AssistantVoiceSearchConsentUiRenderTest extends BlankUiTestActivityTestCase { @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_SEARCH_VOICE) + .build(); private ViewGroup mParentView; private LinearLayout mContentView;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java index 3b7bc79..8e7c2f6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java
@@ -55,7 +55,9 @@ new ChromeTabbedActivityTestRule(); @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_SEARCH_VOICE) + .build(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java index 48caea1..872c886fe 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java
@@ -109,7 +109,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_BUBBLES_PAGE_INFO) + .build(); @Mock private PageInfoAboutThisSiteController.Natives mMockAboutThisSiteJni;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java index c7f32aea..af9140f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java
@@ -62,7 +62,10 @@ @Rule public RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(5).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(5) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_BUBBLES_PAGE_INFO) + .build(); private void loadUrlAndOpenPageInfo(String url) { mActivityTestRule.loadUrl(url);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java index ffd7eda..bd23802 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -181,7 +181,10 @@ @Rule public RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(7).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(7) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_BUBBLES_PAGE_INFO) + .build(); private boolean mIsSystemLocationSettingEnabled = true;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java index 9db4c54..401b30b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
@@ -56,6 +56,7 @@ RenderTestRule.Builder.withPublicCorpus() .setRevision(RENDER_TEST_REVISION) .setDescription(RENDER_TEST_REVISION_DESCRIPTION) + .setBugComponent(RenderTestRule.Component.BLINK_PAYMENTS) .build(); @BeforeClass
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRetryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRetryTest.java index 57251b4..0bb2a57e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRetryTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRetryTest.java
@@ -43,7 +43,10 @@ @Rule public RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(RenderTestRule.Component.BLINK_PAYMENTS) + .build(); @Override public void onMainActivityStarted() throws TimeoutException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java index 961aa38f..0bef3f48 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java
@@ -69,7 +69,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_SETTINGS_PRIVACY) + .build(); @Rule public JniMocker mocker = new JniMocker();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java index 8dd1556..6135379 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -123,9 +123,11 @@ .around(mSettingsActivityTestRule); @Rule - public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() - .setRevision(RENDER_TEST_REVISION) - .build(); + public ChromeRenderTestRule mRenderTestRule = + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(RENDER_TEST_REVISION) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_SETTINGS) + .build(); @Mock public TemplateUrlService mMockTemplateUrlService; @Mock
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java index 29a12fc..1f2528f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java
@@ -87,7 +87,10 @@ public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule - public final RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + public final RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setBugComponent(RenderTestRule.Component.UI_BROWSER_FIRST_RUN) + .build(); @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java index dea5681f..5334a44 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java
@@ -132,6 +132,7 @@ ChromeRenderTestRule.Builder.withPublicCorpus() .setRevision(RENDER_REVISION) .setDescription(RENDER_DESCRIPTION) + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SIGN_IN) .build(); @Mock
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java index 9916f27..b635a4e9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java
@@ -96,7 +96,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_CONTENT_SUGGESTIONS_HISTORY) + .build(); private static final String[] FAKE_MOST_VISITED_URLS = new String[] { "/chrome/test/data/android/navigate/one.html",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java index 532ea94a..43d2597c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java
@@ -68,7 +68,9 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SYNC) + .build(); @Before public void setUp() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java index 75b7f3f..495b0e92 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java
@@ -104,6 +104,7 @@ public final ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() .setRevision(RENDER_TEST_REVISION) + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SYNC) .build(); @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java index df6ed8f..41c2a43 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java
@@ -61,7 +61,10 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(6).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(6) + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SYNC) + .build(); private FakeSyncServiceImpl mFakeSyncServiceImpl;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java index fa51db9d..f908d0ca 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java
@@ -44,7 +44,10 @@ public class PassphraseTypeDialogFragmentTest extends BlankUiTestActivityTestCase { @Rule public RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(RenderTestRule.Component.SERVICES_SYNC) + .build(); private static final String TAG = "PassphraseTypeDialogFragmentTest";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java index b8dc11a..d47d5073 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java
@@ -74,7 +74,10 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(2).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(2) + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SYNC) + .build(); @Before public void setUp() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java index ca80479..ba6823bf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java
@@ -100,7 +100,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_START) + .build(); class ActivityInflationObserver implements ActivityStateListener, InflationObserver { @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java index 9338d10..f7cba99 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java
@@ -58,7 +58,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_TOOLBAR) + .build(); private View mView;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java index b9dfe24ec..1dfeb3e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java
@@ -46,7 +46,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_TAB_SWITCHER) + .build(); private View mView;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadActivityTest.java index 427ed4a2..a1ff76cc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadActivityTest.java
@@ -37,7 +37,10 @@ @Rule public RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(1).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_WEB_APP_INSTALLS) + .build(); private LaunchpadActivity mLaunchpadActivity; private LaunchpadCoordinator mLaunchpadCoordinator;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTriggerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTriggerTest.java index 79329eb..ba5a182 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTriggerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTriggerTest.java
@@ -18,16 +18,16 @@ import org.robolectric.shadows.ShadowLooper; import org.chromium.base.Callback; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.testing.local.LocalRobolectricTestRunner; import java.util.concurrent.TimeUnit; /** * Tests for {@link NavigationInfoCaptureTrigger}. */ -@RunWith(LocalRobolectricTestRunner.class) +@RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class NavigationInfoCaptureTriggerTest { @Mock
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java index 7933238c..db16602 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java
@@ -26,12 +26,12 @@ import org.chromium.base.task.TaskTraits; import org.chromium.base.task.test.ShadowPostTask; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishHandler; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason; import org.chromium.chrome.browser.customtabs.shadows.ShadowExternalNavigationDelegateImpl; import org.chromium.chrome.browser.flags.ActivityType; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.testing.local.LocalRobolectricTestRunner; import org.chromium.url.GURL; /** @@ -40,11 +40,10 @@ * {@link CustomTabActivityNavigationController#navigate} is tested in integration with other * classes in {@link CustomTabActivityUrlLoadingTest}. */ -@RunWith(LocalRobolectricTestRunner.class) -@Config(manifest = Config.NONE, shadows = { - ShadowExternalNavigationDelegateImpl.class, ShadowPostTask.class}) +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, + shadows = {ShadowExternalNavigationDelegateImpl.class, ShadowPostTask.class}) public class CustomTabActivityNavigationControllerTest { - @Rule public final CustomTabActivityContentTestEnvironment env = new CustomTabActivityContentTestEnvironment();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java index b0ed865..84bc00d4 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java
@@ -31,18 +31,18 @@ import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.embedder_support.util.ShadowUrlUtilities; import org.chromium.content_public.browser.WebContents; -import org.chromium.testing.local.LocalRobolectricTestRunner; /** * Tests for {@link CustomTabActivityTabController}. */ -@RunWith(LocalRobolectricTestRunner.class) +@RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE, shadows = {ShadowUrlUtilities.class}) @Features.DisableFeatures({ChromeFeatureList.CCT_EXTERNAL_LINK_HANDLING}) public class CustomTabActivityTabControllerUnitTest {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java index c0772dc..629b12e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
@@ -30,6 +30,7 @@ import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -39,13 +40,12 @@ import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.components.embedder_support.util.UrlUtilitiesJni; import org.chromium.content_public.browser.LoadUrlParams; -import org.chromium.testing.local.LocalRobolectricTestRunner; /** * Integration tests involving several classes in Custom Tabs content layer, checking that urls are * properly loaded in Custom Tabs in different conditions. */ -@RunWith(LocalRobolectricTestRunner.class) +@RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) @Features.DisableFeatures({ChromeFeatureList.CCT_EXTERNAL_LINK_HANDLING}) public class CustomTabActivityUrlLoadingTest {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java index 2dff6c1..f4369723 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java
@@ -10,13 +10,13 @@ import org.junit.runner.RunWith; import org.robolectric.annotation.Config; -import org.chromium.testing.local.LocalRobolectricTestRunner; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.url.JUnitTestGURLs; /** * Tests AMP url handling in the CustomTab Toolbar. */ -@RunWith(LocalRobolectricTestRunner.class) +@RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class CustomTabToolbarUnitTest { @Test
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index de1bcf1..2467744 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4420,8 +4420,7 @@ "//chrome/browser/cart:mojo_bindings", "//chrome/browser/enterprise/signals:utils", "//chrome/browser/first_party_sets", - "//chrome/browser/media/router/discovery:discovery", - "//chrome/browser/media/router/discovery/access_code:access_code_sink_service_factory", + "//chrome/browser/media/router/discovery/access_code:access_code_sink_service", "//chrome/browser/new_tab_page/chrome_colors:generate_chrome_colors_info", "//chrome/browser/new_tab_page/chrome_colors:generate_colors_info", "//chrome/browser/policy:path_parser", @@ -4484,8 +4483,8 @@ "//extensions/buildflags", ] allow_circular_includes_from += [ - # TODO(crbug.com/1030821): Eliminate usages of browser.h from Media Router. - "//chrome/browser/media/router/discovery:discovery", + # TODO(b/220386256): Remove circular dependency from the browser. + "//chrome/browser/media/router/discovery/access_code:access_code_sink_service", # TODO(crbug.com/1200215): Remove cycles and simplify all dependencies. "//chrome/browser/web_applications",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1ef493c..6acb90e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1270,27 +1270,18 @@ {"Signed-out Users", {}, 0, "t4693176"}, {"All Users", {}, 0, "t4693177"}}; +constexpr FeatureEntry::FeatureParam kOmniboxZeroSuggestInMemoryCache[] = { + {"ZeroSuggestCacheCounterfactual", "true"}}; constexpr FeatureEntry::FeatureParam kOmniboxZeroSuggestCacheDuration15Secs[] = {{"ZeroSuggestCacheDurationSec", "15"}, - {"ZeroSuggestCacheCounterfactual", "true"}, - {"ZeroSuggestPrefetchBypassCache", "true"}}; -constexpr FeatureEntry::FeatureParam kOmniboxZeroSuggestCacheDuration30Secs[] = - {{"ZeroSuggestCacheDurationSec", "30"}, - {"ZeroSuggestCacheCounterfactual", "true"}, - {"ZeroSuggestPrefetchBypassCache", "true"}}; -constexpr FeatureEntry::FeatureParam kOmniboxZeroSuggestCacheDuration60Secs[] = - {{"ZeroSuggestCacheDurationSec", "60"}, - {"ZeroSuggestCacheCounterfactual", "true"}, - {"ZeroSuggestPrefetchBypassCache", "true"}}; + {"ZeroSuggestCacheCounterfactual", "true"}}; constexpr FeatureEntry::FeatureVariation kOmniboxZeroSuggestPrefetchingVariations[] = { - {"15 seconds", kOmniboxZeroSuggestCacheDuration15Secs, - std::size(kOmniboxZeroSuggestCacheDuration15Secs), nullptr}, - {"30 seconds", kOmniboxZeroSuggestCacheDuration30Secs, - std::size(kOmniboxZeroSuggestCacheDuration30Secs), nullptr}, - {"60 seconds", kOmniboxZeroSuggestCacheDuration60Secs, - std::size(kOmniboxZeroSuggestCacheDuration60Secs), nullptr}}; + {"In-memory cache", kOmniboxZeroSuggestInMemoryCache, + std::size(kOmniboxZeroSuggestInMemoryCache), nullptr}, + {"15 sec HTTP cache", kOmniboxZeroSuggestCacheDuration15Secs, + std::size(kOmniboxZeroSuggestCacheDuration15Secs), nullptr}}; const FeatureEntry::FeatureParam kOmniboxUIMaxAutocompleteMatches3[] = { {OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam, "3"}}; @@ -2131,28 +2122,6 @@ #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID) -const FeatureEntry::FeatureParam kHomepagePromoCardLarge[] = { - {"promo-card-variation", "Large"}}; -const FeatureEntry::FeatureParam kHomepagePromoCardCompact[] = { - {"promo-card-variation", "Compact"}}; -const FeatureEntry::FeatureParam kHomepagePromoCardSlim[] = { - {"promo-card-variation", "Slim"}}; -const FeatureEntry::FeatureParam kHomepagePromoCardSuppressing[] = { - {"promo-card-variation", "Compact"}, - {"suppressing_sign_in_promo", "true"}}; - -const FeatureEntry::FeatureVariation kHomepagePromoCardVariations[] = { - {"Large", kHomepagePromoCardLarge, std::size(kHomepagePromoCardLarge), - nullptr}, - {"Compact", kHomepagePromoCardCompact, std::size(kHomepagePromoCardCompact), - nullptr}, - {"Slim", kHomepagePromoCardSlim, std::size(kHomepagePromoCardSlim), - nullptr}, - {"Compact_SuppressingSignInPromo", kHomepagePromoCardSuppressing, - std::size(kHomepagePromoCardSuppressing), nullptr}}; -#endif // BUILDFLAG(IS_ANDROID) - -#if BUILDFLAG(IS_ANDROID) const FeatureEntry::FeatureParam kLensCameraAssistedSearchLensButtonStart[] = { {"searchBoxStartVariantForLensCameraAssistedSearch", "true"}}; @@ -4595,10 +4564,6 @@ flag_descriptions::kArcKeyboardShortcutHelperIntegrationDescription, kOsCrOS, FEATURE_VALUE_TYPE(arc::kKeyboardShortcutHelperIntegrationFeature)}, - {"arc-mouse-wheel-smooth-scroll", - flag_descriptions::kArcMouseWheelSmoothScrollName, - flag_descriptions::kArcMouseWheelSmoothScrollDescription, kOsCrOS, - FEATURE_VALUE_TYPE(arc::kMouseWheelSmoothScroll)}, {"arc-native-bridge-toggle", flag_descriptions::kArcNativeBridgeToggleName, flag_descriptions::kArcNativeBridgeToggleDescription, kOsCrOS, FEATURE_VALUE_TYPE(arc::kNativeBridgeToggleFeature)}, @@ -6585,14 +6550,6 @@ FEATURE_VALUE_TYPE(chromeos::features::kCrostiniDiskResizing)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) -#if BUILDFLAG(IS_ANDROID) - {"homepage-promo-card", flag_descriptions::kHomepagePromoCardName, - flag_descriptions::kHomepagePromoCardDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kHomepagePromoCard, - kHomepagePromoCardVariations, - "HomepagePromoAndroid")}, -#endif // BUILDFLAG(IS_ANDROID) - #if BUILDFLAG(IS_CHROMEOS_ASH) {"sync-settings-categorization", flag_descriptions::kSyncSettingsCategorizationName,
diff --git a/chrome/browser/ash/borealis/borealis_power_controller.cc b/chrome/browser/ash/borealis/borealis_power_controller.cc index a039ee2..5c74ee648 100644 --- a/chrome/browser/ash/borealis/borealis_power_controller.cc +++ b/chrome/browser/ash/borealis/borealis_power_controller.cc
@@ -8,23 +8,24 @@ #include "chrome/browser/ash/borealis/borealis_util.h" #include "chrome/browser/ash/borealis/borealis_window_manager.h" #include "content/public/browser/device_service.h" +#include "ui/aura/client/focus_client.h" #include "ui/views/widget/widget.h" namespace borealis { -BorealisPowerController::BorealisPowerController() - : root_focus_observer_(this) { - if (!ash::Shell::HasInstance()) - return; - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()); - root_focus_observer_.Observe(focus_client); +BorealisPowerController::BorealisPowerController() { + if (ash::Shell::HasInstance()) + aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()) + ->AddObserver(this); } BorealisPowerController::~BorealisPowerController() { if (wake_lock_) { wake_lock_->CancelWakeLock(); } + if (ash::Shell::HasInstance()) + aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()) + ->RemoveObserver(this); } void BorealisPowerController::OnWindowFocused(aura::Window* gained_focus,
diff --git a/chrome/browser/ash/borealis/borealis_power_controller.h b/chrome/browser/ash/borealis/borealis_power_controller.h index 1691bd2..6c17d14 100644 --- a/chrome/browser/ash/borealis/borealis_power_controller.h +++ b/chrome/browser/ash/borealis/borealis_power_controller.h
@@ -6,12 +6,10 @@ #define CHROME_BROWSER_ASH_BOREALIS_BOREALIS_POWER_CONTROLLER_H_ #include "ash/wm/window_state.h" -#include "base/scoped_observation.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/device/public/mojom/wake_lock.mojom.h" #include "services/device/public/mojom/wake_lock_provider.mojom.h" #include "ui/aura/client/focus_change_observer.h" -#include "ui/aura/client/focus_client.h" namespace borealis { @@ -41,9 +39,6 @@ } private: - base::ScopedObservation<aura::client::FocusClient, - aura::client::FocusChangeObserver> - root_focus_observer_; mojo::Remote<device::mojom::WakeLockProvider> wake_lock_provider_; mojo::Remote<device::mojom::WakeLock> wake_lock_; };
diff --git a/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc b/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc index 31d10367..f1add77 100644 --- a/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc +++ b/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc
@@ -16,12 +16,16 @@ #include "chrome/browser/ash/file_manager/file_tasks.h" #include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/test/base/testing_profile.h" +#include "components/services/app_service/public/cpp/app_types.h" +#include "components/services/app_service/public/cpp/features.h" +#include "components/services/app_service/public/cpp/intent_filter.h" #include "components/services/app_service/public/cpp/intent_test_util.h" #include "components/services/app_service/public/mojom/types.mojom.h" #include "content/public/test/browser_task_environment.h" #include "extensions/browser/entry_info.h" #include "extensions/common/extension_builder.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/features.h" #include "url/gurl.h" @@ -103,52 +107,61 @@ void AddFakeAppWithIntentFilters( const std::string& app_id, - std::vector<apps::mojom::IntentFilterPtr> intent_filters, - apps::mojom::AppType app_type, - apps::mojom::OptionalBool handles_intents) { - std::vector<apps::mojom::AppPtr> apps; - auto app = apps::mojom::App::New(); + std::vector<apps::IntentFilterPtr> intent_filters, + apps::AppType app_type, + absl::optional<bool> handles_intents) { + std::vector<apps::AppPtr> apps; + auto app = std::make_unique<apps::App>(app_type, app_id); app->app_id = app_id; app->app_type = app_type; app->handles_intents = handles_intents; - app->readiness = apps::mojom::Readiness::kReady; + app->readiness = apps::Readiness::kReady; app->intent_filters = std::move(intent_filters); apps.push_back(std::move(app)); - app_service_proxy_->AppRegistryCache().OnApps( - std::move(apps), app_type, false /* should_notify_initialized */); - app_service_test_.WaitForAppService(); + if (base::FeatureList::IsEnabled( + apps::kAppServiceOnAppUpdateWithoutMojom)) { + app_service_proxy_->AppRegistryCache().OnApps( + std::move(apps), app_type, false /* should_notify_initialized */); + } else { + std::vector<apps::mojom::AppPtr> mojom_apps; + mojom_apps.push_back(apps::ConvertAppToMojomApp(apps[0])); + app_service_proxy_->AppRegistryCache().OnApps( + std::move(mojom_apps), apps::ConvertAppTypeToMojomAppType(app_type), + /*should_notify_initialized=*/false); + app_service_test_.WaitForAppService(); + } } void AddFakeWebApp(const std::string& app_id, const std::string& mime_type, const std::string& file_extension, const std::string& activity_label, - apps::mojom::OptionalBool handles_intents) { - std::vector<apps::mojom::IntentFilterPtr> filters; - filters.push_back(apps_util::CreateFileFilterForView( + absl::optional<bool> handles_intents) { + std::vector<apps::IntentFilterPtr> filters; + filters.push_back(apps_util::MakeFileFilterForView( mime_type, file_extension, activity_label)); - AddFakeAppWithIntentFilters(app_id, std::move(filters), - apps::mojom::AppType::kWeb, handles_intents); + AddFakeAppWithIntentFilters(app_id, std::move(filters), apps::AppType::kWeb, + handles_intents); } void AddTextApp() { AddFakeWebApp(kAppIdText, kMimeTypeText, kFileExtensionText, - kActivityLabelText, apps::mojom::OptionalBool::kTrue); + kActivityLabelText, true); } void AddImageApp() { AddFakeWebApp(kAppIdImage, kMimeTypeImage, kFileExtensionImage, - kActivityLabelImage, apps::mojom::OptionalBool::kTrue); + kActivityLabelImage, true); } void AddTextWildApp() { AddFakeWebApp(kAppIdTextWild, kMimeTypeTextWild, kFileExtensionAny, - kActivityLabelTextWild, apps::mojom::OptionalBool::kTrue); + kActivityLabelTextWild, true); } void AddAnyApp() { AddFakeWebApp(kAppIdAny, kMimeTypeAny, kFileExtensionAny, kActivityLabelAny, - apps::mojom::OptionalBool::kTrue); + true); } // Provides file handlers for all extensions and images. @@ -186,10 +199,9 @@ .Build()); baz_app.SetID(kChromeAppId); auto filters = - apps_util::CreateChromeAppIntentFilters(baz_app.Build().get()); + apps_util::CreateIntentFiltersForChromeApp(baz_app.Build().get()); AddFakeAppWithIntentFilters(kChromeAppId, std::move(filters), - apps::mojom::AppType::kChromeApp, - apps::mojom::OptionalBool::kTrue); + apps::AppType::kChromeApp, true); } void AddChromeAppWithVerbs() { @@ -259,10 +271,9 @@ .Build()); foo_app.SetID(kChromeAppWithVerbsId); auto filters = - apps_util::CreateChromeAppIntentFilters(foo_app.Build().get()); + apps_util::CreateIntentFiltersForChromeApp(foo_app.Build().get()); AddFakeAppWithIntentFilters(kChromeAppWithVerbsId, std::move(filters), - apps::mojom::AppType::kChromeApp, - apps::mojom::OptionalBool::kTrue); + apps::AppType::kChromeApp, true); } // Adds file_browser_handler to handle .txt files. @@ -289,10 +300,9 @@ .Build()); fbh_app.SetID(kExtensionId); auto filters = - apps_util::CreateExtensionIntentFilters(fbh_app.Build().get()); + apps_util::CreateIntentFiltersForExtension(fbh_app.Build().get()); AddFakeAppWithIntentFilters(kExtensionId, std::move(filters), - apps::mojom::AppType::kChromeApp, - apps::mojom::OptionalBool::kTrue); + apps::AppType::kChromeApp, true); } base::test::ScopedFeatureList feature_list_; @@ -330,7 +340,7 @@ // match. TEST_F(AppServiceFileTasksTestEnabled, FindAppServiceFileTasksHandlesIntent) { AddFakeWebApp(kAppIdImage, kMimeTypeImage, kFileExtensionImage, - kActivityLabelImage, apps::mojom::OptionalBool::kFalse); + kActivityLabelImage, false); std::vector<FullTaskDescriptor> tasks = FindAppServiceTasks({{"foo.jpeg", kMimeTypeImage}}); ASSERT_EQ(0U, tasks.size());
diff --git a/chrome/browser/ash/printing/oauth2/authorization_server_session.cc b/chrome/browser/ash/printing/oauth2/authorization_server_session.cc new file mode 100644 index 0000000..7237861 --- /dev/null +++ b/chrome/browser/ash/printing/oauth2/authorization_server_session.cc
@@ -0,0 +1,182 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/printing/oauth2/authorization_server_session.h" + +#include <algorithm> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/containers/flat_set.h" +#include "base/strings/string_split.h" +#include "chrome/browser/ash/printing/oauth2/constants.h" +#include "chrome/browser/ash/printing/oauth2/http_exchange.h" +#include "chromeos/printing/uri.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "url/gurl.h" + +namespace ash { +namespace printing { +namespace oauth2 { + +base::flat_set<std::string> ParseScope(const std::string& scope) { + std::vector<std::string> tokens = base::SplitString( + scope, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + base::flat_set<std::string> output(std::move(tokens)); + return output; +} + +AuthorizationServerSession::AuthorizationServerSession( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const GURL& token_endpoint_uri, + base::flat_set<std::string>&& scope) + : token_endpoint_uri_(token_endpoint_uri), + scope_(scope), + http_exchange_(url_loader_factory) {} + +AuthorizationServerSession::~AuthorizationServerSession() = default; + +bool AuthorizationServerSession::ContainsAll( + const base::flat_set<std::string>& scope) const { + return std::includes(scope_.begin(), scope_.end(), scope.begin(), + scope.end()); +} + +void AuthorizationServerSession::SendFirstTokenRequest( + const std::string& client_id, + const std::string& authorization_code, + const std::string& code_verifier, + StatusCallback callback) { + net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation = + net::DefinePartialNetworkTrafficAnnotation( + "printing_oauth2_first_token_request", + "printing_oauth2_http_exchange", R"(semantics { + description: + "This request opens OAuth 2 session with the Authorization Server by " + "asking it for an access token." + data: + "Identifier of the client obtained from the Authorization server during " + "registration and temporary security codes used during authorization " + "process." + })"); + http_exchange_.Clear(); + // Moves query parameters from URL to the content. + chromeos::Uri uri(token_endpoint_uri_.spec()); + auto query = uri.GetQuery(); + for (const auto& kv : query) { + http_exchange_.AddParamString(kv.first, kv.second); + } + uri.SetQuery({}); + // Prepare the request. + http_exchange_.AddParamString("grant_type", "authorization_code"); + http_exchange_.AddParamString("code", authorization_code); + http_exchange_.AddParamString("redirect_uri", kRedirectURI); + http_exchange_.AddParamString("client_id", client_id); + http_exchange_.AddParamString("code_verifier", code_verifier); + http_exchange_.Exchange( + "POST", GURL(uri.GetNormalized()), ContentFormat::kXWwwFormUrlencoded, + 200, 400, partial_traffic_annotation, + base::BindOnce(&AuthorizationServerSession::OnFirstTokenResponse, + base::Unretained(this), std::move(callback))); +} + +void AuthorizationServerSession::SendNextTokenRequest(StatusCallback callback) { + access_token_.clear(); + if (refresh_token_.empty()) { + std::move(callback).Run(StatusCode::kAuthorizationNeeded, + "No refresh token"); + return; + } + net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation = + net::DefinePartialNetworkTrafficAnnotation( + "printing_oauth2_next_token_request", "printing_oauth2_http_exchange", + R"(semantics { + description: + "This request refreshes OAuth 2 session with the Authorization Server by " + "asking it for a new access token." + data: + "A refresh token previously issued by the Authorization Server." + })"); + http_exchange_.Clear(); + // Move query parameters from URL to the content. + chromeos::Uri uri(token_endpoint_uri_.spec()); + auto query = uri.GetQuery(); + for (const auto& kv : query) { + http_exchange_.AddParamString(kv.first, kv.second); + } + uri.SetQuery({}); + // Prepare the request. + http_exchange_.AddParamString("grant_type", "refresh_token"); + http_exchange_.AddParamString("refresh_token", refresh_token_); + http_exchange_.Exchange( + "POST", GURL(uri.GetNormalized()), ContentFormat::kXWwwFormUrlencoded, + 200, 400, partial_traffic_annotation, + base::BindOnce(&AuthorizationServerSession::OnNextTokenResponse, + base::Unretained(this), std::move(callback))); +} + +void AuthorizationServerSession::OnFirstTokenResponse(StatusCallback callback, + StatusCode status) { + if (status != StatusCode::kOK) { + std::move(callback).Run(status, http_exchange_.GetErrorMessage()); + return; + } + + // Parses response. + std::string scope; + const bool ok = + http_exchange_.ParamStringGet("access_token", true, &access_token_) && + http_exchange_.ParamStringEquals("token_type", true, "bearer") && + http_exchange_.ParamStringGet("refresh_token", false, &refresh_token_) && + http_exchange_.ParamStringGet("scope", false, &scope); + if (!ok) { + // Error occurred. + access_token_.clear(); + refresh_token_.clear(); + std::move(callback).Run(StatusCode::kInvalidResponse, + http_exchange_.GetErrorMessage()); + return; + } + + // Success! + auto new_scope = ParseScope(scope); + scope_.insert(new_scope.begin(), new_scope.end()); + std::move(callback).Run(StatusCode::kOK, access_token_); +} + +void AuthorizationServerSession::OnNextTokenResponse(StatusCallback callback, + StatusCode status) { + if (status == StatusCode::kInvalidAccessToken) { + std::move(callback).Run(StatusCode::kAuthorizationNeeded, + "Refresh token expired"); + return; + } + + if (status != StatusCode::kOK) { + std::move(callback).Run(status, http_exchange_.GetErrorMessage()); + return; + } + + // Parses response. + const bool ok = + http_exchange_.ParamStringGet("access_token", true, &access_token_) && + http_exchange_.ParamStringEquals("token_type", true, "bearer") && + http_exchange_.ParamStringGet("refresh_token", false, &refresh_token_); + if (!ok) { + // Error occurred. + access_token_.clear(); + refresh_token_.clear(); + std::move(callback).Run(StatusCode::kInvalidResponse, + http_exchange_.GetErrorMessage()); + return; + } + + // Success! + std::move(callback).Run(StatusCode::kOK, access_token_); +} + +} // namespace oauth2 +} // namespace printing +} // namespace ash
diff --git a/chrome/browser/ash/printing/oauth2/authorization_server_session.h b/chrome/browser/ash/printing/oauth2/authorization_server_session.h new file mode 100644 index 0000000..8110971 --- /dev/null +++ b/chrome/browser/ash/printing/oauth2/authorization_server_session.h
@@ -0,0 +1,96 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_PRINTING_OAUTH2_AUTHORIZATION_SERVER_SESSION_H_ +#define CHROME_BROWSER_ASH_PRINTING_OAUTH2_AUTHORIZATION_SERVER_SESSION_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/containers/flat_set.h" +#include "base/memory/ref_counted.h" +#include "chrome/browser/ash/printing/oauth2/http_exchange.h" +#include "chrome/browser/ash/printing/oauth2/status_code.h" +#include "url/gurl.h" + +namespace network { +class SharedURLLoaderFactory; +} // namespace network + +namespace ash { +namespace printing { +namespace oauth2 { + +// Helper function that parse scope field (a list of names). +base::flat_set<std::string> ParseScope(const std::string& scope); + +// This class represents single OAuth2 session and is responsible for acquiring +// and refreshing the access token. +class AuthorizationServerSession { + public: + // Constructor. + AuthorizationServerSession( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const GURL& token_endpoint_uri, + base::flat_set<std::string>&& scope); + // Not copyable. + AuthorizationServerSession(const AuthorizationServerSession&) = delete; + AuthorizationServerSession& operator=(const AuthorizationServerSession&) = + delete; + // Destructor. + ~AuthorizationServerSession(); + + // Returns the access token or an empty string if the access token is not + // known yet. + const std::string& access_token() const { return access_token_; } + + // Returns true <=> the scope contains all elements from `scope`. + bool ContainsAll(const base::flat_set<std::string>& scope) const; + + // Prepares and sends First Token Request. Results are returned by `callback`. + // If the request is successful, the callback returns StatusCode::kOK and the + // access token as the second parameter. Otherwise, the error code with + // a message is returned. + void SendFirstTokenRequest(const std::string& client_id, + const std::string& authorization_code, + const std::string& code_verifier, + StatusCallback callback); + + // Resets the current access token to empty string and sends Next Token + // Request to obtain a new one. If the request is successful, the callback + // returns StatusCode::kOK and the access token as the second parameter. + // If the server does not allow to refresh the access token or the refresh + // token expired, the status StatusCode::kAuthorizationNeeded is returned. + // Otherwise, the error code with a message is returned. + void SendNextTokenRequest(StatusCallback callback); + + private: + // Analyzes response for First Token Request. + void OnFirstTokenResponse(StatusCallback callback, StatusCode status); + + // Analyzes response for Next Token Request. + void OnNextTokenResponse(StatusCallback callback, StatusCode status); + + // URL of the endpoint at the Authorization Server. + const GURL token_endpoint_uri_; + + // Set of scopes requested by the client and/or granted by the + // Authorization Server. + base::flat_set<std::string> scope_; + + // Access token of the current OAuth2 session. + std::string access_token_; + // Refresh token of the current OAuth2 session. + std::string refresh_token_; + + // The object used for communication with the Authorization Server. + HttpExchange http_exchange_; +}; + +} // namespace oauth2 +} // namespace printing +} // namespace ash + +#endif // CHROME_BROWSER_ASH_PRINTING_OAUTH2_AUTHORIZATION_SERVER_SESSION_H_
diff --git a/chrome/browser/ash/printing/oauth2/authorization_server_session_unittest.cc b/chrome/browser/ash/printing/oauth2/authorization_server_session_unittest.cc new file mode 100644 index 0000000..995a404f --- /dev/null +++ b/chrome/browser/ash/printing/oauth2/authorization_server_session_unittest.cc
@@ -0,0 +1,239 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/printing/oauth2/authorization_server_session.h" + +#include <memory> +#include <string> + +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" +#include "base/values.h" +#include "chrome/browser/ash/printing/oauth2/constants.h" +#include "chrome/browser/ash/printing/oauth2/status_code.h" +#include "chrome/browser/ash/printing/oauth2/test_authorization_server.h" +#include "net/http/http_status_code.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace ash { +namespace printing { +namespace oauth2 { +namespace { + +class PrintingOAuth2AuthorizationServerSessionTest : public testing::Test { + protected: + // Initialize the `session_` field. + void CreateSession(base::flat_set<std::string>&& scope) { + GURL gurl(url_); + CHECK(gurl.is_valid()); + session_ = std::make_unique<AuthorizationServerSession>( + server_.GetURLLoaderFactory(), gurl, std::move(scope)); + } + // Process the First Token request on the server side and send a response + // with given `access_token` and `refresh_token`. If the `refresh_token` is + // empty the response does not contain the field "refresh_token". + void ProcessFirstTokenRequestAndResponse( + const std::string& access_token, + const std::string& refresh_token = "") { + base::flat_map<std::string, std::string> params; + base::flat_map<std::string, base::Value> fields; + EXPECT_EQ("", server_.ReceivePOSTWithURLParams(url_, params)); + fields["access_token"] = base::Value(access_token); + fields["token_type"] = base::Value("bearer"); + if (!refresh_token.empty()) { + fields["refresh_token"] = base::Value(refresh_token); + } + server_.ResponseWithJSON(net::HttpStatusCode::HTTP_OK, fields); + } + // URL of the endpoint at the server. + const std::string url_ = "https://a.b/c"; + // The object simulating the Authorization Server. + FakeAuthorizationServer server_; + // The testes session, it is created by the method CreateSession(...). + std::unique_ptr<AuthorizationServerSession> session_; +}; + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, ParseScope) { + auto scope = ParseScope(" w szczebrzeszynie chrzaszcz brzmi w trzcinie "); + EXPECT_EQ(scope.size(), 5); + EXPECT_TRUE(scope.contains("w")); + EXPECT_TRUE(scope.contains("szczebrzeszynie")); + EXPECT_TRUE(scope.contains("chrzaszcz")); + EXPECT_TRUE(scope.contains("brzmi")); + EXPECT_TRUE(scope.contains("trzcinie")); +} + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, InitialState) { + CreateSession({"ala", "ma", "kota"}); + EXPECT_TRUE(session_->access_token().empty()); + EXPECT_TRUE(session_->ContainsAll({})); + EXPECT_TRUE(session_->ContainsAll({"kota", "ala"})); + EXPECT_FALSE(session_->ContainsAll({"psa", "ma"})); +} + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, FirstTokenRequest) { + CreateSession({"xxx"}); + CallbackResult cr; + session_->SendFirstTokenRequest("clientID_xe2$", "auth_code_3d#x", + "code_verifier_P2s&", BindResult(cr)); + + // Verify the request. + base::flat_map<std::string, std::string> params; + ASSERT_EQ("", server_.ReceivePOSTWithURLParams(url_, params)); + EXPECT_EQ(params["grant_type"], "authorization_code"); + EXPECT_EQ(params["code"], "auth_code_3d#x"); + EXPECT_EQ(params["redirect_uri"], printing::oauth2::kRedirectURI); + EXPECT_EQ(params["client_id"], "clientID_xe2$"); + EXPECT_EQ(params["code_verifier"], "code_verifier_P2s&"); + + // Prepare and send the response. + base::flat_map<std::string, base::Value> fields; + fields["access_token"] = base::Value("access_token_@(#a"); + fields["token_type"] = base::Value("bearer"); + fields["refresh_token"] = base::Value("refresh_token_X)(@K"); + server_.ResponseWithJSON(net::HttpStatusCode::HTTP_OK, fields); + + // Verify the response. + EXPECT_EQ(cr.status, StatusCode::kOK); + EXPECT_EQ(cr.data, "access_token_@(#a"); + EXPECT_EQ(session_->access_token(), "access_token_@(#a"); +} + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, FirstTokenRequestError) { + CreateSession({"xxx"}); + CallbackResult cr; + session_->SendFirstTokenRequest("a", "b", "c", BindResult(cr)); + + // Receive the request. + base::flat_map<std::string, std::string> params; + ASSERT_EQ("", server_.ReceivePOSTWithURLParams(url_, params)); + EXPECT_EQ(params["code"], "b"); + EXPECT_EQ(params["client_id"], "a"); + EXPECT_EQ(params["code_verifier"], "c"); + + // Prepare and send the response. + base::flat_map<std::string, base::Value> fields; + fields["access_token"] = base::Value("access_token_1"); + // The field "token_type" is wrong. + fields["token_type"] = base::Value("bearer_WRONG"); + fields["refresh_token"] = base::Value("refresh_token_2"); + server_.ResponseWithJSON(net::HttpStatusCode::HTTP_OK, fields); + + // Verify the response. + EXPECT_EQ(cr.status, StatusCode::kInvalidResponse); + // The error message contains "token_type". + EXPECT_NE(cr.data.find("token_type"), std::string::npos); + EXPECT_TRUE(session_->access_token().empty()); +} + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, NextTokenRequest) { + CreateSession({"xxx"}); + CallbackResult cr; + + // Send the First Token Request and process it. + session_->SendFirstTokenRequest("a", "b", "c", BindResult(cr)); + ProcessFirstTokenRequestAndResponse("access_token_1", "refresh_token_X)(@K"); + + // Receive the response and send the Next Token Request. + ASSERT_EQ(cr.status, StatusCode::kOK); + EXPECT_EQ(session_->access_token(), "access_token_1"); + session_->SendNextTokenRequest(BindResult(cr)); + // It should reset the current access token. + EXPECT_TRUE(session_->access_token().empty()); + + // Receive and verify the request. + base::flat_map<std::string, std::string> params; + ASSERT_EQ("", server_.ReceivePOSTWithURLParams(url_, params)); + EXPECT_EQ(params["grant_type"], "refresh_token"); + EXPECT_EQ(params["refresh_token"], "refresh_token_X)(@K"); + + // Prepare and send the response. + base::flat_map<std::string, base::Value> fields; + fields["access_token"] = base::Value("new_access_token_123"); + fields["token_type"] = base::Value("bearer"); + server_.ResponseWithJSON(net::HttpStatusCode::HTTP_OK, fields); + + // Verify the response. + EXPECT_EQ(cr.status, StatusCode::kOK); + EXPECT_EQ(cr.data, "new_access_token_123"); + EXPECT_EQ(session_->access_token(), "new_access_token_123"); +} + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, NextTokenRequestError) { + CreateSession({"xxx"}); + CallbackResult cr; + + // Send the First Token Request and process it. + session_->SendFirstTokenRequest("a", "b", "c", BindResult(cr)); + ProcessFirstTokenRequestAndResponse("access_token_1", "refresh_token_X)(@K"); + + // Receive the response and send the Next Token Request. + ASSERT_EQ(cr.status, StatusCode::kOK); + EXPECT_EQ(session_->access_token(), "access_token_1"); + session_->SendNextTokenRequest(BindResult(cr)); + + // Receive the request and send the response. + base::flat_map<std::string, std::string> params; + ASSERT_EQ("", server_.ReceivePOSTWithURLParams(url_, params)); + EXPECT_EQ(params["refresh_token"], "refresh_token_X)(@K"); + base::flat_map<std::string, base::Value> fields; + fields["token_type"] = base::Value("bearer"); + // The field "access_token" is missing. + server_.ResponseWithJSON(net::HttpStatusCode::HTTP_OK, fields); + + // Verify the response. + EXPECT_EQ(cr.status, StatusCode::kInvalidResponse); + // The error message contains "access_token". + EXPECT_NE(cr.data.find("access_token"), std::string::npos); + EXPECT_TRUE(session_->access_token().empty()); +} + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, NoRefreshTokens) { + CreateSession({}); + CallbackResult cr; + + // Send the First Token Request and process it. + session_->SendFirstTokenRequest("a", "b", "c", BindResult(cr)); + ProcessFirstTokenRequestAndResponse("access_token_@(#a"); + + // Receive the response and send the Next Token Request. + ASSERT_EQ(cr.status, StatusCode::kOK); + EXPECT_EQ(cr.data, "access_token_@(#a"); + session_->SendNextTokenRequest(BindResult(cr)); + + // Verify the response. + EXPECT_EQ(cr.status, StatusCode::kAuthorizationNeeded); + EXPECT_TRUE(session_->access_token().empty()); +} + +TEST_F(PrintingOAuth2AuthorizationServerSessionTest, InvalidRefreshToken) { + CreateSession({"xxx"}); + CallbackResult cr; + + // Send the First Token Request and process it. + session_->SendFirstTokenRequest("a", "b", "c", BindResult(cr)); + ProcessFirstTokenRequestAndResponse("access_token_1", "refresh_token_X)@K"); + + // Receive the response and send the Next Token Request. + ASSERT_EQ(cr.status, StatusCode::kOK); + session_->SendNextTokenRequest(BindResult(cr)); + + // Receive and the request and send the response. + base::flat_map<std::string, std::string> params; + ASSERT_EQ("", server_.ReceivePOSTWithURLParams(url_, params)); + EXPECT_EQ(params["refresh_token"], "refresh_token_X)@K"); + base::flat_map<std::string, base::Value> fields; + fields["error"] = base::Value("invalid_grant"); + server_.ResponseWithJSON(net::HttpStatusCode::HTTP_BAD_REQUEST, fields); + + // Verify the response. + EXPECT_EQ(cr.status, StatusCode::kAuthorizationNeeded); + EXPECT_TRUE(session_->access_token().empty()); +} + +} // namespace +} // namespace oauth2 +} // namespace printing +} // namespace ash
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc index 9f65b4a..3299c8ad 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc
@@ -180,6 +180,16 @@ return; } + if (!is_google_photos_enterprise_enabled_) { + mojo::ReportBadMessage( + "Cannot call `FetchGooglePhotosAlbums()` without confirming that the " + "Google Photos enterprise setting is enabled."); + std::move(callback).Run( + ash::personalization_app::mojom::FetchGooglePhotosAlbumsResponse::New( + absl::nullopt, absl::nullopt)); + return; + } + if (!google_photos_albums_fetcher_) { google_photos_albums_fetcher_ = std::make_unique<wallpaper_handlers::GooglePhotosAlbumsFetcher>( @@ -199,6 +209,14 @@ return; } + if (!is_google_photos_enterprise_enabled_) { + mojo::ReportBadMessage( + "Cannot call `FetchGooglePhotosCount()` without confirming that the " + "Google Photos enterprise setting is enabled."); + std::move(callback).Run(-1); + return; + } + if (!google_photos_count_fetcher_) { google_photos_count_fetcher_ = std::make_unique<wallpaper_handlers::GooglePhotosCountFetcher>( @@ -224,8 +242,11 @@ std::make_unique<wallpaper_handlers::GooglePhotosEnabledFetcher>( profile_); } - google_photos_enabled_fetcher_->AddRequestAndStartIfNecessary( - std::move(callback)); + // base::Unretained is safe to use because |this| outlives + // |google_photos_enabled_fetcher_|. + google_photos_enabled_fetcher_->AddRequestAndStartIfNecessary(base::BindOnce( + &PersonalizationAppWallpaperProviderImpl::OnFetchGooglePhotosEnabled, + base::Unretained(this), std::move(callback))); } void PersonalizationAppWallpaperProviderImpl::FetchGooglePhotosPhotos( @@ -243,6 +264,16 @@ return; } + if (!is_google_photos_enterprise_enabled_) { + mojo::ReportBadMessage( + "Cannot call `FetchGooglePhotosPhotos()` without confirming that the " + "Google Photos enterprise setting is enabled."); + std::move(callback).Run( + ash::personalization_app::mojom::FetchGooglePhotosPhotosResponse::New( + absl::nullopt, absl::nullopt)); + return; + } + if (!google_photos_photos_fetcher_) { google_photos_photos_fetcher_ = std::make_unique<wallpaper_handlers::GooglePhotosPhotosFetcher>( @@ -447,6 +478,14 @@ const std::string& id, ash::WallpaperLayout layout, SelectGooglePhotosPhotoCallback callback) { + if (!is_google_photos_enterprise_enabled_) { + mojo::ReportBadMessage( + "Cannot call `SelectGooglePhotosPhoto()` without confirming that the " + "Google Photos enterprise setting is enabled."); + std::move(callback).Run(false); + return; + } + if (pending_select_google_photos_photo_callback_) std::move(pending_select_google_photos_photo_callback_).Run(false); pending_select_google_photos_photo_callback_ = std::move(callback); @@ -583,6 +622,15 @@ std::move(callback).Run(std::move(result)); } +void PersonalizationAppWallpaperProviderImpl::OnFetchGooglePhotosEnabled( + FetchGooglePhotosEnabledCallback callback, + ash::personalization_app::mojom::GooglePhotosEnablementState state) { + is_google_photos_enterprise_enabled_ = + state == + ash::personalization_app::mojom::GooglePhotosEnablementState::kEnabled; + std::move(callback).Run(state); +} + void PersonalizationAppWallpaperProviderImpl::OnGetLocalImages( GetLocalImagesCallback callback, const std::vector<base::FilePath>& images) {
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h index f3c402b..8e4ba0c 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h
@@ -179,6 +179,10 @@ const std::string& collection_id, const std::vector<backdrop::Image>& images); + void OnFetchGooglePhotosEnabled( + FetchGooglePhotosEnabledCallback callback, + ash::personalization_app::mojom::GooglePhotosEnablementState state); + void OnGetLocalImages(GetLocalImagesCallback callback, const std::vector<base::FilePath>& images); @@ -266,6 +270,12 @@ std::unique_ptr<wallpaper_handlers::GooglePhotosPhotosFetcher> google_photos_photos_fetcher_; + // Set to true when an enabled Google Photos enterprise setting is fetched + // from the server. Attempting to select a Google Photos wallpaper or fetch + // Google Photos data other than the enterprise setting itself will fail if + // this value is false. + bool is_google_photos_enterprise_enabled_ = false; + SelectWallpaperCallback pending_select_wallpaper_callback_; SelectLocalImageCallback pending_select_local_image_callback_;
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc index 107daff..028a4172 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc
@@ -434,6 +434,35 @@ class PersonalizationAppWallpaperProviderImplGooglePhotosTest : public PersonalizationAppWallpaperProviderImplTest { protected: + // Mocks an attempt to fetch the Google Photos enterprise setting from the + // server. A successful attempt, which happens when the Google Photos + // wallpaper integration is enabled, will enable wallpaper selection and + // other Google Photos data fetches to go through. + void FetchGooglePhotosEnabled(size_t num_fetches = 1) { + using ash::personalization_app::mojom::GooglePhotosEnablementState; + + // Mock a fetcher for the enablement state query. + auto* const google_photos_enabled_fetcher = static_cast<::testing::NiceMock< + wallpaper_handlers::MockGooglePhotosEnabledFetcher>*>( + delegate()->SetGooglePhotosEnabledFetcherForTest( + std::make_unique<::testing::NiceMock< + wallpaper_handlers::MockGooglePhotosEnabledFetcher>>( + profile()))); + + EXPECT_CALL(*google_photos_enabled_fetcher, AddRequestAndStartIfNecessary) + .Times(GooglePhotosEnabled() ? num_fetches : 0); + + for (size_t i = 0; i < num_fetches; ++i) { + wallpaper_provider_remote()->get()->FetchGooglePhotosEnabled( + base::BindLambdaForTesting([this](GooglePhotosEnablementState state) { + EXPECT_EQ(state, GooglePhotosEnabled() + ? GooglePhotosEnablementState::kEnabled + : GooglePhotosEnablementState::kError); + })); + } + wallpaper_provider_remote()->FlushForTesting(); + } + // The number of times to start each idempotent API query. static constexpr size_t kNumFetches = 2; // Resume token value used across several tests. @@ -460,6 +489,22 @@ ::testing::_)) .Times(GooglePhotosEnabled() ? kNumFetches : 0); + // Test fetching Google Photos albums before fetching the enterprise setting. + // No requests should be made. + for (size_t i = 0; i < kNumFetches; ++i) { + wallpaper_provider_remote()->get()->FetchGooglePhotosAlbums( + kResumeToken, base::BindLambdaForTesting( + [](ash::personalization_app::mojom:: + FetchGooglePhotosAlbumsResponsePtr response) { + EXPECT_FALSE(response->albums.has_value()); + })); + } + wallpaper_provider_remote()->FlushForTesting(); + + // Test fetching Google Photos albums after fetching the enterprise setting. + // Requests should be made if and only if the Google Photos wallpaper + // integration is enabled. + FetchGooglePhotosEnabled(); for (size_t i = 0; i < kNumFetches; ++i) { wallpaper_provider_remote()->get()->FetchGooglePhotosAlbums( kResumeToken, @@ -485,6 +530,18 @@ EXPECT_CALL(*google_photos_count_fetcher, AddRequestAndStartIfNecessary) .Times(GooglePhotosEnabled() ? kNumFetches : 0); + // Test fetching Google Photos count before fetching the enterprise setting. + // No requests should be made. + for (size_t i = 0; i < kNumFetches; ++i) { + wallpaper_provider_remote()->get()->FetchGooglePhotosCount( + base::BindLambdaForTesting([](int count) { EXPECT_EQ(count, -1); })); + } + wallpaper_provider_remote()->FlushForTesting(); + + // Test fetching Google Photos count after fetching the enterprise setting. + // Requests should be made if and only if the Google Photos wallpaper + // integration is enabled. + FetchGooglePhotosEnabled(); for (size_t i = 0; i < kNumFetches; ++i) { wallpaper_provider_remote()->get()->FetchGooglePhotosCount( base::BindLambdaForTesting([this](int count) { @@ -495,29 +552,9 @@ } TEST_P(PersonalizationAppWallpaperProviderImplGooglePhotosTest, FetchEnabled) { - using ash::personalization_app::mojom::GooglePhotosEnablementState; - - // Mock a fetcher for the enablement state query. - auto* const google_photos_enabled_fetcher = static_cast< - ::testing::NiceMock<wallpaper_handlers::MockGooglePhotosEnabledFetcher>*>( - delegate()->SetGooglePhotosEnabledFetcherForTest( - std::make_unique<::testing::NiceMock< - wallpaper_handlers::MockGooglePhotosEnabledFetcher>>(profile()))); - // Simulate the client making multiple requests for the same information to // test that all callbacks for that query are called. - EXPECT_CALL(*google_photos_enabled_fetcher, AddRequestAndStartIfNecessary) - .Times(GooglePhotosEnabled() ? kNumFetches : 0); - - for (size_t i = 0; i < kNumFetches; ++i) { - wallpaper_provider_remote()->get()->FetchGooglePhotosEnabled( - base::BindLambdaForTesting([this](GooglePhotosEnablementState state) { - EXPECT_EQ(state, GooglePhotosEnabled() - ? GooglePhotosEnablementState::kEnabled - : GooglePhotosEnablementState::kError); - })); - } - wallpaper_provider_remote()->FlushForTesting(); + FetchGooglePhotosEnabled(kNumFetches); } TEST_P(PersonalizationAppWallpaperProviderImplGooglePhotosTest, FetchPhotos) { @@ -538,6 +575,23 @@ absl::make_optional(kResumeToken), ::testing::_)) .Times(GooglePhotosEnabled() ? kNumFetches : 0); + // Test fetching Google Photos photos before fetching the enterprise setting. + // No requests should be made. + for (size_t i = 0; i < kNumFetches; ++i) { + wallpaper_provider_remote()->get()->FetchGooglePhotosPhotos( + item_id, album_id, kResumeToken, + base::BindLambdaForTesting( + [](ash::personalization_app::mojom:: + FetchGooglePhotosPhotosResponsePtr response) { + EXPECT_FALSE(response->photos.has_value()); + })); + } + wallpaper_provider_remote()->FlushForTesting(); + + // Test fetching Google Photos photos after fetching the enterprise setting. + // Requests should be made if and only if the Google Photos wallpaper + // integration is enabled. + FetchGooglePhotosEnabled(); for (size_t i = 0; i < kNumFetches; ++i) { wallpaper_provider_remote()->get()->FetchGooglePhotosPhotos( item_id, album_id, kResumeToken, @@ -874,14 +928,31 @@ const std::string photo_id = "OmnisVirLupus"; bool feature_enabled = GooglePhotosEnabled(); + // Test selecting a wallpaper before fetching the enterprise setting. wallpaper_provider_remote()->get()->SelectGooglePhotosPhoto( photo_id, ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, - base::BindLambdaForTesting([&feature_enabled](bool success) { + base::BindLambdaForTesting([](bool success) { EXPECT_FALSE(success); })); + wallpaper_provider_remote()->FlushForTesting(); + + EXPECT_EQ(0, + test_wallpaper_controller()->set_google_photos_wallpaper_count()); + EXPECT_NE( + ash::WallpaperInfo( + {AccountId::FromUserEmailGaiaId(kFakeTestEmail, kTestGaiaId), + photo_id, ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED}), + test_wallpaper_controller()->wallpaper_info().value_or( + ash::WallpaperInfo())); + + // Test selecting a wallpaper after fetching the enterprise setting. + FetchGooglePhotosEnabled(); + wallpaper_provider_remote()->get()->SelectGooglePhotosPhoto( + photo_id, ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, + base::BindLambdaForTesting([feature_enabled](bool success) { EXPECT_EQ(success, feature_enabled); })); wallpaper_provider_remote()->FlushForTesting(); - EXPECT_EQ(1, + EXPECT_EQ(feature_enabled ? 1 : 0, test_wallpaper_controller()->set_google_photos_wallpaper_count()); EXPECT_EQ( feature_enabled,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 1184359b..3714e2d 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2978,6 +2978,8 @@ "../ash/printing/history/print_job_reporting_service_impl.cc", "../ash/printing/oauth2/authorization_server_data.cc", "../ash/printing/oauth2/authorization_server_data.h", + "../ash/printing/oauth2/authorization_server_session.cc", + "../ash/printing/oauth2/authorization_server_session.h", "../ash/printing/oauth2/constants.h", "../ash/printing/oauth2/http_exchange.cc", "../ash/printing/oauth2/http_exchange.h", @@ -4656,6 +4658,7 @@ "../ash/printing/history/test_print_job_history_service_observer.cc", "../ash/printing/history/test_print_job_history_service_observer.h", "../ash/printing/oauth2/authorization_server_data_unittest.cc", + "../ash/printing/oauth2/authorization_server_session_unittest.cc", "../ash/printing/oauth2/http_exchange_unittest.cc", "../ash/printing/oauth2/test_authorization_server.cc", "../ash/printing/oauth2/test_authorization_server.h", @@ -4851,6 +4854,7 @@ "../ui/webui/settings/chromeos/internet_handler_unittest.cc", "../ui/webui/settings/chromeos/metrics_consent_handler_unittest.cc", "../ui/webui/settings/chromeos/multidevice_handler_unittest.cc", + "../ui/webui/settings/chromeos/multidevice_section_unittest.cc", "../ui/webui/settings/chromeos/os_settings_manager_unittest.cc", "../ui/webui/settings/chromeos/os_settings_section_unittest.cc", "../ui/webui/settings/chromeos/search/per_session_settings_user_action_tracker_unittest.cc",
diff --git a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java index 89ad63c..46ad2083 100644 --- a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java +++ b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java
@@ -55,7 +55,10 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent( + ChromeRenderTestRule.Component.UI_BROWSER_SHOPPING_MERCHANT_TRUST) + .build(); public MerchantTrustMessageViewTest(boolean nightModeEnabled) { NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
diff --git a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/PageInfoStoreInfoViewTest.java b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/PageInfoStoreInfoViewTest.java index 835158cf..b850e09f 100644 --- a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/PageInfoStoreInfoViewTest.java +++ b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/PageInfoStoreInfoViewTest.java
@@ -92,7 +92,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_SHOPPING) + .build(); @Mock private OptimizationGuideBridge.Natives mMockOptimizationGuideBridgeJni;
diff --git a/chrome/browser/component_updater/recovery_component_installer.cc b/chrome/browser/component_updater/recovery_component_installer.cc index 839de739..1d41c57 100644 --- a/chrome/browser/component_updater/recovery_component_installer.cc +++ b/chrome/browser/component_updater/recovery_component_installer.cc
@@ -202,7 +202,7 @@ base::LaunchOptions options; options.start_hidden = true; options.elevated = true; - base::Process process = base::LaunchElevatedProcess(cmdline, options); + base::Process process = base::LaunchProcess(cmdline, options); #elif BUILDFLAG(IS_MAC) base::mac::ScopedAuthorizationRef authRef( base::mac::AuthorizationCreateToRunAsRoot(nullptr));
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java index d7587aa..7be4b4e 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java +++ b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java
@@ -63,7 +63,8 @@ AlertDialog alertDialog = new AlertDialog - .Builder(getActivity(), R.style.Theme_Chromium_AlertDialog_NoActionBar) + .Builder(getActivity(), + R.style.ThemeOverlay_BrowserUI_AlertDialog_NoActionBar) .setView(dialogView) .create(); alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
diff --git a/chrome/browser/download/android/java/res/values-v17/styles.xml b/chrome/browser/download/android/java/res/values-v17/styles.xml index 8be28a21..7031e51 100644 --- a/chrome/browser/download/android/java/res/values-v17/styles.xml +++ b/chrome/browser/download/android/java/res/values-v17/styles.xml
@@ -9,7 +9,7 @@ <style name="TextAppearance.DownloadDialogTitle" parent="TextAppearance.AlertDialogTitleStyle"> <item name="android:textSize">20sp</item> </style> - <style name="Theme.DownloadDateTimePickerDialog" parent="Theme.Chromium.ModalDialog"> + <style name="ThemeOverlay.DownloadDateTimePickerDialog" parent="ThemeOverlay.BrowserUI.ModalDialog"> <item name="android:windowMinWidthMajor">@null</item> <item name="android:windowMinWidthMinor">@null</item> </style>
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadDateTimePickerDialogImpl.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadDateTimePickerDialogImpl.java index 74c5160..7ccdf11 100644 --- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadDateTimePickerDialogImpl.java +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadDateTimePickerDialogImpl.java
@@ -52,9 +52,10 @@ // Setup the date picker. Use null DatePickerDialog.OnDateSetListener due to Android API // issue. - mDatePickerDialog = new DatePickerDialog(context, - R.style.Theme_DownloadDateTimePickerDialog, null, mCalendar.get(Calendar.YEAR), - mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH)); + mDatePickerDialog = + new DatePickerDialog(context, R.style.ThemeOverlay_DownloadDateTimePickerDialog, + null, mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), + mCalendar.get(Calendar.DAY_OF_MONTH)); long minDate = DownloadDialogUtils.getLong( model, DownloadDateTimePickerDialogProperties.MIN_TIME, INVALID_TIMESTAMP); long maxDate = DownloadDialogUtils.getLong(
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java index b7b2e5f..ba19d75 100644 --- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java
@@ -30,7 +30,7 @@ DownloadTimePickerDialog( Context context, @NonNull Controller controller, int hourOfDay, int minute) { - super(context, R.style.Theme_DownloadDateTimePickerDialog, null, hourOfDay, minute, + super(context, R.style.ThemeOverlay_DownloadDateTimePickerDialog, null, hourOfDay, minute, false /*is24HourView*/); mHourOfDay = hourOfDay; mMinute = minute;
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc index b06a4be..7378adb 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc
@@ -245,6 +245,8 @@ trace_analyzer::Query::EventNameIs(std::string(event_name)) && (trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) || + trace_analyzer::Query::EventPhaseIs( + TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_FLOW_BEGIN) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_INSTANT) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_COMPLETE));
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc index c8c492f..97f9b97 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
@@ -291,9 +291,6 @@ #elif BUILDFLAG(IS_LINUX) && defined(ADDRESS_SANITIZER) // TODO(crbug.com/1295824): Flaky on Linux ASAN #define MAYBE_Performance DISABLED_Performance -#elif BUILDFLAG(IS_LINUX) -// TODO(crbug.com/1306912): Failing consistently on Linux -#define MAYBE_Performance DISABLED_Performance #else #define MAYBE_Performance Performance #endif
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index a085cd5..dd5dcc1f 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -245,7 +245,7 @@ { "name": "arc-right-click-long-press", "owners": [ "yhanada", "mduggan" ], - "expiry_milestone": 100 + "expiry_milestone": 102 }, { "name": "arc-rt-vcpu-dual-core", @@ -1470,11 +1470,6 @@ "expiry_milestone": 101 }, { - "name": "enable-android-dark-search", - "owners": [ "wylieb", "twellington", "fgorski" ], - "expiry_milestone": 95 - }, - { "name": "enable-app-discovery-for-oobe", "owners": [ "melzhang", "tsergeant", "chromeos-apps-foundation-team" ], "expiry_milestone": 110 @@ -3550,11 +3545,6 @@ "expiry_milestone": 105 }, { - "name": "homepage-promo-card", - "owners": [ "wenyufu", "clank-app-team@google.com" ], - "expiry_milestone": 90 - }, - { "name": "http-cache-partitioning", "owners": [ "shivanisha" ], "expiry_milestone": 95
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 2d1678d0..dc7d3cd 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3209,12 +3209,6 @@ const char kGridTabSwitcherForTabletsDescription[] = "Enable grid tab switcher for tablets, replacing the tab strip."; -const char kHomepagePromoCardName[] = - "Enable homepage promo card on the New Tab Page"; -const char kHomepagePromoCardDescription[] = - "Enable homepage promo card that will be shown to users with partner " - "configured homepage."; - const char kInstanceSwitcherName[] = "Enable instance switcher"; const char kInstanceSwitcherDescription[] = "Enable instance switcher dialog UI that helps users manage multiple " @@ -4138,12 +4132,6 @@ const char kArcKeyboardShortcutHelperIntegrationDescription[] = "Shows keyboard shortcuts from Android apps in Chrome OS Shortcut Viewer"; -const char kArcMouseWheelSmoothScrollName[] = - "Enable ARC mouse wheel smooth scroll compatibility feature."; -const char kArcMouseWheelSmoothScrollDescription[] = - "Mouse wheel will be converted to simulated smooth scroll in phone-" - "optimized Android apps."; - const char kArcNativeBridgeToggleName[] = "Toggle between native bridge implementations for ARC"; const char kArcNativeBridgeToggleDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 560ac38..b9288ad 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1824,9 +1824,6 @@ extern const char kGridTabSwitcherForTabletsName[]; extern const char kGridTabSwitcherForTabletsDescription[]; -extern const char kHomepagePromoCardName[]; -extern const char kHomepagePromoCardDescription[]; - extern const char kInstanceSwitcherName[]; extern const char kInstanceSwitcherDescription[]; @@ -2380,9 +2377,6 @@ extern const char kArcKeyboardShortcutHelperIntegrationName[]; extern const char kArcKeyboardShortcutHelperIntegrationDescription[]; -extern const char kArcMouseWheelSmoothScrollName[]; -extern const char kArcMouseWheelSmoothScrollDescription[]; - extern const char kArcNativeBridgeToggleName[]; extern const char kArcNativeBridgeToggleDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index f43c19f..e4a56d58 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -131,7 +131,6 @@ &features::kWebNfc, &features::kIncognitoNtpRevamp, &feature_engagement::kEnableAutomaticSnooze, - &feature_engagement::kIPHHomepagePromoCardFeature, &feature_engagement::kIPHNewTabPageHomeButtonFeature, &feature_engagement::kIPHSnooze, &feature_engagement::kIPHTabSwitcherButtonFeature, @@ -234,7 +233,6 @@ &kGoogleLensSdkIntent, &kGridTabSwitcherForTablets, &kHandleMediaIntents, - &kHomepagePromoCard, &kImmersiveUiMode, &kIncognitoReauthenticationForAndroid, &kIncognitoScreenshot, @@ -641,9 +639,6 @@ const base::Feature kHandleMediaIntents{"HandleMediaIntents", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kHomepagePromoCard{"HomepagePromoCard", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kImmersiveUiMode{"ImmersiveUiMode", 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 86d2426..be496af7 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -98,7 +98,6 @@ extern const base::Feature kGoogleLensSdkIntent; extern const base::Feature kGridTabSwitcherForTablets; extern const base::Feature kHandleMediaIntents; -extern const base::Feature kHomepagePromoCard; extern const base::Feature kImmersiveUiMode; extern const base::Feature kIncognitoReauthenticationForAndroid; extern const base::Feature kIncognitoScreenshot;
diff --git a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthViewTest.java b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthViewTest.java index 563fc7b0..d013862 100644 --- a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthViewTest.java +++ b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthViewTest.java
@@ -53,7 +53,9 @@ private Runnable mSeeOtherTabsRunnableMock; @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.PRIVACY_INCOGNITO) + .build(); @Override public void setUpTest() throws Exception {
diff --git a/chrome/browser/media/cast_mirroring_performance_browsertest.cc b/chrome/browser/media/cast_mirroring_performance_browsertest.cc index b36cd51..c2a8263 100644 --- a/chrome/browser/media/cast_mirroring_performance_browsertest.cc +++ b/chrome/browser/media/cast_mirroring_performance_browsertest.cc
@@ -229,6 +229,8 @@ trace_analyzer::Query::EventNameIs(std::string(event_name)) && (trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) || + trace_analyzer::Query::EventPhaseIs( + TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_FLOW_BEGIN) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_INSTANT) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_COMPLETE));
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn index 4aea5385..25d872d 100644 --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn
@@ -195,6 +195,7 @@ testonly = true deps = [ "discovery", + "//chrome/browser/media/router/discovery/access_code:discovery_resources_proto", "//chrome/test:test_support", "//components/cast_channel:cast_channel", "//components/cast_channel:test_support", @@ -206,6 +207,8 @@ ] public_deps = [ ":router" ] sources = [ + "discovery/access_code/access_code_test_util.cc", + "discovery/access_code/access_code_test_util.h", "discovery/mdns/cast_media_sink_service_test_helpers.cc", "discovery/mdns/cast_media_sink_service_test_helpers.h", "providers/test/test_media_route_provider.cc", @@ -304,6 +307,7 @@ "//chrome/browser/media/router/discovery:discovery", "//chrome/browser/media/router/discovery/access_code:access_code_cast_feature", "//chrome/browser/media/router/discovery/access_code:access_code_sink_service", + "//chrome/browser/media/router/discovery/access_code:discovery_resources_proto", "//chrome/test:test_support", "//components/sync_preferences:test_support", "//content/test:test_support",
diff --git a/chrome/browser/media/router/discovery/BUILD.gn b/chrome/browser/media/router/discovery/BUILD.gn index ad437de..75b167a 100644 --- a/chrome/browser/media/router/discovery/BUILD.gn +++ b/chrome/browser/media/router/discovery/BUILD.gn
@@ -16,22 +16,13 @@ "//chrome/browser:browser_process", "//chrome/browser/media/router:data_decoder_util", "//chrome/browser/media/router:media_router_feature", - "//chrome/browser/media/router/discovery/access_code:discovery_resources_proto", - "//chrome/browser/profiles:profile", - "//chrome/browser/signin:identity_manager_provider", - "//chrome/browser/ui/webui/access_code_cast:mojo_bindings", - "//chrome/common:channel_info", "//chrome/common:constants", "//components/cast_channel", - "//components/leveldb_proto:leveldb_proto", "//components/media_router/browser", "//components/media_router/common", "//components/media_router/common/mojom:logger", "//components/net_log", "//components/prefs", - "//components/signin/public/base:base", - "//components/signin/public/identity_manager:identity_manager", - "//components/user_manager:user_manager", "//components/version_info", "//content/public/browser", "//content/public/common", @@ -39,12 +30,6 @@ "//third_party/openscreen/src/cast/common/channel/proto:channel_proto", ] sources = [ - "access_code/access_code_cast_discovery_interface.cc", - "access_code/access_code_cast_discovery_interface.h", - "access_code/access_code_media_sink_util.cc", - "access_code/access_code_media_sink_util.h", - "access_code/access_code_test_util.cc", - "access_code/access_code_test_util.h", "dial/device_description_fetcher.cc", "dial/device_description_fetcher.h", "dial/device_description_service.cc",
diff --git a/chrome/browser/media/router/discovery/access_code/BUILD.gn b/chrome/browser/media/router/discovery/access_code/BUILD.gn index 6ec106bb..e4d014b5 100644 --- a/chrome/browser/media/router/discovery/access_code/BUILD.gn +++ b/chrome/browser/media/router/discovery/access_code/BUILD.gn
@@ -26,8 +26,14 @@ if (!is_android) { static_library("access_code_sink_service") { sources = [ + "access_code_cast_discovery_interface.cc", + "access_code_cast_discovery_interface.h", "access_code_cast_sink_service.cc", "access_code_cast_sink_service.h", + "access_code_cast_sink_service_factory.cc", + "access_code_cast_sink_service_factory.h", + "access_code_media_sink_util.cc", + "access_code_media_sink_util.h", ] public_deps = [ "//base", @@ -41,25 +47,18 @@ ":access_code_cast_feature", "//chrome/browser/media/router:router", "//chrome/browser/media/router/discovery:discovery", - ] - } - - static_library("access_code_sink_service_factory") { - sources = [ - "access_code_cast_sink_service_factory.cc", - "access_code_cast_sink_service_factory.h", - ] - public_deps = [ - "//base", + "//chrome/browser/media/router/discovery/access_code:discovery_resources_proto", "//chrome/browser/profiles:profile", + "//chrome/browser/signin:identity_manager_provider", + "//chrome/browser/ui/webui/access_code_cast:mojo_bindings", + "//chrome/common:channel_info", + "//components/cast_channel:cast_channel", "//components/keyed_service/content:content", - "//components/media_router/browser", - "//components/media_router/common", - ] - deps = [ - ":access_code_cast_feature", - ":access_code_sink_service", - "//chrome/browser/media/router:router", + "//components/leveldb_proto:leveldb_proto", + "//components/signin/public/base:base", + "//components/signin/public/identity_manager:identity_manager", + "//components/user_manager:user_manager", + "//components/version_info:channel", ] } }
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc b/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc index f30b87f..14a5e6b 100644 --- a/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc +++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc
@@ -161,6 +161,7 @@ logger_(logger), endpoint_fetcher_(CreateEndpointFetcher(access_code)) { DCHECK(profile_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } AccessCodeCastDiscoveryInterface::AccessCodeCastDiscoveryInterface( @@ -307,6 +308,8 @@ std::unique_ptr<EndpointFetcher> AccessCodeCastDiscoveryInterface::CreateEndpointFetcher( const std::string& access_code) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + std::vector<std::string> discovery_scopes; discovery_scopes.push_back(kDiscoveryOAuth2Scope); @@ -320,6 +323,7 @@ void AccessCodeCastDiscoveryInterface::ValidateDiscoveryAccessCode( DiscoveryDeviceCallback callback) { DCHECK(!callback_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); callback_ = std::move(callback); auto* const fetcher_ptr = endpoint_fetcher_.get();
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc index 30dfc7e..44435da 100644 --- a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc +++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc
@@ -7,12 +7,14 @@ #include <algorithm> #include "base/bind.h" +#include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/task/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "chrome/browser/media/router/discovery/access_code/access_code_cast_feature.h" +#include "chrome/browser/media/router/discovery/access_code/access_code_media_sink_util.h" #include "chrome/browser/media/router/discovery/mdns/media_sink_util.h" #include "chrome/browser/media/router/discovery/media_sink_discovery_metrics.h" #include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h" @@ -22,6 +24,8 @@ #include "components/media_router/common/media_route.h" #include "components/media_router/common/media_sink.h" #include "components/media_router/common/mojom/media_router.mojom.h" +#include "content/public/browser/browser_thread.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" namespace media_router { @@ -172,7 +176,7 @@ // discovery. auto it = pending_callbacks_.find(sink->id()); if (it != pending_callbacks_.end()) { - std::move(it->second).Run(true); + std::move(it->second).Run(AddSinkResultCode::OK, sink->id()); pending_callbacks_.erase(sink->id()); } else { if (sink->cast_data().discovered_by_access_code) { @@ -218,9 +222,19 @@ } } +void AccessCodeCastSinkService::DiscoverSink(const std::string& access_code, + AddSinkResultCallback callback) { + discovery_server_interface_ = + std::make_unique<AccessCodeCastDiscoveryInterface>( + profile_, access_code, media_router_->GetLogger()); + discovery_server_interface_->ValidateDiscoveryAccessCode( + base::BindOnce(&AccessCodeCastSinkService::OnAccessCodeValidated, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + void AccessCodeCastSinkService::AddSinkToMediaRouter( const MediaSinkInternal& sink, - ChannelOpenedCallback callback) { + AddSinkResultCallback add_sink_callback) { // Check to see if the media sink already exists in the media router. base::PostTaskAndReplyWithResult( cast_media_sink_service_impl_->task_runner().get(), FROM_HERE, @@ -229,12 +243,39 @@ sink.id()), base::BindOnce(&AccessCodeCastSinkService::OpenChannelIfNecessary, weak_ptr_factory_.GetWeakPtr(), sink, - std::move(callback))); + std::move(add_sink_callback))); +} + +void AccessCodeCastSinkService::OnAccessCodeValidated( + AddSinkResultCallback add_sink_callback, + absl::optional<DiscoveryDevice> discovery_device, + AddSinkResultCode result_code) { + if (result_code != AddSinkResultCode::OK) { + std::move(add_sink_callback).Run(result_code, absl::nullopt); + return; + } + if (!discovery_device.has_value()) { + std::move(add_sink_callback) + .Run(AddSinkResultCode::EMPTY_RESPONSE, absl::nullopt); + return; + } + std::pair<absl::optional<MediaSinkInternal>, CreateCastMediaSinkResult> + creation_result = CreateAccessCodeMediaSink(discovery_device.value()); + + if (!creation_result.first.has_value() || + creation_result.second != CreateCastMediaSinkResult::kOk) { + std::move(add_sink_callback) + .Run(AddSinkResultCode::SINK_CREATION_ERROR, absl::nullopt); + return; + } + auto media_sink = creation_result.first.value(); + + AddSinkToMediaRouter(media_sink, std::move(add_sink_callback)); } void AccessCodeCastSinkService::OpenChannelIfNecessary( const MediaSinkInternal& sink, - ChannelOpenedCallback callback, + AddSinkResultCallback add_sink_callback, bool has_sink) { if (has_sink) { media_router_->GetLogger()->LogInfo( @@ -258,12 +299,26 @@ "terminate it.", sink.id(), "", ""); media_router_->TerminateRoute(route_it->media_route_id()); - pending_callbacks_.emplace(sink.id(), std::move(callback)); + pending_callbacks_.emplace(sink.id(), std::move(add_sink_callback)); } else { - std::move(callback).Run(true); + std::move(add_sink_callback).Run(AddSinkResultCode::OK, sink.id()); } return; } + // Task runner for the current thread. + scoped_refptr<base::SequencedTaskRunner> current_task_runner = + base::SequencedTaskRunnerHandle::Get(); + + // The OnChannelOpenedResult() callback needs to be be bound with + // BindPostTask() to ensure that the callback is invoked on this specific task + // runner. + auto channel_cb = base::BindOnce( + &AccessCodeCastSinkService::OnChannelOpenedResult, + weak_ptr_factory_.GetWeakPtr(), std::move(add_sink_callback), sink.id()); + + auto returned_channel_cb = + base::BindPostTask(current_task_runner, std::move(channel_cb)); + auto backoff_entry = std::make_unique<net::BackoffEntry>(&backoff_policy_); media_router_->GetLogger()->LogInfo( mojom::LogCategory::kDiscovery, kLoggerComponent, @@ -273,7 +328,8 @@ base::BindOnce(&CastMediaSinkServiceImpl::OpenChannel, base::Unretained(cast_media_sink_service_impl_), sink, std::move(backoff_entry), SinkSource::kAccessCode, - std::move(callback), CreateCastSocketOpenParams(sink))); + std::move(returned_channel_cb), + CreateCastSocketOpenParams(sink))); } cast_channel::CastSocketOpenParams @@ -286,6 +342,24 @@ cast_channel::CastDeviceCapability::NONE); } +void AccessCodeCastSinkService::OnChannelOpenedResult( + AddSinkResultCallback add_sink_callback, + MediaSink::Id sink_id, + bool channel_opened) { + if (!channel_opened) { + media_router_->GetLogger()->LogError( + mojom::LogCategory::kDiscovery, kLoggerComponent, + "The channel failed to open.", sink_id, "", ""); + std::move(add_sink_callback) + .Run(AddSinkResultCode::CHANNEL_OPEN_ERROR, absl::nullopt); + return; + } + media_router_->GetLogger()->LogInfo( + mojom::LogCategory::kDiscovery, kLoggerComponent, + "The channel successfully opened.", sink_id, "", ""); + std::move(add_sink_callback).Run(AddSinkResultCode::OK, sink_id); +} + void AccessCodeCastSinkService::Shutdown() { // There's no guarantee that MediaRouter is still in the // MediaRoutesObserver. |media_routes_observer_| accesses MediaRouter in its
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.h b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.h index 65183480..f1c9c225 100644 --- a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.h +++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.h
@@ -9,8 +9,10 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.h" #include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/access_code_cast/access_code_cast.mojom.h" #include "components/keyed_service/core/keyed_service.h" #include "components/media_router/browser/logger_impl.h" #include "components/media_router/browser/media_router.h" @@ -22,9 +24,16 @@ namespace media_router { using ChannelOpenedCallback = base::OnceCallback<void(bool)>; +using AddSinkResultCode = access_code_cast::mojom::AddSinkResultCode; class AccessCodeCastSinkService : public KeyedService { public: + using DiscoveryDevice = chrome_browser_media::proto::DiscoveryDevice; + + using AddSinkResultCallback = base::OnceCallback<void( + access_code_cast::mojom::AddSinkResultCode add_sink_result, + absl::optional<MediaSink::Id> sink_id)>; + AccessCodeCastSinkService(const AccessCodeCastSinkService&) = delete; AccessCodeCastSinkService& operator=(const AccessCodeCastSinkService&) = delete; @@ -33,12 +42,20 @@ base::WeakPtr<AccessCodeCastSinkService> GetWeakPtr(); + // With the given |access_code|, make a call to the discovery server to + // validate the device. + // |access_code|: the access code that is sent to the discovery server. + // |callback|: a callback sent that returns a discovery device and the status + // of that device. + void DiscoverSink(const std::string& access_code, + AddSinkResultCallback callback); + // Attempts to add a sink to the Media Router. // |sink|: the sink that is added to the router. // |callback|: a callback that tracks the status of opening a cast channel to // the given media sink. virtual void AddSinkToMediaRouter(const MediaSinkInternal& sink, - ChannelOpenedCallback callback); + AddSinkResultCallback add_sink_callback); private: class AccessCodeMediaRoutesObserver : public MediaRoutesObserver { @@ -81,6 +98,17 @@ AddNewSinkToMediaRouter); FRIEND_TEST_ALL_PREFIXES(AccessCodeCastSinkServiceTest, AddExistingSinkToMediaRouterWithRoute); + FRIEND_TEST_ALL_PREFIXES(AccessCodeCastSinkServiceTest, + DiscoveryDeviceMissingWithOk); + FRIEND_TEST_ALL_PREFIXES(AccessCodeCastSinkServiceTest, + ValidDiscoveryDeviceAndCode); + FRIEND_TEST_ALL_PREFIXES(AccessCodeCastSinkServiceTest, + InvalidDiscoveryDevice); + FRIEND_TEST_ALL_PREFIXES(AccessCodeCastSinkServiceTest, NonOKResultCode); + FRIEND_TEST_ALL_PREFIXES(AccessCodeCastSinkServiceTest, + OnChannelOpenedSuccess); + FRIEND_TEST_ALL_PREFIXES(AccessCodeCastSinkServiceTest, + OnChannelOpenedFailure); // Constructor used for testing. AccessCodeCastSinkService( @@ -92,10 +120,18 @@ // an instance of this service. explicit AccessCodeCastSinkService(Profile* profile); + void OnAccessCodeValidated(AddSinkResultCallback add_sink_callback, + absl::optional<DiscoveryDevice> discovery_device, + AddSinkResultCode result_code); + + void OnChannelOpenedResult(AddSinkResultCallback add_sink_callback, + MediaSink::Id sink_id, + bool channel_opened); + void HandleMediaRouteDiscoveredByAccessCode(const MediaSinkInternal* sink); void OnAccessCodeRouteRemoved(const MediaSinkInternal& sink); void OpenChannelIfNecessary(const MediaSinkInternal& sink, - ChannelOpenedCallback callback, + AddSinkResultCallback add_sink_callback, bool has_sink); cast_channel::CastSocketOpenParams CreateCastSocketOpenParams( @@ -124,12 +160,14 @@ const raw_ptr<media_router::CastMediaSinkServiceImpl> cast_media_sink_service_impl_; + std::unique_ptr<AccessCodeCastDiscoveryInterface> discovery_server_interface_; + net::BackoffEntry::Policy backoff_policy_; // Map of callbacks that we are currently waiting to alert callers about the // completion of discovery. This cannot be done until all routes on any given // sink are terminated. - std::map<MediaSink::Id, ChannelOpenedCallback> pending_callbacks_; + std::map<MediaSink::Id, AddSinkResultCallback> pending_callbacks_; scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_unittest.cc b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_unittest.cc index 3e849ac..cfecede 100644 --- a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_unittest.cc +++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_unittest.cc
@@ -17,6 +17,7 @@ #include "base/test/test_mock_time_task_runner.h" #include "base/timer/mock_timer.h" #include "chrome/browser/media/router/chrome_media_router_factory.h" +#include "chrome/browser/media/router/discovery/access_code/access_code_test_util.h" #include "chrome/browser/media/router/discovery/discovery_network_monitor.h" #include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h" #include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service_test_helpers.h" @@ -41,6 +42,7 @@ #include "testing/gtest/include/gtest/gtest.h" using ::testing::_; +using ::testing::Eq; using ::testing::Return; namespace media_router { @@ -57,6 +59,9 @@ using SinkSource = CastDeviceCountMetrics::SinkSource; using MockBoolCallback = base::MockCallback<base::OnceCallback<void(bool)>>; +using MockAddSinkResultCallback = base::MockCallback< + media_router::AccessCodeCastSinkService::AddSinkResultCallback>; +using DiscoveryDevice = chrome_browser_media::proto::DiscoveryDevice; class AccessCodeCastSinkServiceTest : public testing::Test { public: @@ -202,13 +207,13 @@ TEST_F(AccessCodeCastSinkServiceTest, AddExistingSinkToMediaRouter) { // Ensure that the call to OpenChannel is NOT made since the cast sink already // exists in the media router. - MockBoolCallback mock_callback; + MockAddSinkResultCallback mock_callback; MediaSinkInternal cast_sink1 = CreateCastSink(1); EXPECT_CALL(*mock_cast_media_sink_service_impl(), OpenChannel(cast_sink1, _, SinkSource::kAccessCode, _, _)) .Times(0); - EXPECT_CALL(mock_callback, Run(true)); + EXPECT_CALL(mock_callback, Run(AddSinkResultCode::OK, Eq(cast_sink1.id()))); access_code_cast_sink_service_->OpenChannelIfNecessary( cast_sink1, mock_callback.Get(), true); mock_time_task_runner()->FastForwardUntilNoTasksRemain(); @@ -233,8 +238,8 @@ OpenChannel(cast_sink1, _, SinkSource::kAccessCode, _, _)) .Times(0); - MockBoolCallback mock_callback; - EXPECT_CALL(mock_callback, Run(true)); + MockAddSinkResultCallback mock_callback; + EXPECT_CALL(mock_callback, Run(AddSinkResultCode::OK, _)); access_code_cast_sink_service_->OpenChannelIfNecessary( cast_sink1, mock_callback.Get(), true); @@ -252,15 +257,98 @@ TEST_F(AccessCodeCastSinkServiceTest, AddNewSinkToMediaRouter) { // Make sure that the sink is added to the media router if it does not already // exist. - MockBoolCallback mock_callback; + MockAddSinkResultCallback mock_callback; MediaSinkInternal cast_sink1 = CreateCastSink(1); EXPECT_CALL(*mock_cast_media_sink_service_impl(), OpenChannel(cast_sink1, _, SinkSource::kAccessCode, _, _)); - EXPECT_CALL(mock_callback, Run(true)).Times(0); + EXPECT_CALL(mock_callback, Run(_, _)).Times(0); access_code_cast_sink_service_->OpenChannelIfNecessary( cast_sink1, mock_callback.Get(), false); mock_time_task_runner()->FastForwardUntilNoTasksRemain(); } +TEST_F(AccessCodeCastSinkServiceTest, DiscoveryDeviceMissingWithOk) { + // Test to ensure that the add_sink_callback returns an EMPTY_RESPONSE if the + // the device is missing. + MockAddSinkResultCallback mock_callback; + EXPECT_CALL(mock_callback, + Run(AddSinkResultCode::EMPTY_RESPONSE, Eq(absl::nullopt))); + access_code_cast_sink_service_->OnAccessCodeValidated( + mock_callback.Get(), absl::nullopt, AddSinkResultCode::OK); +} + +TEST_F(AccessCodeCastSinkServiceTest, ValidDiscoveryDeviceAndCode) { + // If discovery device is present, formatted correctly, and code is OK, no + // callback should be run during OnAccessCodeValidated. Instead when the + // channel opens successfully the callback should run with OK. + MockAddSinkResultCallback mock_callback; + MediaSinkInternal cast_sink1 = CreateCastSink(1); + + DiscoveryDevice discovery_device_proto = + media_router::BuildDiscoveryDeviceProto(); + discovery_device_proto.set_id("id1"); + + EXPECT_CALL(mock_callback, Run(AddSinkResultCode::OK, _)); + EXPECT_CALL(*mock_cast_media_sink_service_impl(), HasSink(_)); + EXPECT_CALL(*mock_cast_media_sink_service_impl(), + OpenChannel(_, _, SinkSource::kAccessCode, _, _)); + access_code_cast_sink_service_->OnAccessCodeValidated( + mock_callback.Get(), discovery_device_proto, AddSinkResultCode::OK); + + // Assume sink is not present in the Media Router so a call to OpenChannel is + // made. + access_code_cast_sink_service_->OpenChannelIfNecessary( + cast_sink1, mock_callback.Get(), false); + + // Channel successfully opens. + access_code_cast_sink_service_->OnChannelOpenedResult(mock_callback.Get(), + "123456", true); + mock_time_task_runner()->FastForwardUntilNoTasksRemain(); +} + +TEST_F(AccessCodeCastSinkServiceTest, InvalidDiscoveryDevice) { + // If discovery device is present, but formatted incorrectly, and code is OK, + // then callback should be SINK_CREATION_ERROR. + MockAddSinkResultCallback mock_callback; + + // Create discovery_device with an invalid port + DiscoveryDevice discovery_device_proto = + media_router::BuildDiscoveryDeviceProto("foo_display_name", "1234", + "```````23489:1238:1239"); + + EXPECT_CALL(mock_callback, + Run(AddSinkResultCode::SINK_CREATION_ERROR, Eq(absl::nullopt))); + access_code_cast_sink_service_->OnAccessCodeValidated( + mock_callback.Get(), discovery_device_proto, AddSinkResultCode::OK); +} + +TEST_F(AccessCodeCastSinkServiceTest, NonOKResultCode) { + // Check to see that any result code that isn't OK will return that error. + MockAddSinkResultCallback mock_callback; + + EXPECT_CALL(mock_callback, + Run(AddSinkResultCode::AUTH_ERROR, Eq(absl::nullopt))); + access_code_cast_sink_service_->OnAccessCodeValidated( + mock_callback.Get(), absl::nullopt, AddSinkResultCode::AUTH_ERROR); +} + +TEST_F(AccessCodeCastSinkServiceTest, OnChannelOpenedSuccess) { + // Validate callback calls for OnChannelOpened for success. + MockAddSinkResultCallback mock_callback; + + EXPECT_CALL(mock_callback, Run(AddSinkResultCode::OK, Eq("123456"))); + access_code_cast_sink_service_->OnChannelOpenedResult(mock_callback.Get(), + "123456", true); +} + +TEST_F(AccessCodeCastSinkServiceTest, OnChannelOpenedFailure) { + // Validate callback calls for OnChannelOpened for failure. + MockAddSinkResultCallback mock_callback; + EXPECT_CALL(mock_callback, + Run(AddSinkResultCode::CHANNEL_OPEN_ERROR, Eq(absl::nullopt))); + access_code_cast_sink_service_->OnChannelOpenedResult(mock_callback.Get(), + "123456", false); +} + } // namespace media_router
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h index 2482089..1e3d7e1 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h
@@ -116,7 +116,7 @@ cast_channel::CastSocketOpenParams open_params); // Check to see if the given cast sink exists the sinks_. - bool HasSink(const MediaSink::Id& sink_id); + virtual bool HasSink(const MediaSink::Id& sink_id); // Closes the Cast Channel to the sink, and removes the sink from the sink // service.
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_test_helpers.h b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_test_helpers.h index 48226fc..852df893 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_test_helpers.h +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_test_helpers.h
@@ -61,6 +61,7 @@ ChannelOpenedCallback callback, cast_channel::CastSocketOpenParams open_params), (override)); + MOCK_METHOD(bool, HasSink, (const MediaSink::Id& sink_id), (override)); OnSinksDiscoveredCallback sinks_discovered_cb() { return sinks_discovered_cb_;
diff --git a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc index 0bf73af..1627cb1 100644 --- a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc +++ b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
@@ -659,3 +659,8 @@ base::UmaHistogramMediumTimes( "Nearby.Share.BackgroundScanning.Setup.Notification.TimeToAction", time); } + +void RecordNearbyShareWifiConfigurationResultMetric(bool success) { + base::UmaHistogramBoolean("Nearby.Share.WifiNetworkConfiguration.Result", + success); +}
diff --git a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h index cd4e39f..73bd3f33 100644 --- a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h +++ b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h
@@ -127,4 +127,6 @@ void RecordNearbyShareSetupNotificationTimeToAction(base::TimeDelta time); +void RecordNearbyShareWifiConfigurationResultMetric(bool success); + #endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARE_METRICS_LOGGER_H_
diff --git a/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler.cc b/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler.cc index 587d577..7baa528 100644 --- a/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler.cc +++ b/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler.h" #include "chrome/browser/nearby_sharing/logging/logging.h" +#include "chrome/browser/nearby_sharing/nearby_share_metrics_logger.h" #include "chromeos/network/network_configuration_handler.h" #include "chromeos/services/network_config/in_process_instance.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" @@ -65,11 +66,12 @@ const absl::optional<std::string>& network_guid, const std::string& error_message) { if (network_guid) { - // TODO(b/216833399): Add metrics NS_LOG(VERBOSE) << __func__ << ": Successfully configured to network"; + RecordNearbyShareWifiConfigurationResultMetric(/*success=*/true); } else { NS_LOG(WARNING) << __func__ << ": Failed to configure network because " << error_message; + RecordNearbyShareWifiConfigurationResultMetric(/*success=*/false); } std::move(callback).Run(network_guid, error_message); }
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckDeletionDialogFragment.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckDeletionDialogFragment.java index f0ec4d3..01e9e12 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckDeletionDialogFragment.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckDeletionDialogFragment.java
@@ -30,7 +30,7 @@ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog - .Builder(getActivity(), R.style.Theme_Chromium_AlertDialog_NoActionBar) + .Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog_NoActionBar) .setTitle(R.string.password_entry_edit_delete_credential_dialog_title) .setPositiveButton( R.string.password_entry_edit_delete_credential_dialog_confirm, mHandler)
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/ConfirmationDialogHelper.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/ConfirmationDialogHelper.java index acfd7dc7..027e12b2 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/ConfirmationDialogHelper.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/ConfirmationDialogHelper.java
@@ -63,7 +63,7 @@ if (context == null) return; mConfirmedCallback = confirmedCallback; AlertDialog.Builder builder = - new AlertDialog.Builder(context, R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(context, R.style.ThemeOverlay_BrowserUI_AlertDialog); LayoutInflater inflater = LayoutInflater.from(builder.getContext()); View body = inflater.inflate(R.layout.confirmation_dialog_view, null); TextView titleView = body.findViewById(R.id.confirmation_dialog_title);
diff --git a/chrome/browser/policy/messaging_layer/util/test.h b/chrome/browser/policy/messaging_layer/util/test.h index c38f4c69..98fc0c3 100644 --- a/chrome/browser/policy/messaging_layer/util/test.h +++ b/chrome/browser/policy/messaging_layer/util/test.h
@@ -107,7 +107,7 @@ // A helper function that calls |SetMode| above and casts the type back to the // derived class. template <class DerivedRecordMatcher> - static DerivedRecordMatcher& SetMode(DerivedRecordMatcher record_matcher, + static DerivedRecordMatcher& SetMode(DerivedRecordMatcher&& record_matcher, Mode mode) { static_assert(std::is_base_of<RecordMatcher, DerivedRecordMatcher>::value, "record_matcher must be of type RecordMatcher.");
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index d3432819..4bf67777 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -119,6 +119,7 @@ #include "components/optimization_guide/core/optimization_guide_prefs.h" #include "components/password_manager/core/browser/password_manager.h" #include "components/payments/core/payment_prefs.h" +#include "components/performance_manager/public/user_tuning/prefs.h" #include "components/permissions/permission_actions_history.h" #include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/browser/url_blocklist_manager.h" @@ -1226,6 +1227,7 @@ optimization_guide::prefs::RegisterProfilePrefs(registry); password_manager::PasswordManager::RegisterProfilePrefs(registry); payments::RegisterProfilePrefs(registry); + performance_manager::user_tuning::prefs::RegisterProfilePrefs(registry); permissions::PermissionActionsHistory::RegisterProfilePrefs(registry); PermissionBubbleMediaAccessHandler::RegisterProfilePrefs(registry); PlatformNotificationServiceImpl::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java index c561ba3..0f2d38f 100644 --- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java +++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
@@ -76,7 +76,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_SETTINGS_PRIVACY) + .build(); @Rule public JniMocker mocker = new JniMocker();
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java index 677c24ac..0a43040 100644 --- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java +++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java
@@ -84,7 +84,9 @@ @Rule public ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_SETTINGS_PRIVACY) + .build(); @Rule public HistogramTestRule mHistogramTestRule = new HistogramTestRule();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 05de254a..b1e36c1 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -34,7 +34,6 @@ "background/braille_command_data.js", "background/chromevox_state.js", "background/command_handler_interface.js", - "background/custom_automation_event.js", "background/event_source.js", "background/keymaps/key_map.js", "background/output/locale_output_helper.js", @@ -75,7 +74,6 @@ "common/extension_bridge.js", "common/key_sequence.js", "common/key_util.js", - "common/keyboard_handler.js", "common/msgs.js", "common/spannable.js", "common/tts_interface.js", @@ -97,6 +95,7 @@ "background/color.js", "background/classic_background.js", "background/command_handler.js", + "background/custom_automation_event.js", "background/desktop_automation_handler.js", "background/desktop_automation_interface.js", "background/download_handler.js", @@ -123,6 +122,7 @@ "braille/braille_key_event_rewriter.js", "common/composite_tts.js", "common/editable_text_base.js", + "common/keyboard_handler.js", "common/tts_background.js", "common/tts_base.js", "learn_mode/learn_mode.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js index bfc98450..89e0dd1d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -30,6 +30,9 @@ await importModule( 'ChromeVoxBackground', '/chromevox/background/classic_background.js'); await importModule( + 'CustomAutomationEvent', + '/chromevox/background/custom_automation_event.js'); + await importModule( 'DesktopAutomationInterface', '/chromevox/background/desktop_automation_interface.js'); await importModule(
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js index ef9e94f..7419709 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js
@@ -6,6 +6,8 @@ * @fileoverview Basic facillities to handle events from a single automation * node. */ +import {ChromeVoxEvent} from './custom_automation_event.js'; + const ActionType = chrome.automation.ActionType; const AutomationEvent = chrome.automation.AutomationEvent; const AutomationNode = chrome.automation.AutomationNode;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js index be5c97161c..28df8f7 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -6,11 +6,13 @@ * @fileoverview ChromeVox commands. */ import {TypingEcho} from '../common/editable_text_base.js'; +import {ChromeVoxKbHandler} from '../common/keyboard_handler.js'; import {AutoScrollHandler} from './auto_scroll_handler.js'; import {BrailleBackground} from './braille_background.js'; import {ChromeVoxBackground} from './classic_background.js'; import {Color} from './color.js'; +import {CustomAutomationEvent} from './custom_automation_event.js'; import {DesktopAutomationInterface} from './desktop_automation_interface.js'; import {GestureGranularity} from './gesture_command_data.js'; import {GestureInterface} from './gesture_interface.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/custom_automation_event.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/custom_automation_event.js index e78510c6..36666c1 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/custom_automation_event.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/custom_automation_event.js
@@ -9,18 +9,15 @@ * construct, unlike the object from the extension system. */ -goog.provide('ChromeVoxEvent'); -goog.provide('CustomAutomationEvent'); - /** * @typedef{chrome.automation.AutomationEvent|CustomAutomationEvent} */ -let ChromeVoxEvent; +export let ChromeVoxEvent; /** * An object we can use instead of a chrome.automation.AutomationEvent. */ -CustomAutomationEvent = class { +export class CustomAutomationEvent { /** * @param {chrome.automation.EventType} type The event type. * @param {!chrome.automation.AutomationNode} target The event target. @@ -43,4 +40,4 @@ stopPropagation() { throw Error('Can\'t call stopPropagation on a CustomAutomationEvent'); } -}; +}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js index d422e695..c9862e2 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
@@ -6,6 +6,7 @@ * @fileoverview Handles automation from a desktop automation node. */ import {AutoScrollHandler} from './auto_scroll_handler.js'; +import {ChromeVoxEvent, CustomAutomationEvent} from './custom_automation_event.js'; import {DesktopAutomationInterface} from './desktop_automation_interface.js'; import {TextEditHandler} from './editing/editing.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js index 6f6264ba..cb817d8 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js
@@ -17,6 +17,9 @@ window.press = this.press; await importModule( + 'CustomAutomationEvent', + '/chromevox/background/custom_automation_event.js'); + await importModule( 'DesktopAutomationHandler', '/chromevox/background/desktop_automation_handler.js'); await importModule(
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js index d0d8cd5..c72373d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js
@@ -7,9 +7,10 @@ * appropriate spoken and braille feedback. */ import {ChromeVoxEditableTextBase, TextChangeEvent} from '../../common/editable_text_base.js'; - import {BrailleBackground} from '../braille_background.js'; import {Color} from '../color.js'; +import {ChromeVoxEvent} from '../custom_automation_event.js'; + import {EditableLine} from './editable_line.js'; import {IntentHandler} from './intent_handler.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js index 892a2735..380e8e95 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js
@@ -6,6 +6,7 @@ * @fileoverview Handles automation events on the currently focused node. */ import {BaseAutomationHandler} from './base_automation_handler.js'; +import {ChromeVoxEvent} from './custom_automation_event.js'; const AutomationEvent = chrome.automation.AutomationEvent; const AutomationNode = chrome.automation.AutomationNode;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/keyboard_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/keyboard_handler.js index 1515fa82..24a62ef 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/keyboard_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/keyboard_handler.js
@@ -5,6 +5,7 @@ /** * @fileoverview ChromeVox keyboard handler. */ +import {ChromeVoxKbHandler} from '../common/keyboard_handler.js'; /** * @enum {string}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js index 3702e5a..167efb6a 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js
@@ -20,20 +20,21 @@ goog.require('BrailleKeyEvent'); goog.require('BrailleTranslatorManager'); goog.require('ChromeVox'); -goog.require('ChromeVoxKbHandler'); goog.require('ChromeVoxPrefs'); goog.require('ChromeVoxState'); goog.require('ChromeVoxStateObserver'); goog.require('CommandHandlerInterface'); goog.require('CommandStore'); goog.require('ConsoleTts'); -goog.require('CustomAutomationEvent'); goog.require('EventGenerator'); goog.require('EventSourceState'); goog.require('EventStreamLogger'); goog.require('ExtensionBridge'); goog.require('JaPhoneticMap'); goog.require('KeyCode'); +goog.require('KeyMap'); +goog.require('KeySequence'); +goog.require('KeyUtil'); goog.require('LibLouis.FormType'); goog.require('LocaleOutputHelper'); goog.require('LogStore');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js index 12b4a14..9d958e1 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js
@@ -6,6 +6,7 @@ * @fileoverview Handles page loading sounds based on automation events. */ import {BaseAutomationHandler} from './base_automation_handler.js'; +import {ChromeVoxEvent} from './custom_automation_event.js'; const ActionType = chrome.automation.ActionType; const AutomationNode = chrome.automation.AutomationNode;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js index 7bc8ddd3..ad14567 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js
@@ -7,6 +7,7 @@ * either user touch or mouse input. */ import {BaseAutomationHandler} from './base_automation_handler.js'; +import {CustomAutomationEvent} from './custom_automation_event.js'; import {DesktopAutomationInterface} from './desktop_automation_interface.js'; const AutomationEvent = chrome.automation.AutomationEvent;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js index e90a1a8..88a2b67 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js
@@ -6,6 +6,7 @@ * @fileoverview Handles automation from ChromeVox's current range. */ import {BaseAutomationHandler} from './base_automation_handler.js'; +import {ChromeVoxEvent, CustomAutomationEvent} from './custom_automation_event.js'; import {DesktopAutomationHandler} from './desktop_automation_handler.js'; const AutomationEvent = chrome.automation.AutomationEvent;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js index e69d712..9e2c262 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js
@@ -15,6 +15,8 @@ await importModule( 'BackgroundKeyboardHandler', '/chromevox/background/keyboard_handler.js'); + await importModule( + 'ChromeVoxKbHandler', '/chromevox/common/keyboard_handler.js'); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js index fb12c78..cbd4b34 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js
@@ -13,6 +13,7 @@ * extended to override methods that extract lines for multiline fields * or to provide other customizations. */ +import {ChromeVoxEvent} from '../background/custom_automation_event.js'; /** * A class containing the information needed to speak
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/keyboard_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/keyboard_handler.js index 327f8c9..431bc4b8 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/keyboard_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/keyboard_handler.js
@@ -2,19 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -goog.provide('ChromeVoxKbHandler'); - -goog.require('ChromeVox'); -goog.require('KeyMap'); -goog.require('KeySequence'); -goog.require('KeyUtil'); -goog.require('ChromeVoxState'); - /** * @fileoverview Handles user keyboard input events. - * */ -ChromeVoxKbHandler = {}; +export const ChromeVoxKbHandler = {}; /** * The key map
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer_loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer_loader.js index d674d2b7b..4089af5 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer_loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer_loader.js
@@ -11,9 +11,11 @@ goog.require('Spannable'); goog.require('AbstractTts'); goog.require('BrailleKeyCommand'); -goog.require('ChromeVoxKbHandler'); +goog.require('ChromeVox'); +goog.require('ChromeVoxState'); goog.require('CommandStore'); goog.require('KeyMap'); +goog.require('KeySequence'); goog.require('KeyUtil'); goog.require('LibLouis'); goog.require('Msgs');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js index 0f79c3e..8cd5e9f 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js
@@ -7,6 +7,7 @@ * */ import {GestureCommandData} from '../background/gesture_command_data.js'; +import {ChromeVoxKbHandler} from '../common/keyboard_handler.js'; /** * Class to manage the keyboard explorer.
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_loader.js index 37c22c2a..1323afd 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_loader.js
@@ -14,6 +14,5 @@ goog.require('BrailleTable'); goog.require('BrailleTranslatorManager'); goog.require('ChromeVox'); -goog.require('ChromeVoxKbHandler'); goog.require('ChromeVoxPrefs'); goog.require('ExtensionBridge');
diff --git a/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn b/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn index 5a34e4b..a2b2428 100644 --- a/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn +++ b/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn
@@ -27,6 +27,7 @@ "extension_app.svg", "finance.svg", "google_g.svg", + "google_g_transparent.svg", "incognito.svg", "linux_share.svg", "mac_share.svg",
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.ts b/chrome/browser/resources/settings/autofill_page/passwords_section.ts index 148f8db..97510200 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.ts +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.ts
@@ -548,6 +548,10 @@ } // <if expr="chromeos_ash or chromeos_lacros"> + getTokenRequestManagerForTest(): BlockingRequestManager { + return this.tokenRequestManager_; + } + /** * When this event fired, it means that the password-prompt-dialog succeeded * in creating a fresh token in the quickUnlockPrivate API. Because new tokens
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java index 58a5f99..5937421 100644 --- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java +++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java
@@ -214,16 +214,29 @@ // The metricsSuffix string shouldn't be changed. When adding a new access point, please // also update the "SafeBrowsing.Settings.AccessPoint" histogram suffix in the // histograms.xml file. - if (mAccessPoint == SettingsAccessPoint.PARENT_SETTINGS) { - metricsSuffix = "ParentSettings"; - } else if (mAccessPoint == SettingsAccessPoint.SAFETY_CHECK) { - metricsSuffix = "SafetyCheck"; - } else if (mAccessPoint == SettingsAccessPoint.SURFACE_EXPLORER_PROMO_SLINGER) { - metricsSuffix = "SurfaceExplorerPromoSlinger"; - } else if (mAccessPoint == SettingsAccessPoint.SECURITY_INTERSTITIAL) { - metricsSuffix = "SecurityInterstitial"; - } else { - metricsSuffix = "Default"; + switch (mAccessPoint) { + case SettingsAccessPoint.DEFAULT: + metricsSuffix = "Default"; + break; + case SettingsAccessPoint.PARENT_SETTINGS: + metricsSuffix = "ParentSettings"; + break; + case SettingsAccessPoint.SAFETY_CHECK: + metricsSuffix = "SafetyCheck"; + break; + case SettingsAccessPoint.SURFACE_EXPLORER_PROMO_SLINGER: + metricsSuffix = "SurfaceExplorerPromoSlinger"; + break; + case SettingsAccessPoint.SECURITY_INTERSTITIAL: + metricsSuffix = "SecurityInterstitial"; + break; + case SettingsAccessPoint.TAILORED_SECURITY: + metricsSuffix = "TailoredSecurity"; + break; + default: + assert false : "Should not be reached."; + metricsSuffix = ""; + break; } RecordHistogram.recordEnumeratedHistogram( "SafeBrowsing.Settings.UserAction." + metricsSuffix, userAction,
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/SaveBitmapDelegate.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/SaveBitmapDelegate.java index 8f801ab..be7fde3 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/SaveBitmapDelegate.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/SaveBitmapDelegate.java
@@ -63,7 +63,7 @@ if (!mWindowAndroid.hasPermission(permission.WRITE_EXTERNAL_STORAGE) && !mWindowAndroid.canRequestPermission(permission.WRITE_EXTERNAL_STORAGE)) { AlertDialog.Builder builder = - new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(mContext, R.style.ThemeOverlay_BrowserUI_AlertDialog); builder.setMessage(R.string.sharing_hub_storage_disabled_text) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/scroll_capture/ScrollCaptureCallbackRenderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/scroll_capture/ScrollCaptureCallbackRenderTest.java index cf143706..5d4a984 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/scroll_capture/ScrollCaptureCallbackRenderTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/scroll_capture/ScrollCaptureCallbackRenderTest.java
@@ -67,10 +67,12 @@ new BlankCTATabInitialStateRule(sActivityTestRule, false); @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus() - .setRevision(2) - .setDescription("new test html") - .build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setRevision(2) + .setDescription("new test html") + .setBugComponent(RenderTestRule.Component.UI_BROWSER_SHARING) + .build(); private ScrollCaptureCallbackDelegate mCallback; private Tab mTab;
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java index 5f84ec6..e527900b 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java
@@ -88,7 +88,9 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SIGN_IN) + .build(); @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java index 73c9b3bb..e8aaac5 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java
@@ -42,7 +42,9 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SIGN_IN) + .build(); @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc index db5611e..29eeda4 100644 --- a/chrome/browser/themes/theme_service_unittest.cc +++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -88,7 +88,7 @@ std::string ColorIdToString(int id) { #define E(color_id, theme_property_id, ...) \ {theme_property_id, #theme_property_id}, -#define E_CPONLY(color_id) +#define E_CPONLY(color_id, ...) static constexpr const auto kMap = base::MakeFixedFlatMap<int, const char*>({CHROME_COLOR_IDS}); @@ -377,7 +377,7 @@ }; #define E(color_id, theme_property_id, ...) theme_property_id, -#define E_CPONLY(color_id) +#define E_CPONLY(color_id, ...) static constexpr int kTestIdValues[] = {CHROME_COLOR_IDS}; #undef E #undef E_CPONLY
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 2b4e204..86996472 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1729,7 +1729,6 @@ "//chrome/browser/media/router", "//chrome/browser/media/router/discovery:discovery", "//chrome/browser/media/router/discovery/access_code:access_code_sink_service", - "//chrome/browser/media/router/discovery/access_code:access_code_sink_service_factory", "//chrome/browser/new_tab_page/chrome_colors:generate_chrome_colors_info", "//chrome/browser/new_tab_page/modules/drive:mojo_bindings", "//chrome/browser/new_tab_page/modules/photos:mojo_bindings",
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialog.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialog.java index 39c057a..aa5781bf 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialog.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialog.java
@@ -63,7 +63,7 @@ } String description = getString( R.string.sign_in_managed_account_description, getArguments().getString(KEY_DOMAIN)); - return new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + return new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.sign_in_managed_account) .setMessage(description) .setPositiveButton(
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineDelegate.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineDelegate.java index dfbc47b3..100d912 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineDelegate.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineDelegate.java
@@ -67,7 +67,8 @@ dismiss(); } - return new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + return new AlertDialog + .Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setView(R.layout.signin_progress_bar_dialog) .setNegativeButton(R.string.cancel, (dialog, i) -> dialog.cancel()) .create(); @@ -109,7 +110,8 @@ dismiss(); } - return new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + return new AlertDialog + .Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.sign_in_timeout_title) .setMessage(R.string.sign_in_timeout_message) .setNegativeButton(R.string.cancel, (dialog, which) -> dialog.cancel())
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogFragment.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogFragment.java index 2057c40..bfc9ab3 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogFragment.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogFragment.java
@@ -80,7 +80,7 @@ } private Dialog createDialogForManagedAccount(String domain) { - return new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) + return new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.signout_managed_account_title) .setPositiveButton(R.string.continue_button, this) .setNegativeButton(R.string.cancel, this) @@ -92,7 +92,7 @@ @SuppressWarnings("UseGetLayoutInflater") private Dialog createDialog() { AlertDialog.Builder builder = - new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog); LayoutInflater inflater = LayoutInflater.from(builder.getContext()); View body = inflater.inflate(R.layout.signout_wipe_storage_dialog, null); mWipeUserData = body.findViewById(R.id.remove_local_data);
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java index dd2e9b11..651beb15 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogRenderTest.java
@@ -50,7 +50,9 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SIGN_IN) + .build(); @Rule public final JniMocker mocker = new JniMocker();
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java index 760e8a6..e570d09 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java
@@ -102,7 +102,10 @@ @Rule public final RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setRevision(3).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(3) + .setBugComponent(RenderTestRule.Component.SERVICES_SIGN_IN) + .build(); @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerDialogTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerDialogTest.java index 6d09957..50211a70 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerDialogTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerDialogTest.java
@@ -52,7 +52,9 @@ public class AccountPickerDialogTest extends BlankUiTestActivityTestCase { @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.SERVICES_SIGN_IN) + .build(); @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java index 9817ee4..3958768a 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java
@@ -71,7 +71,9 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().build(); + ChromeRenderTestRule.Builder.withPublicCorpus() + .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_FIRST_RUN) + .build(); @Mock private Listener mListenerMock;
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index c513d1d..09edbc4 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -4829,6 +4829,10 @@ To use this device as a security key, set a screen lock </message> + <message name="IDS_CABLEV2_ERROR_DISCO_CRED" desc="The description of an error shown when the user is trying to use their phone to register or authenticate with a website on a laptop, but the phone doesn't support the type of sign-in requested."> + This verification method isn’t available for this device. Pick a different option on your other device. + </message> + <message name="IDS_CABLEV2_ERROR_GENERIC" desc="The description of an error shown when the user is trying to use their phone to sign into a website on a laptop, but some generic error occured."> Try another verification option </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_ERROR_DISCO_CRED.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_ERROR_DISCO_CRED.png.sha1 new file mode 100644 index 0000000..7cb0f73 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_ERROR_DISCO_CRED.png.sha1
@@ -0,0 +1 @@ +46cd0de5eb97658b2ebdd691705443bd08b68328 \ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java index cf9da0a5..88916d2 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java
@@ -12,7 +12,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator; import org.chromium.components.embedder_support.util.UrlConstants; -import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.feature_engagement.Tracker; import org.chromium.components.profile_metrics.BrowserProfileType; @@ -136,10 +135,6 @@ if (tab == null || tracker == null) return; tracker.notifyEvent(EventConstants.HOMEPAGE_BUTTON_CLICKED); - - if (UrlUtilities.isNTPUrl(homepageUrl)) { - tracker.notifyEvent(EventConstants.NTP_HOME_BUTTON_CLICKED); - } } private void recordHomeButtonUserPerProfileType() {
diff --git a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc index cf88a17..b665323 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
@@ -46,6 +46,8 @@ #include "chromeos/dbus/seneschal/seneschal_client.h" #include "components/crx_file/id_util.h" #include "components/services/app_service/public/cpp/app_types.h" +#include "components/services/app_service/public/cpp/features.h" +#include "components/services/app_service/public/cpp/icon_types.h" #include "components/services/app_service/public/cpp/stub_icon_loader.h" #include "components/services/app_service/public/mojom/types.mojom.h" #include "components/sessions/content/content_test_helper.h" @@ -118,22 +120,31 @@ } void UpdateIconKey(apps::AppServiceProxy& proxy, const std::string& app_id) { - apps::mojom::AppPtr app = apps::mojom::App::New(); - app->app_id = app_id; + apps::AppType app_type; + apps::IconKeyPtr icon_key; proxy.AppRegistryCache().ForOneApp( - app_id, [&app](const apps::AppUpdate& update) { - app->app_type = ConvertAppTypeToMojomAppType(update.AppType()); - app->icon_key = apps::mojom::IconKey::New( + app_id, [&app_type, &icon_key](const apps::AppUpdate& update) { + app_type = update.AppType(); + icon_key = std::make_unique<apps::IconKey>( update.IconKey()->timeline + 1, update.IconKey()->resource_id, update.IconKey()->icon_effects); }); - std::vector<apps::mojom::AppPtr> apps; - apps.push_back(app.Clone()); - proxy.AppRegistryCache().OnApps(std::move(apps), - apps::mojom::AppType::kUnknown, - false /* should_notify_initialized */); - proxy.FlushMojoCallsForTesting(); + std::vector<apps::AppPtr> apps; + apps::AppPtr app = std::make_unique<apps::App>(app_type, app_id); + app->icon_key = std::move(*icon_key); + apps.push_back(std::move(app)); + if (base::FeatureList::IsEnabled(apps::kAppServiceOnAppUpdateWithoutMojom)) { + proxy.AppRegistryCache().OnApps(std::move(apps), apps::AppType::kUnknown, + false /* should_notify_initialized */); + } else { + std::vector<apps::mojom::AppPtr> mojom_apps; + mojom_apps.push_back(apps::ConvertAppToMojomApp(apps[0])); + proxy.AppRegistryCache().OnApps(std::move(mojom_apps), + apps::mojom::AppType::kUnknown, + false /* should_notify_initialized */); + proxy.FlushMojoCallsForTesting(); + } } class AppSearchProviderTest : public AppListTestBase {
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 ee5642e..de9f412 100644 --- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -130,6 +130,8 @@ #include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/prefs/pref_service.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/app_types.h" +#include "components/services/app_service/public/cpp/features.h" #include "components/services/app_service/public/cpp/instance.h" #include "components/services/app_service/public/cpp/instance_registry.h" #include "components/services/app_service/public/mojom/types.mojom-forward.h" @@ -368,31 +370,40 @@ const std::string& app_id, bool block, bool pause, - apps::mojom::OptionalBool show_in_shelf) { - std::vector<apps::mojom::AppPtr> apps; - apps::mojom::AppPtr app = apps::mojom::App::New(); - app->app_type = apps::mojom::AppType::kChromeApp; + absl::optional<bool> show_in_shelf) { + std::vector<apps::AppPtr> apps; + apps::AppPtr app = + std::make_unique<apps::App>(apps::AppType::kChromeApp, app_id); app->app_id = app_id; if (block) - app->readiness = apps::mojom::Readiness::kDisabledByPolicy; + app->readiness = apps::Readiness::kDisabledByPolicy; else - app->readiness = apps::mojom::Readiness::kReady; + app->readiness = apps::Readiness::kReady; if (pause) - app->paused = apps::mojom::OptionalBool::kTrue; + app->paused = true; else - app->paused = apps::mojom::OptionalBool::kFalse; + app->paused = false; - if (show_in_shelf != apps::mojom::OptionalBool::kUnknown) + if (show_in_shelf.has_value()) app->show_in_shelf = show_in_shelf; apps.push_back(std::move(app)); - apps::AppServiceProxyFactory::GetForProfile(profile) - ->AppRegistryCache() - .OnApps(std::move(apps), apps::mojom::AppType::kChromeApp, - false /* should_notify_initialized */); + if (base::FeatureList::IsEnabled(apps::kAppServiceOnAppUpdateWithoutMojom)) { + apps::AppServiceProxyFactory::GetForProfile(profile) + ->AppRegistryCache() + .OnApps(std::move(apps), apps::AppType::kChromeApp, + false /* should_notify_initialized */); + } else { + std::vector<apps::mojom::AppPtr> mojom_apps; + mojom_apps.push_back(apps::ConvertAppToMojomApp(apps[0])); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->AppRegistryCache() + .OnApps(std::move(mojom_apps), apps::mojom::AppType::kChromeApp, + false /* should_notify_initialized */); + } } } // namespace @@ -5126,16 +5137,24 @@ AddExtension(extension2_.get()); // Set App1.show_in_shelf to false. - std::vector<apps::mojom::AppPtr> apps; - apps::mojom::AppPtr app = apps::mojom::App::New(); - app->app_type = apps::mojom::AppType::kChromeApp; - app->app_id = extension1_->id(); - app->show_in_shelf = apps::mojom::OptionalBool::kFalse; + std::vector<apps::AppPtr> apps; + apps::AppPtr app = + std::make_unique<apps::App>(apps::AppType::kChromeApp, extension1_->id()); + app->show_in_shelf = false; apps.push_back(std::move(app)); - apps::AppServiceProxyFactory::GetForProfile(profile()) - ->AppRegistryCache() - .OnApps(std::move(apps), apps::mojom::AppType::kChromeApp, - false /* should_notify_initialized */); + if (base::FeatureList::IsEnabled(apps::kAppServiceOnAppUpdateWithoutMojom)) { + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->AppRegistryCache() + .OnApps(std::move(apps), apps::AppType::kChromeApp, + false /* should_notify_initialized */); + } else { + std::vector<apps::mojom::AppPtr> mojom_apps; + mojom_apps.push_back(apps::ConvertAppToMojomApp(apps[0])); + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->AppRegistryCache() + .OnApps(std::move(mojom_apps), apps::mojom::AppType::kChromeApp, + false /* should_notify_initialized */); + } InitShelfController(); EXPECT_EQ("Chrome, App2", GetPinnedAppStatus()); @@ -5289,9 +5308,8 @@ AddExtension(extension1_.get()); // Set the app as paused - UpdateAppRegistryCache( - profile(), extension1_->id(), false /* block */, true /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), false /* block */, + true /* pause */, absl::nullopt /* show_in_shelf */); InitShelfController(); @@ -5300,21 +5318,18 @@ EXPECT_EQ(ash::AppStatus::kPaused, model_->items()[1].app_status); // Set the app as blocked - UpdateAppRegistryCache( - profile(), extension1_->id(), true /* block */, true /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), true /* block */, + true /* pause */, absl::nullopt /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kBlocked, model_->items()[1].app_status); // Set the app as ready, but still paused; - UpdateAppRegistryCache( - profile(), extension1_->id(), false /* block */, true /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), false /* block */, + true /* pause */, absl::nullopt /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kPaused, model_->items()[1].app_status); // Set the app as ready, and not paused; - UpdateAppRegistryCache( - profile(), extension1_->id(), false /* block */, false /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), false /* block */, + false /* pause */, absl::nullopt /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kReady, model_->items()[1].app_status); } @@ -5324,9 +5339,8 @@ AddExtension(extension1_.get()); // Set the app as blocked - UpdateAppRegistryCache( - profile(), extension1_->id(), true /* block */, false /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), true /* block */, + false /* pause */, absl::nullopt /* show_in_shelf */); InitShelfController(); @@ -5335,40 +5349,34 @@ EXPECT_EQ(ash::AppStatus::kBlocked, model_->items()[1].app_status); // Set the app as paused - UpdateAppRegistryCache( - profile(), extension1_->id(), true /* block */, true /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), true /* block */, + true /* pause */, absl::nullopt /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kBlocked, model_->items()[1].app_status); // Set the app as blocked, but un-paused - UpdateAppRegistryCache( - profile(), extension1_->id(), true /* block */, false /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), true /* block */, + false /* pause */, absl::nullopt /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kBlocked, model_->items()[1].app_status); // Set the app as ready, and not paused - UpdateAppRegistryCache( - profile(), extension1_->id(), false /* block */, false /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), false /* block */, + false /* pause */, absl::nullopt /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kReady, model_->items()[1].app_status); // Set the app as blocked and hidden UpdateAppRegistryCache(profile(), extension1_->id(), true /* block */, - false /* pause */, - apps::mojom::OptionalBool::kFalse /* show_in_shelf */); + false /* pause */, false /* show_in_shelf */); EXPECT_FALSE(shelf_controller_->IsAppPinned(extension1_->id())); // Set the app as blocked and visible UpdateAppRegistryCache(profile(), extension1_->id(), true /* block */, - false /* pause */, - apps::mojom::OptionalBool::kTrue /* show_in_shelf */); + false /* pause */, true /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kBlocked, model_->items()[1].app_status); EXPECT_TRUE(shelf_controller_->IsAppPinned(extension1_->id())); // Set the app as ready - UpdateAppRegistryCache( - profile(), extension1_->id(), false /* block */, false /* pause */, - apps::mojom::OptionalBool::kUnknown /* show_in_shelf */); + UpdateAppRegistryCache(profile(), extension1_->id(), false /* block */, + false /* pause */, absl::nullopt /* show_in_shelf */); EXPECT_EQ(ash::AppStatus::kReady, model_->items()[1].app_status); } @@ -5386,13 +5394,13 @@ // longer pinned. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); EXPECT_FALSE(shelf_controller_->IsAppPinned(extension1_->id())); // Update the app so it's allowed in shelf again, verify it gets pinned. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kTrue); + /*show_in_shelf=*/true); EXPECT_TRUE(model_->IsAppPinned(extension1_->id())); EXPECT_TRUE(model_->AllowedToSetAppPinState(extension1_->id(), false)); EXPECT_EQ(1, model_->ItemIndexByAppID(extension1_->id())); @@ -5414,13 +5422,13 @@ // longer pinned. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); EXPECT_FALSE(shelf_controller_->IsAppPinned(extension1_->id())); // Update the app so it's allowed in shelf again, verify it gets pinned. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kTrue); + /*show_in_shelf=*/true); EXPECT_TRUE(model_->IsAppPinned(extension1_->id())); EXPECT_TRUE(model_->AllowedToSetAppPinState(extension1_->id(), false)); EXPECT_EQ(0, model_->ItemIndexByAppID(extension1_->id())); @@ -5447,19 +5455,19 @@ // it's no longer pinned. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); UpdateAppRegistryCache(profile(), extension2_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); UpdateAppRegistryCache(profile(), extension5_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); EXPECT_FALSE(shelf_controller_->IsAppPinned(extension2_->id())); // Update app 2 so it's allowed in shelf again, verify it gets pinned. UpdateAppRegistryCache(profile(), extension2_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kTrue); + /*show_in_shelf=*/true); EXPECT_TRUE(model_->IsAppPinned(extension2_->id())); EXPECT_TRUE(model_->AllowedToSetAppPinState(extension2_->id(), false)); EXPECT_EQ(1, model_->ItemIndexByAppID(extension2_->id())); @@ -5485,13 +5493,13 @@ // longer pinned. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); EXPECT_FALSE(model_->IsAppPinned(extension1_->id())); // Update the app so it's allowed in shelf again, verify it gets pinned. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kTrue); + /*show_in_shelf=*/true); EXPECT_TRUE(model_->IsAppPinned(extension1_->id())); EXPECT_FALSE(model_->AllowedToSetAppPinState(extension1_->id(), false)); EXPECT_EQ(1, model_->ItemIndexByAppID(extension1_->id())); @@ -5508,20 +5516,20 @@ // Block the extension so it gets removed from shelf. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/true, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); EXPECT_FALSE(model_->IsAppPinned(extension1_->id())); // Unblock the extension, but mark it as not shown in shelf - verify it // doesn't get pinned/added to shelf. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kFalse); + /*show_in_shelf=*/false); EXPECT_FALSE(model_->IsAppPinned(extension1_->id())); // Allow the app to be shown in shelf, and verify it gets pinned again. UpdateAppRegistryCache(profile(), extension1_->id(), /*block=*/false, /*pause=*/false, - /*show_in_shelf=*/apps::mojom::OptionalBool::kTrue); + /*show_in_shelf=*/true); EXPECT_TRUE(model_->IsAppPinned(extension1_->id())); EXPECT_TRUE(model_->AllowedToSetAppPinState(extension1_->id(), false)); EXPECT_EQ(1, model_->ItemIndexByAppID(extension1_->id()));
diff --git a/chrome/browser/ui/browser_element_identifiers.cc b/chrome/browser/ui/browser_element_identifiers.cc index 58fba19..1719775 100644 --- a/chrome/browser/ui/browser_element_identifiers.cc +++ b/chrome/browser/ui/browser_element_identifiers.cc
@@ -17,6 +17,7 @@ DEFINE_ELEMENT_IDENTIFIER_VALUE(kMediaButtonElementId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kOmniboxElementId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kReadLaterButtonElementId); +DEFINE_ELEMENT_IDENTIFIER_VALUE(kReadLaterSidePanelWebViewElementId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kSavePasswordComboboxElementId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kSideSearchButtonElementId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabAlertIndicatorButtonElementId);
diff --git a/chrome/browser/ui/browser_element_identifiers.h b/chrome/browser/ui/browser_element_identifiers.h index 4b66963..6cb881e 100644 --- a/chrome/browser/ui/browser_element_identifiers.h +++ b/chrome/browser/ui/browser_element_identifiers.h
@@ -26,6 +26,7 @@ DECLARE_ELEMENT_IDENTIFIER_VALUE(kMediaButtonElementId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kOmniboxElementId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kReadLaterButtonElementId); +DECLARE_ELEMENT_IDENTIFIER_VALUE(kReadLaterSidePanelWebViewElementId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kSavePasswordComboboxElementId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kSideSearchButtonElementId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabAlertIndicatorButtonElementId);
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h index 18993df..4af2cda 100644 --- a/chrome/browser/ui/color/chrome_color_id.h +++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -12,9 +12,9 @@ // clang-format off #define COMMON_CHROME_COLOR_IDS \ /* App menu colors. */ \ - /* The kColorAppMenuHighlightSeverityLow color id is used in \ - color_provider_css_colors_test.ts. If changing the variable name, the \ - variable name in the test needs to be changed as well. */ \ + /* The kColorAppMenuHighlightSeverityLow color id is used in */ \ + /* color_provider_css_colors_test.ts. If changing the variable name, the */ \ + /* variable name in the test needs to be changed as well. */ \ E(kColorAppMenuHighlightSeverityLow, \ ThemeProperties::COLOR_APP_MENU_HIGHLIGHT_SEVERITY_LOW, \ kChromeColorsStart) \ @@ -86,11 +86,18 @@ ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_DEFAULT_BUTTON_FOREGROUND) \ E(kColorFeaturePromoBubbleForeground, \ ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_FOREGROUND) \ + /* Find bar colors. */ \ + E_CPONLY(kColorFindBarBackground) \ + E_CPONLY(kColorFindBarForeground) \ + E_CPONLY(kColorFindBarMatchCount) \ + E_CPONLY(kColorFindBarSeparator) \ /* Flying Indicator colors. */ \ E(kColorFlyingIndicatorBackground, \ ThemeProperties::COLOR_FLYING_INDICATOR_BACKGROUND) \ E(kColorFlyingIndicatorForeground, \ ThemeProperties::COLOR_FLYING_INDICATOR_FOREGROUND) \ + /* Default accessibility focus highlight. */ \ + E_CPONLY(kColorFocusHighlightDefault) \ /* Frame caption colors. */ \ E(kColorFrameCaptionActive, ThemeProperties::COLOR_FRAME_CAPTION_ACTIVE) \ E(kColorFrameCaptionInactive, ThemeProperties::COLOR_FRAME_CAPTION_INACTIVE) \
diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc index 3cdf2715..698db8c5 100644 --- a/chrome/browser/ui/color/chrome_color_mixer.cc +++ b/chrome/browser/ui/color/chrome_color_mixer.cc
@@ -254,8 +254,13 @@ mixer[kColorFeaturePromoBubbleDefaultButtonForeground] = { kColorFeaturePromoBubbleBackground}; mixer[kColorFeaturePromoBubbleForeground] = {SK_ColorWHITE}; + mixer[kColorFindBarBackground] = {ui::kColorTextfieldBackground}; + mixer[kColorFindBarForeground] = {ui::kColorTextfieldForeground}; + mixer[kColorFindBarMatchCount] = {ui::kColorSecondaryForeground}; + mixer[kColorFindBarSeparator] = {ui::kColorSeparator}; mixer[kColorFlyingIndicatorBackground] = {kColorToolbar}; mixer[kColorFlyingIndicatorForeground] = {kColorToolbarButtonIcon}; + mixer[kColorFocusHighlightDefault] = {SkColorSetRGB(0x10, 0x10, 0x10)}; mixer[kColorFrameCaptionActive] = ui::GetColorWithMaxContrast({ui::kColorFrameActive}); mixer[kColorFrameCaptionInactive] =
diff --git a/chrome/browser/ui/color/tools/dump_colors.cc b/chrome/browser/ui/color/tools/dump_colors.cc index aa5275b8..0a53ebb 100644 --- a/chrome/browser/ui/color/tools/dump_colors.cc +++ b/chrome/browser/ui/color/tools/dump_colors.cc
@@ -34,7 +34,8 @@ #include "ui/color/color_mixers.h" #endif -constexpr size_t kColorColumnWidth = 19 + 1; // 'kGoogleGreenDark500 ' +// Longest color name, plus a space. Currently, "SK_ColorTRANSPARENT ". +constexpr size_t kColorColumnWidth = 19 + 1; std::string SkColorToString(SkColor color) { std::string color_string = ui::SkColorName(color);
diff --git a/chrome/browser/ui/global_error/global_error.cc b/chrome/browser/ui/global_error/global_error.cc index 0bdce478..048c70e 100644 --- a/chrome/browser/ui/global_error/global_error.cc +++ b/chrome/browser/ui/global_error/global_error.cc
@@ -32,7 +32,7 @@ IDR_INPUT_ALERT_MENU)); #else return ui::ImageModel::FromVectorIcon(kBrowserToolsErrorIcon, - gfx::kGoogleYellow700); + ui::kColorAlertMediumSeverity); #endif }
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index 1db28cc..10ed7d6 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -124,6 +124,12 @@ const base::Feature kSidePanelDragAndDrop{"SidePanelDragAndDrop", base::FEATURE_DISABLED_BY_DEFAULT}; +// Adds improved support for handling multiple contextual and global RHS browser +// side panels. Designed specifically to handle the interim state before the v2 +// side panel project launches. +const base::Feature kSidePanelImprovedClobbering{ + "SidePanelImprovedClobbering", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables tabs to scroll in the tabstrip. https://crbug.com/951078 const base::Feature kScrollableTabStrip{"ScrollableTabStrip", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h index d7ac151..d5f4a81 100644 --- a/chrome/browser/ui/ui_features.h +++ b/chrome/browser/ui/ui_features.h
@@ -68,6 +68,7 @@ // ui_features.cc. This is currently temporarily in reading_list_switches.h. extern const base::Feature kSidePanel; extern const base::Feature kSidePanelDragAndDrop; +extern const base::Feature kSidePanelImprovedClobbering; #if BUILDFLAG(ENABLE_SIDE_SEARCH) extern const base::Feature kSideSearch;
diff --git a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc index 9147ecf0..95589b43 100644 --- a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc +++ b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc
@@ -6,6 +6,7 @@ #include "base/cxx17_backports.h" #include "build/build_config.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/common/pref_names.h" #include "content/public/browser/browser_accessibility_state.h" @@ -60,9 +61,6 @@ } // namespace // static -SkColor AccessibilityFocusHighlight::default_color_; - -// static base::TimeDelta AccessibilityFocusHighlight::fade_in_time_; // static @@ -101,7 +99,6 @@ fade_in_time_ = kFadeInTime; persist_time_ = kHighlightPersistTime; fade_out_time_ = kFadeOutTime; - default_color_ = SkColorSetRGB(0x10, 0x10, 0x10); // #101010 } } @@ -131,17 +128,17 @@ } SkColor AccessibilityFocusHighlight::GetHighlightColor() { + const ui::ColorProvider* color_provider = browser_view_->GetColorProvider(); #if !BUILDFLAG(IS_MAC) // Match behaviour with renderer_preferences_util::UpdateFromSystemSettings // setting prefs->focus_ring_color - return default_color_; + return color_provider->GetColor(kColorFocusHighlightDefault); #else - const ui::ColorProvider* color_provider = browser_view_->GetColorProvider(); SkColor theme_color = color_provider->GetColor(ui::kColorFocusableBorderFocused); if (theme_color == SK_ColorTRANSPARENT || use_default_color_for_testing_) - return default_color_; + return color_provider->GetColor(kColorFocusHighlightDefault); return theme_color; #endif
diff --git a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.h b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.h index a271f5a..026abb4 100644 --- a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.h +++ b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.h
@@ -106,9 +106,6 @@ // The most recent time the layer was updated because focus moved. base::TimeTicks focus_last_changed_time_; - // The default color used for the highlight. - static SkColor default_color_; - // Whether to skip fade in/fade out for testing. static bool no_fade_for_testing_;
diff --git a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight_browsertest.cc b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight_browsertest.cc index 5cc7bb9..8cab2a5 100644 --- a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight_browsertest.cc +++ b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight_browsertest.cc
@@ -9,6 +9,7 @@ #include "build/build_config.h" #include "cc/test/pixel_comparator.h" #include "cc/test/pixel_test_utils.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/accessibility/accessibility_focus_highlight.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/common/chrome_paths.h" @@ -163,7 +164,9 @@ } while (CountPercentPixelsWithColor(image, SkColorSetRGB(204, 255, 255)) < 90.0f); - SkColor highlight_color = AccessibilityFocusHighlight::default_color_; + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); + SkColor highlight_color = + browser_view->GetColorProvider()->GetColor(kColorFocusHighlightDefault); // Initially less than 0.05% of the image should be the focus ring's highlight // color.
diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc index 734668b..de07334 100644 --- a/chrome/browser/ui/views/find_bar_view.cc +++ b/chrome/browser/ui/views/find_bar_view.cc
@@ -13,6 +13,7 @@ #include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/themes/theme_properties.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/find_bar/find_bar_controller.h" #include "chrome/browser/ui/find_bar/find_bar_state.h" #include "chrome/browser/ui/find_bar/find_bar_state_factory.h" @@ -33,10 +34,8 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/theme_provider.h" -#include "ui/color/color_id.h" #include "ui/color/color_provider.h" #include "ui/events/event.h" -#include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/background.h" @@ -442,8 +441,7 @@ void FindBarView::OnThemeChanged() { views::View::OnThemeChanged(); const ui::ColorProvider* color_provider = GetColorProvider(); - SkColor bg_color = SkColorSetA( - color_provider->GetColor(ui::kColorTextfieldBackground), 0xFF); + SkColor bg_color = color_provider->GetColor(kColorFindBarBackground); auto border = std::make_unique<views::BubbleBorder>( views::BubbleBorder::NONE, views::BubbleBorder::STANDARD_SHADOW, bg_color); @@ -454,21 +452,18 @@ SetBackground(std::make_unique<views::BubbleBackground>(border.get())); SetBorder(std::move(border)); - const SkColor base_foreground_color = - color_provider->GetColor(ui::kColorTextfieldForeground); - match_count_text_->SetBackgroundColor(bg_color); match_count_text_->SetEnabledColor( - SkColorSetA(base_foreground_color, gfx::kGoogleGreyAlpha700)); - separator_->SetColor( - SkColorSetA(base_foreground_color, gfx::kGoogleGreyAlpha300)); + color_provider->GetColor(kColorFindBarMatchCount)); + separator_->SetColor(color_provider->GetColor(kColorFindBarSeparator)); - views::SetImageFromVectorIcon( - find_previous_button_, vector_icons::kCaretUpIcon, base_foreground_color); + const SkColor fg_color = color_provider->GetColor(kColorFindBarForeground); + views::SetImageFromVectorIcon(find_previous_button_, + vector_icons::kCaretUpIcon, fg_color); views::SetImageFromVectorIcon(find_next_button_, vector_icons::kCaretDownIcon, - base_foreground_color); + fg_color); views::SetImageFromVectorIcon(close_button_, vector_icons::kCloseRoundedIcon, - base_foreground_color); + fg_color); } BEGIN_METADATA(FindBarView, views::View)
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index e19f59b9..bbf4a79 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -23,6 +23,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" +#include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -689,6 +690,110 @@ }; /////////////////////////////////////////////////////////////////////////////// +// BrowserView::SidePanelVisibilityController: +// +// Coordinating class that manages side panel visibility such that there is a +// single RHS side panel open at a given time. It enforces the following policy: +// - Only one RHS panel is visible at a time. +// - When the contextual panel is shown, the state of the global panels is +// captured and global panels are hidden. +// - When the contextual panel is hidden, the state of the global panels is +// restored. +// +// TODO(tluk): This is intended to manage the visibility of the read later +// (global), google lens (global) and side search (contextual) panels for the +// interim period before side panel v2 rolls out. +class BrowserView::SidePanelVisibilityController : public views::ViewObserver { + public: + // Structures that hold the global panel views and their captured visibility + // state. + struct PanelStateEntry { + const raw_ptr<views::View> panel_view; + absl::optional<bool> captured_visibility_state; + }; + using Panels = std::vector<PanelStateEntry>; + + SidePanelVisibilityController(views::View* side_search_panel, + views::View* lens_panel, + views::View* rhs_panel) + : side_search_panel_(side_search_panel) { + if (lens_panel) + global_panels_.push_back({lens_panel, absl::nullopt}); + if (rhs_panel) + global_panels_.push_back({rhs_panel, absl::nullopt}); + + // Observing the side search panel is only necessary when enabling the + // improved clobbering functionality. + if (side_search_panel_ && + base::FeatureList::IsEnabled(features::kSidePanelImprovedClobbering)) { + side_search_panel_observation_.Observe(side_search_panel_); + } + } + ~SidePanelVisibilityController() override = default; + + // views::ViewObserver: + void OnViewVisibilityChanged(views::View* observed_view, + View* starting_from) override { + DCHECK_EQ(side_search_panel_, observed_view); + if (side_search_panel_->GetVisible()) { + CaptureGlobalPanelVisibilityStateAndHide(); + } else { + RestoreGlobalPanelVisibilityState(); + } + } + + // Called when the contextual panel is shown. Captures the current visibility + // state of the global panel before hiding the panel. The captured state of + // the global panels remains valid while the contextual panel is open. + void CaptureGlobalPanelVisibilityStateAndHide() { + for (PanelStateEntry& entry : global_panels_) { + auto panel_view = entry.panel_view; + entry.captured_visibility_state = panel_view->GetVisible(); + panel_view->SetVisible(false); + } + } + + // Called when the contextual panel is hidden. Restores the visibility state + // of the global panels. + void RestoreGlobalPanelVisibilityState() { + for (PanelStateEntry& entry : global_panels_) { + if (entry.captured_visibility_state.has_value()) { + entry.panel_view->SetVisible(entry.captured_visibility_state.value()); + + // After restoring global panel state reset the stored visibility bits. + // These will not remain valid while the contextual panel is closed. + entry.captured_visibility_state.reset(); + } + } + } + + // Returns true if one of its managed panels is currently visible in the + // browser window. + bool IsManagedSidePanelVisible() const { + if (side_search_panel_ && side_search_panel_->GetVisible()) + return true; + return base::ranges::any_of(global_panels_, + [](const PanelStateEntry& entry) { + return entry.panel_view->GetVisible(); + }); + } + + private: + // We observe the side search panel when improved clobbering is enabled to + // implement the correct view visibility transitions. + const raw_ptr<views::View> side_search_panel_; + + // The set of global panels that this maintains visibility for. + Panels global_panels_; + + // Keep track of the side search panel's visibility so that we can hide / + // restore global panels as the side search panel is shown / hidden + // respectively. + base::ScopedObservation<views::View, views::ViewObserver> + side_search_panel_observation_{this}; +}; + +/////////////////////////////////////////////////////////////////////////////// // BrowserView, public: BrowserView::BrowserView(std::unique_ptr<Browser> browser) @@ -874,10 +979,11 @@ if (tabstrip_) tabstrip_->parent()->RemoveChildViewT(tabstrip_.get()); - // This highlighter refers to side-panel objects (children of this) and to - // children inside ToolbarView and of this, remove this observer before those - // children are removed. + // This highlighter and visibility controller refer to side-panel objects + // (children of this) and to children inside ToolbarView and of this, remove + // this observer before those children are removed. side_panel_button_highlighter_.reset(); + side_panel_visibility_controller_.reset(); // Child views maintain PrefMember attributes that point to // OffTheRecordProfile's PrefService which gets deleted by ~Browser. @@ -3201,33 +3307,30 @@ bool BrowserView::CloseOpenRightAlignedSidePanel(bool exclude_lens, bool exclude_side_search) { - // Hide Chrome side panel (Reading List/Bookmarks) if enabled and showing. - if (toolbar()->side_panel_button() && - right_aligned_side_panel()->GetVisible()) { - toolbar()->side_panel_button()->HideSidePanel(); - return true; + // Check if any side panels are open before closing side panels. + if (!side_panel_visibility_controller_ || + !side_panel_visibility_controller_->IsManagedSidePanelVisible()) { + return false; } -#if BUILDFLAG(GOOGLE_CHROME_BRANDING) - // Hide the Lens side panel if it's showing instead. - if (!exclude_lens && lens_side_panel_controller_ && - lens_side_panel_controller_->IsShowing()) { - lens_side_panel_controller_->Close(); - return true; - } -#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + // Ensure all side panels are closed. Close contextual panels first. #if BUILDFLAG(ENABLE_SIDE_SEARCH) // Hide side search panel if it's right aligned. - if (!exclude_side_search && - base::FeatureList::IsEnabled(features::kSideSearchDSESupport) && - side_search_side_panel_ && side_search_side_panel_->GetVisible()) { + if (!exclude_side_search && side_search_controller_ && + base::FeatureList::IsEnabled(features::kSideSearchDSESupport)) { side_search_controller_->CloseSidePanel(); - return true; } #endif // BUILDFLAG(ENABLE_SIDE_SEARCH) - return false; + toolbar()->side_panel_button()->HideSidePanel(); + +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + if (!exclude_lens && lens_side_panel_controller_) + lens_side_panel_controller_->Close(); +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + + return true; } void BrowserView::MaybeClobberAllSideSearchSidePanels() { @@ -3244,6 +3347,16 @@ #endif // BUILDFLAG(ENABLE_SIDE_SEARCH) } +void BrowserView::RightAlignedSidePanelWasClosed() { + // For the improved side panel clobbering experience we must close all side + // panels for the window when the user explicitly closes a participating side + // panel. + if (base::FeatureList::IsEnabled(features::kSidePanelImprovedClobbering)) { + CloseOpenRightAlignedSidePanel(); + MaybeClobberAllSideSearchSidePanels(); + } +} + #if BUILDFLAG(ENABLE_SIDE_SEARCH) bool BrowserView::IsSideSearchPanelVisible() const { if (side_search_controller_) @@ -3491,6 +3604,11 @@ side_panel_button_highlighter_ = std::make_unique<SidePanelButtonHighlighter>( toolbar_->side_panel_button(), panels); + + side_panel_visibility_controller_ = + std::make_unique<SidePanelVisibilityController>( + side_search_side_panel_, lens_side_panel_, + right_aligned_side_panel_); } #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 786a096..a9a8e1e 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -732,6 +732,11 @@ // kClobberAllSideSearchSidePanels is enabled. void MaybeClobberAllSideSearchSidePanels(); + // Called by right aligned side panels when they are explicitly closed by + // users. This is used to implement improved clobbering logic for the right + // aligned side panels. + void RightAlignedSidePanelWasClosed(); + #if BUILDFLAG(ENABLE_SIDE_SEARCH) bool IsSideSearchPanelVisible() const override; void MaybeRestoreSideSearchStatePerWindow( @@ -747,6 +752,7 @@ FRIEND_TEST_ALL_PREFIXES(BrowserViewTest, AccessibleWindowTitle); class AccessibilityModeObserver; class SidePanelButtonHighlighter; + class SidePanelVisibilityController; // If the browser is in immersive full screen mode, it will reveal the // tabstrip for a short duration. This is useful for shortcuts that perform @@ -1012,6 +1018,14 @@ // as well as the side panels it's observing. std::unique_ptr<SidePanelButtonHighlighter> side_panel_button_highlighter_; + // TODO(tluk): Move this functionality into SidePanelCoordinator when the side + // panel v2 project rolls out. + // This controller manages the visibility of the read later, side search and + // lens side panels. It ensures only one panel is visible at a given time and + // the contextual panel interacts as expected with the global panels. + std::unique_ptr<SidePanelVisibilityController> + side_panel_visibility_controller_; + #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // A controller that handles content hosted in the Lens side panel. std::unique_ptr<lens::LensSidePanelController> lens_side_panel_controller_;
diff --git a/chrome/browser/ui/views/lens/lens_side_panel_controller.cc b/chrome/browser/ui/views/lens/lens_side_panel_controller.cc index 0ec960a51..c0ac367 100644 --- a/chrome/browser/ui/views/lens/lens_side_panel_controller.cc +++ b/chrome/browser/ui/views/lens/lens_side_panel_controller.cc
@@ -105,6 +105,7 @@ GURL(), content::Referrer(), ui::PAGE_TRANSITION_FROM_API, std::string()); side_panel_->SetVisible(false); + browser_view_->RightAlignedSidePanelWasClosed(); base::RecordAction(base::UserMetricsAction("LensSidePanel.Hide")); } if (browser_view_->toolbar()->side_panel_button()) {
diff --git a/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.cc b/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.cc index a6fe959..f0b8ede 100644 --- a/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.cc +++ b/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.cc
@@ -10,10 +10,12 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/bookmarks/bookmark_utils.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" +#include "ui/views/view_class_properties.h" ReadLaterSidePanelWebView::ReadLaterSidePanelWebView( Browser* browser, @@ -31,6 +33,8 @@ /*webui_resizes_host=*/false, /*esc_closes_ui=*/false)), browser_(browser) { + SetProperty(views::kElementIdentifierKey, + kReadLaterSidePanelWebViewElementId); if (base::FeatureList::IsEnabled(features::kSidePanelDragAndDrop)) { extensions::BookmarkManagerPrivateDragEventRouter::CreateForWebContents( contents_wrapper()->web_contents());
diff --git a/chrome/browser/ui/views/side_search/side_search_browser_controller.cc b/chrome/browser/ui/views/side_search/side_search_browser_controller.cc index d3763c557..de469f0 100644 --- a/chrome/browser/ui/views/side_search/side_search_browser_controller.cc +++ b/chrome/browser/ui/views/side_search/side_search_browser_controller.cc
@@ -448,6 +448,7 @@ void SideSearchBrowserController::SidePanelCloseButtonPressed() { CloseSidePanel(SideSearchCloseActionType::kTapOnSideSearchCloseButton); + browser_view_->RightAlignedSidePanelWasClosed(); } void SideSearchBrowserController::OpenSidePanel() { @@ -541,7 +542,11 @@ const bool will_show_side_panel = can_show_side_panel_for_page && GetSidePanelToggledOpen(); + // When side search is shown we only need to close other side panels for the + // basic clobbering experience. The improved experience leverages a + // SidePanelVisibilityController on the browser view. if (base::FeatureList::IsEnabled(features::kSideSearchDSESupport) && + !base::FeatureList::IsEnabled(features::kSidePanelImprovedClobbering) && will_show_side_panel) { browser_view_->CloseOpenRightAlignedSidePanel(/*exclude_lens=*/false, /*exclude_side_search=*/true);
diff --git a/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc b/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc index cbbcbf2..d7e264e 100644 --- a/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc
@@ -22,6 +22,8 @@ #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/side_panel/side_panel.h" +#include "chrome/browser/ui/views/side_panel/side_panel_web_ui_view.h" +#include "chrome/browser/ui/views/toolbar/side_panel_toolbar_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" @@ -80,6 +82,10 @@ ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); InProcessBrowserTest::SetUp(); } + void TearDown() override { + InProcessBrowserTest::TearDown(); + scoped_feature_list_.Reset(); + } void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); @@ -740,6 +746,246 @@ EXPECT_NE(nullptr, GetSidePanelContentsFor(browser(), 0)); } +// Fixture for testing side panel clobbering behavior with global panels. +class SideSearchDSEClobberingTest : public SideSearchBrowserControllerTest { + public: + // SideSearchBrowserControllerTest: + void SetUp() override { + scoped_feature_list_.InitWithFeatures( + {features::kSidePanel, features::kSidePanelImprovedClobbering}, {}); + SideSearchBrowserControllerTest::SetUp(); + } + void TearDown() override { + SideSearchBrowserControllerTest::TearDown(); + scoped_feature_list_.Reset(); + } + + // Immediately open and make visible the global side panel. + void ShowGlobalSidePanel(Browser* browser) { + ASSERT_FALSE(GetGlobalSidePanelFor(browser)->GetVisible()); + auto* side_panel_button = GetToolbarSidePanelButtonFor(browser); + views::test::ButtonTestApi(side_panel_button).NotifyClick(GetDummyEvent()); + + // The WebUI typically loads and is shown asynchronously. Synchronously show + // the view here for testing. + views::View* web_view = + views::ElementTrackerViews::GetInstance()->GetFirstMatchingView( + kReadLaterSidePanelWebViewElementId, + browser->window()->GetElementContext()); + DCHECK(web_view); + views::AsViewClass<SidePanelWebUIView>(web_view)->ShowUI(); + + BrowserViewFor(browser)->GetWidget()->LayoutRootViewIfNecessary(); + } + + // Uses the toolbar side panel button to close whichever side panel is + // currently open. + void CloseActiveSidePanel(Browser* browser) { + ASSERT_TRUE(GetGlobalSidePanelFor(browser)->GetVisible() || + GetSidePanelFor(browser)); + auto* side_panel_button = GetToolbarSidePanelButtonFor(browser); + views::test::ButtonTestApi(side_panel_button).NotifyClick(GetDummyEvent()); + BrowserViewFor(browser)->GetWidget()->LayoutRootViewIfNecessary(); + } + + // Sets up a browser with three tabs, an open global panel and an open side + // search panel for the last tab. + void SetupBrowserForClobberingTests(Browser* browser) { + auto* global_panel = GetGlobalSidePanelFor(browser); + EXPECT_FALSE(global_panel->GetVisible()); + ShowGlobalSidePanel(browser); + EXPECT_TRUE(global_panel->GetVisible()); + + // Add another two tabs, the global panel should remain open for each. + AppendTab(browser, GetNonMatchingUrl()); + ActivateTabAt(browser, 1); + EXPECT_TRUE(global_panel->GetVisible()); + + AppendTab(browser, GetNonMatchingUrl()); + ActivateTabAt(browser, 2); + EXPECT_TRUE(global_panel->GetVisible()); + + // Open the side search contextual panel for the current active tab. + auto* side_search_panel = GetSidePanelFor(browser); + NavigateToMatchingSearchPageAndOpenSidePanel(browser); + EXPECT_TRUE(side_search_panel->GetVisible()); + EXPECT_FALSE(global_panel->GetVisible()); + } + + SidePanelToolbarButton* GetToolbarSidePanelButtonFor(Browser* browser) { + views::View* button_view = + views::ElementTrackerViews::GetInstance()->GetFirstMatchingView( + kReadLaterButtonElementId, browser->window()->GetElementContext()); + return button_view ? views::AsViewClass<SidePanelToolbarButton>(button_view) + : nullptr; + } + + SidePanel* GetGlobalSidePanelFor(Browser* browser) { + return BrowserViewFor(browser)->right_aligned_side_panel(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// Only instantiate tests for the DSE configuration. +INSTANTIATE_TEST_SUITE_P(All, + SideSearchDSEClobberingTest, + ::testing::Values(true)); + +IN_PROC_BROWSER_TEST_P(SideSearchDSEClobberingTest, + GlobalBrowserSidePanelIsToggleable) { + auto* global_panel = GetGlobalSidePanelFor(browser()); + EXPECT_FALSE(global_panel->GetVisible()); + ShowGlobalSidePanel(browser()); + EXPECT_TRUE(global_panel->GetVisible()); +} + +IN_PROC_BROWSER_TEST_P(SideSearchDSEClobberingTest, + ContextualPanelsDoNotClobberGlobalPanels) { + SetupBrowserForClobberingTests(browser()); + auto* global_panel = GetGlobalSidePanelFor(browser()); + auto* side_search_panel = GetSidePanelFor(browser()); + + // Switching to tabs with no open contextual panels should instead show the + // global panel. + ActivateTabAt(browser(), 1); + EXPECT_TRUE(global_panel->GetVisible()); + EXPECT_FALSE(side_search_panel->GetVisible()); + + ActivateTabAt(browser(), 0); + EXPECT_TRUE(global_panel->GetVisible()); + EXPECT_FALSE(side_search_panel->GetVisible()); + + // Switching back to the tab with the contextual panel should show the + // contextual panel and not the global panel. + ActivateTabAt(browser(), 2); + EXPECT_FALSE(global_panel->GetVisible()); + EXPECT_TRUE(side_search_panel->GetVisible()); +} + +IN_PROC_BROWSER_TEST_P(SideSearchDSEClobberingTest, + OpeningGlobalPanelsClosesAllContextualPanels) { + auto* global_panel = GetGlobalSidePanelFor(browser()); + auto* side_search_panel = GetSidePanelFor(browser()); + AppendTab(browser(), GetNonMatchingUrl()); + AppendTab(browser(), GetNonMatchingUrl()); + + // There should be three tabs and no panels open. + for (int i = 0; i < 3; ++i) { + ActivateTabAt(browser(), i); + EXPECT_FALSE(global_panel->GetVisible()); + EXPECT_FALSE(side_search_panel->GetVisible()); + } + + // Open a contextual panel on the last tab. + ActivateTabAt(browser(), 2); + NavigateToMatchingSearchPageAndOpenSidePanel(browser()); + EXPECT_FALSE(global_panel->GetVisible()); + EXPECT_TRUE(side_search_panel->GetVisible()); + + // Switch to the first tab and open a global panel. + ActivateTabAt(browser(), 0); + ShowGlobalSidePanel(browser()); + EXPECT_TRUE(global_panel->GetVisible()); + EXPECT_FALSE(side_search_panel->GetVisible()); + + // The global panel should now be open for all browser tabs. + for (int i = 0; i < 3; ++i) { + ActivateTabAt(browser(), i); + EXPECT_TRUE(global_panel->GetVisible()); + EXPECT_FALSE(side_search_panel->GetVisible()); + } +} + +IN_PROC_BROWSER_TEST_P( + SideSearchDSEClobberingTest, + ContextualAndGlobalPanelsBehaveAsExpectedWhenDraggingBetweenWindows) { + // Open two browsers with three tabs each. Both have open global side panel + // and an open side search panel for their last tab. + Browser* browser2 = CreateBrowser(browser()->profile()); + SetupBrowserForClobberingTests(browser()); + SetupBrowserForClobberingTests(browser2); + + // Move the currently active tab with side search from browser2 to browser1. + std::unique_ptr<content::WebContents> web_contents = + browser2->tab_strip_model()->DetachWebContentsAtForInsertion(2); + browser()->tab_strip_model()->InsertWebContentsAt(3, std::move(web_contents), + TabStripModel::ADD_ACTIVE); + + // The global panel should now be visibe in browser2 and the contextual panel + // should be visible in browser1. + auto* global_panel1 = GetGlobalSidePanelFor(browser()); + auto* global_panel2 = GetGlobalSidePanelFor(browser2); + auto* side_search_panel1 = GetSidePanelFor(browser()); + auto* side_search_panel2 = GetSidePanelFor(browser2); + + EXPECT_TRUE(global_panel2->GetVisible()); + EXPECT_FALSE(side_search_panel2->GetVisible()); + + EXPECT_FALSE(global_panel1->GetVisible()); + EXPECT_TRUE(side_search_panel1->GetVisible()); + + // In browser1 switch to the tab that originally had the side search panel + // open. The global panels should remain closed. + ActivateTabAt(browser(), 2); + EXPECT_FALSE(global_panel1->GetVisible()); + EXPECT_TRUE(side_search_panel1->GetVisible()); + + // In browser1 switch to tabs that did not have a side search panel open. The + // side search panel should be hidden and the global panel should be visible. + ActivateTabAt(browser(), 1); + EXPECT_TRUE(global_panel1->GetVisible()); + EXPECT_FALSE(side_search_panel1->GetVisible()); + + ActivateTabAt(browser(), 0); + EXPECT_TRUE(global_panel1->GetVisible()); + EXPECT_FALSE(side_search_panel1->GetVisible()); +} + +IN_PROC_BROWSER_TEST_P(SideSearchDSEClobberingTest, + ClosingTheContextualPanelClosesAllBrowserPanels) { + SetupBrowserForClobberingTests(browser()); + auto* global_panel = GetGlobalSidePanelFor(browser()); + auto* side_search_panel = GetSidePanelFor(browser()); + + // Append an additional browser tab with an open side search panel. + AppendTab(browser(), GetNonMatchingUrl()); + ActivateTabAt(browser(), 3); + NavigateToMatchingSearchPageAndOpenSidePanel(browser()); + + // Close the contextual panel. The global and contextual panels in the current + // and other tabs should all be closed. + CloseActiveSidePanel(browser()); + for (int i = 0; i < 3; ++i) { + ActivateTabAt(browser(), i); + EXPECT_FALSE(global_panel->GetVisible()); + EXPECT_FALSE(side_search_panel->GetVisible()); + } +} + +IN_PROC_BROWSER_TEST_P(SideSearchDSEClobberingTest, + ClosingTheGlobalPanelClosesAllBrowserPanels) { + SetupBrowserForClobberingTests(browser()); + auto* global_panel = GetGlobalSidePanelFor(browser()); + auto* side_search_panel = GetSidePanelFor(browser()); + + // Append an additional browser tab with an open side search panel. + AppendTab(browser(), GetNonMatchingUrl()); + ActivateTabAt(browser(), 3); + NavigateToMatchingSearchPageAndOpenSidePanel(browser()); + + // Close the global panel. The global and contextual panels in the current + // and other tabs should all be closed. + ActivateTabAt(browser(), 0); + CloseActiveSidePanel(browser()); + for (int i = 0; i < 3; ++i) { + ActivateTabAt(browser(), i); + EXPECT_FALSE(global_panel->GetVisible()); + EXPECT_FALSE(side_search_panel->GetVisible()); + } +} + // Base class for Extensions API tests for the side panel WebContents. class SideSearchExtensionsTest : public SideSearchBrowserControllerTest { public:
diff --git a/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc b/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc index b52f3a75..74a7fd06 100644 --- a/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc +++ b/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc
@@ -518,7 +518,6 @@ content_insets.right())); invalid_credential_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); invalid_credential_label->SetMultiLine(true); - invalid_credential_label->SetEnabledColor(gfx::kGoogleRed600); invalid_credential_label->SizeToFit(content_width); // Cache the pointer so we we can update the invalid credential label when we
diff --git a/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc b/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc index 1161641..31d96518 100644 --- a/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/read_later/reading_list_model_factory.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/chrome_view_class_properties.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.h" @@ -135,6 +136,7 @@ side_panel_webview_.get()); side_panel_webview_ = nullptr; SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_SIDE_PANEL_SHOW)); + browser_view->RightAlignedSidePanelWasClosed(); } }
diff --git a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc index 8ce5b9f..d351b0e 100644 --- a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc +++ b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc
@@ -9,10 +9,9 @@ #include "base/metrics/histogram_functions.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" -#include "base/task/bind_post_task.h" +#include "base/strings/stringprintf.h" #include "base/task/task_runner_util.h" #include "chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_factory.h" -#include "chrome/browser/media/router/discovery/access_code/access_code_media_sink_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/media_router/browser/media_router.h" #include "components/media_router/browser/media_router_factory.h" @@ -22,7 +21,6 @@ #include "components/sessions/content/session_tab_helper.h" #include "mojo/public/cpp/bindings/callback_helpers.h" -using ::media_router::CreateAccessCodeMediaSink; using media_router::mojom::RouteRequestResultCode; // TODO(b/213324920): Remove WebUI from the media_router namespace after // expiration module has been completed. @@ -30,6 +28,50 @@ namespace { +const char* AddSinkResultCodeToStringHelper(AddSinkResultCode value) { + switch (value) { + case AddSinkResultCode::UNKNOWN_ERROR: + return "UNKNOWN_ERROR"; + case AddSinkResultCode::OK: + return "OK"; + case AddSinkResultCode::AUTH_ERROR: + return "AUTH_ERROR"; + case AddSinkResultCode::HTTP_RESPONSE_CODE_ERROR: + return "HTTP_RESPONSE_CODE_ERROR"; + case AddSinkResultCode::RESPONSE_MALFORMED: + return "RESPONSE_MALFORMED"; + case AddSinkResultCode::EMPTY_RESPONSE: + return "EMPTY_RESPONSE"; + case AddSinkResultCode::INVALID_ACCESS_CODE: + return "INVALID_ACCESS_CODE"; + case AddSinkResultCode::ACCESS_CODE_NOT_FOUND: + return "ACCESS_CODE_NOT_FOUND"; + case AddSinkResultCode::TOO_MANY_REQUESTS: + return "TOO_MANY_REQUESTS"; + case AddSinkResultCode::SERVICE_NOT_PRESENT: + return "SERVICE_NOT_PRESENT"; + case AddSinkResultCode::SERVER_ERROR: + return "SERVER_ERROR"; + case AddSinkResultCode::SINK_CREATION_ERROR: + return "SINK_CREATION_ERROR"; + case AddSinkResultCode::CHANNEL_OPEN_ERROR: + return "CHANNEL_OPEN_ERROR"; + case AddSinkResultCode::PROFILE_SYNC_ERROR: + return "PROFILE_SYNC_ERROR"; + default: + return nullptr; + } +} + +std::string AddSinkResultCodeToString(AddSinkResultCode value) { + const char* str = AddSinkResultCodeToStringHelper(value); + if (!str) { + return base::StringPrintf("Unknown AddSinkResultCode value: %i", + static_cast<int32_t>(value)); + } + return str; +} + constexpr char kLoggerComponent[] = "AccessCodeCastHandler"; std::string CastModeSetToString( @@ -134,12 +176,9 @@ std::move(callback), AddSinkResultCode::UNKNOWN_ERROR); DCHECK(media_router_) << "Must have media router!"; - discovery_server_interface_ = - std::make_unique<AccessCodeCastDiscoveryInterface>( - profile_, access_code, media_router_->GetLogger()); - discovery_server_interface_->ValidateDiscoveryAccessCode( - base::BindOnce(&AccessCodeCastHandler::OnAccessCodeValidated, - weak_ptr_factory_.GetWeakPtr())); + access_code_sink_service_->DiscoverSink( + access_code, base::BindOnce(&AccessCodeCastHandler::OnSinkAddedResult, + weak_ptr_factory_.GetWeakPtr())); } bool AccessCodeCastHandler::IsCastModeAvailable(MediaCastMode mode) const { @@ -197,7 +236,9 @@ // Discovery is not complete until the sink is in QRM. This is because any // attempt to create route parameters before the sink is in QRM will fail. void AccessCodeCastHandler::CheckForDiscoveryCompletion() { - DCHECK(add_sink_callback_) << "Dialog already notified!"; + // Dialog has already notified (with most likely an error). + if (!add_sink_callback_) + return; DCHECK(sink_id_) << "Must have a sink id to complete!"; // Verify that the sink is in QRM. @@ -214,64 +255,24 @@ std::move(add_sink_callback_).Run(AddSinkResultCode::OK); } -void AccessCodeCastHandler::OnAccessCodeValidated( - absl::optional<DiscoveryDevice> discovery_device, - AddSinkResultCode result_code) { - if (result_code != AddSinkResultCode::OK) { - std::move(add_sink_callback_).Run(result_code); - return; - } - if (!discovery_device.has_value()) { - std::move(add_sink_callback_).Run(AddSinkResultCode::EMPTY_RESPONSE); - return; - } - std::pair<absl::optional<MediaSinkInternal>, CreateCastMediaSinkResult> - creation_result = CreateAccessCodeMediaSink(discovery_device.value()); - - if (!creation_result.first.has_value() || - creation_result.second != CreateCastMediaSinkResult::kOk) { - media_router_->GetLogger()->LogError( - mojom::LogCategory::kDiscovery, kLoggerComponent, - "An error occured while constructing the sink.", "", "", ""); - std::move(add_sink_callback_).Run(AddSinkResultCode::SINK_CREATION_ERROR); - return; - } - sink_id_ = creation_result.first.value().id(); - - // Task runner for the current thread. - scoped_refptr<base::SequencedTaskRunner> current_task_runner = - base::SequencedTaskRunnerHandle::Get(); - - // The OnChannelOpenedResult() callback needs to be be bound with - // BindPostTask() to ensure that the callback is invoked on this specific task - // runner. - auto channel_cb = - base::BindOnce(&AccessCodeCastHandler::OnChannelOpenedResult, - weak_ptr_factory_.GetWeakPtr()); - auto returned_channel_cb = - base::BindPostTask(current_task_runner, std::move(channel_cb)); - - access_code_sink_service_->AddSinkToMediaRouter( - creation_result.first.value(), std::move(returned_channel_cb)); -} - -void AccessCodeCastHandler::OnChannelOpenedResult(bool channel_opened) { +void AccessCodeCastHandler::OnSinkAddedResult( + access_code_cast::mojom::AddSinkResultCode add_sink_result, + absl::optional<MediaSink::Id> sink_id) { + DCHECK(sink_id || add_sink_result != AddSinkResultCode::OK); // Wait for OnResultsUpdated before triggering the |add_sink_callback_| since // we are not entirely sure the sink is ready to be casted to yet. - if (add_sink_callback_) { - if (channel_opened) { - DCHECK(sink_id_) << "Must have sink_id_ when adding a sink!"; - media_router_->GetLogger()->LogInfo( - mojom::LogCategory::kDiscovery, kLoggerComponent, - "The channel successfully opened.", sink_id_.value(), "", ""); - CheckForDiscoveryCompletion(); - } else { - media_router_->GetLogger()->LogError( - mojom::LogCategory::kDiscovery, kLoggerComponent, - "The channel failed to open.", sink_id_.value(), "", ""); - std::move(add_sink_callback_).Run(AddSinkResultCode::CHANNEL_OPEN_ERROR); - } + if (add_sink_result != AddSinkResultCode::OK && add_sink_callback_) { + auto error_message = + std::string("The device could not be added because of enum error : ") + + AddSinkResultCodeToString(add_sink_result); + media_router_->GetLogger()->LogError( + mojom::LogCategory::kUi, kLoggerComponent, error_message, "", "", ""); + std::move(add_sink_callback_).Run(add_sink_result); } + if (sink_id) { + sink_id_ = sink_id; + } + CheckForDiscoveryCompletion(); } void AccessCodeCastHandler::SetSinkCallbackForTesting(
diff --git a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h index ff1cb8c..4b80259 100644 --- a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h +++ b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_UI_WEBUI_ACCESS_CODE_CAST_ACCESS_CODE_CAST_HANDLER_H_ #include "base/scoped_observation.h" -#include "chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.h" #include "chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.h" #include "chrome/browser/media/router/discovery/access_code/discovery_resources.pb.h" #include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h" @@ -79,19 +78,11 @@ private: friend class AccessCodeCastHandlerTest; - FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, - DiscoveryDeviceMissingWithOk); - FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, - ValidDiscoveryDeviceAndCode); - FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, InvalidDiscoveryDevice); - FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, NonOKResultCode); FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, DiscoveredDeviceAdded); FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, OtherDevicesIgnored); FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, DesktopMirroring); FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, DesktopMirroringError); - FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, OnChannelOpened); - FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, - OnChannelOpenedExistingSink); + FRIEND_TEST_ALL_PREFIXES(AccessCodeCastHandlerTest, OnSinkAddedResult); // Returns true if the specified cast mode is among the cast modes specified // for the dialog to use when it was initialized. @@ -107,11 +98,9 @@ // requisite mirroring casting mode is available. void InitMirroringSources(); - void OnAccessCodeValidated( - absl::optional<DiscoveryDevice> discovery_device, - access_code_cast::mojom::AddSinkResultCode result_code); - - void OnChannelOpenedResult(bool channel_opened); + void OnSinkAddedResult( + access_code_cast::mojom::AddSinkResultCode add_sink_result, + absl::optional<MediaSink::Id> sink_id); // QueryResultManager::Observer: void OnResultsUpdated( @@ -150,8 +139,6 @@ mojo::Remote<access_code_cast::mojom::Page> page_; mojo::Receiver<access_code_cast::mojom::PageHandler> receiver_; - std::unique_ptr<AccessCodeCastDiscoveryInterface> discovery_server_interface_; - // Used to fetch OAuth2 access tokens. raw_ptr<Profile> const profile_;
diff --git a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler_unittest.cc b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler_unittest.cc index 4af3c57..95462cb 100644 --- a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler_unittest.cc +++ b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler_unittest.cc
@@ -44,6 +44,7 @@ base::MockCallback<media_router::AccessCodeCastHandler::CastToSinkCallback>; using media_router::mojom::RouteRequestResultCode; using ::testing::_; +using ::testing::Eq; using ::testing::Exactly; using ::testing::InvokeWithoutArgs; using ::testing::NiceMock; @@ -83,7 +84,7 @@ MOCK_METHOD(void, AddSinkToMediaRouter, (const MediaSinkInternal& sink, - base::OnceCallback<void(bool)> callback), + AddSinkResultCallback add_sink_callback), (override)); }; @@ -336,92 +337,24 @@ MediaSinkInternal cast_sink_2_; }; -TEST_F(AccessCodeCastHandlerTest, DiscoveryDeviceMissingWithOk) { - // Test to ensure that the add_sink_callback returns an EMPTY_RESPONSE if the - // the device is missing. Since |OnAccessCodeValidated| is a public method -- - // we must check the case of an empty |discovery_device| with an OK result - // code. - MockAddSinkCallback mock_callback; - EXPECT_CALL(mock_callback, Run(AddSinkResultCode::EMPTY_RESPONSE)); - handler()->SetSinkCallbackForTesting(mock_callback.Get()); - handler()->OnAccessCodeValidated(absl::nullopt, AddSinkResultCode::OK); -} +TEST_F(AccessCodeCastHandlerTest, OnSinkAddedResult) { + // OnSinkAddedResult should only trigger the callback if the channel opening + // failed somehow. + MockAddSinkCallback mock_callback_failure; + handler()->SetSinkCallbackForTesting(mock_callback_failure.Get()); -TEST_F(AccessCodeCastHandlerTest, ValidDiscoveryDeviceAndCode) { - // If discovery device is present, formatted correctly, and code is OK, then - // callback should be OK. - DiscoveryDevice discovery_device_proto = - media_router::BuildDiscoveryDeviceProto(); - discovery_device_proto.set_id("id1"); + EXPECT_CALL(mock_callback_failure, + Run(AddSinkResultCode::CHANNEL_OPEN_ERROR)); + handler()->OnSinkAddedResult(AddSinkResultCode::CHANNEL_OPEN_ERROR, + absl::nullopt); + EXPECT_FALSE(handler()->sink_id_.has_value()); - EXPECT_CALL(*access_service(), AddSinkToMediaRouter(_, _)); - handler()->OnAccessCodeValidated(discovery_device_proto, - AddSinkResultCode::OK); + MockAddSinkCallback mock_callback_ok; + handler()->SetSinkCallbackForTesting(mock_callback_ok.Get()); - // Validate that the sink id of the discovered device is stored for later - // casting. - EXPECT_EQ(cast_sink_1().sink().id(), handler()->sink_id_); -} - -TEST_F(AccessCodeCastHandlerTest, OnChannelOpened) { - // If the sink is not already present in MR, OnChannelOpened should only - // trigger the callback if the channel opening failed. - handler()->set_sink_id_for_testing(cast_sink_1().sink().id()); - - MockAddSinkCallback mock_callback_true; - handler()->SetSinkCallbackForTesting(mock_callback_true.Get()); - - EXPECT_CALL(mock_callback_true, Run(AddSinkResultCode::CHANNEL_OPEN_ERROR)) - .Times(0); - EXPECT_CALL(mock_callback_true, Run(AddSinkResultCode::OK)).Times(0); - handler()->OnChannelOpenedResult(true); - - MockAddSinkCallback mock_callback_false; - handler()->SetSinkCallbackForTesting(mock_callback_false.Get()); - - EXPECT_CALL(mock_callback_false, Run(AddSinkResultCode::CHANNEL_OPEN_ERROR)); - handler()->OnChannelOpenedResult(false); -} - -TEST_F(AccessCodeCastHandlerTest, OnChannelOpenedExistingSink) { - // OnChannelOpened should trigger success if the sink is already present in - // MR. - handler()->set_sink_id_for_testing(cast_sink_1().sink().id()); - UpdateSinks({cast_sink_1().sink()}, std::vector<url::Origin>()); - - MockAddSinkCallback mock_callback_true; - handler()->SetSinkCallbackForTesting(mock_callback_true.Get()); - - EXPECT_CALL(mock_callback_true, Run(AddSinkResultCode::CHANNEL_OPEN_ERROR)) - .Times(0); - EXPECT_CALL(mock_callback_true, Run(AddSinkResultCode::OK)); - handler()->OnChannelOpenedResult(true); -} - -TEST_F(AccessCodeCastHandlerTest, InvalidDiscoveryDevice) { - // If discovery device is present, but formatted incorrectly, and code is OK, - // then callback should be SINK_CREATION_ERROR. - MockAddSinkCallback mock_callback; - - // Create discovery_device with an invalid port - DiscoveryDevice discovery_device_proto = - media_router::BuildDiscoveryDeviceProto("foo_display_name", "1234", - "```````23489:1238:1239"); - - EXPECT_CALL(mock_callback, Run(AddSinkResultCode::SINK_CREATION_ERROR)); - handler()->SetSinkCallbackForTesting(mock_callback.Get()); - handler()->OnAccessCodeValidated(discovery_device_proto, - AddSinkResultCode::OK); -} - -TEST_F(AccessCodeCastHandlerTest, NonOKResultCode) { - // Check to see that any result code that isn't OK will return that error. - MockAddSinkCallback mock_callback; - - EXPECT_CALL(mock_callback, Run(AddSinkResultCode::AUTH_ERROR)); - handler()->SetSinkCallbackForTesting(mock_callback.Get()); - handler()->OnAccessCodeValidated(absl::nullopt, - AddSinkResultCode::AUTH_ERROR); + EXPECT_CALL(mock_callback_ok, Run(AddSinkResultCode::OK)).Times(0); + handler()->OnSinkAddedResult(AddSinkResultCode::OK, "123456"); + EXPECT_EQ(handler()->sink_id_.value(), "123456"); } // Demonstrates that if the expected device is added to the media router,
diff --git a/chrome/browser/ui/webui/commander/commander_handler.cc b/chrome/browser/ui/webui/commander/commander_handler.cc index 4b02716..85063eb 100644 --- a/chrome/browser/ui/webui/commander/commander_handler.cc +++ b/chrome/browser/ui/webui/commander/commander_handler.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/webui/commander/commander_handler.h" +#include <string> +#include <utility> + #include "base/bind.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/commander/commander_view_model.h" @@ -105,17 +108,17 @@ void CommanderHandler::ViewModelUpdated( commander::CommanderViewModel view_model) { base::DictionaryValue vm; - vm.SetIntKey(kActionKey, view_model.action); - vm.SetIntKey(kResultSetIdKey, view_model.result_set_id); + vm.GetDict().Set(kActionKey, view_model.action); + vm.GetDict().Set(kResultSetIdKey, view_model.result_set_id); if (view_model.action == commander::CommanderViewModel::Action::kDisplayResults) { base::ListValue option_list; for (commander::CommandItemViewModel& item : view_model.items) { base::DictionaryValue option; - option.SetStringKey(kTitleKey, item.title); - option.SetIntKey(kEntityKey, item.entity_type); + option.GetDict().Set(kTitleKey, item.title); + option.GetDict().Set(kEntityKey, item.entity_type); if (!item.annotation.empty()) - option.SetStringKey(kAnnotationKey, item.annotation); + option.GetDict().Set(kAnnotationKey, item.annotation); base::ListValue ranges; for (const gfx::Range& range : item.matched_ranges) { base::ListValue range_value; @@ -123,15 +126,15 @@ range_value.Append(static_cast<int>(range.end())); ranges.Append(std::move(range_value)); } - option.SetKey(kMatchedRangesKey, std::move(ranges)); + option.GetDict().Set(kMatchedRangesKey, std::move(ranges)); option_list.Append(std::move(option)); } - vm.SetKey(kOptionsKey, std::move(option_list)); + vm.GetDict().Set(kOptionsKey, std::move(option_list)); } else { // kDismiss is handled higher in the stack. DCHECK_EQ(view_model.action, commander::CommanderViewModel::Action::kPrompt); - vm.SetStringKey(kPromptTextKey, view_model.prompt_text); + vm.GetDict().Set(kPromptTextKey, view_model.prompt_text); } FireWebUIListener(kViewModelUpdatedEvent, vm); }
diff --git a/chrome/browser/ui/webui/components/components_handler.cc b/chrome/browser/ui/webui/components/components_handler.cc index 908fef5..d364cc2 100644 --- a/chrome/browser/ui/webui/components/components_handler.cc +++ b/chrome/browser/ui/webui/components/components_handler.cc
@@ -21,7 +21,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/ash/crosapi/browser_manager.h" #include "chrome/browser/ash/crosapi/browser_util.h" -#include "chrome/common/webui_url_constants.h" #elif BUILDFLAG(IS_CHROMEOS_LACROS) #include "chrome/browser/lacros/lacros_url_handling.h" #endif @@ -66,8 +65,8 @@ const base::Value& callback_id = args->GetListDeprecated()[0]; base::DictionaryValue result; - result.SetKey("components", - base::Value::FromUniquePtrValue(LoadComponents())); + result.GetDict().Set("components", + base::Value::FromUniquePtrValue(LoadComponents())); #if BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -75,7 +74,7 @@ #else const bool showSystemFlagsLink = true; #endif // BUILDFLAG(IS_CHROMEOS_ASH) - result.SetBoolKey("showOsLink", showSystemFlagsLink); + result.GetDict().Set("showOsLink", showSystemFlagsLink); #endif // BUILDFLAG(IS_CHROMEOS) ResolveJavascriptCallback(callback_id, result); @@ -102,14 +101,15 @@ void ComponentsHandler::OnEvent(Events event, const std::string& id) { base::DictionaryValue parameters; - parameters.SetStringKey("event", ComponentEventToString(event)); + parameters.GetDict().Set("event", ComponentEventToString(event)); if (!id.empty()) { if (event == Events::COMPONENT_UPDATED) { update_client::CrxUpdateItem item; if (component_updater_->GetComponentDetails(id, &item) && item.component) - parameters.SetStringKey("version", item.component->version.GetString()); + parameters.GetDict().Set("version", + item.component->version.GetString()); } - parameters.SetStringKey("id", id); + parameters.GetDict().Set("id", id); } FireWebUIListener("component-event", parameters); } @@ -202,13 +202,13 @@ update_client::CrxUpdateItem item; if (component_updater_->GetComponentDetails(component_ids[j], &item)) { auto component_entry = std::make_unique<base::DictionaryValue>(); - component_entry->SetStringKey("id", component_ids[j]); - component_entry->SetStringKey("status", - ServiceStatusToString(item.state)); + component_entry->GetDict().Set("id", component_ids[j]); + component_entry->GetDict().Set("status", + ServiceStatusToString(item.state)); if (item.component) { - component_entry->SetStringKey("name", item.component->name); - component_entry->SetStringKey("version", - item.component->version.GetString()); + component_entry->GetDict().Set("name", item.component->name); + component_entry->GetDict().Set("version", + item.component->version.GetString()); } component_list->Append(std::move(component_entry)); }
diff --git a/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc b/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc index db082839..51551f9f 100644 --- a/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc +++ b/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc
@@ -480,7 +480,8 @@ ModuleDatabase::GetInstance()->RemoveObserver(this); base::DictionaryValue results; - results.SetIntKey("moduleCount", module_list_->GetListDeprecated().size()); + results.GetDict().Set("moduleCount", + int(module_list_->GetListDeprecated().size())); results.Set("moduleList", std::move(module_list_)); #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chrome/browser/ui/webui/cookies_tree_model_util.cc index c7d6e06..718a0dc 100644 --- a/chrome/browser/ui/webui/cookies_tree_model_util.cc +++ b/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -84,35 +84,35 @@ bool include_quota_nodes, base::Value* dict) { // Use node's address as an id for WebUI to look it up. - dict->SetStringKey(kKeyId, GetTreeNodeId(&node)); - dict->SetStringKey(kKeyTitle, node.GetTitle()); - dict->SetBoolKey(kKeyHasChildren, !node.children().empty()); + dict->GetDict().Set(kKeyId, GetTreeNodeId(&node)); + dict->GetDict().Set(kKeyTitle, node.GetTitle()); + dict->GetDict().Set(kKeyHasChildren, !node.children().empty()); switch (node.GetDetailedInfo().node_type) { case CookieTreeNode::DetailedInfo::TYPE_HOST: { - dict->SetStringKey(kKeyType, "origin"); + dict->GetDict().Set(kKeyType, "origin"); break; } case CookieTreeNode::DetailedInfo::TYPE_COOKIE: { - dict->SetStringKey(kKeyType, "cookie"); + dict->GetDict().Set(kKeyType, "cookie"); const net::CanonicalCookie& cookie = *node.GetDetailedInfo().cookie; - dict->SetStringKey(kKeyName, cookie.Name()); - dict->SetStringKey(kKeyContent, cookie.Value()); - dict->SetStringKey(kKeyDomain, cookie.Domain()); - dict->SetStringKey(kKeyPath, cookie.Path()); - dict->SetStringKey(kKeySendFor, - l10n_util::GetStringUTF16( - CookiesTreeModel::GetSendForMessageID(cookie))); + dict->GetDict().Set(kKeyName, cookie.Name()); + dict->GetDict().Set(kKeyContent, cookie.Value()); + dict->GetDict().Set(kKeyDomain, cookie.Domain()); + dict->GetDict().Set(kKeyPath, cookie.Path()); + dict->GetDict().Set(kKeySendFor, + l10n_util::GetStringUTF16( + CookiesTreeModel::GetSendForMessageID(cookie))); std::string accessible = cookie.IsHttpOnly() ? l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO) : l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES); - dict->SetStringKey(kKeyAccessibleToScript, accessible); - dict->SetStringKey(kKeyCreated, - base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( - cookie.CreationDate()))); - dict->SetStringKey( + dict->GetDict().Set(kKeyAccessibleToScript, accessible); + dict->GetDict().Set(kKeyCreated, + base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + cookie.CreationDate()))); + dict->GetDict().Set( kKeyExpires, cookie.IsPersistent() ? base::UTF16ToUTF8( @@ -122,65 +122,65 @@ break; } case CookieTreeNode::DetailedInfo::TYPE_DATABASE: { - dict->SetStringKey(kKeyType, "database"); + dict->GetDict().Set(kKeyType, "database"); const content::StorageUsageInfo& usage_info = *node.GetDetailedInfo().usage_info; - dict->SetStringKey(kKeyOrigin, usage_info.origin.Serialize()); - dict->SetStringKey(kKeySize, - ui::FormatBytes(usage_info.total_size_bytes)); - dict->SetStringKey(kKeyModified, - base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( - usage_info.last_modified))); + dict->GetDict().Set(kKeyOrigin, usage_info.origin.Serialize()); + dict->GetDict().Set(kKeySize, + ui::FormatBytes(usage_info.total_size_bytes)); + dict->GetDict().Set(kKeyModified, + base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + usage_info.last_modified))); break; } case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE: { - dict->SetStringKey(kKeyType, "local_storage"); + dict->GetDict().Set(kKeyType, "local_storage"); const content::StorageUsageInfo& local_storage_info = *node.GetDetailedInfo().usage_info; - dict->SetStringKey(kKeyOrigin, local_storage_info.origin.Serialize()); - dict->SetStringKey(kKeySize, - ui::FormatBytes(local_storage_info.total_size_bytes)); - dict->SetStringKey(kKeyModified, - base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( - local_storage_info.last_modified))); + dict->GetDict().Set(kKeyOrigin, local_storage_info.origin.Serialize()); + dict->GetDict().Set(kKeySize, + ui::FormatBytes(local_storage_info.total_size_bytes)); + dict->GetDict().Set(kKeyModified, + base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + local_storage_info.last_modified))); break; } case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB: { - dict->SetStringKey(kKeyType, "indexed_db"); + dict->GetDict().Set(kKeyType, "indexed_db"); const content::StorageUsageInfo& usage_info = *node.GetDetailedInfo().usage_info; - dict->SetStringKey(kKeyOrigin, usage_info.origin.Serialize()); - dict->SetStringKey(kKeySize, - ui::FormatBytes(usage_info.total_size_bytes)); - dict->SetStringKey(kKeyModified, - base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( - usage_info.last_modified))); + dict->GetDict().Set(kKeyOrigin, usage_info.origin.Serialize()); + dict->GetDict().Set(kKeySize, + ui::FormatBytes(usage_info.total_size_bytes)); + dict->GetDict().Set(kKeyModified, + base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + usage_info.last_modified))); break; } case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM: { - dict->SetStringKey(kKeyType, "file_system"); + dict->GetDict().Set(kKeyType, "file_system"); const browsing_data::FileSystemHelper::FileSystemInfo& file_system_info = *node.GetDetailedInfo().file_system_info; const storage::FileSystemType kPerm = storage::kFileSystemTypePersistent; const storage::FileSystemType kTemp = storage::kFileSystemTypeTemporary; - dict->SetStringKey(kKeyOrigin, file_system_info.origin.Serialize()); - dict->SetStringKey( + dict->GetDict().Set(kKeyOrigin, file_system_info.origin.Serialize()); + dict->GetDict().Set( kKeyPersistent, base::Contains(file_system_info.usage_map, kPerm) ? base::UTF16ToUTF8(ui::FormatBytes( file_system_info.usage_map.find(kPerm)->second)) : l10n_util::GetStringUTF8(IDS_COOKIES_FILE_SYSTEM_USAGE_NONE)); - dict->SetStringKey( + dict->GetDict().Set( kKeyTemporary, base::Contains(file_system_info.usage_map, kTemp) ? base::UTF16ToUTF8(ui::FormatBytes( @@ -192,7 +192,7 @@ if (!include_quota_nodes) return false; - dict->SetStringKey(kKeyType, "quota"); + dict->GetDict().Set(kKeyType, "quota"); const BrowsingDataQuotaHelper::QuotaInfo& quota_info = *node.GetDetailedInfo().quota_info; @@ -200,66 +200,66 @@ kNegligibleUsage) return false; - dict->SetStringKey(kKeyOrigin, quota_info.host); - dict->SetStringKey( + dict->GetDict().Set(kKeyOrigin, quota_info.host); + dict->GetDict().Set( kKeyTotalUsage, base::UTF16ToUTF8(ui::FormatBytes(quota_info.temporary_usage + quota_info.persistent_usage))); - dict->SetStringKey( + dict->GetDict().Set( kKeyTemporaryUsage, base::UTF16ToUTF8(ui::FormatBytes(quota_info.temporary_usage))); - dict->SetStringKey( + dict->GetDict().Set( kKeyPersistentUsage, base::UTF16ToUTF8(ui::FormatBytes(quota_info.persistent_usage))); break; } case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER: { - dict->SetStringKey(kKeyType, "service_worker"); + dict->GetDict().Set(kKeyType, "service_worker"); const content::StorageUsageInfo& usage_info = *node.GetDetailedInfo().usage_info; - dict->SetStringKey(kKeyOrigin, usage_info.origin.Serialize()); - dict->SetStringKey(kKeySize, - ui::FormatBytes(usage_info.total_size_bytes)); + dict->GetDict().Set(kKeyOrigin, usage_info.origin.Serialize()); + dict->GetDict().Set(kKeySize, + ui::FormatBytes(usage_info.total_size_bytes)); // TODO(jsbell): Include kKeyModified like other storage types. break; } case CookieTreeNode::DetailedInfo::TYPE_SHARED_WORKER: { - dict->SetStringKey(kKeyType, "shared_worker"); + dict->GetDict().Set(kKeyType, "shared_worker"); const browsing_data::SharedWorkerHelper::SharedWorkerInfo& shared_worker_info = *node.GetDetailedInfo().shared_worker_info; - dict->SetStringKey(kKeyOrigin, shared_worker_info.worker.spec()); - dict->SetStringKey(kKeyName, shared_worker_info.name); + dict->GetDict().Set(kKeyOrigin, shared_worker_info.worker.spec()); + dict->GetDict().Set(kKeyName, shared_worker_info.name); break; } case CookieTreeNode::DetailedInfo::TYPE_CACHE_STORAGE: { - dict->SetStringKey(kKeyType, "cache_storage"); + dict->GetDict().Set(kKeyType, "cache_storage"); const content::StorageUsageInfo& usage_info = *node.GetDetailedInfo().usage_info; - dict->SetStringKey(kKeyOrigin, usage_info.origin.Serialize()); - dict->SetStringKey(kKeySize, - ui::FormatBytes(usage_info.total_size_bytes)); - dict->SetStringKey(kKeyModified, - base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( - usage_info.last_modified))); + dict->GetDict().Set(kKeyOrigin, usage_info.origin.Serialize()); + dict->GetDict().Set(kKeySize, + ui::FormatBytes(usage_info.total_size_bytes)); + dict->GetDict().Set(kKeyModified, + base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + usage_info.last_modified))); break; } case CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE: { - dict->SetStringKey(kKeyType, "media_license"); + dict->GetDict().Set(kKeyType, "media_license"); const content::StorageUsageInfo& usage_info = *node.GetDetailedInfo().media_license_usage_info; - dict->SetStringKey(kKeyOrigin, usage_info.origin.GetURL().spec()); - dict->SetStringKey(kKeySize, - ui::FormatBytes(usage_info.total_size_bytes)); - dict->SetStringKey(kKeyModified, - base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( - usage_info.last_modified))); + dict->GetDict().Set(kKeyOrigin, usage_info.origin.GetURL().spec()); + dict->GetDict().Set(kKeySize, + ui::FormatBytes(usage_info.total_size_bytes)); + dict->GetDict().Set(kKeyModified, + base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + usage_info.last_modified))); break; } default: @@ -274,11 +274,11 @@ for (extensions::ExtensionSet::const_iterator it = protecting_apps->begin(); it != protecting_apps->end(); ++it) { base::Value app_info(base::Value::Type::DICTIONARY); - app_info.SetStringKey(kKeyId, (*it)->id()); - app_info.SetStringKey(kKeyName, (*it)->name()); + app_info.GetDict().Set(kKeyId, (*it)->id()); + app_info.GetDict().Set(kKeyName, (*it)->name()); app_infos.Append(std::move(app_info)); } - dict->SetKey(kKeyAppsProtectingThis, std::move(app_infos)); + dict->GetDict().Set(kKeyAppsProtectingThis, std::move(app_infos)); } #endif @@ -298,8 +298,8 @@ // TODO(dschuyler): This ID path is an artifact from using tree nodes to // hold the cookies. Can this be changed to a dictionary with a key // lookup (and remove use of id_map_)? - dict.SetStringKey("idPath", - cookie_id_path + GetTreeNodeId(details.get())); + dict.GetDict().Set("idPath", + cookie_id_path + GetTreeNodeId(details.get())); list->Append(std::move(dict)); } }
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc index b68df168..7d05301 100644 --- a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc +++ b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
@@ -88,7 +88,7 @@ html_source->UseStringsJs(); // Register callback to handle "cancel-button-event" from nearby_*.html files. - web_ui->RegisterDeprecatedMessageCallback( + web_ui->RegisterMessageCallback( "close", base::BindRepeating(&NearbyShareDialogUI::HandleClose, base::Unretained(this))); @@ -167,15 +167,14 @@ Navigate(&nav_params); } -void NearbyShareDialogUI::HandleClose(const base::ListValue* args) { +void NearbyShareDialogUI::HandleClose(const base::Value::List& args) { if (!sharesheet_controller_) return; - base::Value::ConstListView args_list = args->GetListDeprecated(); - CHECK_EQ(1u, args_list.size()); - CHECK_GE(args_list[0].GetInt(), 0); - CHECK_LE(args_list[0].GetInt(), static_cast<int>(CloseReason::kMax)); - CloseReason reason = static_cast<CloseReason>(args_list[0].GetInt()); + CHECK_EQ(1u, args.size()); + CHECK_GE(args[0].GetInt(), 0); + CHECK_LE(args[0].GetInt(), static_cast<int>(CloseReason::kMax)); + CloseReason reason = static_cast<CloseReason>(args[0].GetInt()); sharesheet::SharesheetResult sharesheet_result; switch (reason) {
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h index 86ffc2d..801efda 100644 --- a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h +++ b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h
@@ -63,7 +63,7 @@ content::WebContents* new_contents) override; private: - void HandleClose(const base::ListValue* args); + void HandleClose(const base::Value::List& args); // Search for a query parameter such as file, text, address, phone, or url, // then use it to populate an attachment, if found; otherwise, do nothing.
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc index e375ac7..36924b9 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc
@@ -9,6 +9,7 @@ #include "ash/components/phonehub/screen_lock_manager.h" #include "ash/components/phonehub/url_constants.h" #include "ash/constants/ash_features.h" +#include "ash/constants/ash_pref_names.h" #include "ash/services/multidevice_setup/public/cpp/prefs.h" #include "ash/services/multidevice_setup/public/cpp/url_provider.h" #include "ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" @@ -321,7 +322,8 @@ phone_hub_manager_(phone_hub_manager), android_sms_service_(android_sms_service), pref_service_(pref_service), - eche_app_manager_(eche_app_manager) { + eche_app_manager_(eche_app_manager), + html_source_(nullptr) { if (NearbySharingServiceFactory::IsNearbyShareSupportedForBrowserContext( profile)) { NearbySharingService* nearby_sharing_service = @@ -334,6 +336,13 @@ OnEnabledChanged(nearby_share_settings->GetEnabled()); RefreshNearbyBackgroundScanningShareSearchConcepts(); } + if (features::IsEcheSWAEnabled()) { + pref_change_registrar_.Init(pref_service_); + pref_change_registrar_.Add( + ash::prefs::kEnableAutoScreenLock, + base::BindRepeating(&MultiDeviceSection::OnEnableScreenLockChanged, + base::Unretained(this))); + } // Note: |multidevice_setup_client_| is null when multi-device features are // prohibited by policy. @@ -346,12 +355,14 @@ } MultiDeviceSection::~MultiDeviceSection() { + pref_change_registrar_.RemoveAll(); if (multidevice_setup_client_) multidevice_setup_client_->RemoveObserver(this); } void MultiDeviceSection::AddLoadTimeData( content::WebUIDataSource* html_source) { + html_source_ = html_source; static constexpr webui::LocalizedString kLocalizedStrings[] = { {"multidevicePageTitle", IDS_SETTINGS_MULTIDEVICE}, {"multideviceSetupButton", IDS_SETTINGS_MULTIDEVICE_SETUP_BUTTON}, @@ -602,11 +613,7 @@ phonehub::ScreenLockManager::LockStatus::kLockedOn; html_source->AddBoolean("isPhoneScreenLockEnabled", is_phone_screen_lock_enabled); - const bool is_screen_lock_enabled = - SessionControllerClientImpl::CanLockScreen() && - SessionControllerClientImpl::ShouldLockScreenAutomatically(); - html_source->AddBoolean("isChromeosScreenLockEnabled", - is_screen_lock_enabled); + OnEnableScreenLockChanged(); html_source->AddBoolean("isOnePageOnboardingEnabled", base::FeatureList::IsEnabled( ::features::kNearbySharingOnePageOnboarding)); @@ -816,5 +823,15 @@ RefreshNearbyBackgroundScanningShareSearchConcepts(); } +void MultiDeviceSection::OnEnableScreenLockChanged() { + const bool is_screen_lock_enabled = + SessionControllerClientImpl::CanLockScreen() && + SessionControllerClientImpl::ShouldLockScreenAutomatically(); + if (html_source_) { + html_source_->AddBoolean("isChromeosScreenLockEnabled", + is_screen_lock_enabled); + } +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h index a8e17e5..8d92c01 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h
@@ -46,6 +46,7 @@ ~MultiDeviceSection() override; private: + friend class MultiDeviceSectionTest; // OsSettingsSection: void AddLoadTimeData(content::WebUIDataSource* html_source) override; void AddHandlers(content::WebUI* web_ui) override; @@ -64,8 +65,8 @@ const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& feature_states_map) override; - // Nearby Share enabled pref change observer. - void OnNearbySharingEnabledChanged(); + // Screen lock enabled pref change observer. + void OnEnableScreenLockChanged(); bool IsFeatureSupported(ash::multidevice_setup::mojom::Feature feature); void RefreshNearbyBackgroundScanningShareSearchConcepts(); @@ -92,6 +93,7 @@ PrefService* pref_service_; PrefChangeRegistrar pref_change_registrar_; ash::eche_app::EcheAppManager* eche_app_manager_; + content::WebUIDataSource* html_source_; }; } // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_section_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_section_unittest.cc new file mode 100644 index 0000000..3552cc0 --- /dev/null +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_section_unittest.cc
@@ -0,0 +1,145 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/multidevice_section.h" + +#include "ash/components/multidevice/logging/logging.h" +#include "ash/components/phonehub/fake_phone_hub_manager.h" +#include "ash/components/phonehub/pref_names.h" +#include "ash/constants/ash_features.h" +#include "ash/constants/ash_pref_names.h" +#include "ash/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/ash/android_sms/android_sms_service_factory.h" +#include "chrome/browser/ash/eche_app/eche_app_manager_factory.h" +#include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/components/local_search_service/public/cpp/local_search_service_proxy.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace settings { + +class MockWebUIDataSource : public content::WebUIDataSource { + public: + MockWebUIDataSource() = default; + ~MockWebUIDataSource() override = default; + MockWebUIDataSource(const MockWebUIDataSource&) = delete; + MockWebUIDataSource& operator=(const MockWebUIDataSource&) = delete; + + // WebUIDataSource: + MOCK_METHOD(void, + AddBoolean, + (base::StringPiece name, bool value), + (override)); + void AddString(base::StringPiece name, const std::u16string& value) override { + } + void AddString(base::StringPiece name, const std::string& value) override {} + void AddLocalizedString(base::StringPiece name, int ids) override {} + void AddLocalizedStrings( + base::span<const webui::LocalizedString> strings) override {} + void AddLocalizedStrings( + const base::DictionaryValue& localized_strings) override {} + void AddInteger(base::StringPiece name, int32_t value) override {} + void AddDouble(base::StringPiece name, double value) override {} + void UseStringsJs() override {} + void AddResourcePath(base::StringPiece path, int resource_id) override {} + void AddResourcePaths(base::span<const webui::ResourcePath> paths) override {} + void SetDefaultResource(int resource_id) override {} + void SetRequestFilter(const WebUIDataSource::ShouldHandleRequestCallback& + should_handle_request_callback, + const WebUIDataSource::HandleRequestCallback& + handle_request_callback) override {} + void DisableReplaceExistingSource() override {} + void DisableContentSecurityPolicy() override {} + void OverrideContentSecurityPolicy(network::mojom::CSPDirectiveName directive, + const std::string& value) override {} + void OverrideCrossOriginOpenerPolicy(const std::string& value) override {} + void OverrideCrossOriginEmbedderPolicy(const std::string& value) override {} + void OverrideCrossOriginResourcePolicy(const std::string& value) override {} + void DisableTrustedTypesCSP() override {} + void DisableDenyXFrameOptions() override {} + void EnableReplaceI18nInJS() override {} + std::string GetSource() override { return ""; } + void AddFrameAncestor(const GURL& frame_ancestor) override {} +}; + +class MultiDeviceSectionTest : public testing::Test { + protected: + MultiDeviceSectionTest() + : profile_manager_(TestingBrowserProcess::GetGlobal()) { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{features::kEcheSWA}, + /*disabled_features=*/{}); + } + MultiDeviceSectionTest(const MultiDeviceSectionTest&) = delete; + MultiDeviceSectionTest& operator=(const MultiDeviceSectionTest&) = delete; + ~MultiDeviceSectionTest() override = default; + + // testing::Test: + void SetUp() override { + ASSERT_TRUE(profile_manager_.SetUp()); + pref_service_.registry()->RegisterBooleanPref( + ash::prefs::kEnableAutoScreenLock, false); + pref_service_.registry()->RegisterIntegerPref( + ash::phonehub::prefs::kScreenLockStatus, + static_cast<int>( + ash::phonehub::ScreenLockManager::LockStatus::kLockedOn)); + mock_web_ui_data_source_ = std::make_unique<MockWebUIDataSource>(); + service_proxy_ = + std::make_unique<local_search_service::LocalSearchServiceProxy>( + /*for_testing=*/true); + search_tag_registry_ = + std::make_unique<SearchTagRegistry>(service_proxy_.get()); + TestingProfile* profile = + profile_manager_.CreateTestingProfile("TestingProfile"); + fake_multidevice_setup_client_ = + std::make_unique<multidevice_setup::FakeMultiDeviceSetupClient>(); + fake_phone_hub_manager_ = std::make_unique<phonehub::FakePhoneHubManager>(); + multi_device_section_ = std::make_unique<MultiDeviceSection>( + profile, search_tag_registry_.get(), + fake_multidevice_setup_client_.get(), fake_phone_hub_manager_.get(), + android_sms::AndroidSmsServiceFactory::GetForBrowserContext(profile), + &pref_service_, + ash::eche_app::EcheAppManagerFactory::GetForProfile(profile)); + } + + void VerifyOnEnableScreenLockChangedIsCalled() { + EXPECT_CALL(*mock_web_ui_data_source_, AddBoolean(testing::_, testing::_)) + .Times(testing::AnyNumber()); + multi_device_section_->AddLoadTimeData(mock_web_ui_data_source_.get()); + + EXPECT_CALL( + *mock_web_ui_data_source_, + AddBoolean(testing::Eq("isChromeosScreenLockEnabled"), testing::_)) + .Times(1); + pref_service_.SetBoolean(ash::prefs::kEnableAutoScreenLock, true); + } + + private: + content::BrowserTaskEnvironment task_environment_; + base::test::ScopedFeatureList scoped_feature_list_; + TestingProfileManager profile_manager_; + TestingPrefServiceSimple pref_service_; + std::unique_ptr<MockWebUIDataSource> mock_web_ui_data_source_; + std::unique_ptr<local_search_service::LocalSearchServiceProxy> service_proxy_; + std::unique_ptr<SearchTagRegistry> search_tag_registry_; + std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient> + fake_multidevice_setup_client_; + std::unique_ptr<phonehub::FakePhoneHubManager> fake_phone_hub_manager_; + std::unique_ptr<MultiDeviceSection> multi_device_section_; +}; + +TEST_F(MultiDeviceSectionTest, OnEnableScreenLockChanged) { + VerifyOnEnableScreenLockChangedIsCalled(); +} + +} // namespace settings +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index 9c7eec5..d2a47fb 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -55,7 +55,9 @@ #include "components/permissions/permission_uma_util.h" #include "components/permissions/test/object_permission_context_base_mock_permission_observer.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/cpp/features.h" #include "components/services/app_service/public/mojom/types.mojom.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "components/ukm/test_ukm_recorder.h" @@ -114,14 +116,12 @@ {{"http://127.0.0.1", "location"}, {true, ""}}, // Localhost is secure. {{"http://[::1]", "location"}, {true, ""}}}; -apps::mojom::AppPtr MakeApp(const std::string& app_id, - apps::mojom::AppType app_type, - const std::string& publisher_id, - apps::mojom::Readiness readiness, - apps::mojom::InstallReason install_reason) { - apps::mojom::AppPtr app = apps::mojom::App::New(); - app->app_id = app_id; - app->app_type = app_type; +apps::AppPtr MakeApp(const std::string& app_id, + apps::AppType app_type, + const std::string& publisher_id, + apps::Readiness readiness, + apps::InstallReason install_reason) { + apps::AppPtr app = std::make_unique<apps::App>(app_type, app_id); app->publisher_id = publisher_id; app->readiness = readiness; app->install_reason = install_reason; @@ -131,13 +131,20 @@ void InstallWebApp(Profile* profile, const GURL& start_url) { apps::AppRegistryCache& cache = apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); - std::vector<apps::mojom::AppPtr> deltas; - deltas.push_back(MakeApp( - web_app::GenerateAppId(/*manifest_id=*/absl::nullopt, start_url), - apps::mojom::AppType::kWeb, start_url.spec(), - apps::mojom::Readiness::kReady, apps::mojom::InstallReason::kSync)); - cache.OnApps(std::move(deltas), apps::mojom::AppType::kWeb, - /*should_notify_initialized=*/true); + std::vector<apps::AppPtr> deltas; + deltas.push_back( + MakeApp(web_app::GenerateAppId(/*manifest_id=*/absl::nullopt, start_url), + apps::AppType::kWeb, start_url.spec(), apps::Readiness::kReady, + apps::InstallReason::kSync)); + if (base::FeatureList::IsEnabled(apps::kAppServiceOnAppUpdateWithoutMojom)) { + cache.OnApps(std::move(deltas), apps::AppType::kWeb, + /*should_notify_initialized=*/true); + } else { + std::vector<apps::mojom::AppPtr> mojom_deltas; + mojom_deltas.push_back(apps::ConvertAppToMojomApp(deltas[0])); + cache.OnApps(std::move(mojom_deltas), apps::mojom::AppType::kWeb, + /*should_notify_initialized=*/true); + } } } // namespace
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc index 368ff9c..8afcf50 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc
@@ -60,18 +60,18 @@ DiceWebSigninInterceptHandler::~DiceWebSigninInterceptHandler() = default; void DiceWebSigninInterceptHandler::RegisterMessages() { - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "accept", base::BindRepeating(&DiceWebSigninInterceptHandler::HandleAccept, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "cancel", base::BindRepeating(&DiceWebSigninInterceptHandler::HandleCancel, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "guest", base::BindRepeating(&DiceWebSigninInterceptHandler::HandleGuest, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "pageLoaded", base::BindRepeating(&DiceWebSigninInterceptHandler::HandlePageLoaded, base::Unretained(this))); @@ -115,23 +115,25 @@ return bubble_parameters_.intercepted_account; } -void DiceWebSigninInterceptHandler::HandleAccept(const base::ListValue* args) { +void DiceWebSigninInterceptHandler::HandleAccept( + const base::Value::List& args) { if (callback_) std::move(callback_).Run(SigninInterceptionUserChoice::kAccept); } -void DiceWebSigninInterceptHandler::HandleCancel(const base::ListValue* args) { +void DiceWebSigninInterceptHandler::HandleCancel( + const base::Value::List& args) { if (callback_) std::move(callback_).Run(SigninInterceptionUserChoice::kDecline); } -void DiceWebSigninInterceptHandler::HandleGuest(const base::ListValue* args) { +void DiceWebSigninInterceptHandler::HandleGuest(const base::Value::List& args) { if (callback_) std::move(callback_).Run(SigninInterceptionUserChoice::kGuest); } void DiceWebSigninInterceptHandler::HandlePageLoaded( - const base::ListValue* args) { + const base::Value::List& args) { AllowJavascript(); // Update the account info and the images. @@ -153,7 +155,8 @@ if (primary_account().given_name.empty()) bubble_parameters_.primary_account.given_name = primary_account().email; - const base::Value& callback_id = args->GetListDeprecated()[0]; + DCHECK(!args.empty()); + const base::Value& callback_id = args[0]; ResolveJavascriptCallback(callback_id, GetInterceptionParametersValue()); }
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h index be7296a..4f8cf497 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h
@@ -16,10 +16,6 @@ #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/identity_manager.h" -namespace base { -class ListValue; -} - // WebUI message handler for the Dice web signin intercept bubble. class DiceWebSigninInterceptHandler : public content::WebUIMessageHandler, public signin::IdentityManager::Observer { @@ -46,10 +42,10 @@ const AccountInfo& primary_account(); const AccountInfo& intercepted_account(); - void HandleAccept(const base::ListValue* args); - void HandleCancel(const base::ListValue* args); - void HandleGuest(const base::ListValue* args); - void HandlePageLoaded(const base::ListValue* args); + void HandleAccept(const base::Value::List& args); + void HandleCancel(const base::Value::List& args); + void HandleGuest(const base::Value::List& args); + void HandlePageLoaded(const base::Value::List& args); // Gets the values sent to javascript. base::Value GetAccountInfoValue(const AccountInfo& info);
diff --git a/chrome/browser/ui/webui/signin/profile_customization_handler.cc b/chrome/browser/ui/webui/signin/profile_customization_handler.cc index 6b4ff6e..e3eb6ec 100644 --- a/chrome/browser/ui/webui/signin/profile_customization_handler.cc +++ b/chrome/browser/ui/webui/signin/profile_customization_handler.cc
@@ -40,11 +40,11 @@ void ProfileCustomizationHandler::RegisterMessages() { profile_path_ = Profile::FromWebUI(web_ui())->GetPath(); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "initialized", base::BindRepeating(&ProfileCustomizationHandler::HandleInitialized, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "done", base::BindRepeating(&ProfileCustomizationHandler::HandleDone, base::Unretained(this))); } @@ -85,17 +85,16 @@ } void ProfileCustomizationHandler::HandleInitialized( - const base::ListValue* args) { - CHECK_EQ(1u, args->GetListDeprecated().size()); + const base::Value::List& args) { + CHECK_EQ(1u, args.size()); AllowJavascript(); - const base::Value& callback_id = args->GetListDeprecated()[0]; + const base::Value& callback_id = args[0]; ResolveJavascriptCallback(callback_id, GetProfileInfoValue()); } -void ProfileCustomizationHandler::HandleDone(const base::ListValue* args) { - CHECK_EQ(1u, args->GetListDeprecated().size()); - std::u16string profile_name = - base::UTF8ToUTF16(args->GetListDeprecated()[0].GetString()); +void ProfileCustomizationHandler::HandleDone(const base::Value::List& args) { + CHECK_EQ(1u, args.size()); + std::u16string profile_name = base::UTF8ToUTF16(args[0].GetString()); base::TrimWhitespace(profile_name, base::TRIM_ALL, &profile_name); DCHECK(!profile_name.empty());
diff --git a/chrome/browser/ui/webui/signin/profile_customization_handler.h b/chrome/browser/ui/webui/signin/profile_customization_handler.h index 733581d..2386414 100644 --- a/chrome/browser/ui/webui/signin/profile_customization_handler.h +++ b/chrome/browser/ui/webui/signin/profile_customization_handler.h
@@ -12,10 +12,6 @@ #include "base/scoped_observation.h" #include "chrome/browser/profiles/profile_attributes_storage.h" -namespace base { -class ListValue; -} - class ProfileAttributesEntry; // WebUI message handler for the profile customization bubble. @@ -46,8 +42,8 @@ private: // Handlers for messages from javascript. - void HandleInitialized(const base::ListValue* args); - void HandleDone(const base::ListValue* args); + void HandleInitialized(const base::Value::List& args); + void HandleDone(const base::Value::List& args); // Sends an updated profile info (avatar and colors) to the WebUI. // `profile_path` is the path of the profile being updated, this function does
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_handler.cc b/chrome/browser/ui/webui/signin/signin_reauth_handler.cc index d1a7606..eba8fe7 100644 --- a/chrome/browser/ui/webui/signin/signin_reauth_handler.cc +++ b/chrome/browser/ui/webui/signin/signin_reauth_handler.cc
@@ -25,13 +25,13 @@ SigninReauthHandler::~SigninReauthHandler() = default; void SigninReauthHandler::RegisterMessages() { - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "initialize", base::BindRepeating(&SigninReauthHandler::HandleInitialize, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "confirm", base::BindRepeating(&SigninReauthHandler::HandleConfirm, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "cancel", base::BindRepeating(&SigninReauthHandler::HandleCancel, base::Unretained(this))); } @@ -61,27 +61,25 @@ FireWebUIListener("reauth-type-determined"); } -void SigninReauthHandler::HandleInitialize(const base::ListValue* args) { +void SigninReauthHandler::HandleInitialize(const base::Value::List& args) { AllowJavascript(); } -void SigninReauthHandler::HandleConfirm(const base::ListValue* args) { +void SigninReauthHandler::HandleConfirm(const base::Value::List& args) { if (controller_) controller_->OnReauthConfirmed(BuildConsent(args)); } -void SigninReauthHandler::HandleCancel(const base::ListValue* args) { +void SigninReauthHandler::HandleCancel(const base::Value::List& args) { if (controller_) controller_->OnReauthDismissed(); } sync_pb::UserConsentTypes::AccountPasswordsConsent -SigninReauthHandler::BuildConsent(const base::ListValue* args) const { - CHECK_EQ(2U, args->GetListDeprecated().size()); - base::Value::ConstListView consent_description = - args->GetListDeprecated()[0].GetListDeprecated(); - const std::string& consent_confirmation = - args->GetListDeprecated()[1].GetString(); +SigninReauthHandler::BuildConsent(const base::Value::List& args) const { + CHECK_EQ(2U, args.size()); + base::Value::ConstListView consent_description = args[0].GetListDeprecated(); + const std::string& consent_confirmation = args[1].GetString(); // The strings returned by the WebUI are not free-form, they must belong into // a pre-determined set of strings (stored in |string_to_grd_id_map_|). As
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_handler.h b/chrome/browser/ui/webui/signin/signin_reauth_handler.h index f2fb66b..fd1b53e 100644 --- a/chrome/browser/ui/webui/signin/signin_reauth_handler.h +++ b/chrome/browser/ui/webui/signin/signin_reauth_handler.h
@@ -11,10 +11,6 @@ #include "chrome/browser/ui/signin_reauth_view_controller.h" #include "content/public/browser/web_ui_message_handler.h" -namespace base { -class ListValue; -} - // WebUI message handler for the signin reauth dialog. class SigninReauthHandler : public content::WebUIMessageHandler, public SigninReauthViewController::Observer { @@ -38,20 +34,20 @@ protected: // Handles "initialize" message from the page. No arguments. - virtual void HandleInitialize(const base::ListValue* args); + virtual void HandleInitialize(const base::Value::List& args); // Handles "confirm" message from the page. No arguments. // This message is sent when the user confirms that they want complete the // reauth flow. - virtual void HandleConfirm(const base::ListValue* args); + virtual void HandleConfirm(const base::Value::List& args); // Handles "cancel" message from the page. No arguments. This message is sent // when the user cancels the reauth flow. - virtual void HandleCancel(const base::ListValue* args); + virtual void HandleCancel(const base::Value::List& args); private: sync_pb::UserConsentTypes::AccountPasswordsConsent BuildConsent( - const base::ListValue* args) const; + const base::Value::List& args) const; // May be null if |controller_| gets destroyed earlier than |this|. raw_ptr<SigninReauthViewController> controller_;
diff --git a/chrome/browser/ui/webui/welcome/bookmark_handler.cc b/chrome/browser/ui/webui/welcome/bookmark_handler.cc index da566685..b508780 100644 --- a/chrome/browser/ui/webui/welcome/bookmark_handler.cc +++ b/chrome/browser/ui/webui/welcome/bookmark_handler.cc
@@ -17,29 +17,28 @@ BookmarkHandler::~BookmarkHandler() {} void BookmarkHandler::RegisterMessages() { - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "toggleBookmarkBar", base::BindRepeating(&BookmarkHandler::HandleToggleBookmarkBar, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "isBookmarkBarShown", base::BindRepeating(&BookmarkHandler::HandleIsBookmarkBarShown, base::Unretained(this))); } -void BookmarkHandler::HandleToggleBookmarkBar(const base::ListValue* args) { - const auto& list = args->GetListDeprecated(); - CHECK(!list.empty()); - const bool show = list[0].GetBool(); +void BookmarkHandler::HandleToggleBookmarkBar(const base::Value::List& args) { + CHECK(!args.empty()); + const bool show = args[0].GetBool(); prefs_->SetBoolean(bookmarks::prefs::kShowBookmarkBar, show); } -void BookmarkHandler::HandleIsBookmarkBarShown(const base::ListValue* args) { +void BookmarkHandler::HandleIsBookmarkBarShown(const base::Value::List& args) { AllowJavascript(); - CHECK_EQ(1U, args->GetListDeprecated().size()); - const base::Value& callback_id = args->GetListDeprecated()[0]; + CHECK_EQ(1U, args.size()); + const base::Value& callback_id = args[0]; ResolveJavascriptCallback( callback_id,
diff --git a/chrome/browser/ui/webui/welcome/bookmark_handler.h b/chrome/browser/ui/webui/welcome/bookmark_handler.h index 7f0b2432..421b5fe 100644 --- a/chrome/browser/ui/webui/welcome/bookmark_handler.h +++ b/chrome/browser/ui/webui/welcome/bookmark_handler.h
@@ -26,8 +26,8 @@ void RegisterMessages() override; // Callbacks for JS APIs. - void HandleToggleBookmarkBar(const base::ListValue* args); - void HandleIsBookmarkBarShown(const base::ListValue* args); + void HandleToggleBookmarkBar(const base::Value::List& args); + void HandleIsBookmarkBarShown(const base::Value::List& args); private: // Weak reference.
diff --git a/chrome/browser/ui/webui/welcome/google_apps_handler.cc b/chrome/browser/ui/webui/welcome/google_apps_handler.cc index 02c0cda..4b4989bd 100644 --- a/chrome/browser/ui/webui/welcome/google_apps_handler.cc +++ b/chrome/browser/ui/webui/welcome/google_apps_handler.cc
@@ -92,21 +92,21 @@ GoogleAppsHandler::~GoogleAppsHandler() {} void GoogleAppsHandler::RegisterMessages() { - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "cacheGoogleAppIcon", base::BindRepeating(&GoogleAppsHandler::HandleCacheGoogleAppIcon, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "getGoogleAppsList", base::BindRepeating(&GoogleAppsHandler::HandleGetGoogleAppsList, base::Unretained(this))); } -void GoogleAppsHandler::HandleCacheGoogleAppIcon(const base::ListValue* args) { - const auto& list = args->GetListDeprecated(); - CHECK_GE(list.size(), 1u); - int app_id = list[0].GetInt(); +void GoogleAppsHandler::HandleCacheGoogleAppIcon( + const base::Value::List& args) { + CHECK_GE(args.size(), 1u); + int app_id = args[0].GetInt(); const BookmarkItem* selectedApp = nullptr; for (const auto& google_app : google_apps_) { @@ -130,10 +130,10 @@ gfx::Size(kGoogleAppIconSize, kGoogleAppIconSize)); } -void GoogleAppsHandler::HandleGetGoogleAppsList(const base::ListValue* args) { +void GoogleAppsHandler::HandleGetGoogleAppsList(const base::Value::List& args) { AllowJavascript(); - CHECK_EQ(1U, args->GetListDeprecated().size()); - const base::Value& callback_id = args->GetListDeprecated()[0]; + CHECK_EQ(1U, args.size()); + const base::Value& callback_id = args[0]; ResolveJavascriptCallback( callback_id, BookmarkItemsToListValue(google_apps_.data(), google_apps_.size()));
diff --git a/chrome/browser/ui/webui/welcome/google_apps_handler.h b/chrome/browser/ui/webui/welcome/google_apps_handler.h index 725d6f0c..245a87c 100644 --- a/chrome/browser/ui/webui/welcome/google_apps_handler.h +++ b/chrome/browser/ui/webui/welcome/google_apps_handler.h
@@ -37,8 +37,8 @@ void RegisterMessages() override; // Callbacks for JS APIs. - void HandleCacheGoogleAppIcon(const base::ListValue* args); - void HandleGetGoogleAppsList(const base::ListValue* args); + void HandleCacheGoogleAppIcon(const base::Value::List& args); + void HandleGetGoogleAppsList(const base::Value::List& args); private: std::vector<BookmarkItem> google_apps_;
diff --git a/chrome/browser/ui/webui/welcome/ntp_background_handler.cc b/chrome/browser/ui/webui/welcome/ntp_background_handler.cc index 4a95e47c..cb603f9 100644 --- a/chrome/browser/ui/webui/welcome/ntp_background_handler.cc +++ b/chrome/browser/ui/webui/welcome/ntp_background_handler.cc
@@ -35,32 +35,33 @@ NtpBackgroundHandler::~NtpBackgroundHandler() {} void NtpBackgroundHandler::RegisterMessages() { - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "clearBackground", base::BindRepeating(&NtpBackgroundHandler::HandleClearBackground, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "getBackgrounds", base::BindRepeating(&NtpBackgroundHandler::HandleGetBackgrounds, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "setBackground", base::BindRepeating(&NtpBackgroundHandler::HandleSetBackground, base::Unretained(this))); } -void NtpBackgroundHandler::HandleClearBackground(const base::ListValue* args) { +void NtpBackgroundHandler::HandleClearBackground( + const base::Value::List& args) { auto* service = NtpCustomBackgroundServiceFactory::GetForProfile( Profile::FromWebUI(web_ui())); service->ResetCustomBackgroundInfo(); } -void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) { +void NtpBackgroundHandler::HandleGetBackgrounds(const base::Value::List& args) { AllowJavascript(); - CHECK_EQ(1U, args->GetListDeprecated().size()); - const base::Value& callback_id = args->GetListDeprecated()[0]; + CHECK_EQ(1U, args.size()); + const base::Value& callback_id = args[0]; base::Value::List list_value; std::array<GURL, kNtpBackgroundsCount> NtpBackgrounds = GetNtpBackgrounds(); @@ -121,10 +122,9 @@ ResolveJavascriptCallback(callback_id, base::Value(std::move(list_value))); } -void NtpBackgroundHandler::HandleSetBackground(const base::ListValue* args) { - const auto& list = args->GetListDeprecated(); - CHECK_EQ(1U, list.size()); - int background_index = list[0].GetInt(); +void NtpBackgroundHandler::HandleSetBackground(const base::Value::List& args) { + CHECK_EQ(1U, args.size()); + int background_index = args[0].GetInt(); std::array<GURL, kNtpBackgroundsCount> NtpBackgrounds = GetNtpBackgrounds(); auto* service = NtpCustomBackgroundServiceFactory::GetForProfile(
diff --git a/chrome/browser/ui/webui/welcome/ntp_background_handler.h b/chrome/browser/ui/webui/welcome/ntp_background_handler.h index 7bbfaa1..b911cd8 100644 --- a/chrome/browser/ui/webui/welcome/ntp_background_handler.h +++ b/chrome/browser/ui/webui/welcome/ntp_background_handler.h
@@ -22,9 +22,9 @@ void RegisterMessages() override; // Callbacks for JS APIs. - void HandleClearBackground(const base::ListValue* args); - void HandleGetBackgrounds(const base::ListValue* args); - void HandleSetBackground(const base::ListValue* args); + void HandleClearBackground(const base::Value::List& args); + void HandleGetBackgrounds(const base::Value::List& args); + void HandleSetBackground(const base::Value::List& args); }; } // namespace welcome
diff --git a/chrome/browser/ui/webui/welcome/welcome_handler.cc b/chrome/browser/ui/webui/welcome/welcome_handler.cc index 2ea1abd..3ae8399 100644 --- a/chrome/browser/ui/webui/welcome/welcome_handler.cc +++ b/chrome/browser/ui/webui/welcome/welcome_handler.cc
@@ -52,7 +52,7 @@ } // Handles backend events necessary when user clicks "Sign in." -void WelcomeHandler::HandleActivateSignIn(const base::ListValue* args) { +void WelcomeHandler::HandleActivateSignIn(const base::Value::List& args) { result_ = WelcomeResult::STARTED_SIGN_IN; base::RecordAction(base::UserMetricsAction("WelcomePage_SignInClicked")); @@ -65,8 +65,8 @@ GoToNewTabPage(); } else { GURL redirect_url = GURL::EmptyGURL(); - if (args->GetListDeprecated().size() == 1U) { - const std::string& url_string = args->GetListDeprecated()[0].GetString(); + if (args.size() == 1U) { + const std::string& url_string = args[0].GetString(); redirect_url = GURL(url_string); DCHECK(redirect_url.is_valid()); } @@ -79,7 +79,7 @@ } // Handles backend events necessary when user clicks "Get started." -void WelcomeHandler::HandleUserDecline(const base::ListValue* args) { +void WelcomeHandler::HandleUserDecline(const base::Value::List& args) { result_ = WelcomeResult::DECLINED_SIGN_IN; GoToNewTabPage(); } @@ -91,11 +91,11 @@ // constructor, because web_ui hasn't loaded yet at that time. is_redirected_welcome_impression_ = isValidRedirectUrl(); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "handleActivateSignIn", base::BindRepeating(&WelcomeHandler::HandleActivateSignIn, base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( + web_ui()->RegisterMessageCallback( "handleUserDecline", base::BindRepeating(&WelcomeHandler::HandleUserDecline, base::Unretained(this)));
diff --git a/chrome/browser/ui/webui/welcome/welcome_handler.h b/chrome/browser/ui/webui/welcome/welcome_handler.h index d0bfd78..48e332ee 100644 --- a/chrome/browser/ui/webui/welcome/welcome_handler.h +++ b/chrome/browser/ui/webui/welcome/welcome_handler.h
@@ -45,8 +45,8 @@ WELCOME_RESULT_MAX }; - void HandleActivateSignIn(const base::ListValue* args); - void HandleUserDecline(const base::ListValue* args); + void HandleActivateSignIn(const base::Value::List& args); + void HandleUserDecline(const base::Value::List& args); void GoToNewTabPage(); void GoToURL(GURL url); bool isValidRedirectUrl();
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 607781f..88648ef 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1648133989-84788d19695d4ddcb485bf65f608066e5f6d319d.profdata +chrome-win32-main-1648155422-141ba16e22bbbd8aa760dfc86e2f4a05a810e7f1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index a18a8698..f066b11 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1648144804-ce09408549800609c8c3db07d2b084d099da417c.profdata +chrome-win64-main-1648155422-19d2500873166865703fbc30aa2ee02d166c26d0.profdata
diff --git a/chrome/installer/util/google_update_util.cc b/chrome/installer/util/google_update_util.cc index 063d81c..babe91f 100644 --- a/chrome/installer/util/google_update_util.cc +++ b/chrome/installer/util/google_update_util.cc
@@ -88,13 +88,8 @@ base::LaunchOptions launch_options; launch_options.force_breakaway_from_job_ = true; - - if (base::win::UserAccountControlIsEnabled()) { - launch_options.elevated = true; - base::LaunchElevatedProcess(cmd, launch_options); - } else { - base::LaunchProcess(cmd, launch_options); - } + launch_options.elevated = base::win::UserAccountControlIsEnabled(); + base::LaunchProcess(cmd, launch_options); } } // namespace google_update
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 66376f1..6ba85101 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1178,6 +1178,7 @@ "//chrome/browser/resource_coordinator:tab_metrics_event_proto", "//chrome/browser/safe_browsing:verdict_cache_manager_factory", "//chrome/browser/sharing/proto", + "//chrome/browser/ui/color:color_headers", "//chrome/browser/ui/tabs:tab_enums", "//chrome/browser/ui/webui/history_clusters:mojo_bindings", "//chrome/browser/web_applications:browser_tests", @@ -2671,16 +2672,15 @@ "//third_party/liblouis/wasm/liblouis_wrapper_browsertest.cc", ] deps += [ "//chrome/browser/chromeos" ] - data_deps += [ "//third_party/liblouis:liblouis_test_data" ] + data_deps += [ + "//ppapi/native_client:irt", + "//third_party/liblouis:liblouis_test_data", + ] - # TODO(https://crbug.com/1299021): Implement building these NaCl - # targets as ARM32 when Chrome is built for ARM64 (for Linux/Chrome - # OS). + # TODO(https://crbug.com/1299021): Implement building this NaCl target + # as ARM32 when Chrome is built for ARM64 (for Linux/Chrome OS). if (target_cpu != "arm64") { - data_deps += [ - "//components/nacl/loader:nacl_helper", - "//ppapi/native_client:irt", - ] + data_deps += [ "//components/nacl/loader:nacl_helper" ] } }
diff --git a/chrome/test/data/nacl/BUILD.gn b/chrome/test/data/nacl/BUILD.gn index 31d5213..da8406ac 100644 --- a/chrome/test/data/nacl/BUILD.gn +++ b/chrome/test/data/nacl/BUILD.gn
@@ -6,10 +6,11 @@ import("//build/config/features.gni") import("//build/config/nacl/config.gni") import("//components/nacl/features.gni") +import("//components/nacl/target_cpu.gni") import("//ppapi/native_client/nacl_test_data.gni") group("nacl") { - newlib = "//build/toolchain/nacl:clang_newlib_${target_cpu}" + newlib = "//build/toolchain/nacl:clang_newlib_${nacl_target_cpu}" pnacl = "//build/toolchain/nacl:newlib_pnacl" data_deps = [ ":exit_status_test($newlib)", @@ -56,7 +57,7 @@ ":sysconf_nprocessors_onln_test($newlib)", ":sysconf_nprocessors_onln_test($pnacl)", ] - if (target_cpu != "arm") { + if (nacl_target_cpu != "arm") { data_deps += [ ":partly_invalid($newlib)" ] } if (target_cpu != "mipsel" && !is_mac && !is_win) { @@ -64,7 +65,7 @@ # The GlibC toolchain is based on gcc, which no longer runs on mac; # it still runs on Windows but is flaky due to its use of cygwin, so also # disable it there. - glibc = "//build/toolchain/nacl:glibc_${target_cpu}" + glibc = "//build/toolchain/nacl:glibc_${nacl_target_cpu}" data_deps += [ ":exit_status_test($glibc)", ":extension_validation_cache($glibc)", @@ -83,11 +84,6 @@ ":sysconf_nprocessors_onln_test($glibc)", ] } - # TODO(https://crbug.com/1299021): Implement building these NaCl targets as - # ARM32 when Chrome is built for ARM64 (for Linux/Chrome OS). - if (target_cpu == "arm64") { - data_deps = [] - } } if (is_nacl) {
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js index 2f54a9a..1a47724 100644 --- a/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js +++ b/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {fakeHelpContentList} from 'chrome://os-feedback/fake_data.js'; -import {HelpContentList, HelpContentType} from 'chrome://os-feedback/feedback_types.js'; +import {fakeHelpContentList, fakePopularHelpContentList} from 'chrome://os-feedback/fake_data.js'; +import {HelpContentList, HelpContentType, SearchResult} from 'chrome://os-feedback/feedback_types.js'; import {HelpContentElement} from 'chrome://os-feedback/help_content.js'; import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; @@ -22,15 +22,26 @@ helpContentElement = null; }); - /** @param {!HelpContentList} contentList */ - function initializeHelpContentElement(contentList) { + /** + * @param {!HelpContentList} contentList + * @param {boolean} isQueryEmpty + * @param {boolean} isPopularContent + * + */ + function initializeHelpContentElement( + contentList, isQueryEmpty, isPopularContent) { assertFalse(!!helpContentElement); helpContentElement = /** @type {!HelpContentElement} */ ( document.createElement('help-content')); assertTrue(!!helpContentElement); - helpContentElement.helpContentList = contentList; + helpContentElement.searchResult = { + contentList: contentList, + isQueryEmpty: isQueryEmpty, + isPopularContent: isPopularContent + }; + document.body.appendChild(helpContentElement); return flushTasks(); @@ -62,14 +73,55 @@ } } - /** Test that expected html elements are in the element. */ - test('HelpContentLoaded', async () => { - await initializeHelpContentElement(fakeHelpContentList); + // Verify that all popular help content are displayed. + function verifyPopularHelpContent() { + assertEquals(2, getElement('dom-repeat').items.length); + const helpLinks = + helpContentElement.shadowRoot.querySelectorAll('.help-item a'); + assertEquals(2, helpLinks.length); + + // Verify the help links are displayed in order with correct title, url and + // icon. + assertEquals('fake article', helpLinks[0].innerText); + assertEquals( + 'https://support.google.com/chromebook/?q=article', helpLinks[0].href); + verifyIconName(helpLinks[0], fakePopularHelpContentList[0].contentType); + + assertEquals('fake forum', helpLinks[1].innerText); + assertEquals( + 'https://support.google.com/chromebook/?q=forum', helpLinks[1].href); + verifyIconName(helpLinks[1], fakePopularHelpContentList[1].contentType); + } + + /** + * Test that expected HTML elements are in the element when query is empty. + */ + test('ColdStart', async () => { + await initializeHelpContentElement( + fakePopularHelpContentList, /* isQueryEmpty= */ true, + /* isPopularContent= */ true); // Verify the title is in the helpContentElement. const title = getElement('#helpContentLabel'); assertTrue(!!title); - assertEquals('Suggested help content:', title.textContent); + assertEquals('Popular help content', title.textContent); + + verifyPopularHelpContent(); + }); + + /** + * Test that expected HTML elements are in the element when the query is not + * empty and there are matches. + */ + test('SuggestedHelpContentLoaded', async () => { + await initializeHelpContentElement( + fakeHelpContentList, /* isQueryEmpty =*/ false, + /* isPopularContent =*/ false); + + // Verify the title is in the helpContentElement. + const title = getElement('#helpContentLabel'); + assertTrue(!!title); + assertEquals('Suggested help content', title.textContent); // Verify the help content is populated with correct number of items. assertEquals(5, getElement('dom-repeat').items.length); @@ -77,8 +129,8 @@ helpContentElement.shadowRoot.querySelectorAll('.help-item a'); assertEquals(5, helpLinks.length); - // Verify the help links are displayed in order with correct title and - // url. + // Verify the help links are displayed in order with correct title, url and + // icon. assertEquals('Fix connection problems', helpLinks[0].innerText); assertEquals( 'https://support.google.com/chromebook/?q=6318213', helpLinks[0].href); @@ -111,4 +163,23 @@ 'https://support.google.com/chromebook/?q=22864239', helpLinks[4].href); verifyIconName(helpLinks[4], fakeHelpContentList[4].contentType); }); + + + /** + * Test that expected HTML elements are in the element when query is not empty + * and there are no matches. + */ + test('NoMatches', async () => { + await initializeHelpContentElement( + fakePopularHelpContentList, /* isQueryEmpty= */ false, + /* isPopularContent= */ true); + + // Verify the title is in the helpContentElement. + const title = getElement('#helpContentLabel'); + assertTrue(!!title); + assertEquals( + 'No matched results, see popular help content', title.textContent); + + verifyPopularHelpContent(); + }); }
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js index f6b1c3c..f1c04c0 100644 --- a/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js +++ b/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js
@@ -142,7 +142,9 @@ }); const data = { - response: fakeSearchResponse, + contentList: fakeSearchResponse.results, + isQueryEmpty: true, + isPopularContent: true }; iframe.contentWindow.postMessage(data, OS_FEEDBACK_UNTRUSTED_ORIGIN);
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn index 79976cb..829b362 100644 --- a/chrome/test/data/webui/settings/BUILD.gn +++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -137,7 +137,7 @@ "system_page_tests.ts", ] } else { - non_preprocessed_files += [ "passwords_section_test_cros.js" ] + non_preprocessed_files += [ "passwords_section_test_cros.ts" ] } if (!is_mac && !is_chromeos_ash) {
diff --git a/chrome/test/data/webui/settings/passwords_section_test_cros.js b/chrome/test/data/webui/settings/passwords_section_test_cros.js deleted file mode 100644 index 9c3d8ff..0000000 --- a/chrome/test/data/webui/settings/passwords_section_test_cros.js +++ /dev/null
@@ -1,320 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Tests of CrOS specific saved password settings. Note that - * although these tests for only for CrOS, they are testing a CrOS specific - * aspects of the implementation of a browser feature rather than an entirely - * native CrOS feature. See http://crbug.com/917178 for more detail. - */ - -// clang-format off -import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {BlockingRequestManager} from 'chrome://settings/lazy_load.js'; -import {MultiStorePasswordUiEntry, PasswordManagerImpl} from 'chrome://settings/settings.js'; -import {MockTimer} from 'chrome://test/mock_timer.js'; -import {createPasswordEntry, PasswordSectionElementFactory} from './passwords_and_autofill_fake_data.js'; -import {runCancelExportTest, runExportFlowErrorRetryTest, runExportFlowErrorTest, runExportFlowFastTest, runExportFlowSlowTest, runFireCloseEventAfterExportCompleteTest,runStartExportTest} from './passwords_export_test.js'; -import {TestPasswordManagerProxy} from './test_password_manager_proxy.js'; - -// clang-format on - -suite('PasswordsSection_Cros', function() { - /** - * Promise resolved when an auth token request is made. - * @type {Promise} - */ - let requestPromise = null; - - /** - * Promise resolved when a saved password is retrieved. - * @type {Promise} - */ - let passwordPromise = null; - - /** - * Implementation of PasswordSectionElementFactory with parameters that help - * tests to track auth token and saved password requests. - */ - class CrosPasswordSectionElementFactory extends - PasswordSectionElementFactory { - /** - * @param {HTMLDocument} document The test's |document| object. - * @param {request: Function} tokenRequestManager Fake for - * BlockingRequestManager provided to subelements of password-section - * that normally have their tokenRequestManager property bound to the - * password section's tokenRequestManager_ property. Note: - * Tests of the password-section element need to use the full - * implementation, which is created by default when the element is - * attached. - * @param {MultiStorePasswordUiEntry} passwordItem - */ - constructor(document, tokenRequestManager, passwordItem) { - super(document); - this.tokenRequestManager = tokenRequestManager; - this.passwordItem = passwordItem; - } - - /** @override */ - createPasswordsSection(passwordManager) { - return super.createPasswordsSection(passwordManager, [], []); - } - - /** @override */ - createPasswordEditDialog() { - return this.decorateShowPasswordElement_('password-edit-dialog'); - } - - /** @override */ - createPasswordListItem() { - return this.decorateShowPasswordElement_('password-list-item'); - } - - /** @override */ - createExportPasswordsDialog(passwordManager, overrideRequestManager) { - const dialog = super.createExportPasswordsDialog(passwordManager); - dialog.tokenRequestManager = new BlockingRequestManager(); - return overrideRequestManager ? - Object.assign( - dialog, {tokenRequestManager: this.tokenRequestManager}) : - dialog; - } - - /** - * Creates an element with ShowPasswordBehavior, decorates it with - * with the testing data provided in the constructor, and attaches it to - * |this.document|. - * @param {string} showPasswordElementName Tag name of a Polymer element - * with ShowPasswordBehavior. - * @return {!HTMLElement} Element decorated with test data. - */ - decorateShowPasswordElement_(showPasswordElementName) { - const element = this.document.createElement(showPasswordElementName); - element.item = this.passwordItem; - element.tokenRequestManager = this.tokenRequestManager; - this.document.body.appendChild(element); - flush(); - return element; - } - } - - function fail() { - throw new Error(); - } - - /** @type {TestPasswordManagerProxy} */ - let passwordManager = null; - - /** @type {CrosPasswordSectionElementFactory} */ - let elementFactory = null; - - setup(function() { - PolymerTest.clearBody(); - // Override the PasswordManagerImpl for testing. - passwordManager = new TestPasswordManagerProxy(); - PasswordManagerImpl.setInstance(passwordManager); - - // Define a fake BlockingRequestManager to track when a token request - // comes in by resolving requestPromise. - let requestManager; - requestPromise = new Promise(resolve => { - requestManager = {request: resolve}; - }); - - /** - * @type {ShowPasswordBehavior.UiEntryWithPassword} Password item (i.e. - * entry with password text) that overrides the password property - * with get/set to track receipt of a saved password and make that - * information available by resolving |passwordPromise|. - */ - let passwordItem; - passwordPromise = new Promise(resolve => { - passwordItem = { - entry: createPasswordEntry(), - set password(newPassword) { - if (newPassword && newPassword !== this.password_) { - resolve(newPassword); - } - this.password_ = newPassword; - }, - get password() { - return this.password_; - } - }; - }); - - elementFactory = new CrosPasswordSectionElementFactory( - document, requestManager, passwordItem); - }); - - // Note (rbpotter): this passes locally, but may still be flaky (see - // https://www.crbug.com/1021474) - test.skip('export passwords button requests auth token', function() { - passwordPromise.then(fail); - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, true); - exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click(); - return requestPromise; - }); - - // Note (rbpotter): this passes locally, but may still be flaky (see - // https://www.crbug.com/1021474) - test.skip( - 'list-item does not request token if it gets password to show', - function() { - requestPromise.then(fail); - const passwordListItem = elementFactory.createPasswordListItem(); - passwordManager.setPlaintextPassword('password'); - passwordListItem.shadowRoot.querySelector('#showPasswordButton') - .click(); - return passwordPromise; - }); - - // Note (rbpotter): this fails locally, possibly out of date - test.skip( - 'list-item requests token if it does not get password to show', - function() { - passwordPromise.then(fail); - const passwordListItem = elementFactory.createPasswordListItem(); - passwordManager.setPlaintextPassword(''); - passwordListItem.shadowRoot.querySelector('#showPasswordButton') - .click(); - return requestPromise; - }); - - // TODO(crbug.com/1274569): add test for edit-dialog requesting token when - // switching from ADD to EDIT mode when other tests are fixed. - - // Note (rbpotter): this passes locally, but may still be flaky (see - // https://www.crbug.com/1021474) - test.skip( - 'edit-dialog does not request token if it gets password to show', - function() { - requestPromise.then(fail); - const passwordEditDialog = elementFactory.createPasswordEditDialog(); - passwordManager.setPlaintextPassword('password'); - passwordEditDialog.shadowRoot.querySelector('#showPasswordButton') - .click(); - return passwordPromise; - }); - - // Note (rbpotter): this fails locally, possibly out of date - test.skip( - 'edit-dialog requests token if it does not get password to show', - function() { - passwordPromise.then(fail); - const passwordEditDialog = elementFactory.createPasswordEditDialog(); - passwordManager.setPlaintextPassword(''); - passwordEditDialog.shadowRoot.querySelector('#showPasswordButton') - .click(); - return requestPromise; - }); - - // Note (rbpotter): this passes locally, but may still be flaky (see - // https://www.crbug.com/1021474) - test.skip('password-prompt-dialog appears on auth token request', function() { - const passwordsSection = - elementFactory.createPasswordsSection(passwordManager); - assertTrue(!passwordsSection.shadowRoot.querySelector( - 'settings-password-prompt-dialog')); - passwordsSection.tokenRequestManager_.request(fail); - flush(); - assertTrue(!!passwordsSection.shadowRoot.querySelector( - 'settings-password-prompt-dialog')); - }); - - // Note (rbpotter): this fails locally, possibly out of date - test.skip( - 'password-section resolves request on auth token receipt', - function(done) { - const passwordsSection = - elementFactory.createPasswordsSection(passwordManager); - passwordsSection.tokenRequestManager_.request(done); - passwordsSection.authToken_ = 'auth token'; - }); - - // Note (rbpotter): this fails locally, possibly out of date - test.skip( - 'password-section only triggers callback on most recent request', - function(done) { - const passwordsSection = - elementFactory.createPasswordsSection(passwordManager); - // Make request that SHOULD NOT be resolved. - passwordsSection.tokenRequestManager_.request(fail); - // Make request that should be resolved. - passwordsSection.tokenRequestManager_.request(done); - passwordsSection.authToken_ = 'auth token'; - }); - - // Note (rbpotter): this fails locally, possibly out of date - test.skip( - 'user is not prompted for password if they cannot enter it', - function(done) { - loadTimeData.overrideValues({userCannotManuallyEnterPassword: true}); - const passwordsSection = document.createElement('passwords-section'); - document.body.appendChild(passwordsSection); - flush(); - assertTrue(!passwordsSection.shadowRoot.querySelector( - 'settings-password-prompt-dialog')); - passwordsSection.tokenRequestManager_.request(() => { - flush(); - assertTrue(!passwordsSection.shadowRoot.querySelector( - 'settings-password-prompt-dialog')); - done(); - }); - }); - - // Test that tapping "Export passwords..." notifies the browser. - test('startExport', function(done) { - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, false); - runStartExportTest(exportDialog, passwordManager, done); - }); - - // Test the export flow. If exporting is fast, we should skip the - // in-progress view altogether. - test('exportFlowFast', function(done) { - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, false); - runExportFlowFastTest(exportDialog, passwordManager, done); - }); - - // The error view is shown when an error occurs. - test('exportFlowError', function(done) { - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, false); - runExportFlowErrorTest(exportDialog, passwordManager, done); - }); - - // The error view allows to retry. - test('exportFlowErrorRetry', function(done) { - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, false); - runExportFlowErrorRetryTest(exportDialog, passwordManager, done); - }); - - // Test the export flow. If exporting is slow, Chrome should show the - // in-progress dialog for at least 1000ms. - test('exportFlowSlow', function(done) { - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, false); - runExportFlowSlowTest(exportDialog, passwordManager, done); - }); - - // Test that canceling the dialog while exporting will also cancel the - // export on the browser. - test('cancelExport', function(done) { - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, false); - runCancelExportTest(exportDialog, passwordManager, done); - }); - - test('fires close event after export complete', () => { - const exportDialog = - elementFactory.createExportPasswordsDialog(passwordManager, false); - return runFireCloseEventAfterExportCompleteTest( - exportDialog, passwordManager); - }); -});
diff --git a/chrome/test/data/webui/settings/passwords_section_test_cros.ts b/chrome/test/data/webui/settings/passwords_section_test_cros.ts new file mode 100644 index 0000000..254a3184 --- /dev/null +++ b/chrome/test/data/webui/settings/passwords_section_test_cros.ts
@@ -0,0 +1,237 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Tests of CrOS specific saved password settings. Note that + * although these tests for only for CrOS, they are testing a CrOS specific + * aspects of the implementation of a browser feature rather than an entirely + * native CrOS feature. See http://crbug.com/917178 for more detail. + */ + +// clang-format off +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {BlockingRequestManager} from 'chrome://settings/lazy_load.js'; +import {PasswordManagerImpl} from 'chrome://settings/settings.js'; +import {assertTrue} from 'chrome://webui-test/chai_assert.js'; + +import {createPasswordEntry, PasswordSectionElementFactory} from './passwords_and_autofill_fake_data.js'; +import {runCancelExportTest, runExportFlowErrorRetryTest, runExportFlowErrorTest, runExportFlowFastTest, runExportFlowSlowTest, runFireCloseEventAfterExportCompleteTest,runStartExportTest} from './passwords_export_test.js'; +import {TestPasswordManagerProxy} from './test_password_manager_proxy.js'; + +// clang-format on + +suite('PasswordsSection_Cros', function() { + /** + * Promise resolved when an auth token request is made. + */ + let requestPromise: Promise<void>; + + /** + * Promise resolved when a saved password is retrieved. + */ + let passwordPromise: Promise<void>; + + class PasswordItem { + private password_: string = ''; + entry: chrome.passwordsPrivate.PasswordUiEntry = createPasswordEntry(); + resolve: (p: void) => void; + + constructor(callback: (p: void) => void) { + this.resolve = callback; + } + + set password(newPassword: string) { + if (newPassword && newPassword !== this.password_) { + this.resolve(); + } + this.password_ = newPassword; + } + + get password(): string { + return this.password_; + } + } + + /** + * Implementation of PasswordSectionElementFactory with parameters that help + * tests to track auth token and saved password requests. + */ + class CrosPasswordSectionElementFactory extends + PasswordSectionElementFactory { + tokenRequestManager: {request: (p: any) => void}|null; + passwordItem: PasswordItem|null; + + /** + * @param document The test's |document| object. + * @param tokenRequestManager Fake for + * BlockingRequestManager provided to subelements of password-section + * that normally have their tokenRequestManager property bound to the + * password section's tokenRequestManager_ property. Note: + * Tests of the password-section element need to use the full + * implementation, which is created by default when the element is + * attached. + */ + constructor( + document: HTMLDocument, + tokenRequestManager: {request: (p: any) => void}|null, + passwordItem: PasswordItem|null) { + super(document); + this.tokenRequestManager = tokenRequestManager; + this.passwordItem = passwordItem; + } + + override createPasswordsSection( + passwordManager: TestPasswordManagerProxy, + _passwordList: chrome.passwordsPrivate.PasswordUiEntry[], + _exceptionList: chrome.passwordsPrivate.ExceptionEntry[]) { + return super.createPasswordsSection(passwordManager, [], []); + } + + override createExportPasswordsDialog( + passwordManager: TestPasswordManagerProxy, + overrideRequestManager?: boolean) { + const dialog = super.createExportPasswordsDialog(passwordManager); + dialog.tokenRequestManager = new BlockingRequestManager(); + return overrideRequestManager ? + Object.assign( + dialog, {tokenRequestManager: this.tokenRequestManager}) : + dialog; + } + } + + function fail() { + throw new Error(); + } + + let passwordManager: TestPasswordManagerProxy; + + let elementFactory: CrosPasswordSectionElementFactory; + + setup(function() { + document.body.innerHTML = ''; + // Override the PasswordManagerImpl for testing. + passwordManager = new TestPasswordManagerProxy(); + PasswordManagerImpl.setInstance(passwordManager); + + // Define a fake BlockingRequestManager to track when a token request + // comes in by resolving requestPromise. + let requestManager: {request: (p: any) => void}|null = null; + requestPromise = new Promise(resolve => { + requestManager = {request: resolve}; + }); + + /** + * Password item (i.e. + * entry with password text) that overrides the password property + * with get/set to track receipt of a saved password and make that + * information available by resolving |passwordPromise|. + */ + let passwordItem: PasswordItem|null = null; + passwordPromise = new Promise(resolve => { + passwordItem = new PasswordItem(resolve); + }); + + elementFactory = new CrosPasswordSectionElementFactory( + document, requestManager, passwordItem); + }); + + // Note (rbpotter): this passes locally, but may still be flaky (see + // https://www.crbug.com/1021474) + test.skip('export passwords button requests auth token', function() { + passwordPromise.then(fail); + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, true); + exportDialog.shadowRoot! + .querySelector<HTMLElement>('#exportPasswordsButton')!.click(); + return requestPromise; + }); + + // TODO(crbug.com/1274569): add test for edit-dialog requesting token when + // switching from ADD to EDIT mode when other tests are fixed. + + + // Note (rbpotter): this passes locally, but may still be flaky (see + // https://www.crbug.com/1021474) + test.skip('password-prompt-dialog appears on auth token request', function() { + const passwordsSection = + elementFactory.createPasswordsSection(passwordManager, [], []); + assertTrue(!passwordsSection.shadowRoot!.querySelector( + 'settings-password-prompt-dialog')); + passwordsSection.getTokenRequestManagerForTest().request(fail); + flush(); + assertTrue(!!passwordsSection.shadowRoot!.querySelector( + 'settings-password-prompt-dialog')); + }); + + // Note (rbpotter): this fails locally, possibly out of date + test.skip( + 'user is not prompted for password if they cannot enter it', + function(done) { + loadTimeData.overrideValues({userCannotManuallyEnterPassword: true}); + const passwordsSection = document.createElement('passwords-section'); + document.body.appendChild(passwordsSection); + flush(); + assertTrue(!passwordsSection.shadowRoot!.querySelector( + 'settings-password-prompt-dialog')); + passwordsSection.getTokenRequestManagerForTest().request(() => { + flush(); + assertTrue(!passwordsSection.shadowRoot!.querySelector( + 'settings-password-prompt-dialog')); + done(); + }); + }); + + // Test that tapping "Export passwords..." notifies the browser. + test('startExport', function(done) { + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, false); + runStartExportTest(exportDialog, passwordManager, done); + }); + + // Test the export flow. If exporting is fast, we should skip the + // in-progress view altogether. + test('exportFlowFast', function(done) { + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, false); + runExportFlowFastTest(exportDialog, passwordManager, done); + }); + + // The error view is shown when an error occurs. + test('exportFlowError', function(done) { + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, false); + runExportFlowErrorTest(exportDialog, passwordManager, done); + }); + + // The error view allows to retry. + test('exportFlowErrorRetry', function(done) { + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, false); + runExportFlowErrorRetryTest(exportDialog, passwordManager, done); + }); + + // Test the export flow. If exporting is slow, Chrome should show the + // in-progress dialog for at least 1000ms. + test('exportFlowSlow', function(done) { + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, false); + runExportFlowSlowTest(exportDialog, passwordManager, done); + }); + + // Test that canceling the dialog while exporting will also cancel the + // export on the browser. + test('cancelExport', function(done) { + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, false); + runCancelExportTest(exportDialog, passwordManager, done); + }); + + test('fires close event after export complete', () => { + const exportDialog = + elementFactory.createExportPasswordsDialog(passwordManager, false); + return runFireCloseEventAfterExportCompleteTest( + exportDialog, passwordManager); + }); +});
diff --git a/chrome/updater/mac/BUILD.gn b/chrome/updater/mac/BUILD.gn index f32cb2be..4ad1c9b9 100644 --- a/chrome/updater/mac/BUILD.gn +++ b/chrome/updater/mac/BUILD.gn
@@ -349,24 +349,22 @@ action_foreach("syms") { script = "//build/redirect_stdout.py" sources = _symbols_sources + dump_syms = "//third_party/breakpad:dump_syms($host_toolchain)" public_deps = [ ":updater_bundle", - "//third_party/breakpad:dump_syms($host_toolchain)", + dump_syms, ] outputs = [ "$root_out_dir/{{source_file_part}}-$chrome_version_full.breakpad" ] - # Use an absolute path to dump_syms in case a user has it in their path. - args = rebase_path(outputs, root_out_dir) + [ - rebase_path( - get_label_info( - "//third_party/breakpad:dump_syms($host_toolchain)", - "root_out_dir") + "/dump_syms", - root_out_dir), + args = rebase_path(outputs, root_build_dir) + [ + rebase_path(get_label_info(dump_syms, "root_out_dir") + "/" + + get_label_info(dump_syms, "name"), + root_build_dir), "-g", rebase_path( "$root_out_dir/{{source_file_part}}.dSYM/Contents/Resources/DWARF/{{source_file_part}}", - root_out_dir), + root_build_dir), "{{source}}", ] }
diff --git a/chromeos/components/hps/BUILD.gn b/chromeos/components/hps/BUILD.gn index 09e4731..340915b 100644 --- a/chromeos/components/hps/BUILD.gn +++ b/chromeos/components/hps/BUILD.gn
@@ -4,6 +4,7 @@ import("//build/buildflag_header.gni") import("//chrome/test/base/js2gtest.gni") +import("//tools/typescript/ts_library.gni") assert(is_chromeos_ash) @@ -24,6 +25,16 @@ ] } +ts_library("hps_internals_ts") { + root_dir = "." + in_files = [ "resources/hps_internals.ts" ] + definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ] + deps = [ + "//third_party/polymer/v3_0:library", + "//ui/webui/resources:library", + ] +} + source_set("unit_tests") { testonly = true sources = [ "hps_configuration_unittest.cc" ]
diff --git a/chromeos/components/hps/resources/hps_internals.js b/chromeos/components/hps/resources/hps_internals.ts similarity index 60% rename from chromeos/components/hps/resources/hps_internals.js rename to chromeos/components/hps/resources/hps_internals.ts index 793cd44..794c874 100644 --- a/chromeos/components/hps/resources/hps_internals.js +++ b/chromeos/components/hps/resources/hps_internals.ts
@@ -8,32 +8,58 @@ const POLL_INTERVAL_MS = 500; // Matches hpsd polling rate. const MAX_HISTORY = 512 / 4; -const HPS_RESULT_DISABLED = -1; -const HPS_RESULT_UNKNOWN = 0; -const HPS_RESULT_NEGATIVE = 1; -const HPS_RESULT_POSITIVE = 2; -let g_senseState = HPS_RESULT_DISABLED; -let g_notifyState = HPS_RESULT_DISABLED; -let g_pollTimer = undefined; +enum HpsResult { + DISABLED = -1, + UNKNOWN = 0, + NEGATIVE = 1, + POSITIVE = 2, +}; -function hpsResultToString(result) { - return { - [HPS_RESULT_DISABLED]: 'disabled', - [HPS_RESULT_UNKNOWN]: 'unknown', - [HPS_RESULT_NEGATIVE]: 'negative', - [HPS_RESULT_POSITIVE]: 'positive', - }[result]; +interface ConnectionState { + connected: boolean; +}; + +interface HpsResultState { + state?: number; + disabled?: boolean; +}; + +let g_senseState = HpsResult.DISABLED; +let g_notifyState = HpsResult.DISABLED; +let g_pollTimer: number|undefined = undefined; + +function hpsResultToString(result: HpsResult) { + switch (result) { + case HpsResult.DISABLED: + return 'disabled'; + case HpsResult.UNKNOWN: + return 'unknown'; + case HpsResult.NEGATIVE: + return 'negative'; + case HpsResult.POSITIVE: + return 'positive'; + } } -function onConnected(state) { +function hpsResultToClass(result: HpsResult) { + // For now we reuse the display strings for class names, but if the UI is ever + // translated, this should be adapted. + return hpsResultToString(result); +} + +function enableButton(selector: string, enabled: boolean) { + ($(selector) as HTMLButtonElement).disabled = !enabled; +} + +function onConnected(state: ConnectionState) { const connected = state.connected; onSenseChanged({disabled: true}); onNotifyChanged({disabled: true}); - $('enable-sense').disabled = true; - $('disable-sense').disabled = true; - $('enable-notify').disabled = true; - $('disable-notify').disabled = true; + enableButton('enable-sense', false); + enableButton('disable-sense', false); + enableButton('enable-notify', false); + enableButton('disable-notify', false); $('connection-error').style.display = connected ? 'none' : 'block'; if (connected) { // Query the state of each feature to see if they are enabled or not. @@ -47,33 +73,33 @@ $('enable-error').style.display = 'block'; } -function onSenseChanged(value) { +function onSenseChanged(value: HpsResultState) { if (value.disabled) { - $('enable-sense').disabled = false; - $('disable-sense').disabled = true; - g_senseState = HPS_RESULT_DISABLED; + enableButton('enable-sense', true); + enableButton('disable-sense', false); + g_senseState = HpsResult.DISABLED; } else { - $('enable-sense').disabled = true; - $('disable-sense').disabled = false; - g_senseState = value.state; + enableButton('enable-sense', false); + enableButton('disable-sense', true); + g_senseState = value.state!; } $('sense-state').textContent = hpsResultToString(g_senseState); - $('sense-state').className = hpsResultToString(g_senseState); + $('sense-state').className = hpsResultToClass(g_senseState); updatePolling(); } -function onNotifyChanged(value) { +function onNotifyChanged(value: HpsResultState) { if (value.disabled) { - $('enable-notify').disabled = false; - $('disable-notify').disabled = true; - g_notifyState = HPS_RESULT_DISABLED; + enableButton('enable-notify', true); + enableButton('disable-notify', false); + g_notifyState = HpsResult.DISABLED; } else { - $('enable-notify').disabled = true; - $('disable-notify').disabled = false; - g_notifyState = value.state; + enableButton('enable-notify', false); + enableButton('disable-notify', true); + g_notifyState = value.state!; } $('notify-state').textContent = hpsResultToString(g_notifyState); - $('notify-state').className = hpsResultToString(g_notifyState); + $('notify-state').className = hpsResultToClass(g_notifyState); updatePolling(); } @@ -118,8 +144,8 @@ function updatePolling() { const shouldPoll = - g_notifyState !== HPS_RESULT_DISABLED || - g_senseState !== HPS_RESULT_DISABLED; + g_notifyState !== HpsResult.DISABLED || + g_senseState !== HpsResult.DISABLED; if (shouldPoll && g_pollTimer === undefined) { g_pollTimer = setInterval(recordSample, POLL_INTERVAL_MS); recordSample(); @@ -130,22 +156,22 @@ $('root').dispatchEvent(new CustomEvent('state-updated-for-test')); } -function pruneSamples(container) { +function pruneSamples(container: HTMLElement) { while (container.childElementCount > MAX_HISTORY) { - container.firstChild.remove(); + container.firstChild!.remove(); } } function recordSample() { if (g_senseState !== undefined) { let sample = document.createElement('span'); - sample.className = hpsResultToString(g_senseState); + sample.className = hpsResultToClass(g_senseState); $('sense-history').appendChild(sample); pruneSamples($('sense-history')); } if (g_notifyState !== undefined) { let sample = document.createElement('span'); - sample.className = hpsResultToString(g_notifyState); + sample.className = hpsResultToClass(g_notifyState); $('notify-history').appendChild(sample); pruneSamples($('notify-history')); }
diff --git a/chromeos/resources/BUILD.gn b/chromeos/resources/BUILD.gn index 681cfb5..7c2a4d40 100644 --- a/chromeos/resources/BUILD.gn +++ b/chromeos/resources/BUILD.gn
@@ -26,6 +26,7 @@ ] deps = [ + "//chromeos/components/hps:hps_internals_ts", "//chromeos/language/public/mojom:mojom_js", "//chromeos/services/bluetooth_config/public/mojom:mojom_js",
diff --git a/chromeos/resources/hps_resources.grdp b/chromeos/resources/hps_resources.grdp index 9f1b500..592d8d7 100644 --- a/chromeos/resources/hps_resources.grdp +++ b/chromeos/resources/hps_resources.grdp
@@ -2,6 +2,10 @@ <grit-part> <include name="IDR_HPS_INTERNALS_HTML" file="../components/hps/resources/hps_internals.html" type="BINDATA" /> <include name="IDR_HPS_INTERNALS_CSS" file="../components/hps/resources/hps_internals.css" type="BINDATA" /> - <include name="IDR_HPS_INTERNALS_JS" file="../components/hps/resources/hps_internals.js" type="BINDATA" /> <include name="IDR_HPS_INTERNALS_ICON" file="../components/hps/resources/hps_internals_icon.svg" type="BINDATA" /> + <include name="IDR_HPS_INTERNALS_JS" + file="${root_gen_dir}/chromeos/components/hps/resources/hps_internals.js" + resource_path="chromeos/components/hps/resources/hps_internals.js" + use_base_dir="false" + type="BINDATA" /> </grit-part>
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc index 40d2d82..0aa199b 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -616,27 +616,6 @@ unmask_auth_flow_type_); } - // Local boolean denotes whether to fill the form immediately. If CVC - // authentication failed, report error immediately. If GetRealPan did not - // return card authorization token (we can't call any FIDO-related flows, - // either opt-in or register new card, without token), fill the form - // immediately. - bool should_respond_immediately = - !response.did_succeed || response.card_authorization_token.empty(); -#if BUILDFLAG(IS_ANDROID) - // GetRealPan did not return RequestOptions (user did not specify intent to - // opt-in) AND flow is not registering a new card, also fill the form - // directly. - should_respond_immediately |= - (!response.request_options.has_value() && - unmask_auth_flow_type_ != UnmaskAuthFlowType::kCvcThenFido); -#else - // On desktop, if flow is not kCvcThenFido, it means it is not registering a - // new card, we can fill the form immediately. - should_respond_immediately |= - unmask_auth_flow_type_ != UnmaskAuthFlowType::kCvcThenFido; -#endif - // Local boolean denotes whether to call AdditionallyPerformFidoAuth which // delays the form filling and invokes an Authorization flow. If // |unmask_auth_flow_type_| is kCvcThenFido, then the user is already opted-in @@ -674,10 +653,10 @@ ->IsMaxStrikesLimitReached(); #endif - // Ensure that |should_respond_immediately| and |should_authorize_with_fido| - // can't be true at the same time - DCHECK(!(should_respond_immediately && should_authorize_with_fido)); - if (should_respond_immediately) { + if (ShouldRespondImmediately(response)) { + // If ShouldRespondImmediately() returns true, |should_authorize_with_fido| + // should be false. + DCHECK(!should_authorize_with_fido); accessor_->OnCreditCardFetched(response.did_succeed ? CreditCardFetchResult::kSuccess : CreditCardFetchResult::kTransientError, @@ -877,6 +856,27 @@ unmask_details_.fido_eligible_card_ids.end(); } +bool CreditCardAccessManager::ShouldRespondImmediately( + const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response) { +#if BUILDFLAG(IS_ANDROID) + // GetRealPan did not return RequestOptions (user did not specify intent to + // opt-in) AND flow is not registering a new card, so fill the form + // directly. + if (!response.request_options.has_value() && + unmask_auth_flow_type_ != UnmaskAuthFlowType::kCvcThenFido) { + return true; + } +#else + if (unmask_auth_flow_type_ != UnmaskAuthFlowType::kCvcThenFido) + return true; +#endif + // If the response did not succeed, report the error immediately. If + // GetRealPan did not return a card authorization token (we can't call any + // FIDO-related flows, either opt-in or register new card, without the token), + // fill the form immediately. + return !response.did_succeed || response.card_authorization_token.empty(); +} + void CreditCardAccessManager::ShowWebauthnOfferDialog( std::string card_authorization_token) { #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h index e9b3ff6e..5e3662b 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.h +++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -308,9 +308,16 @@ // FIDO eligible. bool IsSelectedCardFidoAuthorized(); + // Returns true if there should be an immediate response after a CVC + // Authentication. The cases where we would have an immediate response is if + // there is no need for FIDO authentication after a successful CVC + // authentication, or the CVC authentication was unsuccessful. + bool ShouldRespondImmediately( + const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response); + // TODO(crbug.com/991037): Move this function under the build flags after the - // refactoring is done. - // Offer the option to use WebAuthn for authenticating future card unmasking. + // refactoring is done. Offer the option to use WebAuthn for authenticating + // future card unmasking. void ShowWebauthnOfferDialog(std::string card_authorization_token); #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantInfoPopup.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantInfoPopup.java index 5f35aac..6974dd6 100644 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantInfoPopup.java +++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantInfoPopup.java
@@ -48,12 +48,13 @@ @CalledByNative public void show(Context context) { - AlertDialog.Builder builder = new AlertDialog - .Builder(context, - org.chromium.components.autofill_assistant.R - .style.Theme_Chromium_AlertDialog) - .setTitle(mTitle) - .setMessage(mText); + AlertDialog.Builder builder = + new AlertDialog + .Builder(context, + org.chromium.components.autofill_assistant.R.style + .ThemeOverlay_BrowserUI_AlertDialog) + .setTitle(mTitle) + .setMessage(mText); if (mPositiveButton != null) { builder.setPositiveButton(mPositiveButton.getLabel(),
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewInteractions.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewInteractions.java index 2aed4ec..a3d1fce80 100644 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewInteractions.java +++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewInteractions.java
@@ -151,7 +151,7 @@ new AlertDialog .Builder(context, org.chromium.components.autofill_assistant.R.style - .Theme_Chromium_AlertDialog) + .ThemeOverlay_BrowserUI_AlertDialog) .setView(contentView) .setOnDismissListener(unused -> delegate.onGenericPopupDismissed(popupIdentifier)) .show();
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java index c39c4e7..44ffb6d 100644 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java +++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java
@@ -159,7 +159,7 @@ cancelDialog = mContext.getString(R.string.cancel); } - mDialog = new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog) + mDialog = new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setPositiveButton(acceptDialog, (DialogInterface dialog, int unused) -> { // Hide the dialog, but don't hide the bottom sheet content,
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/DialogOnboardingCoordinator.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/DialogOnboardingCoordinator.java index 3fbe513..214c1594 100644 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/DialogOnboardingCoordinator.java +++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/onboarding/DialogOnboardingCoordinator.java
@@ -63,7 +63,7 @@ mDialog = new AlertDialog .Builder(getContext(), org.chromium.components.autofill_assistant.R.style - .Theme_Chromium_AlertDialog) + .ThemeOverlay_BrowserUI_AlertDialog) .create(); mDialog.setOnDismissListener((OnDismissListener) dialog
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantDataOriginNotice.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantDataOriginNotice.java index bd36b535..a7a9f61 100644 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantDataOriginNotice.java +++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantDataOriginNotice.java
@@ -94,13 +94,14 @@ } private AlertDialog createAlertDialog() { - AlertDialog dialog = new AlertDialog.Builder(mActivity, R.style.Theme_Chromium_AlertDialog) - .setTitle(mDialogTitle) - .setMessage(AssistantTextUtils.applyVisualAppearanceTags( - mDialogText, mActivity, this::onDataOriginLinkClicked)) - .setPositiveButton(mDialogButtonText, - (DialogInterface dialogInterface, int unused) -> {}) - .create(); + AlertDialog dialog = + new AlertDialog.Builder(mActivity, R.style.ThemeOverlay_BrowserUI_AlertDialog) + .setTitle(mDialogTitle) + .setMessage(AssistantTextUtils.applyVisualAppearanceTags( + mDialogText, mActivity, this::onDataOriginLinkClicked)) + .setPositiveButton(mDialogButtonText, + (DialogInterface dialogInterface, int unused) -> {}) + .create(); return dialog; } }
diff --git a/components/browser_ui/client_certificate/android/java/src/org/chromium/components/browser_ui/client_certificate/SSLClientCertificateRequest.java b/components/browser_ui/client_certificate/android/java/src/org/chromium/components/browser_ui/client_certificate/SSLClientCertificateRequest.java index 75e3634..6cb78909 100644 --- a/components/browser_ui/client_certificate/android/java/src/org/chromium/components/browser_ui/client_certificate/SSLClientCertificateRequest.java +++ b/components/browser_ui/client_certificate/android/java/src/org/chromium/components/browser_ui/client_certificate/SSLClientCertificateRequest.java
@@ -230,7 +230,7 @@ */ public void show() { final AlertDialog.Builder builder = - new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(mContext, R.style.ThemeOverlay_BrowserUI_AlertDialog); builder.setTitle(R.string.client_cert_unsupported_title) .setMessage(R.string.client_cert_unsupported_message) .setNegativeButton(R.string.close,
diff --git a/components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/ContactsPickerDialogTest.java b/components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/ContactsPickerDialogTest.java index 10cd2a28c..06539f00 100644 --- a/components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/ContactsPickerDialogTest.java +++ b/components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/ContactsPickerDialogTest.java
@@ -79,7 +79,10 @@ private WebContents mWebContents; @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setBugComponent(RenderTestRule.Component.BLINK_CONTACTS) + .build(); // The dialog we are testing. private ContactsPickerDialog mDialog;
diff --git a/components/browser_ui/http_auth/android/java/src/org/chromium/components/browser_ui/http_auth/LoginPrompt.java b/components/browser_ui/http_auth/android/java/src/org/chromium/components/browser_ui/http_auth/LoginPrompt.java index 0910beb..2b90219 100644 --- a/components/browser_ui/http_auth/android/java/src/org/chromium/components/browser_ui/http_auth/LoginPrompt.java +++ b/components/browser_ui/http_auth/android/java/src/org/chromium/components/browser_ui/http_auth/LoginPrompt.java
@@ -87,7 +87,7 @@ TextView explanationView = (TextView) v.findViewById(R.id.explanation); explanationView.setText(mMessageBody); - mDialog = new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog) + mDialog = new AlertDialog.Builder(mContext, R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.login_dialog_title) .setView(v) .setPositiveButton(R.string.login_dialog_ok_button_label,
diff --git a/components/browser_ui/modaldialog/android/java/res/values/styles.xml b/components/browser_ui/modaldialog/android/java/res/values/styles.xml index 850c459..70b1f86 100644 --- a/components/browser_ui/modaldialog/android/java/res/values/styles.xml +++ b/components/browser_ui/modaldialog/android/java/res/values/styles.xml
@@ -5,66 +5,66 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- The dim amount should match the alpha of modal_dialog_scrim_color. --> - <style name="Theme.Chromium.ModalDialog" parent="Theme.Chromium.AlertDialog"> + <style name="ThemeOverlay.BrowserUI.ModalDialog" parent="ThemeOverlay.BrowserUI.AlertDialog"> <item name="android:windowFrame">@null</item> <item name="android:backgroundDimAmount">0.65</item> <item name="android:windowSoftInputMode">adjustResize|stateHidden</item> </style> - <style name="Theme.Chromium.ModalDialog.TextPrimaryButton" parent="Theme.Chromium.ModalDialog"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.TextPrimaryButton" parent="ThemeOverlay.BrowserUI.ModalDialog"> <item name="buttonBarButtonStyle">@style/TextButton</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding</item> </style> - <style name="Theme.Chromium.ModalDialog.FilledPrimaryButton" parent="Theme.Chromium.ModalDialog"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.FilledPrimaryButton" parent="ThemeOverlay.BrowserUI.ModalDialog"> <item name="buttonBarPositiveButtonStyle">@style/FilledButton.Flat</item> <item name="buttonBarNegativeButtonStyle">@style/TextButton</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding_filled</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding_filled</item> </style> - <style name="Theme.Chromium.ModalDialog.FilledNegativeButton" parent="Theme.Chromium.ModalDialog"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.FilledNegativeButton" parent="ThemeOverlay.BrowserUI.ModalDialog"> <item name="buttonBarPositiveButtonStyle">@style/TextButton</item> <item name="buttonBarNegativeButtonStyle">@style/FilledButton.Flat</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding_filled</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding_filled</item> </style> - <style name="ThemeOverlay.Chromium.ModalDialog.TextPrimaryButton.Fullscreen" parent="ThemeOverlay.BrowserUI.Fullscreen"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.TextPrimaryButton.Fullscreen" parent="ThemeOverlay.BrowserUI.Fullscreen"> <item name="buttonBarButtonStyle">@style/TextButton</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding</item> </style> - <style name="ThemeOverlay.Chromium.ModalDialog.FilledPrimaryButton.Fullscreen" parent="ThemeOverlay.BrowserUI.Fullscreen"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.FilledPrimaryButton.Fullscreen" parent="ThemeOverlay.BrowserUI.Fullscreen"> <item name="buttonBarPositiveButtonStyle">@style/FilledButton.Flat</item> <item name="buttonBarNegativeButtonStyle">@style/TextButton</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding_filled</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding_filled</item> </style> - <style name="ThemeOverlay.Chromium.ModalDialog.FilledNegativeButton.Fullscreen" parent="ThemeOverlay.BrowserUI.Fullscreen"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.FilledNegativeButton.Fullscreen" parent="ThemeOverlay.BrowserUI.Fullscreen"> <item name="buttonBarPositiveButtonStyle">@style/TextButton</item> <item name="buttonBarNegativeButtonStyle">@style/FilledButton.Flat</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding_filled</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding_filled</item> </style> - <style name="ThemeOverlay.Chromium.ModalDialog.TextPrimaryButton.DialogWhenLarge" parent="ThemeOverlay.BrowserUI.Fullscreen.DialogWhenLarge"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.TextPrimaryButton.DialogWhenLarge" parent="ThemeOverlay.BrowserUI.Fullscreen.DialogWhenLarge"> <item name="buttonBarButtonStyle">@style/TextButton</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding</item> </style> - <style name="ThemeOverlay.Chromium.ModalDialog.FilledPrimaryButton.DialogWhenLarge" parent="ThemeOverlay.BrowserUI.Fullscreen.DialogWhenLarge"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.FilledPrimaryButton.DialogWhenLarge" parent="ThemeOverlay.BrowserUI.Fullscreen.DialogWhenLarge"> <item name="buttonBarPositiveButtonStyle">@style/FilledButton.Flat</item> <item name="buttonBarNegativeButtonStyle">@style/TextButton</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding_filled</item> <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding_filled</item> </style> - <style name="ThemeOverlay.Chromium.ModalDialog.FilledNegativeButton.DialogWhenLarge" parent="ThemeOverlay.BrowserUI.Fullscreen.DialogWhenLarge"> + <style name="ThemeOverlay.BrowserUI.ModalDialog.FilledNegativeButton.DialogWhenLarge" parent="ThemeOverlay.BrowserUI.Fullscreen.DialogWhenLarge"> <item name="buttonBarPositiveButtonStyle">@style/TextButton</item> <item name="buttonBarNegativeButtonStyle">@style/FilledButton.Flat</item> <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding_filled</item>
diff --git a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/AppModalPresenter.java b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/AppModalPresenter.java index 26662d9..6c5cde0b 100644 --- a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/AppModalPresenter.java +++ b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/AppModalPresenter.java
@@ -55,15 +55,15 @@ @Override protected void addDialogView(PropertyModel model) { int styles[][] = { - {R.style.Theme_Chromium_ModalDialog_TextPrimaryButton, - R.style.ThemeOverlay_Chromium_ModalDialog_TextPrimaryButton_Fullscreen, - R.style.ThemeOverlay_Chromium_ModalDialog_TextPrimaryButton_DialogWhenLarge}, - {R.style.Theme_Chromium_ModalDialog_FilledPrimaryButton, - R.style.ThemeOverlay_Chromium_ModalDialog_FilledPrimaryButton_Fullscreen, - R.style.ThemeOverlay_Chromium_ModalDialog_FilledPrimaryButton_DialogWhenLarge}, - {R.style.Theme_Chromium_ModalDialog_FilledNegativeButton, - R.style.ThemeOverlay_Chromium_ModalDialog_FilledNegativeButton_Fullscreen, - R.style.ThemeOverlay_Chromium_ModalDialog_FilledNegativeButton_DialogWhenLarge}}; + {R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton, + R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton_Fullscreen, + R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton_DialogWhenLarge}, + {R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledPrimaryButton, + R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledPrimaryButton_Fullscreen, + R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledPrimaryButton_DialogWhenLarge}, + {R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledNegativeButton, + R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledNegativeButton_Fullscreen, + R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledNegativeButton_DialogWhenLarge}}; int index = 0; if (model.get(ModalDialogProperties.FULLSCREEN_DIALOG)) { index = 1;
diff --git a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java index f5bf4c0..0cc06a3 100644 --- a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java +++ b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java
@@ -91,7 +91,7 @@ mModalDialogView = (ModalDialogView) LayoutInflater .from(new ContextThemeWrapper(sActivity, - R.style.Theme_Chromium_ModalDialog_TextPrimaryButton)) + R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton)) .inflate(R.layout.modal_dialog_view, null); sContentView.addView(mModalDialogView, MATCH_PARENT, WRAP_CONTENT);
diff --git a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/TabModalPresenter.java b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/TabModalPresenter.java index 0a8400cb..24a0cdd8 100644 --- a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/TabModalPresenter.java +++ b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/TabModalPresenter.java
@@ -122,13 +122,13 @@ protected void addDialogView(PropertyModel model) { if (mDialogContainer == null) mDialogContainer = createDialogContainer(); - int style = R.style.Theme_Chromium_ModalDialog_TextPrimaryButton; + int style = R.style.ThemeOverlay_BrowserUI_ModalDialog_TextPrimaryButton; int buttonStyles = model.get(ModalDialogProperties.BUTTON_STYLES); if (buttonStyles == ModalDialogProperties.ButtonStyles.PRIMARY_FILLED_NEGATIVE_OUTLINE) { - style = R.style.Theme_Chromium_ModalDialog_FilledPrimaryButton; + style = R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledPrimaryButton; } else if (buttonStyles == ModalDialogProperties.ButtonStyles.PRIMARY_OUTLINE_NEGATIVE_FILLED) { - style = R.style.Theme_Chromium_ModalDialog_FilledNegativeButton; + style = R.style.ThemeOverlay_BrowserUI_ModalDialog_FilledNegativeButton; } mDialogView = loadDialogView(style); mModelChangeProcessor =
diff --git a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java index 90f1add..d120ca7 100644 --- a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java +++ b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java
@@ -69,7 +69,10 @@ private static final long WAIT_TIMEOUT_SECONDS = 30L; @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MEDIA_PICKER) + .build(); private WindowAndroid mWindowAndroid;
diff --git a/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java b/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java index 6884fa4e..bfcdef4f 100644 --- a/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java +++ b/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java
@@ -266,7 +266,7 @@ final ShareDialogAdapter adapter = new ShareDialogAdapter(context, manager, resolveInfoList); AlertDialog.Builder builder = - new AlertDialog.Builder(context, R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(context, R.style.ThemeOverlay_BrowserUI_AlertDialog); builder.setTitle(context.getString(R.string.share_link_chooser_title)); builder.setAdapter(adapter, null);
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AddExceptionPreference.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AddExceptionPreference.java index 2e71afc5..b0c3489 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AddExceptionPreference.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AddExceptionPreference.java
@@ -150,7 +150,7 @@ }; AlertDialog.Builder alert = - new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog); + new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog); AlertDialog alertDialog = alert.setTitle(R.string.website_settings_add_site_dialog_title) .setMessage(mDialogMessage)
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ChosenObjectSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ChosenObjectSettings.java index 8e1aa82c2..24b457c 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ChosenObjectSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ChosenObjectSettings.java
@@ -239,7 +239,8 @@ header.setTitle(titleText); header.setImageView(R.drawable.ic_delete_white_24dp, R.string.website_settings_revoke_all_permissions_for_device, (View view) -> { - new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog) + new AlertDialog + .Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.reset) .setMessage(dialogMsg) .setPositiveButton(R.string.reset,
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java index 14e5fdc0..79c85a4 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
@@ -1112,7 +1112,7 @@ descriptions[1] = getString(ContentSettingsResources.getSiteSummary(ContentSettingValues.BLOCK)); - return new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog) + return new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setPositiveButton(R.string.cancel, null) .setNegativeButton(R.string.remove, (dialog, which) -> {
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java index 9af97562..7ad949d 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -1102,7 +1102,7 @@ int buttonResId = mHideNonPermissionPreferences ? R.string.reset : titleResId; // Handle the Clear & Reset preference click by showing a confirmation. mConfirmationDialog = - new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(titleResId) .setMessage(confirmationText) .setPositiveButton(buttonResId,
diff --git a/components/browser_ui/theme/android/java/res/values/themes.xml b/components/browser_ui/theme/android/java/res/values/themes.xml index 2a05e0d3..0e8927c9 100644 --- a/components/browser_ui/theme/android/java/res/values/themes.xml +++ b/components/browser_ui/theme/android/java/res/values/themes.xml
@@ -145,8 +145,9 @@ <!-- Overridden by night mode. --> <style name="Theme.BrowserUI.DialogWhenLarge.DayNight" parent="Theme.BrowserUI.DialogWhenLarge"/> - <!-- Unlike |Theme.Chromium.AlertDialog|, this is a complete theme that can be used as an - activity theme on its own. This should be kept in sync with |Theme.Chromium.AlertDialog|. + <!-- Unlike |ThemeOverlay.BrowserUI.AlertDialog|, this is a complete theme that can be used as + an activity theme on its own. This should be kept in sync with + |ThemeOverlay.BrowserUI.AlertDialog|. --> <style name="Theme.BrowserUI.AlertDialog.NoActionBar" parent="Theme.MaterialComponents.DayNight.Dialog.Alert">
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 b594ec6..8b80d3d5 100644 --- a/components/browser_ui/widget/android/java/res/values/styles.xml +++ b/components/browser_ui/widget/android/java/res/values/styles.xml
@@ -4,11 +4,9 @@ found in the LICENSE file. --> <resources xmlns:tools="http://schemas.android.com/tools"> - <!-- TODO(https://crbug.com/1242702): Rename to ThemeOverlay.Chromium.AlertDialog. --> <!-- AlertDialog styles --> <!-- This should be kept in sync with |Theme.BrowserUI.AlertDialog.NoActionBar|. --> - <style name="Base.Theme.Chromium.AlertDialog" - parent="ThemeOverlay.MaterialComponents.Dialog.Alert"> + <style name="ThemeOverlay.BrowserUI.AlertDialog" parent="ThemeOverlay.MaterialComponents.Dialog.Alert"> <item name="android:textColorPrimary">@macro/default_text_color</item> <item name="android:windowBackground">@drawable/dialog_bg_no_shadow</item> <item name="android:windowTitleStyle">@style/TextAppearance.AlertDialogTitleStyle</item> @@ -26,9 +24,11 @@ <item name="android:buttonBarButtonStyle">@style/AlertDialogButtonStyle</item> <item name="buttonBarButtonStyle">@style/AlertDialogButtonStyle</item> </style> - <style name="Theme.Chromium.AlertDialog" parent="Base.Theme.Chromium.AlertDialog" /> + <!-- TODO(https://crbug.com/1242702): Remove this once the style in downstream that depends on + this is removed. --> + <style name="Theme.Chromium.AlertDialog" parent="ThemeOverlay.BrowserUI.AlertDialog" tools:ignore="UnusedResources"/> - <style name="Theme.Chromium.AlertDialog.NoActionBar"> + <style name="ThemeOverlay.BrowserUI.AlertDialog.NoActionBar"> <item name="windowNoTitle">true</item> <item name="windowActionBar">false</item> </style>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/PromoDialogRenderTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/PromoDialogRenderTest.java index 6ce4aa1a..04e044b 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/PromoDialogRenderTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/PromoDialogRenderTest.java
@@ -42,7 +42,10 @@ new NightModeTestUtils.NightModeParams().getParameters(); @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE) + .build(); private static final String LONG_STRING = "A very very very very very very very very very" + "very very very very long string";
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonRenderTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonRenderTest.java index dc2dd94..92d157f1 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonRenderTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonRenderTest.java
@@ -47,10 +47,12 @@ "Use Google standard colors as the background."; @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus() - .setRevision(REVISION) - .setDescription(REVISION_DESCRIPTION) - .build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setRevision(REVISION) + .setDescription(REVISION_DESCRIPTION) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE) + .build(); private RadioButtonWithDescriptionLayout mLayout;
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithIconRenderTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithIconRenderTest.java index 23c65bb..e870bc6 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithIconRenderTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithIconRenderTest.java
@@ -45,10 +45,12 @@ "Test rendering of the icon in a disabled state."; @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus() - .setRevision(REVISION) - .setDescription(REVISION_DESCRIPTION) - .build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setRevision(REVISION) + .setDescription(REVISION_DESCRIPTION) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE) + .build(); private RadioButtonWithDescriptionLayout mLayout;
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/ListMenuRenderTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/ListMenuRenderTest.java index de72c8f..ef3b9f7e 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/ListMenuRenderTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/ListMenuRenderTest.java
@@ -44,7 +44,10 @@ new NightModeTestUtils.NightModeParams().getParameters(); @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE) + .build(); private View mView;
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/promo/PromoCardViewRenderTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/promo/PromoCardViewRenderTest.java index c9a16cf..badcaf9 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/promo/PromoCardViewRenderTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/promo/PromoCardViewRenderTest.java
@@ -48,7 +48,10 @@ new NightModeTestUtils.NightModeParams().getParameters(); @Rule - public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + public RenderTestRule mRenderTestRule = + RenderTestRule.Builder.withPublicCorpus() + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE) + .build(); public PromoCardViewRenderTest(boolean nightModeEnabled) { NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
diff --git a/components/exo/wayland/protocol/chrome-color-management.xml b/components/exo/wayland/protocol/chrome-color-management.xml index 458e5ef..2120b1e 100644 --- a/components/exo/wayland/protocol/chrome-color-management.xml +++ b/components/exo/wayland/protocol/chrome-color-management.xml
@@ -587,6 +587,28 @@ <arg name="whitepoint" type="uint" enum="zcr_color_manager_v1.whitepoint_names" summary="whitepoint"/> </event> + <event name="params"> + <description summary="RGB primaries along with whitepoint defining color space"> + This event may be sent only as a response to + zcr_color_space_v1.get_information. + + The RGB primary value arguments along with the whitepoint value arguments + and eotf can be used to define an arbitrary or custom color space. + + The eotf enum contains well known names of that property, but the compositor + should not assume that all clients will understand those names. + </description> + <arg name="eotf" type="uint" enum="zcr_color_manager_v1.eotf_names" summary="EOTF"/> + <arg name="primary_r_x" type="uint" summary="red primary X * 10000"/> + <arg name="primary_r_y" type="uint" summary="red primary Y * 10000"/> + <arg name="primary_g_x" type="uint" summary="green primary X * 10000"/> + <arg name="primary_g_y" type="uint" summary="green primary Y * 10000"/> + <arg name="primary_b_x" type="uint" summary="blue primary X * 10000"/> + <arg name="primary_b_y" type="uint" summary="blue primary Y * 10000"/> + <arg name="white_point_x" type="uint" summary="white point X * 10000"/> + <arg name="white_point_y" type="uint" summary="white point Y * 10000"/> + </event> + <event name="done"> <description summary="end of color space information"> This event may be sent only as a response to
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java index e2eecbc..fb853d0 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -1121,7 +1121,7 @@ protected AlertDialog showLeavingIncognitoAlert(final Context context, final ExternalNavigationParams params, final Intent intent, final GURL fallbackUrl, final boolean proxy) { - return new AlertDialog.Builder(context, R.style.Theme_Chromium_AlertDialog) + return new AlertDialog.Builder(context, R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.external_app_leave_incognito_warning_title) .setMessage(R.string.external_app_leave_incognito_warning) .setPositiveButton(R.string.external_app_leave_incognito_leave,
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java index 0fc00b4..9219146f 100644 --- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java +++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java
@@ -186,10 +186,6 @@ /** 'Manage windows' menu for multi-instance support feature was tapped. */ public static final String INSTANCE_SWITCHER_IPH_USED = "instance_switcher_iph_used"; - /** HomepagePromo has been accepted. */ - public static final String NTP_SHOWN = "ntp_shown"; - public static final String NTP_HOME_BUTTON_CLICKED = "ntp_homebutton_clicked"; - public static final String TAB_SWITCHER_BUTTON_CLICKED = "tab_switcher_button_clicked"; public static final String FOREGROUND_SESSION_DESTROYED = "foreground_session_destroyed";
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc index afa48650..b39b99b 100644 --- a/components/feature_engagement/public/feature_constants.cc +++ b/components/feature_engagement/public/feature_constants.cc
@@ -179,8 +179,6 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHGenericAlwaysTriggerHelpUiFeature{ "IPH_GenericAlwaysTriggerHelpUiFeature", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kIPHHomepagePromoCardFeature{ - "IPH_HomepagePromoCard", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHIdentityDiscFeature{"IPH_IdentityDisc", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHInstanceSwitcherFeature{
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h index c7cfa79a..7eec6d7 100644 --- a/components/feature_engagement/public/feature_constants.h +++ b/components/feature_engagement/public/feature_constants.h
@@ -112,7 +112,6 @@ extern const base::Feature kIPHGenericAlwaysTriggerHelpUiFeature; extern const base::Feature kIPHHomePageButtonFeature; extern const base::Feature kIPHHomepageTileFeature; -extern const base::Feature kIPHHomepagePromoCardFeature; extern const base::Feature kIPHIdentityDiscFeature; extern const base::Feature kIPHInstanceSwitcherFeature; extern const base::Feature kIPHKeyboardAccessoryAddressFillingFeature;
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc index 1274231..7031524 100644 --- a/components/feature_engagement/public/feature_list.cc +++ b/components/feature_engagement/public/feature_list.cc
@@ -61,7 +61,6 @@ &kIPHFeatureNotificationGuideVoiceSearchUsedFeature, &kIPHFeedCardMenuFeature, &kIPHGenericAlwaysTriggerHelpUiFeature, - &kIPHHomepagePromoCardFeature, &kIPHIdentityDiscFeature, &kIPHInstanceSwitcherFeature, &kIPHKeyboardAccessoryAddressFillingFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h index b4fd160..63763496 100644 --- a/components/feature_engagement/public/feature_list.h +++ b/components/feature_engagement/public/feature_list.h
@@ -129,7 +129,6 @@ DEFINE_VARIATION_PARAM(kIPHFeedCardMenuFeature, "IPH_FeedCardMenu"); DEFINE_VARIATION_PARAM(kIPHGenericAlwaysTriggerHelpUiFeature, "IPH_GenericAlwaysTriggerHelpUiFeature"); -DEFINE_VARIATION_PARAM(kIPHHomepagePromoCardFeature, "IPH_HomepagePromoCard"); DEFINE_VARIATION_PARAM(kIPHIdentityDiscFeature, "IPH_IdentityDisc"); DEFINE_VARIATION_PARAM(kIPHInstanceSwitcherFeature, "IPH_InstanceSwitcher"); DEFINE_VARIATION_PARAM(kIPHKeyboardAccessoryAddressFillingFeature, @@ -303,7 +302,6 @@ VARIATION_ENTRY(kIPHDownloadInfoBarDownloadsAreFasterFeature), VARIATION_ENTRY(kIPHEphemeralTabFeature), VARIATION_ENTRY(kIPHFeedCardMenuFeature), - VARIATION_ENTRY(kIPHHomepagePromoCardFeature), VARIATION_ENTRY(kIPHIdentityDiscFeature), VARIATION_ENTRY(kIPHInstanceSwitcherFeature), VARIATION_ENTRY(kIPHKeyboardAccessoryAddressFillingFeature),
diff --git a/components/nacl/target_cpu.gni b/components/nacl/target_cpu.gni new file mode 100644 index 0000000..83cdc86 --- /dev/null +++ b/components/nacl/target_cpu.gni
@@ -0,0 +1,14 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# nacl_target_cpu is the CPU architecture to use for the NaCl sandbox. +# +# On ARM64 builds of Chromium where NaCl is enabled, we use the 32-bit ARM +# NaCl sandbox (ARM32/AArch32). (There is no NaCl sandbox implemented for +# ARM64.) +if (target_cpu == "arm64") { + nacl_target_cpu = "arm" +} else { + nacl_target_cpu = target_cpu +}
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc index 24b7a66..024e4ceb 100644 --- a/components/omnibox/browser/zero_suggest_provider.cc +++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -80,7 +80,7 @@ ZERO_SUGGEST_REQUEST_INVALIDATED = 2, ZERO_SUGGEST_RESPONSE_RECEIVED = 3, ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE = 4, - ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE_IS_OUT_OF_DATE = 5, + ZERO_SUGGEST_CACHED_RESPONSE_IS_OUT_OF_DATE = 5, ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE }; @@ -209,7 +209,7 @@ done_ = false; - MaybeUseStoredResponse(); + const std::string original_response = MaybeUseStoredResponse(); search_terms_args.current_page_url = result_type_running_ == REMOTE_SEND_URL ? current_query_ : std::string(); @@ -222,7 +222,7 @@ weak_ptr_factory_.GetWeakPtr(), is_prefetch), base::BindOnce(&ZeroSuggestProvider::OnURLLoadComplete, weak_ptr_factory_.GetWeakPtr(), client()->GetWeakPtr(), - search_terms_args, is_prefetch, + search_terms_args, is_prefetch, original_response, base::TimeTicks::Now())); } @@ -327,6 +327,7 @@ const base::WeakPtr<AutocompleteProviderClient> client, TemplateURLRef::SearchTermsArgs search_terms_args, bool is_prefetch, + const std::string& original_response, base::TimeTicks request_time, const network::SimpleURLLoader* source, std::unique_ptr<std::string> response_body) { @@ -336,40 +337,34 @@ LogOmniboxZeroSuggestRequestRoundTripTime( base::TimeTicks::Now() - request_time, is_prefetch); LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_RESPONSE_RECEIVED, is_prefetch); + if (source->LoadedFromCache()) { + LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE, + is_prefetch); + } + + // Issue a follow-up non-cacheable request in the counterfactual arm. The new + // response is compared against the originally reported cached response to + // determine its freshness. + if (OmniboxFieldTrial::kZeroSuggestCacheCounterfactual.Get() && client) { + // Make sure the request is not cacheable. + search_terms_args.zero_suggest_cache_duration_sec = 0; + + client->GetRemoteSuggestionsService(/*create_if_necessary=*/true) + ->CreateSuggestionsRequest( + search_terms_args, client->GetTemplateURLService(), + base::BindOnce(&ZeroSuggestProvider:: + OnRemoteSuggestionsCounterfactualLoaderAvailable, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce( + &ZeroSuggestProvider::OnCounterfactualURLLoadComplete, + weak_ptr_factory_.GetWeakPtr(), is_prefetch, + original_response)); + } const bool response_received = response_body && source->NetError() == net::OK && (source->ResponseInfo() && source->ResponseInfo()->headers && source->ResponseInfo()->headers->response_code() == 200); - - if (source->LoadedFromCache()) { - LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE, - is_prefetch); - - // Issue a follow-up non-cacheable request in the counterfactual arm if the - // response is loaded from the HTTP cache. The new response is compared - // against the original cached response to determine HTTP cache validity. - if (OmniboxFieldTrial::kZeroSuggestCacheCounterfactual.Get() && - OmniboxFieldTrial::kZeroSuggestCacheDurationSec.Get() > 0 && - response_received && client) { - // Make sure the request is not cacheable. - search_terms_args.zero_suggest_cache_duration_sec = 0; - - const std::string original_response = *response_body; - client->GetRemoteSuggestionsService(/*create_if_necessary=*/true) - ->CreateSuggestionsRequest( - search_terms_args, client->GetTemplateURLService(), - base::BindOnce( - &ZeroSuggestProvider:: - OnRemoteSuggestionsCounterfactualLoaderAvailable, - weak_ptr_factory_.GetWeakPtr()), - base::BindOnce( - &ZeroSuggestProvider::OnCounterfactualURLLoadComplete, - weak_ptr_factory_.GetWeakPtr(), is_prefetch, - original_response)); - } - } - const bool results_updated = response_received && UpdateResults(SearchSuggestionParser::ExtractJsonData( @@ -393,9 +388,8 @@ DCHECK(!source->LoadedFromCache()); if (response && original_response != *response) { - LogOmniboxZeroSuggestRequest( - ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE_IS_OUT_OF_DATE, - original_is_prefetch); + LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_CACHED_RESPONSE_IS_OUT_OF_DATE, + original_is_prefetch); } counterfactual_loader_.reset(); @@ -600,10 +594,10 @@ return true; } -void ZeroSuggestProvider::MaybeUseStoredResponse() { +std::string ZeroSuggestProvider::MaybeUseStoredResponse() { // Use the stored response only if running the REMOTE_NO_URL variant. if (result_type_running_ != REMOTE_NO_URL) { - return; + return ""; } std::string json_data = @@ -615,6 +609,7 @@ &results_)) ConvertResultsToAutocompleteMatches(); } + return json_data; } // static
diff --git a/components/omnibox/browser/zero_suggest_provider.h b/components/omnibox/browser/zero_suggest_provider.h index 30bd087..3db3065d 100644 --- a/components/omnibox/browser/zero_suggest_provider.h +++ b/components/omnibox/browser/zero_suggest_provider.h
@@ -134,6 +134,7 @@ void OnURLLoadComplete(const base::WeakPtr<AutocompleteProviderClient> client, TemplateURLRef::SearchTermsArgs search_terms_args, bool is_prefetch, + const std::string& original_response, base::TimeTicks request_time, const network::SimpleURLLoader* source, std::unique_ptr<std::string> response_body); @@ -197,8 +198,9 @@ // functions, so the reader has to look in two places. bool AllowZeroSuggestSuggestions(const AutocompleteInput& input) const; - // Populates |matches_| using the stored zero suggest response, if any. - void MaybeUseStoredResponse(); + // Populates |matches_| using the stored zero suggest response, if applicable. + // Returns the stored zero suggest response, whether or not it was used. + std::string MaybeUseStoredResponse(); // Returns the type of results that should be generated for the current // context.
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java index 6e1084d..fde55fc 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
@@ -353,7 +353,7 @@ button.setOnClickListener((View v) -> { recordAction(PageInfoAction.PAGE_INFO_FORGET_SITE_OPENED); mForgetSiteDialog = - new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(mContext, R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.page_info_forget_site_title) .setMessage(R.string.page_info_forget_site_message) .setPositiveButton(R.string.page_info_forget_site_confirmation_button,
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesPreference.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesPreference.java index 99a0b2f..9334fb4 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesPreference.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesPreference.java
@@ -103,7 +103,7 @@ if (mDeleteDisabled || !mDataUsed) return; mConfirmationDialog = - new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.page_info_cookies_clear) .setMessage(R.string.page_info_cookies_clear_confirmation) .setMessage(
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java index d6a322a..21ac5fa5 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java
@@ -271,7 +271,7 @@ // Fetch the dim amount from styles.xml and default to 0.65 if not found. int[] attrs = {android.R.attr.backgroundDimAmount}; TypedArray typedArray = mSheetDialog.getContext().obtainStyledAttributes( - R.style.Theme_Chromium_ModalDialog, attrs); + R.style.ThemeOverlay_BrowserUI_ModalDialog, attrs); float dimAmount = typedArray.getFloat(0, 0.65f); mSheetDialog.getWindow().setDimAmount(dimAmount);
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/AndroidPaymentApp.java b/components/payments/content/android/java/src/org/chromium/components/payments/AndroidPaymentApp.java index e1c7cc3..7d7391a 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/AndroidPaymentApp.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/AndroidPaymentApp.java
@@ -130,7 +130,7 @@ denyCallback.onResult(ErrorStrings.ACTIVITY_NOT_FOUND); return; } - new AlertDialog.Builder(context, R.style.Theme_Chromium_AlertDialog) + new AlertDialog.Builder(context, R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle(R.string.external_app_leave_incognito_warning_title) .setMessage(R.string.external_payment_app_leave_incognito_warning) .setPositiveButton(
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn index 819693d..66e69e7 100644 --- a/components/performance_manager/BUILD.gn +++ b/components/performance_manager/BUILD.gn
@@ -148,6 +148,7 @@ "public/render_frame_host_proxy.h", "public/render_process_host_id.h", "public/render_process_host_proxy.h", + "public/user_tuning/prefs.h", "public/v8_memory/v8_detailed_memory.h", "public/v8_memory/v8_detailed_memory_any_seq.h", "public/v8_memory/web_memory.h", @@ -164,6 +165,7 @@ "service_worker_context_adapter.h", "tab_helper_frame_node_source.cc", "tab_helper_frame_node_source.h", + "user_tuning/prefs.cc", "v8_memory/v8_context_tracker.cc", "v8_memory/v8_context_tracker.h", "v8_memory/v8_context_tracker_helpers.cc", @@ -189,6 +191,7 @@ deps = [ "//build:chromeos_buildflags", + "//components/pref_registry:pref_registry", "//third_party/blink/public/common:headers", ]
diff --git a/components/performance_manager/DEPS b/components/performance_manager/DEPS index 5686d456f..e33abcc 100644 --- a/components/performance_manager/DEPS +++ b/components/performance_manager/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+components/memory_pressure", + "+components/pref_registry", "+components/services/storage/public/cpp", "+components/ukm", "+content/public/common",
diff --git a/components/performance_manager/public/user_tuning/prefs.h b/components/performance_manager/public/user_tuning/prefs.h new file mode 100644 index 0000000..a2ea8c2 --- /dev/null +++ b/components/performance_manager/public/user_tuning/prefs.h
@@ -0,0 +1,22 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_USER_TUNING_PREFS_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_USER_TUNING_PREFS_H_ + +namespace user_prefs { +class PrefRegistrySyncable; +} + +namespace performance_manager::user_tuning::prefs { + +extern const char kHighEfficiencyModeEnabled[]; + +extern const char kBatterySaverModeEnabled[]; + +void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + +} // namespace performance_manager::user_tuning::prefs + +#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_USER_TUNING_PREFS_H_
diff --git a/components/performance_manager/user_tuning/prefs.cc b/components/performance_manager/user_tuning/prefs.cc new file mode 100644 index 0000000..0c698319 --- /dev/null +++ b/components/performance_manager/user_tuning/prefs.cc
@@ -0,0 +1,22 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/public/user_tuning/prefs.h" + +#include "components/pref_registry/pref_registry_syncable.h" + +namespace performance_manager::user_tuning::prefs { + +const char kHighEfficiencyModeEnabled[] = + "performance_tuning.high_efficiency_mode.enabled"; + +const char kBatterySaverModeEnabled[] = + "performance_tuning.battery_saver_mode.enabled"; + +void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterBooleanPref(kHighEfficiencyModeEnabled, false); + registry->RegisterBooleanPref(kBatterySaverModeEnabled, false); +} + +} // namespace performance_manager::user_tuning::prefs \ No newline at end of file
diff --git a/components/reporting/util/test_support_callbacks.h b/components/reporting/util/test_support_callbacks.h index 4422e67..5ed5619 100644 --- a/components/reporting/util/test_support_callbacks.h +++ b/components/reporting/util/test_support_callbacks.h
@@ -5,12 +5,15 @@ #ifndef COMPONENTS_REPORTING_UTIL_TEST_SUPPORT_CALLBACKS_H_ #define COMPONENTS_REPORTING_UTIL_TEST_SUPPORT_CALLBACKS_H_ -#include <atomic> #include <tuple> -#include "base/callback.h" +#include "base/atomic_ref_count.h" +#include "base/bind.h" +#include "base/callback_forward.h" #include "base/logging.h" #include "base/run_loop.h" +#include "base/synchronization/lock.h" +#include "base/thread_annotations.h" namespace reporting { namespace test { @@ -24,6 +27,9 @@ // ... = e.result(); // Will wait for e.cb() to be called and return the // collected result. // +// This class follows base::BarrierCallback in using mutex Lock. +// It can only be done in tests, never in production code. +// template <typename ResType> class TestEvent { public: @@ -33,6 +39,7 @@ TestEvent& operator=(const TestEvent& other) = delete; ResType result() { run_loop_.Run(); + base::ReleasableAutoLock lock(&mutex_); return std::forward<ResType>(result_); } @@ -42,17 +49,22 @@ // when the caller requires it. // If the caller expects OnceCallback, result will be converted automatically. base::RepeatingCallback<void(ResType res)> cb() { - return base::BindRepeating( - [](base::RunLoop* run_loop, ResType* result, ResType res) { - *result = std::forward<ResType>(res); - run_loop->Quit(); - }, - base::Unretained(&run_loop_), base::Unretained(&result_)); + return base::BindRepeating(&TestEvent<ResType>::Callback, + base::Unretained(this)); } private: + void Callback(ResType res) { + { + base::ReleasableAutoLock lock(&mutex_); + result_ = std::forward<ResType>(res); + } + run_loop_.Quit(); + } + base::RunLoop run_loop_; - ResType result_; + base::Lock mutex_; + ResType result_ GUARDED_BY(mutex_); }; // Usage (in tests only): @@ -64,6 +76,9 @@ // caller. std::tie(res1, res2, ...) = e.result(); // Will wait for e.cb() to // be called and return the collected results. // +// This class follows base::BarrierCallback in using mutex Lock. +// It can only be done in tests, never in production code. +// template <typename... ResType> class TestMultiEvent { public: @@ -73,23 +88,28 @@ TestMultiEvent& operator=(const TestMultiEvent& other) = delete; std::tuple<ResType...> result() { run_loop_.Run(); + base::ReleasableAutoLock lock(&mutex_); return std::forward<std::tuple<ResType...>>(result_); } // Completion callback to hand over to the processing method. base::RepeatingCallback<void(ResType... res)> cb() { - return base::BindRepeating( - [](base::RunLoop* run_loop, std::tuple<ResType...>* result, - ResType... res) { - *result = std::forward_as_tuple(res...); - run_loop->Quit(); - }, - base::Unretained(&run_loop_), base::Unretained(&result_)); + return base::BindRepeating(&TestMultiEvent<ResType...>::Callback, + base::Unretained(this)); } private: + void Callback(ResType... res) { + { + base::ReleasableAutoLock lock(&mutex_); + result_ = std::forward_as_tuple(res...); + } + run_loop_.Quit(); + } + base::RunLoop run_loop_; - std::tuple<ResType...> result_; + base::Lock mutex_; + std::tuple<ResType...> result_ GUARDED_BY(mutex_); }; // Usage (in tests only): @@ -114,15 +134,13 @@ TestCallbackWaiter(const TestCallbackWaiter& other) = delete; TestCallbackWaiter& operator=(const TestCallbackWaiter& other) = delete; - void Attach(size_t more = 1) { - const size_t old_counter = counter_.fetch_add(more); - DCHECK_GT(old_counter, 0u) << "Cannot attach when already being released"; + void Attach(int more = 1) { + const int old_counter = counter_.Increment(more); + DCHECK_GT(old_counter, 0) << "Cannot attach when already being released"; } void Signal() { - const size_t old_counter = counter_.fetch_sub(1); - DCHECK_GT(old_counter, 0u) << "Already being released"; - if (old_counter > 1u) { + if (counter_.Decrement()) { // There are more owners. return; } @@ -136,11 +154,11 @@ } private: - std::atomic<size_t> counter_{1}; // Owned by constructor. + base::AtomicRefCount counter_{1}; // Owned by constructor. base::RunLoop run_loop_; }; -// RAAI wrapper for TestCallbackWaiter. +// RAII wrapper for TestCallbackWaiter. // // Usage: // {
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc index cef74a5..376a27d 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
@@ -184,8 +184,7 @@ NOTIMPLEMENTED(); } -#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) && !BUILDFLAG(IS_CHROMEOS) && \ - !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) void FlatBufferModelScorer::ApplyVisualTfLiteModel( const SkBitmap& bitmap, base::OnceCallback<void(std::vector<double>)> callback) const {
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h index 9d3505b3..7a8d42888 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h +++ b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h
@@ -54,9 +54,7 @@ base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback) const override; -// TODO(crbug/1278502): This is disabled as a temporary measure due to crashes. -#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) && !BUILDFLAG(IS_CHROMEOS) && \ - !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) void ApplyVisualTfLiteModel( const SkBitmap& bitmap, base::OnceCallback<void(std::vector<double>)> callback) const override;
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc index 821e84f..60809e379 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
@@ -289,9 +289,7 @@ *bitmap_, std::move(verdict), base::BindOnce(&PhishingClassifier::OnVisualTargetsMatched, weak_factory_.GetWeakPtr())); -// TODO(crbug/1278502): This is disabled as a temporary measure due to crashes. -#elif BUILDFLAG(BUILD_WITH_TFLITE_LIB) && !BUILDFLAG(IS_CHROMEOS) && \ - !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#elif BUILDFLAG(BUILD_WITH_TFLITE_LIB) scorer_->ApplyVisualTfLiteModel( *bitmap_, base::BindOnce(&PhishingClassifier::OnVisualTfLiteModelDone, weak_factory_.GetWeakPtr(), std::move(verdict))); @@ -308,10 +306,7 @@ } base::UmaHistogramTimes("SBClientPhishing.VisualComparisonTime", base::TimeTicks::Now() - visual_matching_start_); - -// TODO(crbug/1278502): This is disabled as a temporary measure due to crashes. -#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) && !BUILDFLAG(IS_CHROMEOS) && \ - !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) scorer_->ApplyVisualTfLiteModel( *bitmap_, base::BindOnce(&PhishingClassifier::OnVisualTfLiteModelDone, weak_factory_.GetWeakPtr(), std::move(verdict)));
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc index 62c81167..392cfe55 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc
@@ -150,8 +150,7 @@ std::move(callback)); } -#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) && !BUILDFLAG(IS_CHROMEOS) && \ - !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) void ProtobufModelScorer::ApplyVisualTfLiteModel( const SkBitmap& bitmap, base::OnceCallback<void(std::vector<double>)> callback) const {
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h index a562327..eccf1fc 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h +++ b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h
@@ -52,9 +52,7 @@ base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback) const override; -// TODO(crbug/1278502): This is disabled as a temporary measure due to crashes. -#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) && !BUILDFLAG(IS_CHROMEOS) && \ - !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) void ApplyVisualTfLiteModel( const SkBitmap& bitmap, base::OnceCallback<void(std::vector<double>)> callback) const override;
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h index 51c3ac8..4e32fe0e 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h +++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
@@ -78,9 +78,7 @@ base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback) const = 0; -// TODO(crbug/1278502): This is disabled as a temporary measure due to crashes. -#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) && !BUILDFLAG(IS_CHROMEOS) && \ - !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) // This method applies the TfLite visual model to the given bitmap. It // asynchronously returns the list of scores for each category, in the same // order as `tflite_thresholds()`.
diff --git a/components/safe_browsing/content/resources/download_file_types.asciipb b/components/safe_browsing/content/resources/download_file_types.asciipb index b00c499c..05a2ba86 100644 --- a/components/safe_browsing/content/resources/download_file_types.asciipb +++ b/components/safe_browsing/content/resources/download_file_types.asciipb
@@ -8,7 +8,7 @@ ## ## Top level settings ## -version_id: 49 +version_id: 50 sampled_ping_probability: 0.01 max_archived_binaries_to_report: 10 default_file_type { @@ -1769,6 +1769,16 @@ auto_open_hint: DISALLOW_AUTO_OPEN } } +file_types { + extension: "inetloc" + uma_value: 398 + ping_setting: FULL_PING + platform_settings { + platform: PLATFORM_MAC + danger_level: DANGEROUS + auto_open_hint: DISALLOW_AUTO_OPEN + } +} # VBScript files. May open with Windows Script Host and execute with # user privileges.
diff --git a/components/safe_browsing/content/resources/download_file_types_experiment.asciipb b/components/safe_browsing/content/resources/download_file_types_experiment.asciipb index e4699f25..615c1cf 100644 --- a/components/safe_browsing/content/resources/download_file_types_experiment.asciipb +++ b/components/safe_browsing/content/resources/download_file_types_experiment.asciipb
@@ -12,7 +12,7 @@ ## version id is larger than the version id in download_file_types.asciipb. If ## there isn't an ongoing experiment, this version id is equal to the version id ## in download_file_types.asciipb. -version_id: 49 +version_id: 50 sampled_ping_probability: 0.01 max_archived_binaries_to_report: 10 default_file_type { @@ -1773,6 +1773,16 @@ auto_open_hint: DISALLOW_AUTO_OPEN } } +file_types { + extension: "inetloc" + uma_value: 398 + ping_setting: FULL_PING + platform_settings { + platform: PLATFORM_MAC + danger_level: DANGEROUS + auto_open_hint: DISALLOW_AUTO_OPEN + } +} # VBScript files. May open with Windows Script Host and execute with # user privileges.
diff --git a/components/segmentation_platform/components_unittests.filter b/components/segmentation_platform/components_unittests.filter index 14bfe5a..31e8d1d 100644 --- a/components/segmentation_platform/components_unittests.filter +++ b/components/segmentation_platform/components_unittests.filter
@@ -19,6 +19,7 @@ SegmentationResultPrefsTest.* SegmentationUkmHelperTest.* SegmentInfoDatabaseTest.* +SegmentResultProviderTest.* SegmentScoreProviderTest.* SegmentSelectorTest.* ServiceProxyImplTest.* @@ -30,9 +31,9 @@ StatsTest.* TrainingDataCollectorImplTest.* UkmConfigTest.* -UkmObserverTest.* -UrlSignalHandlerTest.* UkmDatabaseBackendTest.* UkmMetricsTableTest.* +UkmObserverTest.* UkmUrlTableTest.* +UrlSignalHandlerTest.* UserActionSignalHandlerTest.*
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn index a24fca41..60ee5cb 100644 --- a/components/segmentation_platform/internal/BUILD.gn +++ b/components/segmentation_platform/internal/BUILD.gn
@@ -222,6 +222,7 @@ "scheduler/model_execution_scheduler_unittest.cc", "segmentation_platform_service_impl_unittest.cc", "segmentation_ukm_helper_unittest.cc", + "selection/segment_result_provider_unittest.cc", "selection/segment_score_provider_unittest.cc", "selection/segment_selector_unittest.cc", "selection/segmentation_result_prefs_unittest.cc",
diff --git a/components/segmentation_platform/internal/execution/default_model_manager.cc b/components/segmentation_platform/internal/execution/default_model_manager.cc index d939590..20ab094d 100644 --- a/components/segmentation_platform/internal/execution/default_model_manager.cc +++ b/components/segmentation_platform/internal/execution/default_model_manager.cc
@@ -11,7 +11,8 @@ DefaultModelManager::DefaultModelManager( ModelProviderFactory* model_provider_factory, - const std::vector<OptimizationTarget>& segment_ids) { + const std::vector<OptimizationTarget>& segment_ids) + : model_provider_factory_(model_provider_factory) { for (OptimizationTarget segment_id : segment_ids) { if (!model_provider_factory) continue; @@ -26,6 +27,14 @@ DefaultModelManager::~DefaultModelManager() = default; +ModelProvider* DefaultModelManager::GetDefaultProvider( + OptimizationTarget segment_id) { + auto it = default_model_providers_.find(segment_id); + if (it != default_model_providers_.end()) + return it->second.get(); + return nullptr; +} + void DefaultModelManager::GetAllSegmentInfoFromDefaultModel( const std::vector<OptimizationTarget>& segment_ids, MultipleSegmentInfoCallback callback) { @@ -118,4 +127,9 @@ std::move(callback).Run(std::move(merged_results)); } +void DefaultModelManager::SetDefaultProvidersForTesting( + std::map<OptimizationTarget, std::unique_ptr<ModelProvider>>&& providers) { + default_model_providers_ = std::move(providers); +} + } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/execution/default_model_manager.h b/components/segmentation_platform/internal/execution/default_model_manager.h index 1724217..c66a0ad 100644 --- a/components/segmentation_platform/internal/execution/default_model_manager.h +++ b/components/segmentation_platform/internal/execution/default_model_manager.h
@@ -52,13 +52,19 @@ SegmentInfoDatabase* segment_database, MultipleSegmentInfoCallback callback); - private: // Called to get the segment info from the default model for a given set of // segment IDs. virtual void GetAllSegmentInfoFromDefaultModel( const std::vector<OptimizationTarget>& segment_ids, MultipleSegmentInfoCallback callback); + // Returns the default provider or `nulllptr` when unavailable. + ModelProvider* GetDefaultProvider(OptimizationTarget segment_id); + + void SetDefaultProvidersForTesting( + std::map<OptimizationTarget, std::unique_ptr<ModelProvider>>&& providers); + + private: void GetNextSegmentInfoFromDefaultModel( std::unique_ptr<SegmentInfoList> result, std::deque<OptimizationTarget> remaining_segment_ids, @@ -84,6 +90,7 @@ // Default model providers. std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> default_model_providers_; + const raw_ptr<ModelProviderFactory> model_provider_factory_; base::WeakPtrFactory<DefaultModelManager> weak_ptr_factory_{this}; };
diff --git a/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc b/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc index 8d151a0..52f5691 100644 --- a/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc +++ b/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc
@@ -34,6 +34,7 @@ void DummyModelExecutionManager::ExecuteModel( const proto::SegmentInfo& segment_info, + ModelProvider* explicit_provider, ModelExecutionCallback callback) { base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE,
diff --git a/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h b/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h index 8cdfdbd..dd5fc5a 100644 --- a/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h +++ b/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h
@@ -28,6 +28,7 @@ // ModelExecutionManager overrides. void ExecuteModel(const proto::SegmentInfo& segment_info, + ModelProvider* explicit_provider, ModelExecutionCallback callback) override; };
diff --git a/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc b/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc index d3cd9f6..f41b69e8 100644 --- a/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc +++ b/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc
@@ -35,7 +35,7 @@ void ExecuteModel() { base::RunLoop loop; model_execution_manager_->ExecuteModel( - proto::SegmentInfo(), + proto::SegmentInfo(), nullptr, base::BindOnce(&DummyModelExecutionManagerTest::OnExecutionCallback, base::Unretained(this), loop.QuitClosure())); loop.Run();
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager.h b/components/segmentation_platform/internal/execution/model_execution_manager.h index ca6666c..66211ca 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager.h +++ b/components/segmentation_platform/internal/execution/model_execution_manager.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_H_ #define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_H_ +#include <memory> #include <utility> #include "base/callback_forward.h" @@ -15,6 +16,8 @@ class SegmentInfo; } // namespace proto +class ModelProvider; + // The ModelExecutionManager is the core class for interacting with the ML // framework. The only requirement is to pass in the segment ID to execute the // model for, and a callback will be posted with the result, once the @@ -38,7 +41,10 @@ // Called to execute a given model. This assumes that data has been collected // for long enough for each of the individual ML features. + // If `explicit_provider` is set, then the execution will use it instead of + // the original provider. virtual void ExecuteModel(const proto::SegmentInfo& segment_info, + ModelProvider* explicit_provider, ModelExecutionCallback callback) = 0; protected:
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc b/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc index c7de750..836c83f 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc +++ b/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc
@@ -68,7 +68,7 @@ segment_info.set_segment_id( OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB); model_execution_manager->ExecuteModel( - segment_info, + segment_info, nullptr, base::BindOnce( [](base::RepeatingClosure quit, const std::pair<float, ModelExecutionStatus>&) { quit.Run(); },
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc index 2318c6c2..ef085df 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
@@ -77,6 +77,7 @@ OptimizationTarget segment_id; int64_t model_version = 0; raw_ptr<ModelProvider> model_provider = nullptr; + bool is_explicit_provider = false; ModelExecutionCallback callback; std::vector<float> input_tensor; base::Time total_execution_start_time; @@ -124,25 +125,33 @@ void ModelExecutionManagerImpl::ExecuteModel( const proto::SegmentInfo& segment_info, + ModelProvider* explicit_provider, ModelExecutionCallback callback) { OptimizationTarget segment_id = segment_info.segment_id(); - auto model_provider_it = model_providers_.find(segment_id); - DCHECK(model_provider_it != model_providers_.end()); - - ModelProvider& provider = *model_provider_it->second; // Create an ExecutionState that will stay with this request until it has been // fully processed. auto state = std::make_unique<ExecutionState>(); state->segment_id = segment_id; - state->model_provider = &provider; + + if (explicit_provider) { + state->model_provider = explicit_provider; + state->is_explicit_provider = true; + } else { + auto model_provider_it = model_providers_.find(segment_id); + DCHECK(model_provider_it != model_providers_.end()); + state->model_provider = model_provider_it->second.get(); + state->is_explicit_provider = false; + } + DCHECK(state->model_provider); + state->callback = std::move(callback); state->total_execution_start_time = clock_->Now(); ModelExecutionTraceEvent trace_event( "ModelExecutionManagerImpl::ExecuteModel", *state); - if (!provider.ModelAvailable()) { + if (!state->model_provider->ModelAvailable()) { RunModelExecutionCallback(std::move(state), 0, ModelExecutionStatus::kSkippedModelNotReady); return; @@ -184,11 +193,6 @@ std::unique_ptr<ExecutionState> state) { ModelExecutionTraceEvent trace_event( "ModelExecutionManagerImpl::ExecuteModel", *state); - auto it = model_providers_.find(state->segment_id); - DCHECK(it != model_providers_.end()); - - ModelProvider* handler = (*it).second.get(); - if (VLOG_IS_ON(1)) { std::stringstream log_input; for (unsigned i = 0; i < state->input_tensor.size(); ++i) @@ -202,7 +206,8 @@ stats::RecordModelExecutionZeroValuePercent(state->segment_id, const_input_tensor); state->model_execution_start_time = clock_->Now(); - handler->ExecuteModelWithInput( + ModelProvider* model = state->model_provider; + model->ExecuteModelWithInput( const_input_tensor, base::BindOnce(&ModelExecutionManagerImpl::OnModelExecutionComplete, weak_ptr_factory_.GetWeakPtr(), std::move(state))); @@ -244,7 +249,8 @@ stats::RecordModelExecutionDurationTotal( state->segment_id, status, clock_->Now() - state->total_execution_start_time); - stats::RecordModelExecutionStatus(state->segment_id, status); + stats::RecordModelExecutionStatus(state->segment_id, + state->is_explicit_provider, status); std::move(state->callback).Run(std::make_pair(result, status)); }
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl.h b/components/segmentation_platform/internal/execution/model_execution_manager_impl.h index 957140d..818a2fe 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl.h +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl.h
@@ -68,6 +68,7 @@ // ModelExecutionManager overrides. void ExecuteModel(const proto::SegmentInfo& segment_info, + ModelProvider* explicit_provider, ModelExecutionCallback callback) override; private:
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc index 2b197ca9..cb4eb56 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
@@ -126,12 +126,13 @@ void RunUntilIdle() { task_environment_.RunUntilIdle(); } - void ExecuteModel(const std::pair<float, ModelExecutionStatus>& expected) { + void ExecuteModel(const std::pair<float, ModelExecutionStatus>& expected, + ModelProvider* explicit_provider = nullptr) { proto::SegmentInfo* info = segment_database_->FindOrCreateSegment( OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB); base::RunLoop loop; model_execution_manager_->ExecuteModel( - *info, + *info, std::move(explicit_provider), base::BindOnce(&ModelExecutionManagerTest::OnExecutionCallback, base::Unretained(this), loop.QuitClosure(), expected)); loop.Run(); @@ -427,4 +428,37 @@ ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess)); } +TEST_F(ModelExecutionManagerTest, ExecuteWithExplicitProvider) { + auto segment_id = + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; + CreateModelExecutionManager({segment_id}, base::DoNothing()); + + // Initialize with required metadata. + segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR); + std::string user_action_name = "some_user_action"; + segment_database_->AddUserActionFeature(segment_id, user_action_name, 3, 3, + proto::Aggregation::BUCKETED_COUNT); + + EXPECT_CALL(*feature_list_query_processor_, + ProcessFeatureList(_, segment_id, clock_.Now(), _)) + .WillOnce(RunOnceCallback<3>(/*error=*/false, + std::vector<float>{1, 2, 3, 4, 5, 6, 7})); + + // This provider should not be used since `explicit_provider` is set, and + // explicit prvider should be used for execution. + EXPECT_CALL(FindHandler(segment_id), ModelAvailable()).Times(0); + EXPECT_CALL(FindHandler(segment_id), ExecuteModelWithInput(_, _)).Times(0); + + auto explicit_provider = + std::make_unique<MockModelProvider>(segment_id, base::DoNothing()); + EXPECT_CALL(*explicit_provider, ModelAvailable()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*explicit_provider, + ExecuteModelWithInput(std::vector<float>{1, 2, 3, 4, 5, 6, 7}, _)) + .WillOnce(RunOnceCallback<1>(absl::make_optional(0.8))); + + ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess), + explicit_provider.get()); +} + } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc b/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc index 7d54139..c136c5f 100644 --- a/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc +++ b/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc
@@ -14,6 +14,7 @@ #include "components/segmentation_platform/internal/execution/model_execution_manager.h" #include "components/segmentation_platform/internal/platform_options.h" #include "components/segmentation_platform/internal/stats.h" +#include "components/segmentation_platform/public/model_provider.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace segmentation_platform { @@ -72,7 +73,7 @@ base::BindOnce(&ModelExecutionSchedulerImpl::OnModelExecutionCompleted, weak_ptr_factory_.GetWeakPtr(), segment_id))); model_execution_manager_->ExecuteModel( - segment_info, outstanding_requests_[segment_id].callback()); + segment_info, nullptr, outstanding_requests_[segment_id].callback()); } void ModelExecutionSchedulerImpl::OnModelExecutionCompleted( @@ -126,6 +127,7 @@ VLOG(1) << "Segmentation model not executed since it has fresh results."; stats::RecordModelExecutionStatus( segment_info.segment_id(), + /*default_provider=*/false, ModelExecutionStatus::kSkippedHasFreshResults); return false; } @@ -136,6 +138,7 @@ VLOG(1) << "Segmentation model not executed since results are not expired."; stats::RecordModelExecutionStatus( segment_info.segment_id(), + /*default_provider=*/false, ModelExecutionStatus::kSkippedResultNotExpired); return false; } @@ -145,6 +148,7 @@ segment_info.model_metadata())) { stats::RecordModelExecutionStatus( segment_info.segment_id(), + /*default_provider=*/false, ModelExecutionStatus::kSkippedNotEnoughSignals); VLOG(1) << "Segmentation model not executed since metadata requirements " "not met."; @@ -170,7 +174,9 @@ // TODO(ssid): Consider removing this enum, this is the only case where the // execution status is recorded twice for the same execution request. stats::RecordModelExecutionStatus( - segment_id, ModelExecutionStatus::kFailedToSaveResultAfterSuccess); + segment_id, + /*default_provider=*/false, + ModelExecutionStatus::kFailedToSaveResultAfterSuccess); return; }
diff --git a/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc b/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc index d6fb943..8e791d4 100644 --- a/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc +++ b/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc
@@ -13,6 +13,7 @@ #include "components/segmentation_platform/internal/database/test_segment_info_database.h" #include "components/segmentation_platform/internal/execution/model_execution_manager.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" +#include "components/segmentation_platform/public/model_provider.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -43,7 +44,9 @@ MockModelExecutionManager() = default; MOCK_METHOD(void, ExecuteModel, - (const proto::SegmentInfo&, ModelExecutionCallback)); + (const proto::SegmentInfo&, + ModelProvider*, + ModelExecutionCallback)); }; class ModelExecutionSchedulerTest : public testing::Test { @@ -89,7 +92,7 @@ // If the metadata DOES NOT meet the signal requirement, we SHOULD NOT try to // execute the model. EXPECT_CALL(model_execution_manager_, - ExecuteModel(IsForTarget(kTestOptimizationTarget), _)) + ExecuteModel(IsForTarget(kTestOptimizationTarget), _, _)) .Times(0); EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) .WillOnce(Return(false)); @@ -98,7 +101,7 @@ // If the metadata DOES meet the signal requirement, and we have no old, // PredictionResult we SHOULD try to execute the model. EXPECT_CALL(model_execution_manager_, - ExecuteModel(IsForTarget(kTestOptimizationTarget), _)) + ExecuteModel(IsForTarget(kTestOptimizationTarget), nullptr, _)) .Times(1); EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) .WillOnce(Return(true)); @@ -110,7 +113,7 @@ prediction_result->set_timestamp_us( clock_.Now().ToDeltaSinceWindowsEpoch().InMicroseconds()); EXPECT_CALL(model_execution_manager_, - ExecuteModel(IsForTarget(kTestOptimizationTarget), _)) + ExecuteModel(IsForTarget(kTestOptimizationTarget), _, _)) .Times(0); EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) .WillRepeatedly(Return(true)); // Ensure this part has positive result. @@ -124,7 +127,7 @@ prediction_result->set_timestamp_us( not_expired_timestamp.ToDeltaSinceWindowsEpoch().InMicroseconds()); EXPECT_CALL(model_execution_manager_, - ExecuteModel(IsForTarget(kTestOptimizationTarget), _)) + ExecuteModel(IsForTarget(kTestOptimizationTarget), _, _)) .Times(0); model_execution_scheduler_->OnNewModelInfoReady(*segment_info); @@ -135,7 +138,7 @@ prediction_result->set_timestamp_us( just_expired_timestamp.ToDeltaSinceWindowsEpoch().InMicroseconds()); EXPECT_CALL(model_execution_manager_, - ExecuteModel(IsForTarget(kTestOptimizationTarget), _)) + ExecuteModel(IsForTarget(kTestOptimizationTarget), nullptr, _)) .Times(1); model_execution_scheduler_->OnNewModelInfoReady(*segment_info); } @@ -148,12 +151,12 @@ // etc. EXPECT_CALL(model_execution_manager_, - ExecuteModel(IsForTarget(kTestOptimizationTarget), _)) + ExecuteModel(IsForTarget(kTestOptimizationTarget), nullptr, _)) .Times(1); EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) .WillRepeatedly(Return(true)); EXPECT_CALL(model_execution_manager_, - ExecuteModel(IsForTarget(kTestOptimizationTarget2), _)) + ExecuteModel(IsForTarget(kTestOptimizationTarget2), _, _)) .Times(0); // TODO(shaktisahu): Add test when the signal collection returns false.
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc index ec1718bf..1431a87 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
@@ -151,7 +151,8 @@ std::make_unique<SegmentSelectorImpl>( segment_info_database_.get(), signal_storage_config_.get(), segmentation_result_prefs_.get(), config.get(), clock, - platform_options_, model_provider_factory_.get()); + platform_options_, default_model_manager_.get(), + model_execution_manager_.get()); } proxy_ = std::make_unique<ServiceProxyImpl>(segment_info_database_.get(),
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider.cc b/components/segmentation_platform/internal/selection/segment_result_provider.cc index f8cec69..93bcc4cc 100644 --- a/components/segmentation_platform/internal/selection/segment_result_provider.cc +++ b/components/segmentation_platform/internal/selection/segment_result_provider.cc
@@ -12,22 +12,40 @@ #include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" +#include "components/segmentation_platform/internal/execution/default_model_manager.h" +#include "components/segmentation_platform/internal/execution/model_execution_manager.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" +#include "components/segmentation_platform/public/model_provider.h" namespace segmentation_platform { namespace { +int ComputeDiscreteMapping(const std::string& segmentation_key, + const proto::SegmentInfo& segment_info) { + int rank = metadata_utils::ConvertToDiscreteScore( + segmentation_key, segment_info.prediction_result().result(), + segment_info.model_metadata()); + VLOG(1) << __func__ + << ": segment=" << OptimizationTarget_Name(segment_info.segment_id()) + << ": result=" << segment_info.prediction_result().result() + << ", rank=" << rank; + + return rank; +} + class SegmentResultProviderImpl : public SegmentResultProvider { public: SegmentResultProviderImpl(SegmentInfoDatabase* segment_database, SignalStorageConfig* signal_storage_config, - ModelProviderFactory* model_provider_factory, + DefaultModelManager* default_model_manager, + ModelExecutionManager* execution_manager, base::Clock* clock, bool force_refresh_results) : segment_database_(segment_database), signal_storage_config_(signal_storage_config), - model_provider_factory_(model_provider_factory), + default_model_manager_(default_model_manager), + execution_manager_(execution_manager), clock_(clock), force_refresh_results_(force_refresh_results), task_runner_(base::SequencedTaskRunnerHandle::Get()) {} @@ -40,14 +58,34 @@ SegmentResultProviderImpl& operator=(SegmentResultProviderImpl&) = delete; private: - void OnGetSegmentInfo(OptimizationTarget segment_id, - const std::string& segmentation_key, - SegmentResultCallback callback, + struct RequestState { + OptimizationTarget segment_id; + SegmentResultCallback callback; + raw_ptr<ModelProvider> default_provider; + std::string segmentation_key; + }; + + void OnGetSegmentInfo(std::unique_ptr<RequestState> request_state, absl::optional<proto::SegmentInfo> available_segment); + void TryGetScoreFromDefaultModel( + std::unique_ptr<RequestState> request_state, + SegmentResultProvider::ResultState existing_state); + void OnDefaultModelFetched( + std::unique_ptr<RequestState> request_state, + std::unique_ptr<DefaultModelManager::SegmentInfoList> metadata_list); + void OnDefaultModelExecuted( + std::unique_ptr<RequestState> request_state, + proto::SegmentInfo segment_info, + const std::pair<float, ModelExecutionStatus>& result); + + void PostResultCallback(std::unique_ptr<RequestState> request_state, + std::unique_ptr<SegmentResult> result); + const raw_ptr<SegmentInfoDatabase> segment_database_; const raw_ptr<SignalStorageConfig> signal_storage_config_; - const raw_ptr<ModelProviderFactory> model_provider_factory_; + const raw_ptr<DefaultModelManager> default_model_manager_; + const raw_ptr<ModelExecutionManager> execution_manager_; const raw_ptr<base::Clock> clock_; const bool force_refresh_results_; scoped_refptr<base::SequencedTaskRunner> task_runner_; @@ -59,70 +97,141 @@ OptimizationTarget segment_id, const std::string& segmentation_key, SegmentResultCallback callback) { + auto request_state = std::make_unique<RequestState>(); + request_state = std::make_unique<RequestState>(); + request_state->segment_id = segment_id; + request_state->segmentation_key = segmentation_key; + request_state->callback = std::move(callback); + // Factory can be null in tests. + request_state->default_provider = + default_model_manager_ + ? default_model_manager_->GetDefaultProvider(segment_id) + : nullptr; + // TODO(ssid): Change default model manager to return both info instead of + // requesting here. segment_database_->GetSegmentInfo( - segment_id, base::BindOnce(&SegmentResultProviderImpl::OnGetSegmentInfo, - weak_ptr_factory_.GetWeakPtr(), segment_id, - segmentation_key, std::move(callback))); + segment_id, + base::BindOnce(&SegmentResultProviderImpl::OnGetSegmentInfo, + weak_ptr_factory_.GetWeakPtr(), std::move(request_state))); } void SegmentResultProviderImpl::OnGetSegmentInfo( - OptimizationTarget segment_id, - const std::string& segmentation_key, - SegmentResultCallback callback, + std::unique_ptr<RequestState> request_state, absl::optional<proto::SegmentInfo> available_segment) { // Don't compute results if we don't have enough signals, or don't have // valid unexpired results for any of the segments. - proto::SegmentInfo* segment_info = nullptr; - if (available_segment) { - segment_info = &available_segment.value(); - } else { - VLOG(1) << __func__ << ": segment=" << OptimizationTarget_Name(segment_id) + if (!available_segment) { + VLOG(1) << __func__ << ": segment=" + << OptimizationTarget_Name(request_state->segment_id) << " does not have segment info."; - task_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - std::make_unique<SegmentResult>( - ResultState::kSegmentNotAvailable))); + TryGetScoreFromDefaultModel(std::move(request_state), + ResultState::kSegmentNotAvailable); return; } + proto::SegmentInfo& segment_info = *available_segment; // TODO(ssid): Remove this check since scheduler does this before executing // the model. if (!force_refresh_results_ && !signal_storage_config_->MeetsSignalCollectionRequirement( - segment_info->model_metadata())) { + segment_info.model_metadata())) { VLOG(1) << __func__ << ": segment=" - << OptimizationTarget_Name(segment_info->segment_id()) + << OptimizationTarget_Name(segment_info.segment_id()) << " does not meet signal collection requirements."; - task_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - std::make_unique<SegmentResult>( - ResultState::kSignalsNotCollected))); + TryGetScoreFromDefaultModel(std::move(request_state), + ResultState::kSignalsNotCollected); return; } - if (metadata_utils::HasExpiredOrUnavailableResult(*segment_info, + if (metadata_utils::HasExpiredOrUnavailableResult(segment_info, clock_->Now())) { VLOG(1) << __func__ << ": segment=" - << OptimizationTarget_Name(segment_info->segment_id()) + << OptimizationTarget_Name(segment_info.segment_id()) << " has expired or unavailable result."; - task_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - std::make_unique<SegmentResult>( - ResultState::kDatabaseScoreNotReady))); + TryGetScoreFromDefaultModel(std::move(request_state), + ResultState::kDatabaseScoreNotReady); return; } - int rank = metadata_utils::ConvertToDiscreteScore( - segmentation_key, segment_info->prediction_result().result(), - segment_info->model_metadata()); - VLOG(1) << __func__ << ": segment=" << OptimizationTarget_Name(segment_id) - << ": result=" << segment_info->prediction_result().result() - << ", rank=" << rank; + int rank = + ComputeDiscreteMapping(request_state->segmentation_key, segment_info); + PostResultCallback( + std::move(request_state), + std::make_unique<SegmentResult>(ResultState::kSuccessFromDatabase, rank)); +} - auto result = - std::make_unique<SegmentResult>(ResultState::kSuccessFromDatabase, rank); +void SegmentResultProviderImpl::TryGetScoreFromDefaultModel( + std::unique_ptr<RequestState> request_state, + SegmentResultProvider::ResultState existing_state) { + if (!request_state->default_provider || + !request_state->default_provider->ModelAvailable()) { + PostResultCallback(std::move(request_state), + std::make_unique<SegmentResult>(existing_state)); + return; + } + + OptimizationTarget segment_id = request_state->segment_id; + default_model_manager_->GetAllSegmentInfoFromDefaultModel( + {segment_id}, + base::BindOnce(&SegmentResultProviderImpl::OnDefaultModelFetched, + weak_ptr_factory_.GetWeakPtr(), std::move(request_state))); +} + +void SegmentResultProviderImpl::OnDefaultModelFetched( + std::unique_ptr<RequestState> request_state, + std::unique_ptr<DefaultModelManager::SegmentInfoList> metadata_list) { + if (!metadata_list || metadata_list->size() != 1 || + metadata_list->back().first != request_state->segment_id) { + PostResultCallback(std::move(request_state), + std::make_unique<SegmentResult>( + ResultState::kDefaultModelMetadataMissing)); + return; + } + + proto::SegmentInfo& segment_info = (*metadata_list)[0].second; + DCHECK_EQ(metadata_utils::ValidationResult::kValidationSuccess, + metadata_utils::ValidateMetadata(segment_info.model_metadata())); + if (!signal_storage_config_->MeetsSignalCollectionRequirement( + segment_info.model_metadata())) { + PostResultCallback(std::move(request_state), + std::make_unique<SegmentResult>( + ResultState::kDefaultModelSignalNotCollected)); + return; + } + + ModelProvider* default_provider = request_state->default_provider; + DCHECK(default_provider); + execution_manager_->ExecuteModel( + segment_info, default_provider, + base::BindOnce(&SegmentResultProviderImpl::OnDefaultModelExecuted, + weak_ptr_factory_.GetWeakPtr(), std::move(request_state), + segment_info)); +} + +void SegmentResultProviderImpl::OnDefaultModelExecuted( + std::unique_ptr<RequestState> request_state, + proto::SegmentInfo segment_info, + const std::pair<float, ModelExecutionStatus>& result) { + if (result.second == ModelExecutionStatus::kSuccess) { + segment_info.mutable_prediction_result()->set_result(result.first); + int rank = + ComputeDiscreteMapping(request_state->segmentation_key, segment_info); + PostResultCallback(std::move(request_state), + std::make_unique<SegmentResult>( + ResultState::kDefaultModelScoreUsed, rank)); + } else { + PostResultCallback(std::move(request_state), + std::make_unique<SegmentResult>( + ResultState::kDefaultModelExecutionFailed)); + } +} + +void SegmentResultProviderImpl::PostResultCallback( + std::unique_ptr<RequestState> request_state, + std::unique_ptr<SegmentResult> result) { task_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(result))); + FROM_HERE, + base::BindOnce(std::move(request_state->callback), std::move(result))); } } // namespace @@ -137,12 +246,13 @@ std::unique_ptr<SegmentResultProvider> SegmentResultProvider::Create( SegmentInfoDatabase* segment_database, SignalStorageConfig* signal_storage_config, - ModelProviderFactory* model_provider_factory, + DefaultModelManager* default_model_manager, + ModelExecutionManager* execution_manager, base::Clock* clock, bool force_refresh_results) { return std::make_unique<SegmentResultProviderImpl>( - segment_database, signal_storage_config, model_provider_factory, clock, - force_refresh_results); + segment_database, signal_storage_config, default_model_manager, + execution_manager, clock, force_refresh_results); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider.h b/components/segmentation_platform/internal/selection/segment_result_provider.h index a730ea49..2db62f4 100644 --- a/components/segmentation_platform/internal/selection/segment_result_provider.h +++ b/components/segmentation_platform/internal/selection/segment_result_provider.h
@@ -15,7 +15,8 @@ } namespace segmentation_platform { -class ModelProviderFactory; +class DefaultModelManager; +class ModelExecutionManager; class SignalStorageConfig; // Used for retrieving the result of a particular model. @@ -30,6 +31,10 @@ kSegmentNotAvailable = 2, kSignalsNotCollected = 3, kDatabaseScoreNotReady = 4, + kDefaultModelSignalNotCollected = 5, + kDefaultModelMetadataMissing = 6, + kDefaultModelExecutionFailed = 7, + kDefaultModelScoreUsed = 8, }; struct SegmentResult { explicit SegmentResult(ResultState state); @@ -48,7 +53,8 @@ static std::unique_ptr<SegmentResultProvider> Create( SegmentInfoDatabase* segment_info_database, SignalStorageConfig* signal_storage_config, - ModelProviderFactory* model_provider_factory, + DefaultModelManager* default_model_manager, + ModelExecutionManager* execution_manager, base::Clock* clock, bool force_refresh_results);
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc b/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc new file mode 100644 index 0000000..27c27bb --- /dev/null +++ b/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc
@@ -0,0 +1,289 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/segmentation_platform/internal/selection/segment_result_provider.h" + +#include "base/test/gmock_callback_support.h" +#include "base/test/simple_test_clock.h" +#include "base/test/task_environment.h" +#include "components/optimization_guide/machine_learning_tflite_buildflags.h" +#include "components/segmentation_platform/internal/database/mock_signal_database.h" +#include "components/segmentation_platform/internal/database/mock_signal_storage_config.h" +#include "components/segmentation_platform/internal/database/test_segment_info_database.h" +#include "components/segmentation_platform/internal/execution/default_model_manager.h" +#include "components/segmentation_platform/internal/execution/mock_feature_list_query_processor.h" +#include "components/segmentation_platform/internal/execution/mock_model_provider.h" +#include "components/segmentation_platform/internal/execution/model_execution_manager.h" +#include "components/segmentation_platform/internal/execution/model_execution_manager_factory.h" +#include "components/segmentation_platform/public/model_provider.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace segmentation_platform { +namespace { + +using ::base::test::RunOnceCallback; +using ::testing::_; +using ::testing::ByMove; +using ::testing::Return; + +const OptimizationTarget kTestSegment = + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; +const OptimizationTarget kTestSegment2 = + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE; + +constexpr float kDefaultScore = 0.1; +constexpr float kModelScore = 0.6; +constexpr int kDefaultRank = 0; +constexpr int kModelRank = 1; + +class DefaultProvider : public ModelProvider { + public: + static constexpr int64_t kVersion = 10; + explicit DefaultProvider(OptimizationTarget segment) + : ModelProvider(segment) {} + + void InitAndFetchModel( + const ModelUpdatedCallback& model_updated_callback) override { + proto::SegmentationModelMetadata metadata; + metadata.set_time_unit(proto::TimeUnit::DAY); + model_updated_callback.Run(optimization_target_, metadata, kVersion); + } + + void ExecuteModelWithInput(const std::vector<float>& inputs, + ExecutionCallback callback) override { + std::move(callback).Run(kDefaultScore); + } + + // Returns true if a model is available. + bool ModelAvailable() override { return true; } +}; + +} // namespace + +class SegmentResultProviderTest : public testing::Test { + public: + SegmentResultProviderTest() : provider_factory_(&model_providers_) {} + ~SegmentResultProviderTest() override = default; + + void SetUp() override { + default_manager_ = std::make_unique<DefaultModelManager>( + &provider_factory_, + std::vector<OptimizationTarget>({kTestSegment, kTestSegment2})); + segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>(); + model_execution_ = CreateModelExecutionManager( + &provider_factory_, task_environment_.GetMainThreadTaskRunner(), + {kTestSegment}, &clock_, segment_database_.get(), &signal_database_, + &mock_query_processor_, base::DoNothing()); + score_provider_ = SegmentResultProvider::Create( + segment_database_.get(), &signal_storage_config_, + default_manager_.get(), model_execution_.get(), &clock_, + /*force_refresh_results=*/false); + } + + void TearDown() override { + score_provider_.reset(); + segment_database_.reset(); + default_manager_.reset(); + } + + void ExpectSegmentResultOnGet( + OptimizationTarget segment_id, + SegmentResultProvider::ResultState expected_state, + absl::optional<int> expected_rank) { + base::RunLoop wait_for_result; + score_provider_->GetSegmentResult( + segment_id, "test_key", + base::BindOnce( + [](SegmentResultProvider::ResultState expected_state, + absl::optional<int> expected_rank, base::OnceClosure quit, + std::unique_ptr<SegmentResultProvider::SegmentResult> result) { + EXPECT_EQ(result->state, expected_state); + if (expected_rank) { + EXPECT_EQ(*expected_rank, result->rank); + } else { + EXPECT_FALSE(result->rank); + } + std::move(quit).Run(); + }, + expected_state, expected_rank, wait_for_result.QuitClosure())); + wait_for_result.Run(); + } + + void SetSegmentResult(OptimizationTarget segment, + absl::optional<float> score) { + absl::optional<proto::PredictionResult> result; + if (score) { + result = proto::PredictionResult(); + result->set_result(*score); + } + base::RunLoop wait_for_save; + segment_database_->SaveSegmentResult( + segment, std::move(result), + base::BindOnce( + [](base::OnceClosure quit, bool success) { std::move(quit).Run(); }, + wait_for_save.QuitClosure())); + wait_for_save.Run(); + } + + void InitializeMetadata(OptimizationTarget segment_id) { + segment_database_->FindOrCreateSegment(segment_id) + ->mutable_model_metadata() + ->set_result_time_to_live(7); + segment_database_->SetBucketDuration(segment_id, 1, proto::TimeUnit::DAY); + + // Initialize metadata so that score from default model returns default rank + // and score from model score returns model rank. + float mapping[][2] = {{kDefaultScore + 0.1, kDefaultRank}, + {kModelScore - 0.1, kModelRank}}; + segment_database_->AddDiscreteMapping(segment_id, mapping, 2, "test_key"); + } + + protected: + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + TestModelProviderFactory::Data model_providers_; + TestModelProviderFactory provider_factory_; + MockSignalDatabase signal_database_; + MockFeatureListQueryProcessor mock_query_processor_; + std::unique_ptr<DefaultModelManager> default_manager_; + std::unique_ptr<ModelExecutionManager> model_execution_; + base::SimpleTestClock clock_; + std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_; + MockSignalStorageConfig signal_storage_config_; + std::unique_ptr<SegmentResultProvider> score_provider_; +}; + +TEST_F(SegmentResultProviderTest, GetScoreWithoutInfo) { + ExpectSegmentResultOnGet( + kTestSegment, SegmentResultProvider::ResultState::kSegmentNotAvailable, + absl::nullopt); +} + +TEST_F(SegmentResultProviderTest, GetScoreFromDbWithoutResult) { + SetSegmentResult(kTestSegment, absl::nullopt); + + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(true)); + ExpectSegmentResultOnGet( + kTestSegment, SegmentResultProvider::ResultState::kDatabaseScoreNotReady, + absl::nullopt); +} + +TEST_F(SegmentResultProviderTest, GetScoreNotEnoughSignals) { + SetSegmentResult(kTestSegment, absl::nullopt); + + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(false)); + ExpectSegmentResultOnGet( + kTestSegment, SegmentResultProvider::ResultState::kSignalsNotCollected, + absl::nullopt); +} + +TEST_F(SegmentResultProviderTest, GetScoreFromDb) { + InitializeMetadata(kTestSegment); + SetSegmentResult(kTestSegment, kModelScore); + + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(true)); + ExpectSegmentResultOnGet( + kTestSegment, SegmentResultProvider::ResultState::kSuccessFromDatabase, + kModelRank); +} + +TEST_F(SegmentResultProviderTest, DefaultNeedsSignal) { + SetSegmentResult(kTestSegment, absl::nullopt); + std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; + p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); + default_manager_->SetDefaultProvidersForTesting(std::move(p)); + + // First call is to check opt guide model, and second is to check default + // model signals. + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + ExpectSegmentResultOnGet( + kTestSegment, + SegmentResultProvider::ResultState::kDefaultModelSignalNotCollected, + absl::nullopt); +} + +TEST_F(SegmentResultProviderTest, DefaultModelFailedExecution) { + SetSegmentResult(kTestSegment, absl::nullopt); + std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; + p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); + default_manager_->SetDefaultProvidersForTesting(std::move(p)); + + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(true)) + .WillOnce(Return(true)); + +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) + // Set error while computing features. + EXPECT_CALL(mock_query_processor_, ProcessFeatureList(_, _, _, _)) + .WillOnce(RunOnceCallback<3>(/*error=*/true, std::vector<float>{{1, 2}})); + ExpectSegmentResultOnGet( + kTestSegment, + SegmentResultProvider::ResultState::kDefaultModelExecutionFailed, + absl::nullopt); +#else + ExpectSegmentResultOnGet( + kTestSegment, + SegmentResultProvider::ResultState::kDefaultModelExecutionFailed, + absl::nullopt); +#endif +} + +#if BUILDFLAG(BUILD_WITH_TFLITE_LIB) +TEST_F(SegmentResultProviderTest, GetFromDefault) { + SetSegmentResult(kTestSegment, absl::nullopt); + std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; + p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); + default_manager_->SetDefaultProvidersForTesting(std::move(p)); + + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(true)) + .WillOnce(Return(true)); + EXPECT_CALL(mock_query_processor_, ProcessFeatureList(_, _, _, _)) + .WillOnce( + RunOnceCallback<3>(/*error=*/false, std::vector<float>{{1, 2}})); + ExpectSegmentResultOnGet( + kTestSegment, SegmentResultProvider::ResultState::kDefaultModelScoreUsed, + kDefaultRank); +} + +TEST_F(SegmentResultProviderTest, MultipleRequests) { + InitializeMetadata(kTestSegment); + SetSegmentResult(kTestSegment, absl::nullopt); + InitializeMetadata(kTestSegment2); + SetSegmentResult(kTestSegment2, kModelScore); + + std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; + p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); + p.emplace(kTestSegment2, std::make_unique<DefaultProvider>(kTestSegment2)); + default_manager_->SetDefaultProvidersForTesting(std::move(p)); + + // For the first request, the database does not have valid result, and default + // provider fails execution. + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(true)) + .WillOnce(Return(true)); + EXPECT_CALL(mock_query_processor_, ProcessFeatureList(_, _, _, _)) + .WillOnce( + RunOnceCallback<3>(/*error=*/false, std::vector<float>{{1, 2}})); + ExpectSegmentResultOnGet( + kTestSegment, SegmentResultProvider::ResultState::kDefaultModelScoreUsed, + kDefaultRank); + + // For the second request the database has valid result. + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_)) + .WillOnce(Return(true)); + EXPECT_CALL(mock_query_processor_, ProcessFeatureList(_, _, _, _)).Times(0); + ExpectSegmentResultOnGet( + kTestSegment2, SegmentResultProvider::ResultState::kSuccessFromDatabase, + kModelRank); +} +#endif + +} // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.cc b/components/segmentation_platform/internal/selection/segment_selector_impl.cc index d7034c7e7..a74cdb9 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_impl.cc +++ b/components/segmentation_platform/internal/selection/segment_selector_impl.cc
@@ -31,6 +31,7 @@ switch (result_state) { case SegmentResultProvider::ResultState::kUnknown: case SegmentResultProvider::ResultState::kSuccessFromDatabase: + case SegmentResultProvider::ResultState::kDefaultModelScoreUsed: NOTREACHED(); return stats::SegmentationSelectionFailureReason::kMaxValue; case SegmentResultProvider::ResultState::kDatabaseScoreNotReady: @@ -42,6 +43,15 @@ case SegmentResultProvider::ResultState::kSignalsNotCollected: return stats::SegmentationSelectionFailureReason:: kAtLeastOneSegmentSignalsNotCollected; + case SegmentResultProvider::ResultState::kDefaultModelMetadataMissing: + return stats::SegmentationSelectionFailureReason:: + kAtLeastOneSegmentDefaultMissingMetadata; + case SegmentResultProvider::ResultState::kDefaultModelSignalNotCollected: + return stats::SegmentationSelectionFailureReason:: + kAtLeastOneSegmentDefaultSignalNotCollected; + case SegmentResultProvider::ResultState::kDefaultModelExecutionFailed: + return stats::SegmentationSelectionFailureReason:: + kAtLeastOneSegmentDefaultExecFailed; } } @@ -56,11 +66,13 @@ const Config* config, base::Clock* clock, const PlatformOptions& platform_options, - ModelProviderFactory* model_provider_factory) + DefaultModelManager* default_model_manager, + ModelExecutionManager* execution_manager) : segment_result_provider_(SegmentResultProvider::Create( segment_database, signal_storage_config, - model_provider_factory, + default_model_manager, + execution_manager, clock, platform_options.force_refresh_results)), segment_database_(segment_database), @@ -68,8 +80,7 @@ result_prefs_(result_prefs), config_(config), clock_(clock), - platform_options_(platform_options), - model_provider_factory_(model_provider_factory) { + platform_options_(platform_options) { // Read selected segment from prefs. const auto& selected_segment = result_prefs_->ReadSegmentationResultFromPref(config_->segmentation_key);
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.h b/components/segmentation_platform/internal/selection/segment_selector_impl.h index 03823b53..c7ffe4bc 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_impl.h +++ b/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -21,8 +21,8 @@ namespace segmentation_platform { struct Config; -class ModelExecutionScheduler; -class ModelProviderFactory; +class ModelExecutionManager; +class DefaultModelManager; class SegmentationResultPrefs; class SignalStorageConfig; @@ -34,7 +34,8 @@ const Config* config, base::Clock* clock, const PlatformOptions& platform_options, - ModelProviderFactory* model_provider_factory); + DefaultModelManager* default_model_manager, + ModelExecutionManager* execution_manager); ~SegmentSelectorImpl() override; @@ -46,8 +47,6 @@ // the selection if the new result is unknown. virtual void UpdateSelectedSegment(OptimizationTarget new_selection); - // ModelExecutionScheduler::Observer overrides. - // Called whenever a model eval completes. Runs segment selection to find the // best segment, and writes it to the pref. void OnModelExecutionCompleted(OptimizationTarget segment_id) override; @@ -97,8 +96,6 @@ const PlatformOptions platform_options_; - const raw_ptr<ModelProviderFactory> model_provider_factory_; - // Segment selection result is read from prefs on init and used for serving // the clients in the current session. SegmentSelectionResult selected_segment_last_session_;
diff --git a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc index 1f271c2..f2b8b35 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc +++ b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
@@ -12,6 +12,8 @@ #include "components/segmentation_platform/internal/database/mock_signal_storage_config.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/test_segment_info_database.h" +#include "components/segmentation_platform/internal/execution/default_model_manager.h" +#include "components/segmentation_platform/internal/execution/mock_model_provider.h" #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h" #include "components/segmentation_platform/public/config.h" #include "testing/gmock/include/gmock/gmock.h" @@ -61,17 +63,20 @@ class SegmentSelectorTest : public testing::Test { public: - SegmentSelectorTest() = default; + SegmentSelectorTest() : provider_factory_(&model_providers_) {} ~SegmentSelectorTest() override = default; void SetUpWithConfig(const Config& config) { clock_.SetNow(base::Time::Now()); config_ = config; + default_manager_ = std::make_unique<DefaultModelManager>( + &provider_factory_, config_.segment_ids); segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>(); prefs_ = std::make_unique<TestSegmentationResultPrefs>(); segment_selector_ = std::make_unique<SegmentSelectorImpl>( segment_database_.get(), &signal_storage_config_, prefs_.get(), - &config_, &clock_, PlatformOptions::CreateDefault(), nullptr); + &config_, &clock_, PlatformOptions::CreateDefault(), + default_manager_.get(), nullptr); } void GetSelectedSegment(const SegmentSelectionResult& expected) { @@ -110,10 +115,13 @@ } base::test::TaskEnvironment task_environment_; + TestModelProviderFactory::Data model_providers_; + TestModelProviderFactory provider_factory_; Config config_; base::SimpleTestClock clock_; std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_; MockSignalStorageConfig signal_storage_config_; + std::unique_ptr<DefaultModelManager> default_manager_; std::unique_ptr<TestSegmentationResultPrefs> prefs_; std::unique_ptr<SegmentSelectorImpl> segment_selector_; }; @@ -299,7 +307,7 @@ // Construct a segment selector. It should read result from last session. segment_selector_ = std::make_unique<SegmentSelectorImpl>( segment_database_.get(), &signal_storage_config_, prefs_.get(), &config_, - &clock_, PlatformOptions::CreateDefault(), nullptr); + &clock_, PlatformOptions::CreateDefault(), nullptr, nullptr); SegmentSelectionResult result; result.segment = segment_id0;
diff --git a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc index e538165..16a972d 100644 --- a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc +++ b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
@@ -68,6 +68,7 @@ config, nullptr, PlatformOptions::CreateDefault(), + nullptr, nullptr) {} ~FakeSegmentSelectorImpl() override = default;
diff --git a/components/segmentation_platform/internal/stats.cc b/components/segmentation_platform/internal/stats.cc index 03869ec3..93d52eae 100644 --- a/components/segmentation_platform/internal/stats.cc +++ b/components/segmentation_platform/internal/stats.cc
@@ -468,11 +468,19 @@ } void RecordModelExecutionStatus(OptimizationTarget segment_id, + bool default_provider, ModelExecutionStatus status) { - base::UmaHistogramEnumeration( - "SegmentationPlatform.ModelExecution.Status." + - OptimizationTargetToHistogramVariant(segment_id), - status); + if (!default_provider) { + base::UmaHistogramEnumeration( + "SegmentationPlatform.ModelExecution.Status." + + OptimizationTargetToHistogramVariant(segment_id), + status); + } else { + base::UmaHistogramEnumeration( + "SegmentationPlatform.ModelExecution.DefaultProvider.Status." + + OptimizationTargetToHistogramVariant(segment_id), + status); + } } void RecordModelExecutionZeroValuePercent(OptimizationTarget segment_id,
diff --git a/components/segmentation_platform/internal/stats.h b/components/segmentation_platform/internal/stats.h index e2aafb2..d1165f5 100644 --- a/components/segmentation_platform/internal/stats.h +++ b/components/segmentation_platform/internal/stats.h
@@ -118,6 +118,7 @@ bool success); // Records the final execution status for any ML model execution. void RecordModelExecutionStatus(OptimizationTarget segment_id, + bool default_provider, ModelExecutionStatus status); // Records the percent of features in a tensor that are equal to 0 when the // segmentation model is executed. @@ -160,7 +161,10 @@ kInvalidSelectionResultInPrefs = 9, kDBInitFailure = 10, kAtLeastOneSegmentNotAvailable = 11, - kMaxValue = kAtLeastOneSegmentNotAvailable + kAtLeastOneSegmentDefaultSignalNotCollected = 12, + kAtLeastOneSegmentDefaultExecFailed = 13, + kAtLeastOneSegmentDefaultMissingMetadata = 14, + kMaxValue = kAtLeastOneSegmentDefaultMissingMetadata }; // Records the reason for failure or success to compute a segment selection.
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index a7d468f..7f83f77d 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -225,15 +225,6 @@ } bool IsUsingSkiaRenderer() { -#if BUILDFLAG(IS_CHROMEOS_ASH) - // TODO(https://crbug.com/1145180): SkiaRenderer isn't supported on Chrome - // OS boards that still use the legacy video decoder. - auto* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch( - switches::kPlatformDisallowsChromeOSDirectVideoDecoder)) - return false; -#endif - return base::FeatureList::IsEnabled(kUseSkiaRenderer) || features::IsUsingVulkan(); }
diff --git a/components/viz/common/switches.cc b/components/viz/common/switches.cc index 0e142fa..e6d3acb 100644 --- a/components/viz/common/switches.cc +++ b/components/viz/common/switches.cc
@@ -45,14 +45,6 @@ // fullscreen overlay and use it as main framebuffer where possible. const char kEnableHardwareOverlays[] = "enable-hardware-overlays"; -#if BUILDFLAG(IS_CHROMEOS) -// ChromeOS uses one of two VideoDecoder implementations based on SoC/board -// specific configurations that are signalled via this command line flag. -// TODO(b/159825227): remove when the "old" video decoder is fully launched. -const char kPlatformDisallowsChromeOSDirectVideoDecoder[] = - "platform-disallows-chromeos-direct-video-decoder"; -#endif - // Effectively disables pipelining of compositor frame production stages by // waiting for each stage to finish before completing a frame. const char kRunAllCompositorStagesBeforeDraw[] =
diff --git a/components/viz/common/switches.h b/components/viz/common/switches.h index 6ac91e6..b76565e9 100644 --- a/components/viz/common/switches.h +++ b/components/viz/common/switches.h
@@ -8,7 +8,6 @@ #include <stdint.h> #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "components/viz/common/viz_common_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -22,12 +21,6 @@ VIZ_COMMON_EXPORT extern const char kDoubleBufferCompositing[]; VIZ_COMMON_EXPORT extern const char kEnableDeJelly[]; VIZ_COMMON_EXPORT extern const char kEnableHardwareOverlays[]; - -#if BUILDFLAG(IS_CHROMEOS) -VIZ_COMMON_EXPORT extern const char - kPlatformDisallowsChromeOSDirectVideoDecoder[]; -#endif - VIZ_COMMON_EXPORT extern const char kRunAllCompositorStagesBeforeDraw[]; VIZ_COMMON_EXPORT extern const char kShowAggregatedDamage[]; VIZ_COMMON_EXPORT extern const char kTintCompositedContentModulate[];
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 41de23d..e8418751 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -495,8 +495,15 @@ RunHtmlTest(FILE_PATH_LITERAL("a-onclick.html")); } +// TODO(https://crbug.com/1309941): This test is failing on Fuchsia. +#if BUILDFLAG(IS_FUCHSIA) +#define MAYBE_AccessibilityANestedStructure \ + DISABLED_AccessibilityANestedStructure +#else +#define MAYBE_AccessibilityANestedStructure AccessibilityANestedStructure +#endif // BUILDFLAG(IS_FUCHSIA) IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, - AccessibilityANestedStructure) { + MAYBE_AccessibilityANestedStructure) { RunHtmlTest(FILE_PATH_LITERAL("a-nested-structure.html")); } @@ -1865,8 +1872,8 @@ RunHtmlTest(FILE_PATH_LITERAL("fieldset.html")); } -// TODO(crbug.com/1307316): failing on Linux bots. -#if BUILDFLAG(IS_LINUX) +// TODO(crbug.com/1307316): failing on Linux bots and flaky on Fuchsia bots. +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_FUCHSIA) #define MAYBE_AccessibilityFigcaption DISABLED_AccessibilityFigcaption #else #define MAYBE_AccessibilityFigcaption AccessibilityFigcaption @@ -2824,7 +2831,8 @@ RunHtmlTest(FILE_PATH_LITERAL("selectmenu-open.html")); } -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +// TODO(https://crbug.com/1309941): Flaky on Fuchsia +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) #define MAYBE_AccessibilitySource DISABLED_AccessibilitySource #else #define MAYBE_AccessibilitySource AccessibilitySource
diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc index ceeb9bc..f0adf9f 100644 --- a/content/browser/child_process_launcher_helper_win.cc +++ b/content/browser/child_process_launcher_helper_win.cc
@@ -73,7 +73,7 @@ win_options.start_hidden = true; win_options.elevated = true; ChildProcessLauncherHelper::Process process; - process.process = base::LaunchElevatedProcess(*command_line(), win_options); + process.process = base::LaunchProcess(*command_line(), win_options); *launch_result = process.process.IsValid() ? LAUNCH_RESULT_SUCCESS : LAUNCH_RESULT_FAILURE; return process;
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping.cc b/content/browser/fenced_frame/fenced_frame_url_mapping.cc index c9e76582..05e6025 100644 --- a/content/browser/fenced_frame/fenced_frame_url_mapping.cc +++ b/content/browser/fenced_frame/fenced_frame_url_mapping.cc
@@ -95,6 +95,12 @@ FencedFrameURLMapping::MapInfo::MapInfo(const GURL& mapped_url) : mapped_url(mapped_url) {} +FencedFrameURLMapping::MapInfo::MapInfo( + const GURL& mapped_url, + const SharedStorageBudgetMetadata& shared_storage_budget_metadata) + : mapped_url(mapped_url), + shared_storage_budget_metadata(shared_storage_budget_metadata) {} + FencedFrameURLMapping::MapInfo::MapInfo(const MapInfo&) = default; FencedFrameURLMapping::MapInfo::MapInfo(MapInfo&&) = default; FencedFrameURLMapping::MapInfo::~MapInfo() = default; @@ -184,22 +190,22 @@ it->second.erase(observer_it); } -void FencedFrameURLMapping::OnURNMappingResultDetermined( +void FencedFrameURLMapping::OnSharedStorageURNMappingResultDetermined( const GURL& urn_uuid, - const absl::optional<GURL>& mapped_url) { + const SharedStorageURNMappingResult& mapping_result) { auto it = pending_urn_uuid_to_url_map_.find(urn_uuid); DCHECK(it != pending_urn_uuid_to_url_map_.end()); DCHECK(!IsMapped(urn_uuid)); - if (mapped_url) - urn_uuid_to_url_map_.emplace(urn_uuid, mapped_url.value()); + urn_uuid_to_url_map_.emplace( + urn_uuid, MapInfo(mapping_result.mapped_url, mapping_result.metadata)); std::set<raw_ptr<MappingResultObserver>>& observers = it->second; for (raw_ptr<MappingResultObserver> observer : observers) { observer->OnFencedFrameURLMappingComplete( - mapped_url, + absl::make_optional<GURL>(mapping_result.mapped_url), /*ad_auction_data=*/absl::nullopt, /*pending_ad_components_map=*/absl::nullopt); } @@ -207,6 +213,20 @@ pending_urn_uuid_to_url_map_.erase(it); } +absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> +FencedFrameURLMapping::ReleaseSharedStorageBudgetMetadata( + const GURL& urn_uuid) { + auto it = urn_uuid_to_url_map_.find(urn_uuid); + DCHECK(it != urn_uuid_to_url_map_.end()); + + absl::optional<SharedStorageBudgetMetadata> metadata = + it->second.shared_storage_budget_metadata; + + it->second.shared_storage_budget_metadata.reset(); + + return metadata; +} + bool FencedFrameURLMapping::HasObserverForTesting( const GURL& urn_uuid, MappingResultObserver* observer) {
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping.h b/content/browser/fenced_frame/fenced_frame_url_mapping.h index a1e842f..25ea30a 100644 --- a/content/browser/fenced_frame/fenced_frame_url_mapping.h +++ b/content/browser/fenced_frame/fenced_frame_url_mapping.h
@@ -27,9 +27,27 @@ // Keeps a mapping of fenced frames URN:UUID and URL. Also keeps a set of // pending mapped URN:UUIDs to support asynchronous mapping. See -// https://github.com/shivanigithub/fenced-frame/blob/master/OpaqueSrc.md +// https://github.com/shivanigithub/fenced-frame/blob/master/explainer/opaque_src.md class CONTENT_EXPORT FencedFrameURLMapping { public: + // The metadata for the shared storage runURLSelectionOperation's budget, + // which includes the shared storage's origin and the amount of budget to + // charge when a fenced frame that originates from the URN is navigating a top + // frame. Before the fenced frame results in a top navigation, this + // `SharedStorageBudgetMetadata` will be stored/associated with the URN inside + // the `FencedFrameURLMapping`. + struct CONTENT_EXPORT SharedStorageBudgetMetadata { + url::Origin origin; + double budget_to_charge = 0; + }; + + // The runURLSelectionOperation's url mapping result. It contains the mapped + // url and the `SharedStorageBudgetMetadata`. + struct CONTENT_EXPORT SharedStorageURNMappingResult { + GURL mapped_url; + SharedStorageBudgetMetadata metadata; + }; + // When the result of an ad auction is a main ad URL with a set of ad // component URLs (instead of just a single ad URL), a URN that maps to the // main ad URL needs to be loaded in a (parent) fenced frame, and then that @@ -149,16 +167,26 @@ void RemoveObserverForURN(const GURL& urn_uuid, MappingResultObserver* observer); - // Called when the mapping decision is made for `urn_uuid`. On success, - // `mapped_url` will be the result url; on failure,`mapped_url` will be - // absl::nullopt. Should only be invoked with a `urn_uuid` pending to be - // mapped. This method will trigger the observers' - // OnFencedFrameURLMappingComplete() method associated with the `urn_uuid`, - // unregister those observers, and remove `urn_uuid` from - // `pending_urn_uuid_to_url_map_`. If the mapping succeeded, the `urn_uuid` - // will be added to `urn_uuid_to_url_map_`. - void OnURNMappingResultDetermined(const GURL& urn_uuid, - const absl::optional<GURL>& mapped_url); + // Called when the shared storage mapping decision is made for `urn_uuid`. + // Should only be invoked on a `urn_uuid` pending to be mapped. This method + // will trigger the observers' OnFencedFrameURLMappingComplete() method + // associated with the `urn_uuid`, unregister those observers, and move the + // `urn_uuid` from `pending_urn_uuid_to_url_map_` to `urn_uuid_to_url_map_`. + void OnSharedStorageURNMappingResultDetermined( + const GURL& urn_uuid, + const SharedStorageURNMappingResult& mapping_result); + + // Get the `SharedStorageBudgetMetadata` associated with `urn_uuid`, and reset + // the current metadata to absl::nullopt. Precondition: `urn_uuid` exists in + // `urn_uuid_to_url_map_`. + // + // This method will be called when a fenced frame is navigating a top frame: + // if the fenced frame originates from a URN generated from the shared + // storage, then the shared storage origin's budget will be charged. For each + // URN, we only need to charge the budget once, thus the value here is + // released (i.e. returned and reset). + absl::optional<SharedStorageBudgetMetadata> + ReleaseSharedStorageBudgetMetadata(const GURL& urn_uuid); bool HasObserverForTesting(const GURL& urn_uuid, MappingResultObserver* observer); @@ -172,6 +200,8 @@ struct MapInfo { MapInfo(); explicit MapInfo(const GURL& url); + MapInfo(const GURL& url, + const SharedStorageBudgetMetadata& shared_storage_budget_metadata); MapInfo(const MapInfo&); MapInfo(MapInfo&&); ~MapInfo(); @@ -185,6 +215,13 @@ // to fill in `AdAuctionDocumentData` for the fenced frame that navigates // to `mapped_url`. absl::optional<AdAuctionData> ad_auction_data; + + // Contains the metadata needed for shared storage budget charging. Will be + // initialized to absl::nullopt if the associated URN is not generated from + // shared storage; also will be reset to absl::nullopt if the budget has + // already been charged for the associated URN. + absl::optional<SharedStorageBudgetMetadata> shared_storage_budget_metadata; + // Ad component URLs if `mapped_url` is the result of a FLEDGE auction. When // a fenced frame navigates to `mapped_url`, these will be mapped to URNs // themselves, and those URNs will be provided to the fenced frame.
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc b/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc index 6deb1e3..7b13e84 100644 --- a/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc +++ b/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc
@@ -128,36 +128,66 @@ EXPECT_EQ(absl::nullopt, observer.pending_ad_components_map()); } -TEST(FencedFrameURLMappingTest, PendingMappedUUID_MappingSuccess) { +TEST(FencedFrameURLMappingTest, PendingMappedUUID) { FencedFrameURLMapping fenced_frame_url_mapping; - const GURL urn_uuid = fenced_frame_url_mapping.GeneratePendingMappedURN(); + const GURL urn_uuid1 = fenced_frame_url_mapping.GeneratePendingMappedURN(); + const GURL urn_uuid2 = fenced_frame_url_mapping.GeneratePendingMappedURN(); - TestFencedFrameURLMappingResultObserver observer; - fenced_frame_url_mapping.ConvertFencedFrameURNToURL(urn_uuid, &observer); - EXPECT_FALSE(observer.mapping_complete_observed()); + TestFencedFrameURLMappingResultObserver observer1; + fenced_frame_url_mapping.ConvertFencedFrameURNToURL(urn_uuid1, &observer1); + EXPECT_FALSE(observer1.mapping_complete_observed()); - fenced_frame_url_mapping.OnURNMappingResultDetermined( - urn_uuid, GURL("https://foo.com")); + TestFencedFrameURLMappingResultObserver observer2; + fenced_frame_url_mapping.ConvertFencedFrameURNToURL(urn_uuid2, &observer2); + EXPECT_FALSE(observer2.mapping_complete_observed()); - EXPECT_TRUE(observer.mapping_complete_observed()); - EXPECT_EQ(GURL("https://foo.com"), observer.mapped_url()); - EXPECT_EQ(absl::nullopt, observer.pending_ad_components_map()); -} + url::Origin shared_storage_origin = + url::Origin::Create(GURL("https://bar.com")); + GURL mapped_url = GURL("https://foo.com"); -TEST(FencedFrameURLMappingTest, PendingMappedUUID_MappingFailure) { - FencedFrameURLMapping fenced_frame_url_mapping; - const GURL urn_uuid = fenced_frame_url_mapping.GeneratePendingMappedURN(); + // Two SharedStorageBudgetMetadata for the same origin can happen if the same + // blink::Document invokes window.sharedStorage.runURLSelectionOperation() + // twice. Each call will generate a distinct URN. And if the input urls have + // different size, the budget_to_charge (i.e. log(n)) will be also different. + SimulateSharedStorageURNMappingComplete(fenced_frame_url_mapping, urn_uuid1, + mapped_url, shared_storage_origin, + /*budget_to_charge=*/2.0); - TestFencedFrameURLMappingResultObserver observer; - fenced_frame_url_mapping.ConvertFencedFrameURNToURL(urn_uuid, &observer); - EXPECT_FALSE(observer.mapping_complete_observed()); + SimulateSharedStorageURNMappingComplete(fenced_frame_url_mapping, urn_uuid2, + mapped_url, shared_storage_origin, + /*budget_to_charge=*/3.0); - fenced_frame_url_mapping.OnURNMappingResultDetermined(urn_uuid, - absl::nullopt); + EXPECT_TRUE(observer1.mapping_complete_observed()); + EXPECT_EQ(mapped_url, observer1.mapped_url()); + EXPECT_EQ(absl::nullopt, observer1.pending_ad_components_map()); - EXPECT_TRUE(observer.mapping_complete_observed()); - EXPECT_EQ(absl::nullopt, observer.mapped_url()); - EXPECT_EQ(absl::nullopt, observer.pending_ad_components_map()); + EXPECT_TRUE(observer2.mapping_complete_observed()); + EXPECT_EQ(mapped_url, observer2.mapped_url()); + EXPECT_EQ(absl::nullopt, observer2.pending_ad_components_map()); + + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> + metadata1_first_retrieval = + fenced_frame_url_mapping.ReleaseSharedStorageBudgetMetadata( + urn_uuid1); + + EXPECT_TRUE(metadata1_first_retrieval); + EXPECT_EQ(metadata1_first_retrieval->origin, shared_storage_origin); + EXPECT_DOUBLE_EQ(metadata1_first_retrieval->budget_to_charge, 2.0); + + EXPECT_FALSE( + fenced_frame_url_mapping.ReleaseSharedStorageBudgetMetadata(urn_uuid1)); + + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> + metadata2_first_retrieval = + fenced_frame_url_mapping.ReleaseSharedStorageBudgetMetadata( + urn_uuid2); + + EXPECT_TRUE(metadata2_first_retrieval); + EXPECT_EQ(metadata2_first_retrieval->origin, shared_storage_origin); + EXPECT_DOUBLE_EQ(metadata2_first_retrieval->budget_to_charge, 3.0); + + EXPECT_FALSE( + fenced_frame_url_mapping.ReleaseSharedStorageBudgetMetadata(urn_uuid2)); } TEST(FencedFrameURLMappingTest, RemoveObserverOnPendingMappedUUID) { @@ -169,8 +199,12 @@ EXPECT_FALSE(observer.mapping_complete_observed()); fenced_frame_url_mapping.RemoveObserverForURN(urn_uuid, &observer); - fenced_frame_url_mapping.OnURNMappingResultDetermined( - urn_uuid, GURL("https://foo.com")); + + SimulateSharedStorageURNMappingComplete( + fenced_frame_url_mapping, urn_uuid, + /*mapped_url=*/GURL("https://foo.com"), + /*shared_storage_origin=*/url::Origin::Create(GURL("https://bar.com")), + /*budget_to_charge=*/2.0); EXPECT_FALSE(observer.mapping_complete_observed()); } @@ -187,8 +221,11 @@ fenced_frame_url_mapping.ConvertFencedFrameURNToURL(urn_uuid, &observer2); EXPECT_FALSE(observer2.mapping_complete_observed()); - fenced_frame_url_mapping.OnURNMappingResultDetermined( - urn_uuid, GURL("https://foo.com")); + SimulateSharedStorageURNMappingComplete( + fenced_frame_url_mapping, urn_uuid, + /*mapped_url=*/GURL("https://foo.com"), + /*shared_storage_origin=*/url::Origin::Create(GURL("https://bar.com")), + /*budget_to_charge=*/2.0); EXPECT_TRUE(observer1.mapping_complete_observed()); EXPECT_EQ(GURL("https://foo.com"), observer1.mapped_url());
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 90c7ace..8b32bf5 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -303,7 +303,6 @@ switches::kReachedCodeSamplingIntervalUs, #endif #if BUILDFLAG(IS_CHROMEOS) - switches::kPlatformDisallowsChromeOSDirectVideoDecoder, switches::kSchedulerBoostUrgent, #endif #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
diff --git a/content/browser/media/DEPS b/content/browser/media/DEPS index e58d970..e19b117e6 100644 --- a/content/browser/media/DEPS +++ b/content/browser/media/DEPS
@@ -1,3 +1,5 @@ include_rules = [ "+ash/components/audio", + "+third_party/widevine/cdm/buildflags.h", + "+third_party/widevine/cdm/widevine_cdm_common.h", ]
diff --git a/content/browser/media/cdm_file_impl.cc b/content/browser/media/cdm_file_impl.cc index af820945..38542a3 100644 --- a/content/browser/media/cdm_file_impl.cc +++ b/content/browser/media/cdm_file_impl.cc
@@ -406,7 +406,6 @@ DVLOG(3) << __func__ << " " << file_name_; DCHECK(IsValidName(file_name_)); DCHECK(host_); - DCHECK(base::FeatureList::IsEnabled(features::kMediaLicenseBackend)); receiver_.Bind(std::move(pending_receiver)); receiver_.set_disconnect_handler(base::BindOnce(
diff --git a/content/browser/media/cdm_storage_impl_unittest.cc b/content/browser/media/cdm_storage_impl_unittest.cc index 076f527..c387881 100644 --- a/content/browser/media/cdm_storage_impl_unittest.cc +++ b/content/browser/media/cdm_storage_impl_unittest.cc
@@ -5,11 +5,13 @@ #include "content/browser/media/cdm_storage_impl.h" #include <memory> +#include <vector> #include "base/bind.h" #include "base/callback.h" #include "base/files/file.h" #include "base/logging.h" +#include "base/test/bind.h" #include "base/test/test_future.h" #include "base/test/with_feature_override.h" #include "content/browser/media/media_license_manager.h" @@ -27,19 +29,36 @@ #include "mojo/public/cpp/bindings/remote.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/storage_key/storage_key.h" +#include "third_party/widevine/cdm/buildflags.h" #include "url/gurl.h" #include "url/origin.h" +#if BUILDFLAG(ENABLE_WIDEVINE) +#include "third_party/widevine/cdm/widevine_cdm_common.h" +#endif // BUILDFLAG(ENABLE_WIDEVINE) + using media::mojom::CdmFile; using media::mojom::CdmStorage; namespace content { +using CdmFileId = MediaLicenseManager::CdmFileId; +using CdmFileIdAndContents = MediaLicenseManager::CdmFileIdAndContents; namespace { const media::CdmType kTestCdmType{base::Token{1234, 5678}, "test_file_system"}; +const media::CdmType kDifferentCdmType{base::Token{8765, 4321}, + "different_plugin"}; +const media::CdmType kUnrecognizedCdmType{base::Token{1111, 2222}, "imposter"}; + const char kTestOrigin[] = "http://www.test.com"; +const std::vector<MediaLicenseManager::CdmFileIdAndContents> kDefaultFiles{ + {{"file1", kTestCdmType}, {'r', 'a', 'n', 'd'}}, + {{"file2", kTestCdmType}, {'r', 'a', 'n', 'd', 'o'}}, + {{"file3", kTestCdmType}, {'r', 'a', 'n', 'd', 'o', 'm'}}, +}; + // Helper functions to manipulate RenderFrameHosts. void SimulateNavigation(RenderFrameHost** rfh, const GURL& url) { @@ -140,7 +159,65 @@ return status == CdmFile::Status::kSuccess; } - private: + void WriteFiles(const std::vector<CdmFileIdAndContents>& files) { + // Write some data using the old backend. + for (const auto& file : files) { + mojo::AssociatedRemote<CdmFile> remote; + EXPECT_TRUE(Open(file.file.name, remote)); + ASSERT_TRUE(remote.is_bound()); + EXPECT_TRUE(Write(remote.get(), file.data)); + } + } + + void ReadFiles(const std::vector<CdmFileIdAndContents>& files) { + for (const auto& file : files) { + mojo::AssociatedRemote<CdmFile> remote; + EXPECT_TRUE(Open(file.file.name, remote)); + ASSERT_TRUE(remote.is_bound()); + std::vector<uint8_t> data_read; + EXPECT_TRUE(Read(remote.get(), data_read)); + EXPECT_EQ(file.data, data_read); + } + } + + void ExpectFilesEmpty(const std::vector<CdmFileIdAndContents>& files) { + for (const auto& file : files) { + mojo::AssociatedRemote<CdmFile> remote; + EXPECT_TRUE(Open(file.file.name, remote)); + ASSERT_TRUE(remote.is_bound()); + std::vector<uint8_t> data_read; + EXPECT_TRUE(Read(remote.get(), data_read)); + EXPECT_TRUE(data_read.empty()); + } + } + + void ResetAndBindToOldBackend(const blink::StorageKey& storage_key, + const media::CdmType& cdm_type) { + cdm_storage_.reset(); + + SimulateNavigation(&rfh_, storage_key.origin().GetURL()); + CdmStorageImpl::Create(rfh_, cdm_type, + cdm_storage_.BindNewPipeAndPassReceiver()); + } + + void ResetAndBindToNewBackend(const blink::StorageKey& storage_key, + const media::CdmType& cdm_type) { + cdm_storage_.reset(); + + SimulateNavigation(&rfh_, storage_key.origin().GetURL()); + media_license_manager()->OpenCdmStorage( + MediaLicenseManager::BindingContext(storage_key, cdm_type), + cdm_storage_.BindNewPipeAndPassReceiver()); + } + + MediaLicenseManager* media_license_manager() const { + auto* media_license_manager = + static_cast<StoragePartitionImpl*>(rfh_->GetStoragePartition()) + ->GetMediaLicenseManager(); + DCHECK(media_license_manager); + return media_license_manager; + } + RenderFrameHost* rfh_ = nullptr; mojo::Remote<CdmStorage> cdm_storage_; }; @@ -155,21 +232,21 @@ const char kFileName[] = "openfile\u1234"; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_FALSE(Open(kFileName, cdm_file)); - EXPECT_FALSE(cdm_file.is_bound()); + ASSERT_FALSE(cdm_file.is_bound()); } TEST_P(CdmStorageTest, InvalidFileNameEmpty) { const char kFileName[] = ""; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_FALSE(Open(kFileName, cdm_file)); - EXPECT_FALSE(cdm_file.is_bound()); + ASSERT_FALSE(cdm_file.is_bound()); } TEST_P(CdmStorageTest, InvalidFileNameStartWithUnderscore) { const char kFileName[] = "_invalid"; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_FALSE(Open(kFileName, cdm_file)); - EXPECT_FALSE(cdm_file.is_bound()); + ASSERT_FALSE(cdm_file.is_bound()); } TEST_P(CdmStorageTest, InvalidFileNameTooLong) { @@ -177,57 +254,57 @@ const std::string kFileName(257, 'a'); mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_FALSE(Open(kFileName, cdm_file)); - EXPECT_FALSE(cdm_file.is_bound()); + ASSERT_FALSE(cdm_file.is_bound()); } TEST_P(CdmStorageTest, OpenFile) { const char kFileName[] = "test_file_name"; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_TRUE(Open(kFileName, cdm_file)); - EXPECT_TRUE(cdm_file.is_bound()); + ASSERT_TRUE(cdm_file.is_bound()); } TEST_P(CdmStorageTest, OpenFileLocked) { const char kFileName[] = "test_file_name"; mojo::AssociatedRemote<CdmFile> cdm_file1; EXPECT_TRUE(Open(kFileName, cdm_file1)); - EXPECT_TRUE(cdm_file1.is_bound()); + ASSERT_TRUE(cdm_file1.is_bound()); // Second attempt on the same file should fail as the file is locked. mojo::AssociatedRemote<CdmFile> cdm_file2; EXPECT_FALSE(Open(kFileName, cdm_file2)); - EXPECT_FALSE(cdm_file2.is_bound()); + ASSERT_FALSE(cdm_file2.is_bound()); // Now close the first file and try again. It should be free now. cdm_file1.reset(); mojo::AssociatedRemote<CdmFile> cdm_file3; EXPECT_TRUE(Open(kFileName, cdm_file3)); - EXPECT_TRUE(cdm_file3.is_bound()); + ASSERT_TRUE(cdm_file3.is_bound()); } TEST_P(CdmStorageTest, MultipleFiles) { const char kFileName1[] = "file1"; mojo::AssociatedRemote<CdmFile> cdm_file1; EXPECT_TRUE(Open(kFileName1, cdm_file1)); - EXPECT_TRUE(cdm_file1.is_bound()); + ASSERT_TRUE(cdm_file1.is_bound()); const char kFileName2[] = "file2"; mojo::AssociatedRemote<CdmFile> cdm_file2; EXPECT_TRUE(Open(kFileName2, cdm_file2)); - EXPECT_TRUE(cdm_file2.is_bound()); + ASSERT_TRUE(cdm_file2.is_bound()); const char kFileName3[] = "file3"; mojo::AssociatedRemote<CdmFile> cdm_file3; EXPECT_TRUE(Open(kFileName3, cdm_file3)); - EXPECT_TRUE(cdm_file3.is_bound()); + ASSERT_TRUE(cdm_file3.is_bound()); } TEST_P(CdmStorageTest, WriteThenReadFile) { const char kFileName[] = "test_file_name"; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_TRUE(Open(kFileName, cdm_file)); - EXPECT_TRUE(cdm_file.is_bound()); + ASSERT_TRUE(cdm_file.is_bound()); // Write several bytes and read them back. std::vector<uint8_t> kTestData = {'r', 'a', 'n', 'd', 'o', 'm'}; @@ -242,7 +319,7 @@ const char kFileName[] = "empty_file_name"; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_TRUE(Open(kFileName, cdm_file)); - EXPECT_TRUE(cdm_file.is_bound()); + ASSERT_TRUE(cdm_file.is_bound()); // New file should be empty. std::vector<uint8_t> data_read; @@ -261,7 +338,7 @@ const char kFileName[] = "duplicate_read_file_name"; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_TRUE(Open(kFileName, cdm_file)); - EXPECT_TRUE(cdm_file.is_bound()); + ASSERT_TRUE(cdm_file.is_bound()); // Attempts to reads the contents of the previously opened |cdm_file| twice. // We don't really care about the data, just that 1 read succeeds and the @@ -292,7 +369,7 @@ const char kFileName[] = "duplicate_write_file_name"; mojo::AssociatedRemote<CdmFile> cdm_file; EXPECT_TRUE(Open(kFileName, cdm_file)); - EXPECT_TRUE(cdm_file.is_bound()); + ASSERT_TRUE(cdm_file.is_bound()); // Attempts to write the contents of the previously opened |cdm_file| twice. // We don't really care about the data, just that 1 write succeeds and the @@ -317,4 +394,245 @@ << "status 1: " << status1 << ", status2: " << status2; } +TEST_P(CdmStorageTest, MigrateDataNone) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + + // If there's no data to migrate this should run gracefully and without error. + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); +} + +TEST_P(CdmStorageTest, MigrateDataBasic) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + // Write some data using the old backend. + WriteFiles(kDefaultFiles); + + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); + + // Read data using the new backend. + ReadFiles(kDefaultFiles); +} + +TEST_P(CdmStorageTest, MigrateDataAll) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + // Write some data using the old backend. + WriteFiles(kDefaultFiles); + + // Open a new backend using a different CDM type. The original data should + // still have been migrated. + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kDifferentCdmType); + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); + + // Can't read files from another CDM type. + ExpectFilesEmpty(kDefaultFiles); + + // Files from the original CDM type should exist without another migration. + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + ReadFiles(kDefaultFiles); +} + +TEST_P(CdmStorageTest, MigrateDataPluginDataDeleted) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + // Write some data using the old backend. + WriteFiles(kDefaultFiles); + + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); + + // Read data using the new backend. + ReadFiles(kDefaultFiles); + + ResetAndBindToOldBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + + // Data should have been removed from the old backend. + ExpectFilesEmpty(kDefaultFiles); +} + +TEST_P(CdmStorageTest, MigrateDataMultipleCdmTypes) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + // Write some data using the old backend. + WriteFiles(kDefaultFiles); + + // Write data to another CDM type from the same origin. + const std::vector<MediaLicenseManager::CdmFileIdAndContents> kDifferentFiles{ + {{"other0", kDifferentCdmType}, {'e', 'x', 'a', 'm'}}, + {{"other1", kDifferentCdmType}, {'e', 'x', 'a', 'm', 'p'}}, + {{"other2", kDifferentCdmType}, {'e', 'x', 'a', 'm', 'p', 'l'}}, + {{"other3", kDifferentCdmType}, {'e', 'x', 'a', 'm', 'p', 'l', 'e'}}, + }; + ResetAndBindToOldBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kDifferentCdmType); + WriteFiles(kDifferentFiles); + + // Ensure files from the first CDM type can be read by the new backend. + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); + + ReadFiles(kDefaultFiles); + + // Open storage for the other CDM type. All media licenses should have been + // migrated. + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kDifferentCdmType); + + ReadFiles(kDifferentFiles); +} + +TEST_P(CdmStorageTest, MigrateDataUnrecognizedCdmType) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + // Write some data using the old backend. + WriteFiles(kDefaultFiles); + + // Write data an unrecognized CDM type from the same origin. + const std::vector<CdmFileIdAndContents> kDifferentFiles{ + {{"other1", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o'}}, + {{"other2", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o', 'r'}}, + {{"other3", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o', 'r', 'e'}}, + {{"other4", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o', 'r', 'e', 'd'}}, + }; + ResetAndBindToOldBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kUnrecognizedCdmType); + WriteFiles(kDifferentFiles); + + // Read data from the original CDM type using the new backend. + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); + ReadFiles(kDefaultFiles); + + // Open storage for the other CDM type. Media licenses for the unrecognized + // CDM type should NOT have been migrated. + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kUnrecognizedCdmType); + ExpectFilesEmpty(kDifferentFiles); + + // Despite not being migrated, the data should still have been removed from + // the old backend. + ResetAndBindToOldBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + ExpectFilesEmpty(kDefaultFiles); +} + +TEST_P(CdmStorageTest, MigrateDataMultipleOrigins) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + // Write some data using the old backend. + WriteFiles(kDefaultFiles); + + cdm_storage_.reset(); + + const blink::StorageKey kDifferentStorageKey = + blink::StorageKey::CreateFromStringForTesting("http://www.example.com"); + ResetAndBindToOldBackend(kDifferentStorageKey, kTestCdmType); + + const std::vector<CdmFileIdAndContents> kDifferentFiles{ + {{"dif_file1", kTestCdmType}, {'e', 'x', 'a', 'm'}}, + {{"dif_file2", kTestCdmType}, {'e', 'x', 'a', 'm', 'p'}}, + {{"dif_file3", kTestCdmType}, {'e', 'x', 'a', 'm', 'p', 'l'}}, + {{"dif_file4", kTestCdmType}, {'e', 'x', 'a', 'm', 'p', 'l', 'e'}}, + }; + WriteFiles(kDifferentFiles); + + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); + + ReadFiles(kDefaultFiles); + + cdm_storage_.reset(); + + // Open storage for the other origin. All media licenses should have been + // migrated. + ResetAndBindToNewBackend(kDifferentStorageKey, kTestCdmType); + + ReadFiles(kDifferentFiles); +} + +#if BUILDFLAG(ENABLE_WIDEVINE) +TEST_P(CdmStorageTest, MigrateDataWidevine) { + if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { + // No data to migrate if the flag is enabled. + return; + } + + ResetAndBindToOldBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kWidevineCdmType); + + const std::vector<CdmFileIdAndContents> kWidevineFiles{ + {{"wide_file1", kWidevineCdmType}, {'e', 'x', 'a', 'm'}}, + {{"wide_file2", kWidevineCdmType}, {'e', 'x', 'a', 'm', 'p'}}, + {{"wide_file3", kWidevineCdmType}, {'e', 'x', 'a', 'm', 'p', 'l'}}, + {{"wide_file4", kWidevineCdmType}, {'e', 'x', 'a', 'm', 'p', 'l', 'e'}}, + }; + + // Write some Widevine data using the old backend. + WriteFiles(kWidevineFiles); + + ResetAndBindToNewBackend( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kWidevineCdmType); + base::RunLoop loop; + media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); + loop.Run(); + + // Read data using the new backend. + ReadFiles(kWidevineFiles); +} +#endif // BUILDFLAG(ENABLE_WIDEVINE) + } // namespace content
diff --git a/content/browser/media/media_license_manager.cc b/content/browser/media/media_license_manager.cc index ec395fe..50e9039 100644 --- a/content/browser/media/media_license_manager.cc +++ b/content/browser/media/media_license_manager.cc
@@ -6,10 +6,16 @@ #include <memory> #include <utility> +#include <vector> +#include "base/barrier_callback.h" +#include "base/barrier_closure.h" #include "base/bind.h" #include "base/callback_forward.h" +#include "base/containers/flat_map.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/notreached.h" #include "base/sequence_checker.h" @@ -17,12 +23,37 @@ #include "base/task/bind_post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" +#include "base/threading/sequence_bound.h" #include "base/threading/sequenced_task_runner_handle.h" #include "components/services/storage/public/cpp/buckets/constants.h" #include "components/services/storage/public/cpp/constants.h" +#include "content/browser/media/media_license_database.h" #include "content/browser/media/media_license_storage_host.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/cdm_info.h" +#include "media/cdm/cdm_type.h" +#include "media/media_buildflags.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" #include "sql/database.h" +#include "storage/browser/file_system/file_stream_reader.h" +#include "storage/browser/file_system/file_system_context.h" +#include "storage/browser/file_system/file_system_url.h" +#include "storage/browser/file_system/isolated_context.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" +#include "third_party/widevine/cdm/buildflags.h" // nogncheck +#include "url/origin.h" + +#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) +#include "content/public/common/cdm_info.h" +#endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) + +#if BUILDFLAG(ENABLE_WIDEVINE) +#include "third_party/widevine/cdm/widevine_cdm_common.h" // nogncheck +#endif // BUILDFLAG(ENABLE_WIDEVINE) namespace content { @@ -46,13 +77,212 @@ }); } +// TODO(crbug.com/1231162): Yes, this code is ugly. It is only in place while we +// migrate to the new media license backend. +absl::optional<media::CdmType> GetCdmTypeFromFileSystemId( + const std::string& file_system_id) { + if (file_system_id == "application_x-ppapi-clearkey-cdm") { + // `kClearKeyCdmType` from media/cdm/cdm_paths.h + return media::CdmType{ + base::Token{0x3a2e0fadde4bd1b7ull, 0xcb90df3e240d1694ull}, + "application_x-ppapi-clearkey-cdm"}; + } +#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) + else if (file_system_id == "application_chromeos-cdm-factory-daemon") { + return kChromeOsCdmType; + } +#endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) + +#if BUILDFLAG(ENABLE_WIDEVINE) + else if (file_system_id == "application_x-ppapi-widevine-cdm") { + return kWidevineCdmType; + } +#if BUILDFLAG(IS_WIN) + else if (file_system_id == "") { + return kMediaFoundationWidevineCdmType; + } +#endif // BUILDFLAG(IS_WIN) +#endif // BUILDFLAG(ENABLE_WIDEVINE) + else if (file_system_id == "test_file_system") { + // Used in migration tests in cdm_storage_impl_unittest.cc + return media::CdmType{base::Token{1234, 5678}, "test_file_system"}; + } else if (file_system_id == "different_plugin") { + // Used in migration tests in cdm_storage_impl_unittest.cc + return media::CdmType{base::Token{8765, 4321}, "different_plugin"}; + } + + // `file_system_id` doesn't match a known CDM type. + return absl::nullopt; +} + +base::flat_map<blink::StorageKey, std::vector<MediaLicenseManager::CdmFileId>> +GetMediaLicensesOnFileTaskRunner( + scoped_refptr<storage::FileSystemContext> context) { + DCHECK(context); + + storage::PluginPrivateFileSystemBackend* plugin_private_backend = + context->plugin_private_backend(); + + auto storage_keys = + plugin_private_backend->GetStorageKeysForTypeOnFileTaskRunner( + storage::kFileSystemTypePluginPrivate); + + if (storage_keys.empty()) + return {}; + + return base::MakeFlatMap<blink::StorageKey, + std::vector<MediaLicenseManager::CdmFileId>>( + storage_keys, /*comp=*/{}, + [&plugin_private_backend, &context](const auto& storage_key) { + std::vector<MediaLicenseManager::CdmFileId> cdm_files_for_storage_key; + auto cdm_files = plugin_private_backend + ->GetMediaLicenseFilesForOriginOnFileTaskRunner( + context.get(), storage_key.origin()); + for (const auto& cdm_file : cdm_files) { + auto maybe_cdm_type = + GetCdmTypeFromFileSystemId(cdm_file.legacy_file_system_id); + if (!maybe_cdm_type.has_value()) + continue; + + cdm_files_for_storage_key.emplace_back(cdm_file.name, + maybe_cdm_type.value()); + } + + return std::make_pair(storage_key, + std::move(cdm_files_for_storage_key)); + }); +} + +void DidReadFiles( + scoped_refptr<storage::FileSystemContext> context, + base::OnceCallback< + void(std::vector<MediaLicenseManager::CdmFileIdAndContents>)> callback, + const std::vector<MediaLicenseManager::CdmFileIdAndContents>& files) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + // Don't bother migrating empty files. + std::vector<MediaLicenseManager::CdmFileIdAndContents> files_to_migrate; + base::ranges::for_each( + files, + [&files_to_migrate](MediaLicenseManager::CdmFileIdAndContents file) { + if (!file.data.empty()) + files_to_migrate.emplace_back(std::move(file)); + }); + + std::move(callback).Run(std::move(files_to_migrate)); +} + +void DidReadFile( + std::unique_ptr<storage::FileStreamReader> /*reader*/, + scoped_refptr<net::IOBufferWithSize> buffer, + MediaLicenseManager::CdmFileId file, + base::OnceCallback<void(MediaLicenseManager::CdmFileIdAndContents)> + callback, + int result) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (result != buffer->size()) { + std::move(callback).Run({file, {}}); + return; + } + + std::vector<uint8_t> data(buffer->data(), buffer->data() + buffer->size()); + std::move(callback).Run({file, std::move(data)}); +} + +void DidGetLength( + std::unique_ptr<storage::FileStreamReader> reader, + MediaLicenseManager::CdmFileId file, + base::OnceCallback<void(MediaLicenseManager::CdmFileIdAndContents)> + callback, + int64_t result) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + // No need to Read() from `reader` if the file length is 0. + if (result <= 0) { + std::move(callback).Run({file, {}}); + return; + } + + auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(result); + auto* reader_ptr = reader.get(); + reader_ptr->Read(buffer.get(), buffer->size(), + base::BindOnce(&DidReadFile, std::move(reader), buffer, + std::move(file), std::move(callback))); +} + +void ReadFiles( + scoped_refptr<storage::FileSystemContext> context, + std::string file_system_root_uri, + std::vector<MediaLicenseManager::CdmFileId> files, + base::OnceCallback<void( + std::vector<MediaLicenseManager::CdmFileIdAndContents>)> callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + DCHECK(!files.empty()); + + // Kick off a number of read file operations and collect the results. + // Bind `context` to keep it alive while reading files. + auto* context_ptr = context.get(); + auto barrier = + base::BarrierCallback<MediaLicenseManager::CdmFileIdAndContents>( + files.size(), base::BindOnce(&DidReadFiles, std::move(context), + std::move(callback))); + + for (const auto& file : files) { + // Adapted from CdmFileImpl::CreateFileSystemURL(). + const GURL crack_url = GURL(file_system_root_uri + file.name); + const blink::StorageKey crack_storage_key = + blink::StorageKey(url::Origin::Create(crack_url)); + auto url = context_ptr->CrackURL(crack_url, crack_storage_key); + auto reader = context_ptr->CreateFileStreamReader( + url, 0, storage::kMaximumLength, base::Time()); + if (!reader) { + barrier.Run({file, {}}); + continue; + } + auto* reader_ptr = reader.get(); + auto result = reader_ptr->GetLength(base::BindOnce( + &DidGetLength, std::move(reader), std::move(file), barrier)); + // The GetLength() call is expected to run asynchronously. + DCHECK_EQ(result, net::ERR_IO_PENDING); + } +} + +void WriteFilesOnDbThread( + std::vector<MediaLicenseManager::CdmFileIdAndContents> files, + const base::FilePath& database_path) { + auto db = std::make_unique<MediaLicenseDatabase>(database_path); + + for (auto& file : files) { + db->OpenFile(file.file.cdm_type, file.file.name); + db->WriteFile(file.file.cdm_type, file.file.name, file.data); + } +} + } // namespace +MediaLicenseManager::CdmFileId::CdmFileId(const std::string& name, + const media::CdmType& cdm_type) + : name(name), cdm_type(cdm_type) {} +MediaLicenseManager::CdmFileId::CdmFileId(const CdmFileId&) = default; +MediaLicenseManager::CdmFileId::~CdmFileId() = default; + +MediaLicenseManager::CdmFileIdAndContents::CdmFileIdAndContents( + const CdmFileId& file, + std::vector<uint8_t> data) + : file(file), data(std::move(data)) {} +MediaLicenseManager::CdmFileIdAndContents::CdmFileIdAndContents( + const CdmFileIdAndContents&) = default; +MediaLicenseManager::CdmFileIdAndContents::~CdmFileIdAndContents() = default; + MediaLicenseManager::MediaLicenseManager( + scoped_refptr<storage::FileSystemContext> file_system_context, const base::FilePath& bucket_base_path, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) - : db_runner_(CreateDatabaseTaskRunner()), + : file_system_context_(std::move(file_system_context)), + db_runner_(CreateDatabaseTaskRunner()), bucket_base_path_(bucket_base_path), special_storage_policy_(std::move(special_storage_policy)), quota_manager_proxy_(std::move(quota_manager_proxy)), @@ -67,10 +297,197 @@ storage::QuotaClientType::kMediaLicense, {blink::mojom::StorageType::kTemporary}); } + + // TODO(crbug.com/1231162): Consider migrating media licenses here. } MediaLicenseManager::~MediaLicenseManager() = default; +void MediaLicenseManager::MigrateMediaLicenses(base::OnceClosure done_closure) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + DCHECK(plugin_private_data_migration_closure_.is_null()); + plugin_private_data_migration_closure_ = std::move(done_closure); + + context()->default_file_task_runner()->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&GetMediaLicensesOnFileTaskRunner, context()), + base::BindOnce(&MediaLicenseManager::DidGetMediaLicenses, + weak_factory_.GetWeakPtr())); +} + +void MediaLicenseManager::DidGetMediaLicenses( + base::flat_map<blink::StorageKey, std::vector<CdmFileId>> files_map) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!plugin_private_data_migration_closure_.is_null()); + + if (files_map.empty()) { + DidMigrateMediaLicenses(); + return; + } + + // Kick off migration process for each storage key. + base::RepeatingClosure barrier = base::BarrierClosure( + files_map.size(), + base::BindPostTask( + base::SequencedTaskRunnerHandle::Get(), + base::BindOnce(&MediaLicenseManager::DidMigrateMediaLicenses, + weak_factory_.GetWeakPtr()))); + + for (auto& storage_key_and_files : files_map) { + std::vector<CdmFileId> files = std::move(storage_key_and_files.second); + if (files.empty()) { + barrier.Run(); + continue; + } + const blink::StorageKey& storage_key = storage_key_and_files.first; + quota_manager_proxy()->GetOrCreateBucket( + storage_key, storage::kDefaultBucketName, + base::SequencedTaskRunnerHandle::Get(), + base::BindOnce(&MediaLicenseManager::OpenPluginFileSystemsForStorageKey, + weak_factory_.GetWeakPtr(), storage_key, + std::move(files), barrier)); + } +} + +void MediaLicenseManager::OpenPluginFileSystemsForStorageKey( + const blink::StorageKey& storage_key, + std::vector<CdmFileId> files, + base::OnceClosure done_migrating_storage_key_closure, + storage::QuotaErrorOr<storage::BucketInfo> result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!plugin_private_data_migration_closure_.is_null()); + + if (!result.ok()) { + std::move(done_migrating_storage_key_closure).Run(); + return; + } + + // Organize files by plugin name. + base::flat_map<std::string, std::vector<CdmFileId>> files_by_plugin_name; + for (auto& file : files) { + files_by_plugin_name[file.cdm_type.legacy_file_system_id].emplace_back( + std::move(file)); + } + + auto barrier = base::BarrierCallback<std::vector<CdmFileIdAndContents>>( + files_by_plugin_name.size(), + base::BindOnce(&MediaLicenseManager::DidReadFilesForStorageKey, + weak_factory_.GetWeakPtr(), storage_key, + result->ToBucketLocator(), + std::move(done_migrating_storage_key_closure))); + + for (const auto& [plugin_name, files] : files_by_plugin_name) { + // Register and open a file system for this plugin type. + std::string fsid = + storage::IsolatedContext::GetInstance() + ->RegisterFileSystemForVirtualPath( + storage::kFileSystemTypePluginPrivate, + storage::kPluginPrivateRootName, base::FilePath()); + DCHECK(storage::ValidateIsolatedFileSystemId(fsid)); + + std::string file_system_root_uri = + storage::GetIsolatedFileSystemRootURIString( + storage_key.origin().GetURL(), fsid, + storage::kPluginPrivateRootName); + + context()->OpenPluginPrivateFileSystem( + storage_key.origin(), + storage::FileSystemType::kFileSystemTypePluginPrivate, fsid, + plugin_name, + storage::OpenFileSystemMode::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, + base::BindOnce(&MediaLicenseManager::DidOpenPluginFileSystem, + weak_factory_.GetWeakPtr(), storage_key, + std::move(files), std::move(file_system_root_uri), + barrier)); + } +} + +void MediaLicenseManager::DidOpenPluginFileSystem( + const blink::StorageKey& storage_key, + std::vector<CdmFileId> files, + std::string file_system_root_uri, + base::OnceCallback<void(std::vector<CdmFileIdAndContents>)> callback, + base::File::Error error) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!plugin_private_data_migration_closure_.is_null()); + + if (error != base::File::FILE_OK) { + std::move(callback).Run({}); + return; + } + + auto wrapped_callback = base::BindPostTask( + base::SequencedTaskRunnerHandle::Get(), std::move(callback)); + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&ReadFiles, context(), std::move(file_system_root_uri), + std::move(files), std::move(wrapped_callback))); +} + +void MediaLicenseManager::DidReadFilesForStorageKey( + const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, + base::OnceClosure done_migrating_storage_key_closure, + std::vector<std::vector<CdmFileIdAndContents>> collected_files) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!plugin_private_data_migration_closure_.is_null()); + + // Flatten collected files into one vector. + std::vector<CdmFileIdAndContents> files; + for (auto& file_list : collected_files) { + for (auto& file : file_list) { + // Empty files should have been stripped out. + DCHECK(!file.data.empty()); + files.emplace_back(std::move(file)); + } + } + + if (files.empty()) { + std::move(done_migrating_storage_key_closure).Run(); + return; + } + + db_runner()->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&WriteFilesOnDbThread, std::move(files), + GetDatabasePath(bucket_locator)), + std::move(done_migrating_storage_key_closure)); +} + +void MediaLicenseManager::DidMigrateMediaLicenses() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!plugin_private_data_migration_closure_.is_null()); + + // Delete %profile/File System/Plugins since media license data is the only + // thing stored in the Plugin Private File System. + auto plugin_path = context()->plugin_private_backend()->base_path(); + + context()->default_file_task_runner()->PostTaskAndReply( + FROM_HERE, + base::BindOnce(base::IgnoreResult(&base::DeletePathRecursively), + plugin_path), + base::BindOnce(&MediaLicenseManager::DidClearPluginPrivateData, + weak_factory_.GetWeakPtr())); +} + +void MediaLicenseManager::DidClearPluginPrivateData() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!plugin_private_data_migration_closure_.is_null()); + + std::move(plugin_private_data_migration_closure_).Run(); + + // Now that data has been migrated, kick off binding the pending receivers. + for (const auto& receivers : pending_receivers_) { + const auto& storage_key = receivers.first; + // Get the default bucket for `storage_key`. + quota_manager_proxy()->GetOrCreateBucket( + storage_key, storage::kDefaultBucketName, + base::SequencedTaskRunnerHandle::Get(), + base::BindOnce(&MediaLicenseManager::DidGetBucket, + weak_factory_.GetWeakPtr(), storage_key)); + } +} + void MediaLicenseManager::OpenCdmStorage( const BindingContext& binding_context, mojo::PendingReceiver<media::mojom::CdmStorage> receiver) { @@ -86,14 +503,17 @@ auto& receiver_list = pending_receivers_[storage_key]; receiver_list.emplace_back(binding_context, std::move(receiver)); - if (receiver_list.size() > 1) { - // A pending receiver for this storage key already existed, meaning there is - // an in-flight `GetOrCreateBucket()` call for this storage key. + if (receiver_list.size() > 1 || + !plugin_private_data_migration_closure_.is_null()) { + // If a pending receiver for this storage key already existed, there is + // an in-flight `GetOrCreateBucket()` call for this storage key. If we're in + // the process of migrating data from the plugin private file system, + // pending receivers will be handled in `DidClearPluginPrivateData()`. return; } // Get the default bucket for `storage_key`. - quota_manager_proxy_->GetOrCreateBucket( + quota_manager_proxy()->GetOrCreateBucket( storage_key, storage::kDefaultBucketName, base::SequencedTaskRunnerHandle::Get(), base::BindOnce(&MediaLicenseManager::DidGetBucket, @@ -113,7 +533,15 @@ this, result->ToBucketLocator()); auto it = pending_receivers_.find(storage_key); - DCHECK(it != pending_receivers_.end()); + if (it == pending_receivers_.end()) { + // No receivers to bind. + // TODO(crbug.com/1231162): This case can only be hit + // when the migration code is kicked off after `OpenCdmStorage()` has + // already been called, since `OpenCdmStorage()` will not call + // `GetOrCreateBucket()` while there is an in-progress migration. Change + // this to a DCHECK once the migration logic is removed. + return; + } auto receivers_list = std::move(it->second); pending_receivers_.erase(it);
diff --git a/content/browser/media/media_license_manager.h b/content/browser/media/media_license_manager.h index f248837..17c4ad01 100644 --- a/content/browser/media/media_license_manager.h +++ b/content/browser/media/media_license_manager.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_MEDIA_MEDIA_LICENSE_MANAGER_H_ #include <memory> +#include <vector> #include "base/callback_forward.h" #include "base/containers/flat_map.h" @@ -13,10 +14,12 @@ #include "base/memory/scoped_refptr.h" #include "base/task/sequenced_task_runner.h" #include "base/types/pass_key.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/browser/media/media_license_quota_client.h" #include "content/common/content_export.h" #include "media/cdm/cdm_type.h" #include "media/mojo/mojom/cdm_storage.mojom.h" +#include "storage/browser/file_system/file_system_context.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -41,7 +44,35 @@ const media::CdmType cdm_type; }; + // A CDM file for a given storage key can be uniquely identified by its name + // and CDM type. + struct CONTENT_EXPORT CdmFileId { + CdmFileId(const std::string& name, const media::CdmType& cdm_type); + CdmFileId(const CdmFileId&); + ~CdmFileId(); + + bool operator==(const CdmFileId& rhs) const { + return (name == rhs.name) && (cdm_type == rhs.cdm_type); + } + bool operator<(const CdmFileId& rhs) const { + return std::tie(name, cdm_type) < std::tie(rhs.name, rhs.cdm_type); + } + + const std::string name; + const media::CdmType cdm_type; + }; + + struct CONTENT_EXPORT CdmFileIdAndContents { + CdmFileIdAndContents(const CdmFileId& file, std::vector<uint8_t> data); + CdmFileIdAndContents(const CdmFileIdAndContents&); + ~CdmFileIdAndContents(); + + const CdmFileId file; + const std::vector<uint8_t> data; + }; + MediaLicenseManager( + scoped_refptr<storage::FileSystemContext> file_system_context, const base::FilePath& bucket_base_path, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy); @@ -67,6 +98,10 @@ MediaLicenseStorageHost* host, base::PassKey<MediaLicenseStorageHost> pass_key); + void MigrateMediaLicensesForTesting(base::OnceClosure done_closure) { + MigrateMediaLicenses(std::move(done_closure)); + } + const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return quota_manager_proxy_; @@ -82,6 +117,11 @@ return bucket_base_path_.empty(); } + const scoped_refptr<storage::FileSystemContext>& context() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return file_system_context_; + } + private: void DidGetBucket(const blink::StorageKey& storage_key, storage::QuotaErrorOr<storage::BucketInfo> result); @@ -90,8 +130,37 @@ storage::mojom::QuotaClient::DeleteBucketDataCallback callback, bool success); + // TODO(crbug.com/1231162): The following methods are used to migrate from the + // old backend to the new backend. Remove once the migration is complete. + void MigrateMediaLicenses(base::OnceClosure done_closure); + void DidGetMediaLicenses( + base::flat_map<blink::StorageKey, std::vector<CdmFileId>> files); + void OpenPluginFileSystemsForStorageKey( + const blink::StorageKey& storage_key, + std::vector<CdmFileId> files, + base::OnceClosure done_migrating_storage_key_closure, + storage::QuotaErrorOr<storage::BucketInfo> result); + void DidOpenPluginFileSystem( + const blink::StorageKey& storage_key, + std::vector<CdmFileId> files, + std::string file_system_root_uri, + base::OnceCallback<void(std::vector<CdmFileIdAndContents>)> callback, + base::File::Error result); + void DidReadFilesForStorageKey( + const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, + base::OnceClosure done_migrating_storage_key_closure, + std::vector<std::vector<CdmFileIdAndContents>> collected_files); + void DidMigrateMediaLicenses(); + void DidClearPluginPrivateData(); + SEQUENCE_CHECKER(sequence_checker_); + // TODO(crbug.com/1231162): These members are only used to help migrate from + // the old backend to the new backend. Remove once the migration is complete. + const scoped_refptr<storage::FileSystemContext> file_system_context_; + base::OnceClosure plugin_private_data_migration_closure_; + // Task runner which all database operations are routed through. const scoped_refptr<base::SequencedTaskRunner> db_runner_;
diff --git a/content/browser/media/media_license_manager_unittest.cc b/content/browser/media/media_license_manager_unittest.cc index 7f54ae4..a4593219 100644 --- a/content/browser/media/media_license_manager_unittest.cc +++ b/content/browser/media/media_license_manager_unittest.cc
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/memory/scoped_refptr.h" #include "base/strings/strcat.h" #include "base/strings/string_piece_forward.h" #include "base/test/scoped_feature_list.h" @@ -24,8 +25,10 @@ #include "media/cdm/cdm_type.h" #include "media/mojo/mojom/cdm_storage.mojom-forward.h" #include "mojo/public/cpp/bindings/associated_remote.h" +#include "storage/browser/file_system/file_system_context.h" #include "storage/browser/test/mock_quota_manager.h" #include "storage/browser/test/mock_quota_manager_proxy.h" +#include "storage/browser/test/test_file_system_context.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -45,6 +48,7 @@ void SetUp() override { ASSERT_TRUE(bucket_base_path_.CreateUniqueTempDir()); + ASSERT_TRUE(file_system_context_path_.CreateUniqueTempDir()); quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>( /*is_incognito=*/false, bucket_base_path_.GetPath(), base::ThreadTaskRunnerHandle::Get().get(), @@ -52,8 +56,10 @@ quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>( static_cast<storage::MockQuotaManager*>(quota_manager_.get()), base::ThreadTaskRunnerHandle::Get()); + file_system_context_ = storage::CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, file_system_context_path_.GetPath()); manager_ = std::make_unique<MediaLicenseManager>( - bucket_base_path_.GetPath(), + file_system_context_, bucket_base_path_.GetPath(), /*special storage policy=*/nullptr, quota_manager_proxy_); } @@ -122,18 +128,19 @@ } protected: + scoped_refptr<storage::QuotaManager> quota_manager_; + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; + scoped_refptr<storage::FileSystemContext> file_system_context_; + base::test::ScopedFeatureList feature_list_; // This must be above MediaLicenseManager, to ensure that no file is accessed // when the temporary directory is deleted. base::ScopedTempDir bucket_base_path_; - + base::ScopedTempDir file_system_context_path_; base::test::TaskEnvironment task_environment_; std::unique_ptr<MediaLicenseManager> manager_; - - scoped_refptr<storage::QuotaManager> quota_manager_; - scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; }; TEST_F(MediaLicenseManagerTest, DeleteBucketData) { @@ -274,6 +281,7 @@ // Still create this dir so the teardown will confirm it remains empty (on // Windows, at least). ASSERT_TRUE(bucket_base_path_.CreateUniqueTempDir()); + ASSERT_TRUE(file_system_context_path_.CreateUniqueTempDir()); // `bucket_base_path` will be empty for an in-memory profile. base::FilePath bucket_base_path; @@ -284,8 +292,12 @@ quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>( static_cast<storage::MockQuotaManager*>(quota_manager_.get()), base::ThreadTaskRunnerHandle::Get()); + file_system_context_ = storage::CreateIncognitoFileSystemContextForTesting( + base::ThreadTaskRunnerHandle::Get(), + base::ThreadTaskRunnerHandle::Get(), /*quota_manager_proxy=*/nullptr, + file_system_context_path_.GetPath()); manager_ = std::make_unique<MediaLicenseManager>( - bucket_base_path, + file_system_context_, bucket_base_path, /*special storage policy=*/nullptr, quota_manager_proxy_); } };
diff --git a/content/browser/media/media_license_storage_host.cc b/content/browser/media/media_license_storage_host.cc index bdb02b0..0c634f0 100644 --- a/content/browser/media/media_license_storage_host.cc +++ b/content/browser/media/media_license_storage_host.cc
@@ -27,10 +27,7 @@ namespace content { -MediaLicenseStorageHost::CdmFileId::CdmFileId(const std::string& name, - const media::CdmType& cdm_type) - : name(name), cdm_type(cdm_type) {} -MediaLicenseStorageHost::CdmFileId::~CdmFileId() = default; +using CdmFileId = MediaLicenseManager::CdmFileId; MediaLicenseStorageHost::MediaLicenseStorageHost( MediaLicenseManager* manager,
diff --git a/content/browser/media/media_license_storage_host.h b/content/browser/media/media_license_storage_host.h index f4c3b82..f7596d4 100644 --- a/content/browser/media/media_license_storage_host.h +++ b/content/browser/media/media_license_storage_host.h
@@ -81,23 +81,6 @@ } private: - // A CDM file for a given storage key can be uniquely identified by its name - // and CDM type. - struct CdmFileId { - CdmFileId(const std::string& name, const media::CdmType& cdm_type); - ~CdmFileId(); - - bool operator==(const CdmFileId& rhs) const { - return (name == rhs.name) && (cdm_type == rhs.cdm_type); - } - bool operator<(const CdmFileId& rhs) const { - return std::tie(name, cdm_type) < std::tie(rhs.name, rhs.cdm_type); - } - - const std::string name; - const media::CdmType cdm_type; - }; - void OnReceiverDisconnect(); void DidOpenFile(const std::string& file_name, @@ -125,8 +108,8 @@ // Keep track of all media::mojom::CdmFile receivers, as each CdmFileImpl // object keeps a reference to |this|. If |this| goes away unexpectedly, // all remaining CdmFile receivers will be closed. - std::map<CdmFileId, std::unique_ptr<CdmFileImpl>> cdm_files_ - GUARDED_BY_CONTEXT(sequence_checker_); + std::map<MediaLicenseManager::CdmFileId, std::unique_ptr<CdmFileImpl>> + cdm_files_ GUARDED_BY_CONTEXT(sequence_checker_); base::WeakPtrFactory<MediaLicenseStorageHost> weak_factory_ GUARDED_BY_CONTEXT(sequence_checker_){this};
diff --git a/content/browser/net/sandboxed_http_cache_browsertest.cc b/content/browser/net/sandboxed_http_cache_browsertest.cc index 7ac0f54..d046d43 100644 --- a/content/browser/net/sandboxed_http_cache_browsertest.cc +++ b/content/browser/net/sandboxed_http_cache_browsertest.cc
@@ -149,8 +149,15 @@ run_loop.Run(); } +#if BUILDFLAG(IS_ANDROID) +#define MAYBE_CreateSimpleCacheWithParentDirectory \ + DISABLED_CreateSimpleCacheWithParentDirectory +#else +#define MAYBE_CreateSimpleCacheWithParentDirectory \ + CreateSimpleCacheWithParentDirectory +#endif // BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_F(SandboxedHttpCacheBrowserTest, - CreateSimpleCacheWithParentDirectory) { + MAYBE_CreateSimpleCacheWithParentDirectory) { base::RunLoop run_loop; const base::FilePath root_path = GetTempDirPath();
diff --git a/content/browser/renderer_host/frame_tree_browsertest.cc b/content/browser/renderer_host/frame_tree_browsertest.cc index 207b267..233a0b1 100644 --- a/content/browser/renderer_host/frame_tree_browsertest.cc +++ b/content/browser/renderer_host/frame_tree_browsertest.cc
@@ -1084,9 +1084,11 @@ EXPECT_EQ(0, EvalJs(root, "window.frames.length")); } +// Test the scenario where the FF navigation is deferred and then resumed, and +// the mapped url is a valid one. The navigation is expected to succeed. IN_PROC_BROWSER_TEST_P( FencedFrameTreeBrowserTest, - FencedFrameNavigationWithPendingMappedUUID_MappingSuccess) { + FencedFrameNavigationWithPendingMappedUUID_MappingSuccess_ValidURL) { GURL main_url = https_server()->GetURL("b.test", "/hello.html"); EXPECT_TRUE(NavigateToURL(shell(), main_url)); // It is safe to obtain the root frame tree node here, as it doesn't change. @@ -1135,7 +1137,10 @@ EXPECT_TRUE(url_mapping.HasObserverForTesting(urn_uuid, request)); // Trigger the mapping to resume the deferred navigation. - url_mapping.OnURNMappingResultDetermined(urn_uuid, mapped_url); + SimulateSharedStorageURNMappingComplete( + url_mapping, urn_uuid, mapped_url, + /*shared_storage_origin=*/url::Origin::Create(GURL("https://bar.com")), + /*budget_to_charge=*/2.0); EXPECT_FALSE(url_mapping.HasObserverForTesting(urn_uuid, request)); @@ -1146,9 +1151,11 @@ fenced_frame_root_node->current_frame_host()->GetLastCommittedURL()); } +// Test the scenario where the FF navigation is deferred and then resumed, and +// the mapped url is invalid. The navigation is expected to fail. IN_PROC_BROWSER_TEST_P( FencedFrameTreeBrowserTest, - FencedFrameNavigationWithPendingMappedUUID_MappingFailure) { + FencedFrameNavigationWithPendingMappedUUID_MappingSuccess_InvalidURL) { GURL main_url = https_server()->GetURL("b.test", "/hello.html"); EXPECT_TRUE(NavigateToURL(shell(), main_url)); // It is safe to obtain the root frame tree node here, as it doesn't change. @@ -1172,6 +1179,8 @@ root->current_frame_host()->GetPage().fenced_frame_urls_map(); const GURL urn_uuid = url_mapping.GeneratePendingMappedURN(); + const GURL mapped_url = + https_server()->GetURL("a.test", "/fenced_frames/nonexistent-url.html"); std::string navigate_urn_script = JsReplace("f.src = $1;", urn_uuid.spec()); TestFrameNavigationObserver observer( @@ -1195,12 +1204,17 @@ EXPECT_TRUE(url_mapping.HasObserverForTesting(urn_uuid, request)); // Trigger the mapping to resume the deferred navigation. - url_mapping.OnURNMappingResultDetermined(urn_uuid, absl::nullopt); + SimulateSharedStorageURNMappingComplete( + url_mapping, urn_uuid, mapped_url, + /*shared_storage_origin=*/url::Origin::Create(GURL("https://bar.com")), + /*budget_to_charge=*/2.0); EXPECT_FALSE(url_mapping.HasObserverForTesting(urn_uuid, request)); + // In NavigationRequest::OnResponseStarted(), for fenced frame, it manually + // fails the navigation with net::ERR_BLOCKED_BY_RESPONSE. observer.Wait(); - EXPECT_EQ(observer.last_net_error_code(), InvalidUrnError()); + EXPECT_EQ(observer.last_net_error_code(), net::ERR_BLOCKED_BY_RESPONSE); } IN_PROC_BROWSER_TEST_P(
diff --git a/content/browser/renderer_host/navigation_request_unittest.cc b/content/browser/renderer_host/navigation_request_unittest.cc index 2cafff4..b49d581 100644 --- a/content/browser/renderer_host/navigation_request_unittest.cc +++ b/content/browser/renderer_host/navigation_request_unittest.cc
@@ -16,6 +16,7 @@ #include "content/public/common/content_client.h" #include "content/public/common/url_constants.h" #include "content/public/test/test_navigation_throttle.h" +#include "content/test/fenced_frame_test_utils.h" #include "content/test/navigation_simulator_impl.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_render_frame_host.h" @@ -364,7 +365,10 @@ EXPECT_EQ(navigation_simulator->GetNavigationHandle()->GetURL(), urn_uuid); - fenced_frame_urls_map.OnURNMappingResultDetermined(urn_uuid, mapped_url); + SimulateSharedStorageURNMappingComplete( + fenced_frame_urls_map, urn_uuid, mapped_url, + /*shared_storage_origin=*/url::Origin::Create(GURL("https://bar.com")), + /*budget_to_charge=*/2.0); // Expect that the url in the NavigationRequest is already mapped. EXPECT_EQ(navigation_simulator->GetNavigationHandle()->GetURL(), mapped_url);
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc index d952660f..b573856 100644 --- a/content/browser/shared_storage/shared_storage_browsertest.cc +++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -152,18 +152,16 @@ void OnRunURLSelectionOperationOnWorkletFinished( const GURL& urn_uuid, - const std::vector<GURL>& urls, bool success, const std::string& error_message, uint32_t index) override { - OnRunURLSelectionOperationOnWorkletFinishedHelper(urn_uuid, urls, success, + OnRunURLSelectionOperationOnWorkletFinishedHelper(urn_uuid, success, error_message, index, /*initial_message=*/true); } void OnRunURLSelectionOperationOnWorkletFinishedHelper( const GURL& urn_uuid, - const std::vector<GURL>& urls, bool success, const std::string& error_message, uint32_t index, @@ -172,12 +170,12 @@ pending_worklet_messages_.push_back( base::BindOnce(&TestSharedStorageWorkletHost:: OnRunURLSelectionOperationOnWorkletFinishedHelper, - weak_ptr_factory_.GetWeakPtr(), urn_uuid, urls, - success, error_message, index, + weak_ptr_factory_.GetWeakPtr(), urn_uuid, success, + error_message, index, /*initial_message=*/false)); } else { SharedStorageWorkletHost::OnRunURLSelectionOperationOnWorkletFinished( - urn_uuid, urls, success, error_message, index); + urn_uuid, success, error_message, index); } if (initial_message) @@ -290,6 +288,26 @@ ASSERT_TRUE(https_server()->Start()); } + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> + GetSharedStorageBudgetMetadata(const GURL& urn_uuid) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetPrimaryFrameTree() + .root(); + + FencedFrameURLMapping& fenced_frame_url_mapping = + root->current_frame_host()->GetPage().fenced_frame_urls_map(); + + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> + metadata_1st_retrieval = + fenced_frame_url_mapping.ReleaseSharedStorageBudgetMetadata( + GURL(urn_uuid)); + + EXPECT_FALSE(fenced_frame_url_mapping.ReleaseSharedStorageBudgetMetadata( + GURL(urn_uuid))); + + return metadata_1st_retrieval; + } + net::EmbeddedTestServer* https_server() { return &https_server_; } TestSharedStorageWorkletHostManager& test_worklet_host_manager() { @@ -985,6 +1003,12 @@ .GetAttachedWorkletHost() ->WaitForWorkletResponsesCount(2); + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> metadata = + GetSharedStorageBudgetMetadata(GURL(urn_uuid)); + EXPECT_TRUE(metadata); + EXPECT_EQ(metadata->origin, https_server()->GetOrigin("a.test")); + EXPECT_DOUBLE_EQ(metadata->budget_to_charge, std::log2(3)); + GURL url0 = https_server()->GetURL("a.test", "/fenced_frames/title0.html"); GURL url1 = https_server()->GetURL("a.test", "/fenced_frames/title1.html"); GURL url2 = https_server()->GetURL("a.test", "/fenced_frames/title2.html"); @@ -1107,6 +1131,12 @@ observer.Wait(); + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> metadata = + GetSharedStorageBudgetMetadata(GURL(urn_uuid)); + EXPECT_TRUE(metadata); + EXPECT_EQ(metadata->origin, https_server()->GetOrigin("a.test")); + EXPECT_DOUBLE_EQ(metadata->budget_to_charge, std::log2(3)); + EXPECT_EQ( https_server()->GetURL("a.test", "/fenced_frames/title1.html"), fenced_frame_root_node->current_frame_host()->GetLastCommittedURL()); @@ -1286,8 +1316,9 @@ EXPECT_TRUE(request->is_deferred_on_fenced_frame_url_mapping_for_testing()); } - // Fire the keep-alive timer. This will terminate the keep-alive, and will - // fail the URN mapping, and will subsequently fail the deferred navigation. + // Fire the keep-alive timer. This will terminate the keep-alive, and the + // deferred navigation will resume to navigate to the default url (at index + // 0). test_worklet_host_manager() .GetKeepAliveWorkletHost() ->FireKeepAliveTimerNow(); @@ -1296,7 +1327,16 @@ EXPECT_EQ(0u, test_worklet_host_manager().GetKeepAliveWorkletHostsCount()); observer.Wait(); - EXPECT_EQ(observer.last_net_error_code(), InvalidUrnError()); + + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> metadata = + GetSharedStorageBudgetMetadata(GURL(urn_uuid)); + EXPECT_TRUE(metadata); + EXPECT_EQ(metadata->origin, https_server()->GetOrigin("a.test")); + EXPECT_DOUBLE_EQ(metadata->budget_to_charge, 1.0); + + EXPECT_EQ( + https_server()->GetURL("a.test", "/fenced_frames/title0.html"), + fenced_frame_root_node->current_frame_host()->GetLastCommittedURL()); } IN_PROC_BROWSER_TEST_F(SharedStorageBrowserTest, @@ -1332,6 +1372,12 @@ "Promise resolved to a number outside the length of the input urls.", base::UTF16ToUTF8(console_observer.messages().back().message)); + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> metadata = + GetSharedStorageBudgetMetadata(GURL(urn_uuid)); + EXPECT_TRUE(metadata); + EXPECT_EQ(metadata->origin, https_server()->GetOrigin("a.test")); + EXPECT_DOUBLE_EQ(metadata->budget_to_charge, 1.0); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) ->GetPrimaryFrameTree() .root(); @@ -1353,7 +1399,130 @@ EXPECT_EQ(urn_uuid, EvalJs(root, navigate_fenced_frame_to_urn_script)); observer.Wait(); - EXPECT_EQ(observer.last_net_error_code(), InvalidUrnError()); + + EXPECT_EQ( + https_server()->GetURL("a.test", "/fenced_frames/title0.html"), + fenced_frame_root_node->current_frame_host()->GetLastCommittedURL()); +} + +// Test that there's no need to charge budget if the input urls' size is 1. +// This specifically tests the operation success scenario. +IN_PROC_BROWSER_TEST_F( + SharedStorageBrowserTest, + RunURLSelectionOperation_BudgetMetadata_OperationSuccess_SingleInputURL) { + GURL main_url = https_server()->GetURL("a.test", kSimplePagePath); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + WebContentsConsoleObserver console_observer(shell()->web_contents()); + + EXPECT_TRUE(ExecJs(shell(), R"( + sharedStorage.worklet.addModule('shared_storage/simple_module.js'); + )")); + + std::string urn_uuid = EvalJs(shell(), R"( + sharedStorage.runURLSelectionOperation( + 'test-url-selection-operation', + ["fenced_frames/title0.html"], {data: {'mockResult':0}}); + )") + .ExtractString(); + + EXPECT_TRUE(FencedFrameURLMapping::IsValidUrnUuidURL(GURL(urn_uuid))); + + // There are 2 "worklet operations": addModule and runURLSelectionOperation. + test_worklet_host_manager() + .GetAttachedWorkletHost() + ->WaitForWorkletResponsesCount(2); + + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> metadata = + GetSharedStorageBudgetMetadata(GURL(urn_uuid)); + EXPECT_TRUE(metadata); + EXPECT_EQ(metadata->origin, https_server()->GetOrigin("a.test")); + EXPECT_DOUBLE_EQ(metadata->budget_to_charge, 0.0); + + EXPECT_EQ("Finish executing 'test-url-selection-operation'", + base::UTF16ToUTF8(console_observer.messages().back().message)); +} + +// Test that there's no need to charge budget if the input urls' size is 1. +// This specifically tests the operation failure scenario. +IN_PROC_BROWSER_TEST_F( + SharedStorageBrowserTest, + RunURLSelectionOperation_BudgetMetadata_OperationFailure_SingleInputURL) { + GURL main_url = https_server()->GetURL("a.test", kSimplePagePath); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + WebContentsConsoleObserver console_observer(shell()->web_contents()); + + EXPECT_TRUE(ExecJs(shell(), R"( + sharedStorage.worklet.addModule('shared_storage/simple_module.js'); + )")); + + std::string urn_uuid = EvalJs(shell(), R"( + sharedStorage.runURLSelectionOperation( + 'test-url-selection-operation', + ["fenced_frames/title0.html"], {data: {'mockResult':-1}}); + )") + .ExtractString(); + + EXPECT_TRUE(FencedFrameURLMapping::IsValidUrnUuidURL(GURL(urn_uuid))); + + // There are 2 "worklet operations": addModule and runURLSelectionOperation. + test_worklet_host_manager() + .GetAttachedWorkletHost() + ->WaitForWorkletResponsesCount(2); + + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> metadata = + GetSharedStorageBudgetMetadata(GURL(urn_uuid)); + EXPECT_TRUE(metadata); + EXPECT_EQ(metadata->origin, https_server()->GetOrigin("a.test")); + EXPECT_DOUBLE_EQ(metadata->budget_to_charge, 0.0); + + EXPECT_EQ("Promise did not resolve to an uint32 number.", + base::UTF16ToUTF8(console_observer.messages().back().message)); +} + +IN_PROC_BROWSER_TEST_F(SharedStorageBrowserTest, + RunURLSelectionOperation_BudgetMetadata_Origin) { + EXPECT_TRUE(NavigateToURL( + shell(), https_server()->GetURL("a.test", kPageWithBlankIframePath))); + + GURL iframe_url = https_server()->GetURL("b.test", kSimplePagePath); + NavigateIframeToURL(shell()->web_contents(), "test_iframe", iframe_url); + + RenderFrameHost* iframe = + static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetPrimaryFrameTree() + .root() + ->child_at(0) + ->current_frame_host(); + + EXPECT_TRUE(ExecJs(iframe, R"( + sharedStorage.worklet.addModule('shared_storage/simple_module.js'); + )")); + + EXPECT_EQ(1u, test_worklet_host_manager().GetAttachedWorkletHostsCount()); + EXPECT_EQ(0u, test_worklet_host_manager().GetKeepAliveWorkletHostsCount()); + + std::string urn_uuid = EvalJs(iframe, R"( + sharedStorage.runURLSelectionOperation( + 'test-url-selection-operation', + ["fenced_frames/title0.html", "fenced_frames/title1.html", + "fenced_frames/title2.html"], {data: {'mockResult': 1}}); + )") + .ExtractString(); + + EXPECT_TRUE(FencedFrameURLMapping::IsValidUrnUuidURL(GURL(urn_uuid))); + + // There are 2 "worklet operations": addModule and runURLSelectionOperation. + test_worklet_host_manager() + .GetAttachedWorkletHost() + ->WaitForWorkletResponsesCount(2); + + absl::optional<FencedFrameURLMapping::SharedStorageBudgetMetadata> metadata = + GetSharedStorageBudgetMetadata(GURL(urn_uuid)); + EXPECT_TRUE(metadata); + EXPECT_EQ(metadata->origin, https_server()->GetOrigin("b.test")); + EXPECT_DOUBLE_EQ(metadata->budget_to_charge, std::log2(3)); } } // namespace content
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc index 9c93e22..c555633f 100644 --- a/content/browser/shared_storage/shared_storage_worklet_host.cc +++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -18,6 +18,34 @@ constexpr base::TimeDelta kKeepAliveTimeout = base::Seconds(2); +using SharedStorageURNMappingResult = + FencedFrameURLMapping::SharedStorageURNMappingResult; + +using SharedStorageBudgetMetadata = + FencedFrameURLMapping::SharedStorageBudgetMetadata; + +SharedStorageURNMappingResult CalculateSharedStorageURNMappingResult( + bool url_selection_succeeded, + const url::Origin& shared_storage_origin, + const std::vector<GURL>& urls, + uint32_t index) { + DCHECK_GT(urls.size(), 0u); + DCHECK_LT(index, urls.size()); + DCHECK(url_selection_succeeded || index == 0); + + GURL mapped_url = urls[index]; + double budget_to_charge = + (urls.size() > 1u) + ? (url_selection_succeeded ? std::log2(urls.size()) : 1.0) + : 0.0; + + return SharedStorageURNMappingResult{ + .mapped_url = mapped_url, + .metadata = + SharedStorageBudgetMetadata{.origin = shared_storage_origin, + .budget_to_charge = budget_to_charge}}; +} + } // namespace SharedStorageWorkletHost::SharedStorageWorkletHost( @@ -27,7 +55,9 @@ document_service_(document_service.GetWeakPtr()), page_( static_cast<PageImpl&>(document_service.render_frame_host().GetPage()) - .GetWeakPtrImpl()) {} + .GetWeakPtrImpl()), + shared_storage_origin_( + document_service.render_frame_host().GetLastCommittedOrigin()) {} SharedStorageWorkletHost::~SharedStorageWorkletHost() { if (!page_) @@ -35,9 +65,17 @@ // If the worklet is destructed and there are still unresolved URNs (i.e. the // keep-alive timeout is reached), consider the mapping to be failed. - for (const GURL& urn_uuid : unresolved_urns_) { - page_->fenced_frame_urls_map().OnURNMappingResultDetermined(urn_uuid, - absl::nullopt); + auto it = unresolved_urns_.begin(); + while (it != unresolved_urns_.end()) { + const GURL& urn_uuid = it->first; + const std::vector<GURL>& urls = it->second; + + page_->fenced_frame_urls_map().OnSharedStorageURNMappingResultDetermined( + urn_uuid, CalculateSharedStorageURNMappingResult( + /*url_selection_succeeded=*/false, shared_storage_origin_, + urls, /*index=*/0)); + + it = unresolved_urns_.erase(it); } } @@ -126,10 +164,10 @@ GURL urn_uuid = page_->fenced_frame_urls_map().GeneratePendingMappedURN(); - bool insert_succeeded = unresolved_urns_.insert(urn_uuid).second; + bool emplace_succeeded = unresolved_urns_.emplace(urn_uuid, urls).second; // Assert that `urn_uuid` was not in the set before. - DCHECK(insert_succeeded); + DCHECK(emplace_succeeded); std::move(callback).Run( /*success=*/true, /*error_message=*/{}, @@ -139,7 +177,7 @@ name, urls, serialized_data, base::BindOnce(&SharedStorageWorkletHost:: OnRunURLSelectionOperationOnWorkletFinished, - weak_ptr_factory_.GetWeakPtr(), urn_uuid, urls)); + weak_ptr_factory_.GetWeakPtr(), urn_uuid)); } bool SharedStorageWorkletHost::HasPendingOperations() { @@ -295,11 +333,13 @@ void SharedStorageWorkletHost::OnRunURLSelectionOperationOnWorkletFinished( const GURL& urn_uuid, - const std::vector<GURL>& urls, bool success, const std::string& error_message, uint32_t index) { - if (success && index >= urls.size()) { + std::vector<GURL> urls = unresolved_urns_.at(urn_uuid); + unresolved_urns_.erase(urn_uuid); + + if ((success && index >= urls.size()) || (!success && index != 0)) { // This could indicate a compromised worklet environment, so let's terminate // it. mojo::ReportBadMessage( @@ -316,13 +356,9 @@ } if (page_) { - DCHECK(base::Contains(unresolved_urns_, urn_uuid)); - unresolved_urns_.erase(urn_uuid); - - absl::optional<GURL> selected_url = - success ? absl::make_optional<GURL>(urls[index]) : absl::nullopt; - page_->fenced_frame_urls_map().OnURNMappingResultDetermined(urn_uuid, - selected_url); + page_->fenced_frame_urls_map().OnSharedStorageURNMappingResultDetermined( + urn_uuid, CalculateSharedStorageURNMappingResult( + success, shared_storage_origin_, urls, index)); } DecrementPendingOperationsCount();
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.h b/content/browser/shared_storage/shared_storage_worklet_host.h index 48d915a2..86e3eb9 100644 --- a/content/browser/shared_storage/shared_storage_worklet_host.h +++ b/content/browser/shared_storage/shared_storage_worklet_host.h
@@ -112,7 +112,6 @@ virtual void OnRunURLSelectionOperationOnWorkletFinished( const GURL& urn_uuid, - const std::vector<GURL>& urls, bool success, const std::string& error_message, uint32_t index); @@ -163,11 +162,15 @@ // its keep-alive. base::WeakPtr<PageImpl> page_; - // A set of unresolved URNs. Inside `RunURLSelectionOperationOnWorklet()` a - // new URN is generated and is inserted to `unresolved_urns_`. When the - // corresponding `OnRunURLSelectionOperationOnWorkletFinished()` is called, - // the URN is removed from `unresolved_urns_`. - std::set<GURL> unresolved_urns_; + // The shared storage owner document's origin. + url::Origin shared_storage_origin_; + + // A map of unresolved URNs to the candidate URL vector. Inside + // `RunURLSelectionOperationOnWorklet()` a new URN is generated and is + // inserted into `unresolved_urns_`. When the corresponding + // `OnRunURLSelectionOperationOnWorkletFinished()` is called, the URN is + // removed from `unresolved_urns_`. + std::map<GURL, std::vector<GURL>> unresolved_urns_; // The number of unfinished worklet requests, including addModule and // runOperation.
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 8bd8281..621016b94 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -1366,8 +1366,8 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) media_license_manager_ = std::make_unique<MediaLicenseManager>( - GetBucketBasePath(), browser_context_->GetSpecialStoragePolicy(), - quota_manager_proxy); + filesystem_context_, GetBucketBasePath(), + browser_context_->GetSpecialStoragePolicy(), quota_manager_proxy); #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) }
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 95fece613..c618165 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -587,6 +587,7 @@ if (is_chromeos) { sources += [ "lock_screen_storage.h" ] + deps += [ "//ui/ozone:ozone_switches" ] } if (!is_android) {
diff --git a/content/public/browser/DEPS b/content/public/browser/DEPS index f48a82e..20ab9ff 100644 --- a/content/public/browser/DEPS +++ b/content/public/browser/DEPS
@@ -38,6 +38,13 @@ "+third_party/webrtc/modules/desktop_capture/desktop_capture_options.h", ], + "gpu_utils\.cc": [ + # For using switch::kPlatformDisallowsChromeOSDirectVideoDecoder. + # TODO(b/192563524): remove it when the legacy video decoder is replaced for + # all devices. + "+ui/ozone/public/ozone_switches.h", + ], + ".*unittest\.cc": [ "+services/network/network_service.h", ],
diff --git a/content/public/browser/gpu_utils.cc b/content/public/browser/gpu_utils.cc index 9b5dcf7..57350fd 100644 --- a/content/public/browser/gpu_utils.cc +++ b/content/public/browser/gpu_utils.cc
@@ -14,7 +14,6 @@ #include "build/chromeos_buildflags.h" #include "cc/base/switches.h" #include "components/viz/common/features.h" -#include "components/viz/common/switches.h" #include "components/viz/common/viz_utils.h" #include "content/browser/browser_main_loop.h" #include "content/browser/gpu/gpu_process_host.h" @@ -28,6 +27,12 @@ #include "media/media_buildflags.h" #include "ui/gfx/switches.h" +// TODO(b/192563524): remove it when the legacy video decoder is replaced for +// all devices. +#if BUILDFLAG(IS_CHROMEOS) +#include "ui/ozone/public/ozone_switches.h" // nogncheck +#endif // BUILDFLAG(IS_CHROMEOS) + namespace { void KillGpuProcessImpl(content::GpuProcessHost* host) {
diff --git a/content/renderer/media/inspector_media_event_handler.cc b/content/renderer/media/inspector_media_event_handler.cc index 99d374a4..039e1c7 100644 --- a/content/renderer/media/inspector_media_event_handler.cc +++ b/content/renderer/media/inspector_media_event_handler.cc
@@ -13,6 +13,62 @@ namespace { +absl::optional<blink::InspectorPlayerError> ErrorFromParams( + const base::Value& param) { + absl::optional<int> code = param.FindIntKey(media::StatusConstants::kCodeKey); + const std::string* group = + param.FindStringKey(media::StatusConstants::kGroupKey); + const std::string* message = + param.FindStringKey(media::StatusConstants::kMsgKey); + + // message might be empty or not present, but group and code are required. + CHECK(code.has_value() && group); + + blink::InspectorPlayerErrors caused_by; + if (const auto* c = param.FindDictKey(media::StatusConstants::kCauseKey)) { + auto parsed_cause = ErrorFromParams(*c); + if (parsed_cause.has_value()) + caused_by.push_back(*parsed_cause); + } + + blink::WebVector<blink::InspectorPlayerError::SourceLocation> stack_vec; + if (const auto* vec = param.FindDictKey(media::StatusConstants::kStackKey)) { + for (const auto& loc : vec->GetListDeprecated()) { + const std::string* file = + loc.FindStringKey(media::StatusConstants::kFileKey); + absl::optional<int> line = + loc.FindIntKey(media::StatusConstants::kLineKey); + if (!file || !line.has_value()) + continue; + blink::InspectorPlayerError::SourceLocation entry = { + blink::WebString::FromUTF8(*file), *line}; + stack_vec.push_back(std::move(entry)); + } + } + + blink::WebVector<blink::InspectorPlayerError::Data> data_vec; + if (auto* data = param.FindDictKey(media::StatusConstants::kDataKey)) { + for (const auto pair : data->DictItems()) { + std::string json; + base::JSONWriter::Write(pair.second, &json); + blink::InspectorPlayerError::Data entry = { + blink::WebString::FromUTF8(pair.first), + blink::WebString::FromUTF8(json)}; + data_vec.push_back(std::move(entry)); + } + } + + blink::InspectorPlayerError result = { + blink::WebString::FromUTF8(*group), + *code, + blink::WebString::FromUTF8(message ? *message : ""), + std::move(stack_vec), + std::move(caused_by), + std::move(data_vec)}; + + return std::move(result); +} + blink::WebString ToString(const base::Value& value) { if (value.is_string()) { return blink::WebString::FromUTF8(value.GetString()); @@ -83,26 +139,10 @@ break; } case media::MediaLogRecord::Type::kMediaStatus: { - const std::string* group = - event.params.FindStringKey(media::StatusConstants::kGroupKey); - auto code = event.params.FindIntKey(media::StatusConstants::kCodeKey) - .value_or(0); - DCHECK_NE(code, 0); - DCHECK_NE(group, nullptr); - if (group && *group == media::PipelineStatus::Traits::Group()) { - blink::InspectorPlayerError error = { - blink::InspectorPlayerError::Type::kPipelineError, - blink::WebString::FromUTF8(media::PipelineStatusToString( - static_cast<media::PipelineStatusCodes>(code)))}; - errors.emplace_back(std::move(error)); - } else { - std::stringstream formatted; - formatted << *group << ":" << code; - blink::InspectorPlayerError error = { - blink::InspectorPlayerError::Type::kPipelineError, - blink::WebString::FromUTF8(formatted.str())}; - errors.emplace_back(std::move(error)); - } + absl::optional<blink::InspectorPlayerError> error = + ErrorFromParams(event.params); + if (error.has_value()) + errors.emplace_back(std::move(*error)); } } }
diff --git a/content/renderer/media/inspector_media_event_handler_unittest.cc b/content/renderer/media/inspector_media_event_handler_unittest.cc index ac2fc63..0e9a7e233 100644 --- a/content/renderer/media/inspector_media_event_handler_unittest.cc +++ b/content/renderer/media/inspector_media_event_handler_unittest.cc
@@ -150,7 +150,7 @@ bool operator==(const blink::InspectorPlayerError& lhs, const blink::InspectorPlayerError& rhs) { - return lhs.errorCode == rhs.errorCode; + return lhs.group == rhs.group && lhs.code == rhs.code; } bool operator!=(const blink::InspectorPlayerError& lhs, @@ -309,12 +309,8 @@ CreateError(media::PIPELINE_ERROR_EXTERNAL_RENDERER_FAILED)}; blink::InspectorPlayerErrors expected_errors; - blink::InspectorPlayerError first = { - blink::InspectorPlayerError::Type::kPipelineError, - blink::WebString::FromUTF8("PIPELINE_ERROR_NETWORK")}; - blink::InspectorPlayerError second = { - blink::InspectorPlayerError::Type::kPipelineError, - blink::WebString::FromUTF8("PIPELINE_ERROR_EXTERNAL_RENDERER_FAILED")}; + blink::InspectorPlayerError first = {"PipelineStatus", 2, "", {}, {}, {}}; + blink::InspectorPlayerError second = {"PipelineStatus", 21, "", {}, {}, {}}; expected_errors.emplace_back(first); expected_errors.emplace_back(second);
diff --git a/content/test/data/fenced_frames/title0.html b/content/test/data/fenced_frames/title0.html new file mode 100644 index 0000000..c352e71 --- /dev/null +++ b/content/test/data/fenced_frames/title0.html
@@ -0,0 +1,4 @@ +<html> +<head></head> +<body>Page title0</body> +</html> \ No newline at end of file
diff --git a/content/test/data/fenced_frames/title0.html.mock-http-headers b/content/test/data/fenced_frames/title0.html.mock-http-headers new file mode 100644 index 0000000..263e89c4 --- /dev/null +++ b/content/test/data/fenced_frames/title0.html.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Supports-Loading-Mode: fenced-frame \ No newline at end of file
diff --git a/content/test/fenced_frame_test_utils.cc b/content/test/fenced_frame_test_utils.cc index f2a5633..8737e8d 100644 --- a/content/test/fenced_frame_test_utils.cc +++ b/content/test/fenced_frame_test_utils.cc
@@ -23,6 +23,20 @@ return FrameTreeNode::GloballyFindByID(inner_node_id); } +void SimulateSharedStorageURNMappingComplete( + FencedFrameURLMapping& fenced_frame_url_mapping, + const GURL& urn_uuid, + const GURL& mapped_url, + const url::Origin& shared_storage_origin, + double budget_to_charge) { + FencedFrameURLMapping::SharedStorageBudgetMetadata metadata = { + .origin = shared_storage_origin, .budget_to_charge = budget_to_charge}; + + fenced_frame_url_mapping.OnSharedStorageURNMappingResultDetermined( + urn_uuid, FencedFrameURLMapping::SharedStorageURNMappingResult{ + .mapped_url = mapped_url, .metadata = metadata}); +} + TestFencedFrameURLMappingResultObserver:: TestFencedFrameURLMappingResultObserver() = default;
diff --git a/content/test/fenced_frame_test_utils.h b/content/test/fenced_frame_test_utils.h index d66e1f4..ec637653 100644 --- a/content/test/fenced_frame_test_utils.h +++ b/content/test/fenced_frame_test_utils.h
@@ -19,6 +19,13 @@ // we're in the MPArch version of fenced frames FrameTreeNode* GetFencedFrameRootNode(FrameTreeNode* node); +void SimulateSharedStorageURNMappingComplete( + FencedFrameURLMapping& fenced_frame_url_mapping, + const GURL& urn_uuid, + const GURL& mapped_url, + const url::Origin& shared_storage_origin, + double budget_to_charge); + // Tests can use this class to observe and check the URL mapping result. class TestFencedFrameURLMappingResultObserver : public FencedFrameURLMapping::MappingResultObserver {
diff --git a/docs/webui_explainer.md b/docs/webui_explainer.md index 7487560e..5f30e05d 100644 --- a/docs/webui_explainer.md +++ b/docs/webui_explainer.md
@@ -892,25 +892,37 @@ ## JavaScript Error Reporting -By default, errors in the JavaScript of a WebUI page will generate error reports -which appear in Google's internal crash/ reports page. These error reports will -only be generated for Google Chrome builds, not Chromium or other Chromium-based -browsers. +By default, errors in the JavaScript or TypeScript of a WebUI page will generate +error reports which appear in Google's internal [go/crash](http://go/crash) +reports page. These error reports will only be generated for Google Chrome +builds, not Chromium or other Chromium-based browsers. -Specifically, an error report will be generated when the JavaScript for a -WebUI-based chrome:// page does one of the following: +Specifically, an error report will be generated when the JavaScript or +TypeScript for a WebUI-based chrome:// page does one of the following: * Generates an uncaught exception, * Has a promise which is rejected, and no rejection handler is provided, or * Calls `console.error()`. Such errors will appear alongside other crashes in the -`product_name=Chrome_ChromeOS` or `product_name=Chrome_Linux` lists on crash/. -The signature of the error is simply the error message. To avoid -spamming the system, only one error report with a given message will be +`product_name=Chrome_ChromeOS`, `product_name=Chrome_Lacros`, or +`product_name=Chrome_Linux` lists on [go/crash](http://go/crash). + +The signature of the error is the error message followed by the URL on which the +error appeared. For example, if chrome://settings/lazy_load.js throws a +TypeError with a message `Cannot read properties of null (reading 'select')` and +does not catch it, the magic signature would be +``` +Uncaught TypeError: Cannot read properties of null (reading 'select') (chrome://settings) +``` +To avoid spamming the system, only one error report with a given message will be generated per hour. If you are getting error reports for an expected condition, you can turn off the -reports simply by changing `console.error()` into `console.warn()`. +reports simply by changing `console.error()` into `console.warn()`. For +instance, if JavaScript is calling `console.error()` when the user tries to +connect to an unavailable WiFi network at the same time the page shows the user +an error message, the `console.error()` should be replaced with a +`console.warn()`. If you wish to get more control of the JavaScript error messages, for example to change the product name or to add additional data, you may wish to switch to @@ -918,8 +930,28 @@ `WebUIController::IsJavascriptErrorReportingEnabled()` to return false for your page; this will avoid generating redundant error reports. -Known issues: -1. Error reporting is currently enabled only on ChromeOS and Linux. +### Are JavaScript errors actually crashes? +JavaScript errors are not "crashes" in the C++ sense. They do not stop a process +from running, they do not cause a "sad tab" page. Some tooling refers to them as +crashes because they are going through the same pipeline as the C++ crashes, and +that pipeline was originally designed to handle crashes. + +### How much impact does this JavaScript error have? +That depends on the JavaScript error. In some cases, the errors have no user +impact; for instance, the "unavailable WiFi network calling `console.error()`" +example above. In other cases, JavaScript errors may be serious errors that +block the user from completing critical user journeys. For example, if the +JavaScript is supposed to un-hide one of several variants of settings page, but +the JavaScript has an unhandled exception before un-hiding any of them, then +the user will see a blank page and be unable to change that setting. + +Because it is difficult to automatically determine the severity of a given +error, JavaScript errors are currently all classified as "WARNING" level when +computing stability metrics. + +### Known issues +1. Error reporting is currently enabled only on ChromeOS (ash and Lacros) and + Linux. 2. Errors are only reported for chrome:// URLs. 3. Unhandled promise rejections do not have a good stack. 4. The line numbers and column numbers in the stacks are for the minified @@ -929,7 +961,6 @@ error message includes the name of a network, each network name will be its own signature. - ## See also * WebUI's C++ code follows the [Chromium C++ styleguide](../styleguide/c++/c++.md).
diff --git a/gpu/command_buffer/service/external_vk_image_factory_unittest.cc b/gpu/command_buffer/service/external_vk_image_factory_unittest.cc index d38cf18..0fb5ad2 100644 --- a/gpu/command_buffer/service/external_vk_image_factory_unittest.cc +++ b/gpu/command_buffer/service/external_vk_image_factory_unittest.cc
@@ -251,6 +251,11 @@ EXPECT_EQ(pixel[3], 255); } + if (skia_scoped_access->end_state()) { + context_state_->gr_context()->setBackendTextureState( + backend_texture, *skia_scoped_access->end_state()); + } + GrFlushInfo flush_info; flush_info.fNumSemaphores = end_semaphores.size(); flush_info.fSignalSemaphores = end_semaphores.data();
diff --git a/gpu/command_buffer/service/external_vk_image_skia_representation.cc b/gpu/command_buffer/service/external_vk_image_skia_representation.cc index 41773dd..0b51580 100644 --- a/gpu/command_buffer/service/external_vk_image_skia_representation.cc +++ b/gpu/command_buffer/service/external_vk_image_skia_representation.cc
@@ -213,6 +213,17 @@ DCHECK_NE(access_mode_, kNone); DCHECK(backing_impl()->need_synchronization() || !end_access_semaphore_); + // TODO(crbug.com/1307914): This check is specific to the interop case i.e. + // when need_synchronization() is true, but we can generalize this by making + // the client TakeEndState() and asserting that the |end_state_| is null here. +#if DCHECK_IS_ON() + GrVkImageInfo info; + auto result = backing_impl()->backend_texture().getVkImageInfo(&info); + DCHECK(result); + DCHECK(!backing_impl()->need_synchronization() || + info.fCurrentQueueFamily == VK_QUEUE_FAMILY_EXTERNAL); +#endif + backing_impl()->EndAccess(readonly, std::move(end_access_semaphore_), false /* is_gl */);
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index 63fe693..2852cec 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -37,6 +37,7 @@ #include "gpu/command_buffer/service/webgpu_decoder.h" #include "gpu/config/gpu_preferences.h" #include "ipc/ipc_channel.h" +#include "third_party/skia/include/core/SkPromiseImageTexture.h" #include "third_party/skia/include/gpu/GrBackendSemaphore.h" #include "ui/gl/gl_context_egl.h" #include "ui/gl/gl_surface_egl.h" @@ -691,6 +692,17 @@ // Unmap the buffer. procs_.bufferUnmap(buffer); + // Transition the image back to the desired end state. This is used for + // transitioning the image to the external queue for Vulkan/GL interop. + if (scoped_read_access->end_state()) { + if (!shared_context_state_->gr_context()->setBackendTextureState( + scoped_read_access->promise_image_texture()->backendTexture(), + *scoped_read_access->end_state())) { + DLOG(ERROR) << "setBackendTextureState() failed."; + return false; + } + } + // ReadPixels finished; signal the semaphores. SignalSemaphores(std::move(end_semaphores)); @@ -832,6 +844,16 @@ /*x*/ 0, /*y*/ 0); procs_.bufferRelease(buffer); + + // Transition the image back to the desired end state. This is used for + // transitioning the image to the external queue for Vulkan/GL interop. + if (scoped_write_access->end_state()) { + // It's ok to pass in empty GrFlushInfo here since SignalSemaphores() + // will populate it with semaphores and call GrDirectContext::flush. + scoped_write_access->surface()->flush(/*info=*/{}, + scoped_write_access->end_state()); + } + SignalSemaphores(std::move(end_semaphores)); return true;
diff --git a/ios/web/web_view/wk_web_view_util_unittest.mm b/ios/web/web_view/wk_web_view_util_unittest.mm index fc62c84a..93e415d 100644 --- a/ios/web/web_view/wk_web_view_util_unittest.mm +++ b/ios/web/web_view/wk_web_view_util_unittest.mm
@@ -18,98 +18,68 @@ namespace web { -#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 // Tests that CreateFullPagePDF calls createPDFWithConfiguration and it invokes // the callback with NSData. -TEST_F(WKWebViewUtilTest, IOS14EnsureCallbackIsCalledWithData) { +TEST_F(WKWebViewUtilTest, EnsureCallbackIsCalledWithData) { // Expected: callback is called with valid NSData. - if (@available(iOS 14, *)) { - // Mock the web_view and make sure createPDFWithConfiguration's - // completionHandler is invoked with NSData and no errors. - id web_view_mock = OCMClassMock([WKWebView class]); - OCMStub([web_view_mock createPDFWithConfiguration:[OCMArg any] - completionHandler:[OCMArg any]]) - .andDo(^(NSInvocation* invocation) { - void (^completion_block)(NSData* pdf_document_data, NSError* error); - [invocation getArgument:&completion_block atIndex:3]; - completion_block([[NSData alloc] init], nil); - }); - - __block bool callback_called = false; - __block NSData* callback_data = nil; - - CreateFullPagePdf(web_view_mock, base::BindOnce(^(NSData* data) { - callback_called = true; - callback_data = [data copy]; - })); - - ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForPageLoadTimeout, ^bool { - return callback_called; - })); - EXPECT_TRUE(callback_data); - } -} -#endif - -#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 -// Tests that CreateFullPagePDF calls createPDFWithConfiguration and it -// generates an NSError. -TEST_F(WKWebViewUtilTest, IOS14EnsureCallbackIsCalledWithNil) { - // Expected: callback is called with nil. - if (@available(iOS 14, *)) { - // Mock the web_view and make sure createPDFWithConfiguration's - // completionHandler is invoked with NSData and an error. - id web_view_mock = OCMClassMock([WKWebView class]); - NSError* error = - [NSError errorWithDomain:NSURLErrorDomain - code:NSURLErrorServerCertificateHasUnknownRoot - userInfo:nil]; - OCMStub([web_view_mock createPDFWithConfiguration:[OCMArg any] - completionHandler:[OCMArg any]]) - .andDo(^(NSInvocation* invocation) { - void (^completion_block)(NSData* pdf_document_data, NSError* error); - [invocation getArgument:&completion_block atIndex:3]; - completion_block(nil, error); - }); - - __block bool callback_called = false; - __block NSData* callback_data = nil; - - CreateFullPagePdf(web_view_mock, base::BindOnce(^(NSData* data) { - callback_called = true; - callback_data = [data copy]; - })); - - ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForPageLoadTimeout, ^bool { - return callback_called; - })); - EXPECT_FALSE(callback_data); - } -} -#endif - -// Tests that CreateFullPagePDF invokes the callback with nil on iOS 13. -TEST_F(WKWebViewUtilTest, IOS13EnsureCallbackIsCalled) { - // Expected: The callback is called with nil. - if (@available(iOS 14, *)) - return; - - WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init]; - WKWebView* web_view = [[WKWebView alloc] initWithFrame:CGRectZero - configuration:config]; + // Mock the web_view and make sure createPDFWithConfiguration's + // completionHandler is invoked with NSData and no errors. + id web_view_mock = OCMClassMock([WKWebView class]); + OCMStub([web_view_mock createPDFWithConfiguration:[OCMArg any] + completionHandler:[OCMArg any]]) + .andDo(^(NSInvocation* invocation) { + void (^completion_block)(NSData* pdf_document_data, NSError* error); + [invocation getArgument:&completion_block atIndex:3]; + completion_block([[NSData alloc] init], nil); + }); __block bool callback_called = false; __block NSData* callback_data = nil; - CreateFullPagePdf(web_view, base::BindOnce(^(NSData* data) { + CreateFullPagePdf(web_view_mock, base::BindOnce(^(NSData* data) { callback_called = true; callback_data = [data copy]; })); - EXPECT_TRUE(callback_called); - EXPECT_EQ(nil, callback_data); + ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForPageLoadTimeout, ^bool { + return callback_called; + })); + EXPECT_TRUE(callback_data); +} + +// Tests that CreateFullPagePDF calls createPDFWithConfiguration and it +// generates an NSError. +TEST_F(WKWebViewUtilTest, EnsureCallbackIsCalledWithNil) { + // Expected: callback is called with nil. + // Mock the web_view and make sure createPDFWithConfiguration's + // completionHandler is invoked with NSData and an error. + id web_view_mock = OCMClassMock([WKWebView class]); + NSError* error = + [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorServerCertificateHasUnknownRoot + userInfo:nil]; + OCMStub([web_view_mock createPDFWithConfiguration:[OCMArg any] + completionHandler:[OCMArg any]]) + .andDo(^(NSInvocation* invocation) { + void (^completion_block)(NSData* pdf_document_data, NSError* error); + [invocation getArgument:&completion_block atIndex:3]; + completion_block(nil, error); + }); + + __block bool callback_called = false; + __block NSData* callback_data = nil; + + CreateFullPagePdf(web_view_mock, base::BindOnce(^(NSData* data) { + callback_called = true; + callback_data = [data copy]; + })); + + ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForPageLoadTimeout, ^bool { + return callback_called; + })); + EXPECT_FALSE(callback_data); } // Tests that CreateFullPagePDF invokes the callback with NULL if @@ -130,4 +100,4 @@ })); EXPECT_FALSE(callback_data); } -} +} // namespace web
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.h b/ios/web_view/internal/web_view_url_request_context_getter.h index 5f7244e0..26681ba 100644 --- a/ios/web_view/internal/web_view_url_request_context_getter.h +++ b/ios/web_view/internal/web_view_url_request_context_getter.h
@@ -16,11 +16,8 @@ namespace net { class NetLog; -class NetworkDelegate; class ProxyConfigService; -class TransportSecurityPersister; class URLRequestContext; -class URLRequestContextStorage; class SystemCookieStore; } // namespace net @@ -62,11 +59,7 @@ net::NetLog* net_log_; scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; std::unique_ptr<net::ProxyConfigService> proxy_config_service_; - std::unique_ptr<net::NetworkDelegate> network_delegate_; std::unique_ptr<net::URLRequestContext> url_request_context_; - std::unique_ptr<net::URLRequestContextStorage> storage_; - std::unique_ptr<net::TransportSecurityPersister> - transport_security_persister_; // SystemCookieStore must be created on UI thread in // WebViewURLRequestContextGetter's constructor. Later the ownership is passed // to net::URLRequestContextStorage on IO thread. |system_cookie_store_| is
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm index ac21797b..a9862807 100644 --- a/ios/web_view/internal/web_view_url_request_context_getter.mm +++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -18,27 +18,15 @@ #include "ios/web/public/browsing_data/system_cookie_store_util.h" #import "ios/web/public/web_client.h" #include "ios/web/webui/url_data_manager_ios_backend.h" -#include "net/base/cache_type.h" -#include "net/base/network_delegate_impl.h" -#include "net/cert/cert_verifier.h" -#include "net/cert/ct_policy_enforcer.h" -#include "net/dns/host_resolver.h" -#include "net/http/http_auth_handler_factory.h" -#include "net/http/http_cache.h" #include "net/http/http_network_session.h" -#include "net/http/http_server_properties.h" #include "net/http/transport_security_persister.h" #include "net/http/transport_security_state.h" #include "net/log/net_log.h" -#include "net/proxy_resolution/configured_proxy_resolution_service.h" #include "net/proxy_resolution/proxy_config_service_ios.h" -#include "net/quic/quic_context.h" #include "net/ssl/ssl_config_service_defaults.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "net/url_request/static_http_user_agent_settings.h" #include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_storage.h" -#include "net/url_request/url_request_job_factory.h" +#include "net/url_request/url_request_context_builder.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -71,101 +59,29 @@ } if (!url_request_context_) { - url_request_context_.reset(new net::URLRequestContext()); - url_request_context_->set_net_log(net_log_); - DCHECK(!network_delegate_.get()); - network_delegate_ = std::make_unique<net::NetworkDelegateImpl>(); - url_request_context_->set_network_delegate(network_delegate_.get()); - - storage_.reset( - new net::URLRequestContextStorage(url_request_context_.get())); - // Using std::move on a |system_cookie_store_| resets it to null as it's a - // unique_ptr, so |system_cookie_store_| will not be a dangling pointer. - storage_->set_cookie_store(std::make_unique<net::CookieStoreIOS>( - std::move(system_cookie_store_), net_log_)); - web::WebClient* web_client = web::GetWebClient(); DCHECK(web_client); - std::string user_agent = - web_client->GetUserAgent(web::UserAgentType::MOBILE); - storage_->set_http_user_agent_settings( - std::make_unique<net::StaticHttpUserAgentSettings>("en-us,en", - user_agent)); - storage_->set_proxy_resolution_service( - net::ConfiguredProxyResolutionService::CreateUsingSystemProxyResolver( - std::move(proxy_config_service_), url_request_context_->net_log(), - /*quick_check_enabled=*/true)); - storage_->set_ssl_config_service( - std::make_unique<net::SSLConfigServiceDefaults>()); - storage_->set_cert_verifier( - net::CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr)); + net::URLRequestContextBuilder builder; + builder.set_net_log(net_log_); + builder.SetCookieStore(std::make_unique<net::CookieStoreIOS>( + std::move(system_cookie_store_), net_log_)); - storage_->set_transport_security_state( - std::make_unique<net::TransportSecurityState>()); - storage_->set_ct_policy_enforcer( - base::WrapUnique(new net::DefaultCTPolicyEnforcer)); - storage_->set_quic_context(std::make_unique<net::QuicContext>()); + builder.set_accept_language("en-us,en"); + builder.set_user_agent( + web_client->GetUserAgent(web::UserAgentType::MOBILE)); + builder.set_proxy_config_service(std::move(proxy_config_service_)); + builder.set_transport_security_persister_file_path( + base_path_.Append(FILE_PATH_LITERAL("TransportSecurity"))); - base::FilePath transport_security_state_file_path = - base_path_.Append(FILE_PATH_LITERAL("TransportSecurity")); - transport_security_persister_ = - std::make_unique<net::TransportSecurityPersister>( - url_request_context_->transport_security_state(), - base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT}), - transport_security_state_file_path); - - storage_->set_http_server_properties( - std::make_unique<net::HttpServerProperties>()); - - std::unique_ptr<net::HostResolver> host_resolver( - net::HostResolver::CreateStandaloneResolver( - url_request_context_->net_log())); - storage_->set_http_auth_handler_factory( - net::HttpAuthHandlerFactory::CreateDefault()); - storage_->set_host_resolver(std::move(host_resolver)); - - net::HttpNetworkSessionContext network_session_context; - network_session_context.cert_verifier = - url_request_context_->cert_verifier(); - network_session_context.transport_security_state = - url_request_context_->transport_security_state(); - network_session_context.net_log = url_request_context_->net_log(); - network_session_context.proxy_resolution_service = - url_request_context_->proxy_resolution_service(); - network_session_context.ssl_config_service = - url_request_context_->ssl_config_service(); - network_session_context.http_auth_handler_factory = - url_request_context_->http_auth_handler_factory(); - network_session_context.http_server_properties = - url_request_context_->http_server_properties(); - network_session_context.host_resolver = - url_request_context_->host_resolver(); - network_session_context.ct_policy_enforcer = - url_request_context_->ct_policy_enforcer(); - network_session_context.quic_context = url_request_context_->quic_context(); - - base::FilePath cache_path = + net::URLRequestContextBuilder::HttpCacheParams cache_params; + cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::DISK; + cache_params.path = base_path_.Append(FILE_PATH_LITERAL("ChromeWebViewCache")); - std::unique_ptr<net::HttpCache::DefaultBackend> main_backend( - new net::HttpCache::DefaultBackend( - net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, - /*max_bytes=*/0, /*hard_reset=*/false)); + builder.EnableHttpCache(cache_params); - storage_->set_http_network_session( - std::make_unique<net::HttpNetworkSession>( - net::HttpNetworkSessionParams(), network_session_context)); - storage_->set_http_transaction_factory(std::make_unique<net::HttpCache>( - storage_->http_network_session(), std::move(main_backend), - true /* set_up_quic_server_info */)); - - std::unique_ptr<net::URLRequestJobFactory> job_factory = - std::make_unique<net::URLRequestJobFactory>(); - job_factory->SetProtocolHandler(kChromeUIScheme, - std::move(protocol_handler_)); - - storage_->set_job_factory(std::move(job_factory)); + builder.SetProtocolHandler(kChromeUIScheme, std::move(protocol_handler_)); + url_request_context_ = builder.Build(); } return url_request_context_.get();
diff --git a/net/base/features.h b/net/base/features.h index 4ceedfa..3b0acc6 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -153,9 +153,6 @@ // Enables the TLS Encrypted ClientHello feature. // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-13 -// -// TODO(https://crbug.com/1091403): This flag does not currently do much yet. -// ECH is still in development. NET_EXPORT extern const base::Feature kEncryptedClientHello; // Enables optimizing the network quality estimation algorithms in network
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index 233c209..351bb09 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h
@@ -788,6 +788,16 @@ // The start/end of the WebSocketConnectJob::Connect(). EVENT_TYPE(WEB_SOCKET_TRANSPORT_CONNECT_JOB_CONNECT) +// A TLS connection attempt failed because ECH was not negotiated. The +// connection will be retried with a new ECHConfigList from the client-facing +// server. If the new ECHConfigList is the empty string, the server has rolled +// back ECH and the new attempt will have ECH disabled. +// +// { +// "bytes": <The new ECHConfigList, base64-encoded> +// } +EVENT_TYPE(SSL_CONNECT_JOB_RESTART_WITH_ECH_CONFIG_LIST) + // ------------------------------------------------------------------------ // ClientSocketPoolBaseHelper // ------------------------------------------------------------------------
diff --git a/net/socket/connect_job.cc b/net/socket/connect_job.cc index 1ac0251..6600bd92 100644 --- a/net/socket/connect_job.cc +++ b/net/socket/connect_job.cc
@@ -7,11 +7,11 @@ #include <set> #include <utility> -#include "base/no_destructor.h" #include "base/trace_event/trace_event.h" #include "net/base/connection_endpoint_metadata.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" +#include "net/dns/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_auth_controller.h" #include "net/http/http_proxy_connect_job.h" @@ -136,9 +136,9 @@ return nullptr; } -const ConnectionEndpointMetadata& ConnectJob::GetEndpointMetadata() const { - static const base::NoDestructor<ConnectionEndpointMetadata> empty_metadata; - return *empty_metadata; +absl::optional<HostResolverEndpointResult> +ConnectJob::GetHostResolverEndpointResult() const { + return absl::nullopt; } void ConnectJob::SetSocket(std::unique_ptr<StreamSocket> socket,
diff --git a/net/socket/connect_job.h b/net/socket/connect_job.h index 0fd7a19..5d428b2 100644 --- a/net/socket/connect_job.h +++ b/net/socket/connect_job.h
@@ -30,9 +30,9 @@ namespace net { class ClientSocketFactory; -struct ConnectionEndpointMetadata; class HostPortPair; class HostResolver; +struct HostResolverEndpointResult; class HttpAuthCache; class HttpAuthController; class HttpAuthHandlerFactory; @@ -233,9 +233,13 @@ // SSLCertRequestInfo received. Otherwise, returns nullptr. virtual scoped_refptr<SSLCertRequestInfo> GetCertRequestInfo(); - // Returns the `ConnectionEndpointMetadata` structure corresponding to the - // chosen route. Should only be called on a successful connect. - virtual const ConnectionEndpointMetadata& GetEndpointMetadata() const; + // Returns the `HostResolverEndpointResult` structure corresponding to the + // chosen route. Should only be called on a successful connect. If the + // `ConnectJob` does not make DNS queries, or does not use the SVCB/HTTPS + // record, it may return `absl::nullopt`, to avoid callers getting confused by + // an empty `IPEndPoint` list. + virtual absl::optional<HostResolverEndpointResult> + GetHostResolverEndpointResult() const; const LoadTimingInfo::ConnectTiming& connect_timing() const { return connect_timing_;
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 23af62d..d5a236b9 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -791,8 +791,8 @@ SocketDataProvider* data_provider = mock_tcp_data_.GetNextWithoutAsserting(); if (!data_provider) data_provider = mock_data_.GetNext(); - std::unique_ptr<MockTCPClientSocket> socket( - new MockTCPClientSocket(addresses, net_log, data_provider)); + auto socket = + std::make_unique<MockTCPClientSocket>(addresses, net_log, data_provider); if (enable_read_if_ready_) socket->set_enable_read_if_ready(enable_read_if_ready_); return std::move(socket); @@ -850,6 +850,10 @@ EXPECT_EQ(*next_ssl_data->expected_disable_legacy_crypto, ssl_config.disable_legacy_crypto); } + if (next_ssl_data->expected_ech_config_list) { + EXPECT_EQ(*next_ssl_data->expected_ech_config_list, + ssl_config.ech_config_list); + } return std::unique_ptr<SSLClientSocket>(new MockSSLClientSocket( std::move(stream_socket), host_and_port, ssl_config, next_ssl_data)); } @@ -953,6 +957,9 @@ DCHECK(data_); peer_addr_ = data->connect_data().peer_addr; data_->Initialize(this); + if (data_->expected_addresses()) { + EXPECT_EQ(*data_->expected_addresses(), addresses); + } } MockTCPClientSocket::~MockTCPClientSocket() { @@ -1502,10 +1509,7 @@ } std::vector<uint8_t> MockSSLClientSocket::GetECHRetryConfigs() { - // TODO(crbug.com/1091403): Add a mechanism to specify this, when testing the - // retry portions of the recovery flow. - NOTIMPLEMENTED(); - return {}; + return data_->ech_retry_configs; } void MockSSLClientSocket::RunCallbackAsync(CompletionOnceCallback callback,
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 668ee9f..da76ce7 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -287,6 +287,13 @@ } bool set_keep_alive_result() const { return set_keep_alive_result_; } + const absl::optional<AddressList>& expected_addresses() const { + return expected_addresses_; + } + void set_expected_addresses(net::AddressList addresses) { + expected_addresses_ = std::move(addresses); + } + // Returns true if the request should be considered idle, for the purposes of // IsConnectedAndIdle. virtual bool IsIdle() const; @@ -325,6 +332,7 @@ int set_send_buffer_size_result_ = net::OK; bool set_no_delay_result_ = true; bool set_keep_alive_result_ = true; + absl::optional<AddressList> expected_addresses_; }; // The AsyncSocket is an interface used by the SocketDataProvider to @@ -487,6 +495,9 @@ // Result for GetSSLCertRequestInfo(). SSLCertRequestInfo* cert_request_info; + // Result for GetECHRetryConfigs(). + std::vector<uint8_t> ech_retry_configs; + absl::optional<NextProtoVector> next_protos_expected_in_ssl_config; uint16_t expected_ssl_version_min; @@ -496,6 +507,7 @@ absl::optional<HostPortPair> expected_host_and_port; absl::optional<NetworkIsolationKey> expected_network_isolation_key; absl::optional<bool> expected_disable_legacy_crypto; + absl::optional<std::vector<uint8_t>> expected_ech_config_list; bool is_connect_data_consumed = false; bool is_confirm_data_consumed = false;
diff --git a/net/socket/ssl_connect_job.cc b/net/socket/ssl_connect_job.cc index 1d1d9b0..24c9eb1 100644 --- a/net/socket/ssl_connect_job.cc +++ b/net/socket/ssl_connect_job.cc
@@ -23,12 +23,14 @@ #include "net/cert/x509_util.h" #include "net/http/http_proxy_connect_job.h" #include "net/log/net_log_source_type.h" +#include "net/log/net_log_values.h" #include "net/log/net_log_with_source.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/socks_connect_job.h" #include "net/socket/ssl_client_socket.h" #include "net/socket/transport_connect_job.h" +#include "net/socket/websocket_transport_connect_job.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_info.h" @@ -274,9 +276,26 @@ DCHECK(!TimerIsRunning()); next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; - nested_connect_job_ = TransportConnectJob::CreateTransportConnectJob( - params_->GetDirectConnectionParams(), priority(), socket_tag(), - common_connect_job_params(), this, &net_log()); + if (!common_connect_job_params()->websocket_endpoint_lock_manager) { + // If this is an ECH retry, connect to the same server as before. + absl::optional<TransportConnectJob::EndpointResultOverride> + endpoint_result_override; + if (ech_retry_configs_) { + DCHECK(base::FeatureList::IsEnabled(features::kEncryptedClientHello)); + DCHECK(endpoint_result_); + endpoint_result_override.emplace(*endpoint_result_, dns_aliases_); + } + nested_connect_job_ = std::make_unique<TransportConnectJob>( + priority(), socket_tag(), common_connect_job_params(), + params_->GetDirectConnectionParams(), this, &net_log(), + std::move(endpoint_result_override)); + } else { + // TODO(https://crbug.com/1291352): Support ECH for WebSockets. + DCHECK(!ech_retry_configs_); + nested_connect_job_ = std::make_unique<WebSocketTransportConnectJob>( + priority(), socket_tag(), common_connect_job_params(), + params_->GetDirectConnectionParams(), this, &net_log()); + } return nested_connect_job_->Connect(); } @@ -374,14 +393,30 @@ ssl_negotiation_started_ = true; connect_timing_.ssl_start = base::TimeTicks::Now(); + // Save the `HostResolverEndpointResult`. `nested_connect_job_` is destroyed + // at the end of this function. + endpoint_result_ = nested_connect_job_->GetHostResolverEndpointResult(); + SSLConfig ssl_config = params_->ssl_config(); ssl_config.network_isolation_key = params_->network_isolation_key(); ssl_config.privacy_mode = params_->privacy_mode(); ssl_config.disable_legacy_crypto = disable_legacy_crypto_with_fallback_; + if (base::FeatureList::IsEnabled(features::kEncryptedClientHello)) { - ssl_config.ech_config_list = - nested_connect_job_->GetEndpointMetadata().ech_config_list; + if (ech_retry_configs_) { + ssl_config.ech_config_list = *ech_retry_configs_; + } else if (endpoint_result_) { + ssl_config.ech_config_list = endpoint_result_->metadata.ech_config_list; + } + if (!ssl_config.ech_config_list.empty()) { + // Overriding the DNS lookup only works for direct connections. We + // currently do not support ECH with other connection types. + DCHECK_EQ(params_->GetConnectionType(), SSLSocketParams::DIRECT); + // TODO(https://crbug.com/1291352): Support ECH for WebSockets. + DCHECK(!common_connect_job_params()->websocket_endpoint_lock_manager); + } } + ssl_socket_ = client_socket_factory()->CreateSSLClientSocket( ssl_client_context(), std::move(nested_socket_), params_->host_and_port(), ssl_config); @@ -416,6 +451,33 @@ return OK; } + if (base::FeatureList::IsEnabled(features::kEncryptedClientHello) && + !ech_retry_configs_ && result == ERR_ECH_NOT_NEGOTIATED) { + // We used ECH, and the server could not decrypt the ClientHello. However, + // it was able to handshake with the public name and send authenticated + // retry configs. If this is not the first time around, retry the connection + // with the new ECHConfigList, or with ECH disabled (empty retry configs), + // as directed. + // + // See + // https://www.ietf.org/archive/id/draft-ietf-tls-esni-13.html#section-6.1.6 + DCHECK(endpoint_result_ && + !endpoint_result_->metadata.ech_config_list.empty()); + ech_retry_configs_ = ssl_socket_->GetECHRetryConfigs(); + net_log().AddEvent( + NetLogEventType::SSL_CONNECT_JOB_RESTART_WITH_ECH_CONFIG_LIST, [&] { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("bytes", NetLogBinaryValue(*ech_retry_configs_)); + return dict; + }); + + // TODO(https://crbug.com/1091403): Add histograms for how often this + // happens. + ResetStateForRestart(); + next_state_ = GetInitialState(params_->GetConnectionType()); + return OK; + } + const std::string& host = params_->host_and_port().host(); if (result == OK) {
diff --git a/net/socket/ssl_connect_job.h b/net/socket/ssl_connect_job.h index 666dc02..66b9d0f 100644 --- a/net/socket/ssl_connect_job.h +++ b/net/socket/ssl_connect_job.h
@@ -5,9 +5,12 @@ #ifndef NET_SOCKET_SSL_CONNECT_JOB_H_ #define NET_SOCKET_SSL_CONNECT_JOB_H_ +#include <stdint.h> + #include <memory> #include <set> #include <string> +#include <vector> #include "base/memory/ref_counted.h" #include "base/time/time.h" @@ -16,12 +19,14 @@ #include "net/base/net_export.h" #include "net/base/network_isolation_key.h" #include "net/base/privacy_mode.h" +#include "net/dns/host_resolver_results.h" #include "net/dns/public/resolve_error_info.h" #include "net/socket/connect_job.h" #include "net/socket/connection_attempts.h" #include "net/socket/ssl_client_socket.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_config_service.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -205,6 +210,14 @@ // lifetime and the aliases can no longer be retrieved from there by by the // time that the aliases are needed to be passed in SetSocket. std::set<std::string> dns_aliases_; + + // The endpoint result used by `nested_connect_job_`. Stored because + // `nested_connect_job_` has a limited lifetime. + absl::optional<HostResolverEndpointResult> endpoint_result_; + + // If not `absl::nullopt`, the ECH retry configs to use in the ECH recovery + // flow. `endpoint_result_` will then contain the endpoint to reconnect to. + absl::optional<std::vector<uint8_t>> ech_retry_configs_; }; } // namespace net
diff --git a/net/socket/ssl_connect_job_unittest.cc b/net/socket/ssl_connect_job_unittest.cc index 6b908b3a..f04f87e 100644 --- a/net/socket/ssl_connect_job_unittest.cc +++ b/net/socket/ssl_connect_job_unittest.cc
@@ -47,6 +47,7 @@ #include "net/ssl/ssl_legacy_crypto_fallback.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" +#include "net/test/ssl_test_util.h" #include "net/test/test_certificate_data.h" #include "net/test/test_data_directory.h" #include "net/test/test_with_task_environment.h" @@ -60,6 +61,12 @@ namespace net { namespace { +IPAddress ParseIP(const std::string& ip) { + IPAddress address; + CHECK(address.AssignFromIPLiteral(ip)); + return address; +} + // Just check that all connect times are set to base::TimeTicks::Now(), for // tests that don't update the mocked out time. void CheckConnectTimesSet(const LoadTimingInfo::ConnectTiming& connect_timing) { @@ -1239,5 +1246,348 @@ testing::ElementsAre("host")); } +// Test that `SSLConnectJob` retries the connection if there was a stale ECH +// configuration. +TEST_F(SSLConnectJobTest, ECHStaleConfig) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + + std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3; + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list1)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list2)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list3)); + + // Configure two HTTPS RR routes, to test the retry uses the correct one. + HostResolverEndpointResult endpoint1, endpoint2; + endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; + endpoint1.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint1.metadata.ech_config_list = ech_config_list1; + endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)}; + endpoint2.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint2.metadata.ech_config_list = ech_config_list2; + host_resolver_.rules()->AddRule("host", std::vector{endpoint1, endpoint2}); + + // The first connection attempt will be to `endpoint1`, which will fail. + StaticSocketDataProvider data1; + data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints)); + data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); + socket_factory_.AddSocketDataProvider(&data1); + // The second connection attempt will be to `endpoint2`, which will succeed. + StaticSocketDataProvider data2; + data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data2.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data2); + // The handshake will then fail, but then provide retry configs. + SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED); + ssl2.expected_ech_config_list = ech_config_list2; + ssl2.ech_retry_configs = ech_config_list3; + socket_factory_.AddSSLSocketDataProvider(&ssl2); + // The third connection attempt should skip `endpoint1` and retry with only + // `endpoint2`. + StaticSocketDataProvider data3; + data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data3.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data3); + // The handshake should be passed the retry configs. + SSLSocketDataProvider ssl3(ASYNC, OK); + ssl3.expected_ech_config_list = ech_config_list3; + socket_factory_.AddSSLSocketDataProvider(&ssl3); + + // The connection should ultimately succeed. + TestConnectJobDelegate test_delegate; + std::unique_ptr<ConnectJob> ssl_connect_job = + CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM); + EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING)); + EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk()); +} + +// Test that `SSLConnectJob` retries the connection given a secure rollback +// signal. +TEST_F(SSLConnectJobTest, ECHRollback) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + + std::vector<uint8_t> ech_config_list1, ech_config_list2; + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list1)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list2)); + + // Configure two HTTPS RR routes, to test the retry uses the correct one. + HostResolverEndpointResult endpoint1, endpoint2; + endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; + endpoint1.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint1.metadata.ech_config_list = ech_config_list1; + endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)}; + endpoint2.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint2.metadata.ech_config_list = ech_config_list2; + host_resolver_.rules()->AddRule("host", std::vector{endpoint1, endpoint2}); + + // The first connection attempt will be to `endpoint1`, which will fail. + StaticSocketDataProvider data1; + data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints)); + data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); + socket_factory_.AddSocketDataProvider(&data1); + // The second connection attempt will be to `endpoint2`, which will succeed. + StaticSocketDataProvider data2; + data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data2.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data2); + // The handshake will then fail, and provide no retry configs. + SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED); + ssl2.expected_ech_config_list = ech_config_list2; + ssl2.ech_retry_configs = std::vector<uint8_t>(); + socket_factory_.AddSSLSocketDataProvider(&ssl2); + // The third connection attempt should skip `endpoint1` and retry with only + // `endpoint2`. + StaticSocketDataProvider data3; + data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data3.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data3); + // The handshake should not be passed ECH configs. + SSLSocketDataProvider ssl3(ASYNC, OK); + ssl3.expected_ech_config_list = std::vector<uint8_t>(); + socket_factory_.AddSSLSocketDataProvider(&ssl3); + + // The connection should ultimately succeed. + TestConnectJobDelegate test_delegate; + std::unique_ptr<ConnectJob> ssl_connect_job = + CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM); + EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING)); + EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk()); +} + +// Test that `SSLConnectJob` will not retry more than once. +TEST_F(SSLConnectJobTest, ECHTooManyRetries) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + + std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3; + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list1)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list2)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list3)); + + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; + endpoint.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint.metadata.ech_config_list = ech_config_list1; + host_resolver_.rules()->AddRule("host", std::vector{endpoint}); + + // The first connection attempt will succeed. + StaticSocketDataProvider data1; + data1.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data1); + // The handshake will then fail, but provide retry configs. + SSLSocketDataProvider ssl1(ASYNC, ERR_ECH_NOT_NEGOTIATED); + ssl1.expected_ech_config_list = ech_config_list1; + ssl1.ech_retry_configs = ech_config_list2; + socket_factory_.AddSSLSocketDataProvider(&ssl1); + // The second connection attempt will succeed. + StaticSocketDataProvider data2; + data2.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data2); + // The handshake will then fail, but provide new retry configs. + SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED); + ssl2.expected_ech_config_list = ech_config_list2; + ssl2.ech_retry_configs = ech_config_list3; + socket_factory_.AddSSLSocketDataProvider(&ssl2); + // There will be no third connection attempt. + + TestConnectJobDelegate test_delegate; + std::unique_ptr<ConnectJob> ssl_connect_job = + CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM); + EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING)); + EXPECT_THAT(test_delegate.WaitForResult(), + test::IsError(ERR_ECH_NOT_NEGOTIATED)); +} + +// Test that `SSLConnectJob` will not retry for ECH given the wrong error. +TEST_F(SSLConnectJobTest, ECHWrongRetryError) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + + std::vector<uint8_t> ech_config_list1, ech_config_list2; + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list1)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list2)); + + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; + endpoint.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint.metadata.ech_config_list = ech_config_list1; + host_resolver_.rules()->AddRule("host", std::vector{endpoint}); + + // The first connection attempt will succeed. + StaticSocketDataProvider data1; + data1.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data1); + // The handshake will then fail, but provide retry configs. + SSLSocketDataProvider ssl1(ASYNC, ERR_FAILED); + ssl1.expected_ech_config_list = ech_config_list1; + ssl1.ech_retry_configs = ech_config_list2; + socket_factory_.AddSSLSocketDataProvider(&ssl1); + // There will be no second connection attempt. + + TestConnectJobDelegate test_delegate; + std::unique_ptr<ConnectJob> ssl_connect_job = + CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM); + EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING)); + EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_FAILED)); +} + +// Test the legacy crypto callback can trigger after the ECH recovery flow. +TEST_F(SSLConnectJobTest, ECHRecoveryThenLegacyCrypto) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + + std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3; + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list1)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list2)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list3)); + + // Configure two HTTPS RR routes, to test the retry uses the correct one. + HostResolverEndpointResult endpoint1, endpoint2; + endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; + endpoint1.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint1.metadata.ech_config_list = ech_config_list1; + endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)}; + endpoint2.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint2.metadata.ech_config_list = ech_config_list2; + host_resolver_.rules()->AddRule("host", std::vector{endpoint1, endpoint2}); + + // The first connection attempt will be to `endpoint1`, which will fail. + StaticSocketDataProvider data1; + data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints)); + data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); + socket_factory_.AddSocketDataProvider(&data1); + // The second connection attempt will be to `endpoint2`, which will succeed. + StaticSocketDataProvider data2; + data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data2.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data2); + // The handshake will then fail, and provide retry configs. + SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED); + ssl2.expected_ech_config_list = ech_config_list2; + ssl2.expected_disable_legacy_crypto = true; + ssl2.ech_retry_configs = ech_config_list3; + socket_factory_.AddSSLSocketDataProvider(&ssl2); + // The third connection attempt should skip `endpoint1` and retry with only + // `endpoint2`. + StaticSocketDataProvider data3; + data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data3.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data3); + // The handshake should be passed the retry configs. This will progress + // further but trigger the legacy crypto fallback. + SSLSocketDataProvider ssl3(ASYNC, ERR_SSL_PROTOCOL_ERROR); + ssl3.expected_ech_config_list = ech_config_list3; + ssl3.expected_disable_legacy_crypto = true; + socket_factory_.AddSSLSocketDataProvider(&ssl3); + // The third connection attempt should still skip `endpoint1` and retry with + // only `endpoint2`. + StaticSocketDataProvider data4; + data4.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data4.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data4); + // The handshake should still be passed ECH retry configs. This time, the + // connection enables legacy crypto and succeeds. + SSLSocketDataProvider ssl4(ASYNC, OK); + ssl4.expected_ech_config_list = ech_config_list3; + ssl4.expected_disable_legacy_crypto = false; + socket_factory_.AddSSLSocketDataProvider(&ssl4); + + // The connection should ultimately succeed. + TestConnectJobDelegate test_delegate; + std::unique_ptr<ConnectJob> ssl_connect_job = + CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM); + EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING)); + EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk()); +} + +// Test the ECH recovery flow can trigger after the legacy crypto fallback. +TEST_F(SSLConnectJobTest, LegacyCryptoThenECHRecovery) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + + std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3; + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list1)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list2)); + ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128, + &ech_config_list3)); + + // Configure two HTTPS RR routes, to test the retry uses the correct one. + HostResolverEndpointResult endpoint1, endpoint2; + endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; + endpoint1.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint1.metadata.ech_config_list = ech_config_list1; + endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)}; + endpoint2.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint2.metadata.ech_config_list = ech_config_list2; + host_resolver_.rules()->AddRule("host", std::vector{endpoint1, endpoint2}); + + // The first connection attempt will be to `endpoint1`, which will fail. + StaticSocketDataProvider data1; + data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints)); + data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); + socket_factory_.AddSocketDataProvider(&data1); + // The second connection attempt will be to `endpoint2`, which will succeed. + StaticSocketDataProvider data2; + data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data2.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data2); + // The handshake will then fail, and trigger the legacy cryptography fallback. + SSLSocketDataProvider ssl2(ASYNC, ERR_SSL_PROTOCOL_ERROR); + ssl2.expected_ech_config_list = ech_config_list2; + ssl2.expected_disable_legacy_crypto = true; + socket_factory_.AddSSLSocketDataProvider(&ssl2); + // The third and fourth connection attempts proceed as before, but with legacy + // cryptography enabled. + StaticSocketDataProvider data3; + data3.set_expected_addresses(AddressList(endpoint1.ip_endpoints)); + data3.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); + socket_factory_.AddSocketDataProvider(&data3); + StaticSocketDataProvider data4; + data4.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data4.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data4); + // The handshake enables legacy crypto. Now ECH fails with retry configs. + SSLSocketDataProvider ssl4(ASYNC, ERR_ECH_NOT_NEGOTIATED); + ssl4.expected_ech_config_list = ech_config_list2; + ssl4.expected_disable_legacy_crypto = false; + ssl4.ech_retry_configs = ech_config_list3; + socket_factory_.AddSSLSocketDataProvider(&ssl4); + // The fourth connection attempt should still skip `endpoint1` and retry with + // only `endpoint2`. + StaticSocketDataProvider data5; + data5.set_expected_addresses(AddressList(endpoint2.ip_endpoints)); + data5.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + socket_factory_.AddSocketDataProvider(&data5); + // The handshake will now succeed with ECH retry configs and legacy + // cryptography. + SSLSocketDataProvider ssl5(ASYNC, OK); + ssl5.expected_ech_config_list = ech_config_list3; + ssl5.expected_disable_legacy_crypto = false; + socket_factory_.AddSSLSocketDataProvider(&ssl5); + + // The connection should ultimately succeed. + TestConnectJobDelegate test_delegate; + std::unique_ptr<ConnectJob> ssl_connect_job = + CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM); + EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING)); + EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk()); +} + } // namespace } // namespace net
diff --git a/net/socket/transport_connect_job.cc b/net/socket/transport_connect_job.cc index cc7ff40..0629a735 100644 --- a/net/socket/transport_connect_job.cc +++ b/net/socket/transport_connect_job.cc
@@ -150,13 +150,31 @@ delegate, net_log); } +TransportConnectJob::EndpointResultOverride::EndpointResultOverride( + HostResolverEndpointResult result, + std::set<std::string> dns_aliases) + : result(std::move(result)), dns_aliases(std::move(dns_aliases)) {} +TransportConnectJob::EndpointResultOverride::EndpointResultOverride( + EndpointResultOverride&&) = default; +TransportConnectJob::EndpointResultOverride::EndpointResultOverride( + const EndpointResultOverride&) = default; +TransportConnectJob::EndpointResultOverride::~EndpointResultOverride() = + default; +TransportConnectJob::EndpointResultOverride& +TransportConnectJob::EndpointResultOverride::operator=( + EndpointResultOverride&&) = default; +TransportConnectJob::EndpointResultOverride& +TransportConnectJob::EndpointResultOverride::operator=( + const EndpointResultOverride&) = default; + TransportConnectJob::TransportConnectJob( RequestPriority priority, const SocketTag& socket_tag, const CommonConnectJobParams* common_connect_job_params, const scoped_refptr<TransportSocketParams>& params, Delegate* delegate, - const NetLogWithSource* net_log) + const NetLogWithSource* net_log, + absl::optional<EndpointResultOverride> endpoint_result_override) : ConnectJob(priority, socket_tag, ConnectionTimeout(), @@ -170,12 +188,20 @@ resolve_result_(OK) { // This is only set for WebSockets. DCHECK(!common_connect_job_params->websocket_endpoint_lock_manager); + + if (endpoint_result_override) { + has_dns_override_ = true; + endpoint_results_ = {std::move(endpoint_result_override->result)}; + dns_aliases_ = std::move(endpoint_result_override->dns_aliases); + DCHECK(!endpoint_results_.front().ip_endpoints.empty()); + DCHECK(IsEndpointResultUsable(endpoint_results_.front(), + IsSvcbOptional(endpoint_results_))); + } } -TransportConnectJob::~TransportConnectJob() { - // We don't worry about cancelling the host resolution and TCP connect, since - // ~HostResolver::Request and ~StreamSocket will take care of it. -} +// We don't worry about cancelling the host resolution and TCP connect, since +// ~HostResolver::Request and ~StreamSocket will take care of it. +TransportConnectJob::~TransportConnectJob() = default; LoadState TransportConnectJob::GetLoadState() const { switch (next_state_) { @@ -215,10 +241,10 @@ return resolve_error_info_; } -const ConnectionEndpointMetadata& TransportConnectJob::GetEndpointMetadata() - const { +absl::optional<HostResolverEndpointResult> +TransportConnectJob::GetHostResolverEndpointResult() const { CHECK_LT(current_endpoint_result_, endpoint_results_.size()); - return endpoint_results_[current_endpoint_result_].metadata; + return endpoint_results_[current_endpoint_result_]; } // static @@ -298,9 +324,17 @@ } int TransportConnectJob::DoResolveHost() { - next_state_ = STATE_RESOLVE_HOST_COMPLETE; connect_timing_.dns_start = base::TimeTicks::Now(); + if (has_dns_override_) { + DCHECK_EQ(1u, endpoint_results_.size()); + connect_timing_.dns_end = connect_timing_.dns_start; + next_state_ = STATE_TRANSPORT_CONNECT; + return OK; + } + + next_state_ = STATE_RESOLVE_HOST_COMPLETE; + HostResolver::ResolveHostParameters parameters; parameters.initial_priority = priority(); parameters.secure_dns_policy = params_->secure_dns_policy();
diff --git a/net/socket/transport_connect_job.h b/net/socket/transport_connect_job.h index 9a8da3d..07e74f0 100644 --- a/net/socket/transport_connect_job.h +++ b/net/socket/transport_connect_job.h
@@ -128,12 +128,27 @@ ConnectJob::Delegate* delegate, const NetLogWithSource* net_log); + struct NET_EXPORT_PRIVATE EndpointResultOverride { + EndpointResultOverride(HostResolverEndpointResult result, + std::set<std::string> dns_aliases); + EndpointResultOverride(EndpointResultOverride&&); + EndpointResultOverride(const EndpointResultOverride&); + ~EndpointResultOverride(); + EndpointResultOverride& operator=(EndpointResultOverride&&); + EndpointResultOverride& operator=(const EndpointResultOverride&); + + HostResolverEndpointResult result; + std::set<std::string> dns_aliases; + }; + TransportConnectJob(RequestPriority priority, const SocketTag& socket_tag, const CommonConnectJobParams* common_connect_job_params, const scoped_refptr<TransportSocketParams>& params, Delegate* delegate, - const NetLogWithSource* net_log); + const NetLogWithSource* net_log, + absl::optional<EndpointResultOverride> + endpoint_result_override = absl::nullopt); TransportConnectJob(const TransportConnectJob&) = delete; TransportConnectJob& operator=(const TransportConnectJob&) = delete; @@ -145,7 +160,13 @@ bool HasEstablishedConnection() const override; ConnectionAttempts GetConnectionAttempts() const override; ResolveErrorInfo GetResolveErrorInfo() const override; - const ConnectionEndpointMetadata& GetEndpointMetadata() const override; + absl::optional<HostResolverEndpointResult> GetHostResolverEndpointResult() + const override; + + // Skips DNS resolution and instead connects to `endpoint_result`, reporting + // `dns_aliases` as the list of DNS aliases. Must be called before `Connect`. + void SetDnsResultOverride(const HostResolverEndpointResult& endpoint_result, + const std::set<std::string>& dns_aliases); // Rolls |addrlist| forward until the first IPv4 address, if any. // WARNING: this method should only be used to implement the prefer-IPv4 hack. @@ -214,6 +235,7 @@ std::vector<HostResolverEndpointResult> endpoint_results_; size_t current_endpoint_result_ = 0; std::set<std::string> dns_aliases_; + bool has_dns_override_ = false; State next_state_;
diff --git a/net/socket/transport_connect_job_unittest.cc b/net/socket/transport_connect_job_unittest.cc index 16fc8dd..e37008e 100644 --- a/net/socket/transport_connect_job_unittest.cc +++ b/net/socket/transport_connect_job_unittest.cc
@@ -815,9 +815,9 @@ EXPECT_EQ(attempts[1].endpoint, IPEndPoint(ParseIP("1.1.1.1"), 8441)); } -// `GetEndpointMetadata` should surface information about the endpoint that was -// actually used. -TEST_F(TransportConnectJobTest, GetEndpointMetadata) { +// `GetHostResolverEndpointResult` should surface information about the endpoint +// that was actually used. +TEST_F(TransportConnectJobTest, GetHostResolverEndpointResult) { std::vector<HostResolverEndpointResult> endpoints(4); // `endpoints[0]` will be skipped due to ALPN mismatch. endpoints[0].ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; @@ -855,7 +855,8 @@ test_delegate.StartJobExpectingResult(&transport_connect_job, OK, /*expect_sync_result=*/false); - EXPECT_EQ(transport_connect_job.GetEndpointMetadata(), endpoints[2].metadata); + EXPECT_EQ(transport_connect_job.GetHostResolverEndpointResult(), + endpoints[2]); } // If the client and server both support ECH, TransportConnectJob should switch @@ -982,5 +983,36 @@ /*expect_sync_result=*/false); } +// Overriding the endpoint results should skip DNS resolution. +TEST_F(TransportConnectJobTest, EndpointResultOverride) { + // Make DNS resolution fail, to confirm we don't use the result. + host_resolver_.rules()->AddRule(kHostName, ERR_FAILED); + + // `TransportConnectJob` should try `endpoint`. + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)}; + endpoint.metadata.supported_protocol_alpns = {"http/1.1"}; + MockTransportClientSocketFactory::Rule rules[] = { + MockTransportClientSocketFactory::Rule( + MockTransportClientSocketFactory::Type::kSynchronous, + endpoint.ip_endpoints), + }; + client_socket_factory_.SetRules(rules); + + TransportConnectJob::EndpointResultOverride override( + endpoint, {"alias.example", kHostName}); + TestConnectJobDelegate test_delegate; + TransportConnectJob transport_connect_job( + DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_, + DefaultHttpsParams(), &test_delegate, /*net_log=*/nullptr, override); + test_delegate.StartJobExpectingResult(&transport_connect_job, OK, + /*expect_sync_result=*/true); + + // Verify information is reported from the override. + EXPECT_EQ(transport_connect_job.GetHostResolverEndpointResult(), endpoint); + EXPECT_THAT(test_delegate.socket()->GetDnsAliases(), + testing::ElementsAre("alias.example", kHostName)); +} + } // namespace } // namespace net
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index c3886023..8f9f10c9 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -9727,6 +9727,7 @@ d.RunUntilComplete(); + EXPECT_THAT(d.request_status(), IsOk()); EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); @@ -9735,6 +9736,258 @@ } } +// Test that, if the DNS returns a stale ECHConfigList (or other key mismatch), +// the client can recover and connect to the server, provided the server can +// handshake as the public name. +TEST_F(HTTPSRequestTest, EncryptedClientHelloStaleKey) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kEncryptedClientHello); + + static constexpr char kRealNameStale[] = "secret1.example"; + static constexpr char kRealNameWrongPublicName[] = "secret2.example"; + static constexpr char kPublicName[] = "public.example"; + static constexpr char kWrongPublicName[] = "wrong-public.example"; + + std::vector<uint8_t> ech_config_list, ech_config_list_stale, + ech_config_list_wrong_public_name; + bssl::UniquePtr<SSL_ECH_KEYS> ech_keys = + MakeTestEchKeys(kPublicName, /*max_name_len=*/128, &ech_config_list); + ASSERT_TRUE(ech_keys); + ASSERT_TRUE(MakeTestEchKeys(kPublicName, /*max_name_len=*/128, + &ech_config_list_stale)); + ASSERT_TRUE(MakeTestEchKeys(kWrongPublicName, /*max_name_len=*/128, + &ech_config_list_wrong_public_name)); + + // Configure an ECH-supporting server that can speak for all names except + // `kWrongPublicName`. + EmbeddedTestServer::ServerCertificateConfig server_cert_config; + server_cert_config.dns_names = {kRealNameStale, kRealNameWrongPublicName, + kPublicName}; + SSLServerConfig ssl_server_config; + ssl_server_config.ech_keys = std::move(ech_keys); + EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS); + test_server.SetSSLConfig(server_cert_config, ssl_server_config); + RegisterDefaultHandlers(&test_server); + ASSERT_TRUE(test_server.Start()); + + AddressList addr; + ASSERT_TRUE(test_server.GetAddressList(&addr)); + + // Configure `MockHostResolver` to return `ech_config_list_stale` or + // `ech_config_list_wrong_public_name` for the real names. + // + // TODO(https://crbug.com/1264933): Replace this with an end-to-end test + // when the `HostResolver` portion is implemented. + auto host_resolver = std::make_unique<MockHostResolver>(); + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = addr.endpoints(); + endpoint.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint.metadata.ech_config_list = ech_config_list_stale; + host_resolver->rules()->AddRule(kRealNameStale, std::vector{endpoint}); + endpoint.metadata.ech_config_list = ech_config_list_wrong_public_name; + host_resolver->rules()->AddRule(kRealNameWrongPublicName, + std::vector{endpoint}); + auto context_builder = CreateTestURLRequestContextBuilder(); + context_builder->set_host_resolver(std::move(host_resolver)); + auto context = context_builder->Build(); + + // Connecting to `kRealNameStale` should succeed. Although the server will not + // decrypt the ClientHello, it can handshake as `kPublicName` and provide new + // keys for the client to use. + { + TestDelegate d; + std::unique_ptr<URLRequest> r = context->CreateRequest( + test_server.GetURL(kRealNameStale, "/defaultresponse"), + DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS); + r->Start(); + EXPECT_TRUE(r->is_pending()); + + d.RunUntilComplete(); + + EXPECT_THAT(d.request_status(), IsOk()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + EXPECT_NE(0, d.bytes_received()); + EXPECT_TRUE(r->ssl_info().encrypted_client_hello); + } + + // Connecting to `kRealNameWrongPublicName` should fail. The server can + // neither decrypt the ClientHello, nor handshake as `kWrongPublicName`. + { + TestDelegate d; + std::unique_ptr<URLRequest> r = context->CreateRequest( + test_server.GetURL(kRealNameWrongPublicName, "/defaultresponse"), + DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS); + r->Start(); + EXPECT_TRUE(r->is_pending()); + + d.RunUntilComplete(); + + EXPECT_THAT(d.request_status(), + IsError(ERR_ECH_FALLBACK_CERTIFICATE_INVALID)); + } +} + +TEST_F(HTTPSRequestTest, EncryptedClientHelloFallback) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kEncryptedClientHello); + + static constexpr char kRealNameStale[] = "secret1.example"; + static constexpr char kRealNameWrongPublicName[] = "secret2.example"; + static constexpr char kPublicName[] = "public.example"; + static constexpr char kWrongPublicName[] = "wrong-public.example"; + + std::vector<uint8_t> ech_config_list_stale, ech_config_list_wrong_public_name; + ASSERT_TRUE(MakeTestEchKeys(kPublicName, /*max_name_len=*/128, + &ech_config_list_stale)); + ASSERT_TRUE(MakeTestEchKeys(kWrongPublicName, /*max_name_len=*/128, + &ech_config_list_wrong_public_name)); + + // Configure a server, without ECH, that can speak for all names except + // `kWrongPublicName`. + EmbeddedTestServer::ServerCertificateConfig server_cert_config; + server_cert_config.dns_names = {kRealNameStale, kRealNameWrongPublicName, + kPublicName}; + EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS); + test_server.SetSSLConfig(server_cert_config); + RegisterDefaultHandlers(&test_server); + ASSERT_TRUE(test_server.Start()); + + AddressList addr; + ASSERT_TRUE(test_server.GetAddressList(&addr)); + + // Configure `MockHostResolver` to return `ech_config_list_stale` or + // `ech_config_list_wrong_public_name` for the real names. + // + // TODO(https://crbug.com/1264933): Replace this with an end-to-end test + // when the `HostResolver` portion is implemented. + auto host_resolver = std::make_unique<MockHostResolver>(); + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = addr.endpoints(); + endpoint.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint.metadata.ech_config_list = ech_config_list_stale; + host_resolver->rules()->AddRule(kRealNameStale, std::vector{endpoint}); + endpoint.metadata.ech_config_list = ech_config_list_wrong_public_name; + host_resolver->rules()->AddRule(kRealNameWrongPublicName, + std::vector{endpoint}); + auto context_builder = CreateTestURLRequestContextBuilder(); + context_builder->set_host_resolver(std::move(host_resolver)); + auto context = context_builder->Build(); + + // Connecting to `kRealNameStale` should succeed. Although the server will not + // decrypt the ClientHello, it can handshake as `kPublicName` and trigger an + // authenticated fallback. + { + TestDelegate d; + std::unique_ptr<URLRequest> r = context->CreateRequest( + test_server.GetURL(kRealNameStale, "/defaultresponse"), + DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS); + r->Start(); + EXPECT_TRUE(r->is_pending()); + d.RunUntilComplete(); + EXPECT_THAT(d.request_status(), IsOk()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + EXPECT_NE(0, d.bytes_received()); + EXPECT_FALSE(r->ssl_info().encrypted_client_hello); + } + + // Connecting to `kRealNameWrongPublicName` should fail. The server can + // neither decrypt the ClientHello, nor handshake as `kWrongPublicName`. + { + TestDelegate d; + std::unique_ptr<URLRequest> r = context->CreateRequest( + test_server.GetURL(kRealNameWrongPublicName, "/defaultresponse"), + DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS); + r->Start(); + EXPECT_TRUE(r->is_pending()); + d.RunUntilComplete(); + EXPECT_THAT(d.request_status(), + IsError(ERR_ECH_FALLBACK_CERTIFICATE_INVALID)); + } +} + +TEST_F(HTTPSRequestTest, EncryptedClientHelloFallbackTLS12) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kEncryptedClientHello); + + static constexpr char kRealNameStale[] = "secret1.example"; + static constexpr char kRealNameWrongPublicName[] = "secret2.example"; + static constexpr char kPublicName[] = "public.example"; + static constexpr char kWrongPublicName[] = "wrong-public.example"; + + std::vector<uint8_t> ech_config_list_stale, ech_config_list_wrong_public_name; + ASSERT_TRUE(MakeTestEchKeys(kPublicName, /*max_name_len=*/128, + &ech_config_list_stale)); + ASSERT_TRUE(MakeTestEchKeys(kWrongPublicName, /*max_name_len=*/128, + &ech_config_list_wrong_public_name)); + + // Configure a server, without ECH or TLS 1.3, that can speak for all names + // except `kWrongPublicName`. + EmbeddedTestServer::ServerCertificateConfig server_cert_config; + server_cert_config.dns_names = {kRealNameStale, kRealNameWrongPublicName, + kPublicName}; + SSLServerConfig ssl_server_config; + ssl_server_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2; + EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS); + test_server.SetSSLConfig(server_cert_config, ssl_server_config); + RegisterDefaultHandlers(&test_server); + ASSERT_TRUE(test_server.Start()); + + AddressList addr; + ASSERT_TRUE(test_server.GetAddressList(&addr)); + + // Configure `MockHostResolver` to return `ech_config_list_stale` or + // `ech_config_list_wrong_public_name` for the real names. + // + // TODO(https://crbug.com/1264933): Replace this with an end-to-end test + // when the `HostResolver` portion is implemented. + auto host_resolver = std::make_unique<MockHostResolver>(); + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = addr.endpoints(); + endpoint.metadata.supported_protocol_alpns = {"http/1.1"}; + endpoint.metadata.ech_config_list = ech_config_list_stale; + host_resolver->rules()->AddRule(kRealNameStale, std::vector{endpoint}); + endpoint.metadata.ech_config_list = ech_config_list_wrong_public_name; + host_resolver->rules()->AddRule(kRealNameWrongPublicName, + std::vector{endpoint}); + auto context_builder = CreateTestURLRequestContextBuilder(); + context_builder->set_host_resolver(std::move(host_resolver)); + auto context = context_builder->Build(); + + // Connecting to `kRealNameStale` should succeed. Although the server will not + // decrypt the ClientHello, it can handshake as `kPublicName` and trigger an + // authenticated fallback. + { + TestDelegate d; + std::unique_ptr<URLRequest> r = context->CreateRequest( + test_server.GetURL(kRealNameStale, "/defaultresponse"), + DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS); + r->Start(); + EXPECT_TRUE(r->is_pending()); + d.RunUntilComplete(); + EXPECT_THAT(d.request_status(), IsOk()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + EXPECT_NE(0, d.bytes_received()); + EXPECT_FALSE(r->ssl_info().encrypted_client_hello); + } + + // Connecting to `kRealNameWrongPublicName` should fail. The server can + // neither decrypt the ClientHello, nor handshake as `kWrongPublicName`. + { + TestDelegate d; + std::unique_ptr<URLRequest> r = context->CreateRequest( + test_server.GetURL(kRealNameWrongPublicName, "/defaultresponse"), + DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS); + r->Start(); + EXPECT_TRUE(r->is_pending()); + d.RunUntilComplete(); + EXPECT_THAT(d.request_status(), + IsError(ERR_ECH_FALLBACK_CERTIFICATE_INVALID)); + } +} + // A TestDelegate used to test that an appropriate net error code is provided // when an SSL certificate error occurs. class SSLNetErrorTestDelegate : public TestDelegate {
diff --git a/ppapi/BUILD.gn b/ppapi/BUILD.gn index 54f7f7a2..e128f54c 100644 --- a/ppapi/BUILD.gn +++ b/ppapi/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/nacl/config.gni") import("//build/config/nacl/rules.gni") import("//components/nacl/features.gni") +import("//components/nacl/target_cpu.gni") import("//ppapi/buildflags/buildflags.gni") import("//testing/test.gni") if (is_mac) { @@ -385,18 +386,14 @@ group("ppapi_nacl_tests_all") { data_deps = [ ":copy_test_files", - ":ppapi_nacl_tests(//build/toolchain/nacl:clang_newlib_${target_cpu})", + ":ppapi_nacl_tests(//build/toolchain/nacl:clang_newlib_${nacl_target_cpu})", ":ppapi_nacl_tests(//build/toolchain/nacl:newlib_pnacl)", ] if (target_cpu != "mipsel" && !is_mac && !is_win) { - data_deps += - [ ":ppapi_nacl_tests(//build/toolchain/nacl:glibc_${target_cpu})" ] - } - # TODO(https://crbug.com/1299021): Implement building these NaCl targets - # as ARM32 when Chrome is built for ARM64 (for Linux/Chrome OS). - if (target_cpu == "arm64") { - data_deps = [] + data_deps += [ + ":ppapi_nacl_tests(//build/toolchain/nacl:glibc_${nacl_target_cpu})", + ] } } }
diff --git a/ppapi/native_client/BUILD.gn b/ppapi/native_client/BUILD.gn index 040015739..ae3e176 100644 --- a/ppapi/native_client/BUILD.gn +++ b/ppapi/native_client/BUILD.gn
@@ -4,6 +4,7 @@ import("//build/config/features.gni") import("//build/config/nacl/config.gni") +import("//components/nacl/target_cpu.gni") if (is_nacl) { group("ppapi_lib") { @@ -96,8 +97,8 @@ # use nacl_irt as input for actions which require it to be marked # as public dependency as well. irt_deps = [ - ":nacl_irt_debug(//build/toolchain/nacl:irt_${target_cpu})", - ":nacl_irt_debuglink(//build/toolchain/nacl:irt_${target_cpu})", + ":nacl_irt_debug(//build/toolchain/nacl:irt_${nacl_target_cpu})", + ":nacl_irt_debuglink(//build/toolchain/nacl:irt_${nacl_target_cpu})", ] public_deps = irt_deps data_deps = irt_deps @@ -111,10 +112,4 @@ public_deps += irt_x64_deps data_deps += irt_x64_deps } - # TODO(https://crbug.com/1299021): Implement building these NaCl targets as - # ARM32 when Chrome is built for ARM64 (for Linux/Chrome OS). - if (target_cpu == "arm64") { - public_deps = [] - data_deps = [] - } }
diff --git a/ppapi/native_client/nacl_test_data.gni b/ppapi/native_client/nacl_test_data.gni index caf0d78..9294690 100644 --- a/ppapi/native_client/nacl_test_data.gni +++ b/ppapi/native_client/nacl_test_data.gni
@@ -5,6 +5,7 @@ import("//build/config/nacl/config.gni") import("//build/config/nacl/rules.gni") import("//components/nacl/features.gni") +import("//components/nacl/target_cpu.gni") assert(enable_nacl) @@ -101,7 +102,7 @@ extra_pexe_translate_target_name = pexe_translate_target_name + extra_tc_cpu } - pexe_translate_target_name += target_cpu + pexe_translate_target_name += nacl_target_cpu } if (defined(invoker.generate_nmf)) { generate_nmf = invoker.generate_nmf @@ -229,7 +230,7 @@ } nacl_test_data_pretranslate_pexe(pexe_translate_target_name) { - translate_cpu = target_cpu + translate_cpu = nacl_target_cpu } if (defined(extra_tc_cpu)) { nacl_test_data_pretranslate_pexe(extra_pexe_translate_target_name) {
diff --git a/ppapi/tests/extensions/BUILD.gn b/ppapi/tests/extensions/BUILD.gn index b684496..ee052e2 100644 --- a/ppapi/tests/extensions/BUILD.gn +++ b/ppapi/tests/extensions/BUILD.gn
@@ -3,10 +3,11 @@ # found in the LICENSE file. import("//components/nacl/features.gni") +import("//components/nacl/target_cpu.gni") import("//ppapi/native_client/nacl_test_data.gni") group("extensions") { - newlib = "//build/toolchain/nacl:clang_newlib_${target_cpu}" + newlib = "//build/toolchain/nacl:clang_newlib_${nacl_target_cpu}" pnacl = "//build/toolchain/nacl:newlib_pnacl" data_deps = [ ":ppapi_tests_extensions_background_keepalive($newlib)", @@ -19,11 +20,6 @@ ":ppapi_tests_extensions_popup($newlib)", ":ppapi_tests_extensions_socket_permissions($newlib)", ] - # TODO(https://crbug.com/1299021): Implement building these NaCl targets as - # ARM32 when Chrome is built for ARM64 (for Linux/Chrome OS). - if (target_cpu == "arm64") { - data_deps = [] - } } if (is_nacl) {
diff --git a/printing/backend/print_backend.cc b/printing/backend/print_backend.cc index 46513bf9..53ec3447 100644 --- a/printing/backend/print_backend.cc +++ b/printing/backend/print_backend.cc
@@ -95,6 +95,30 @@ #endif // BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_WIN) + +PageOutputQualityAttribute::PageOutputQualityAttribute() = default; + +PageOutputQualityAttribute::PageOutputQualityAttribute( + const std::string& display_name, + const std::string& name) + : display_name(display_name), name(name) {} + +PageOutputQualityAttribute::~PageOutputQualityAttribute() = default; + +bool PageOutputQualityAttribute::operator==( + const PageOutputQualityAttribute& other) const { + return display_name == other.display_name && name == other.name; +} + +PageOutputQuality::PageOutputQuality() = default; + +PageOutputQuality::PageOutputQuality(const PageOutputQuality& other) = default; + +PageOutputQuality::~PageOutputQuality() = default; + +#endif // BUILDFLAG(IS_WIN) + bool PrinterSemanticCapsAndDefaults::Paper::operator==( const PrinterSemanticCapsAndDefaults::Paper& other) const { return display_name == other.display_name && vendor_id == other.vendor_id &&
diff --git a/printing/backend/print_backend.h b/printing/backend/print_backend.h index f95a454..80d3befe 100644 --- a/printing/backend/print_backend.h +++ b/printing/backend/print_backend.h
@@ -16,12 +16,13 @@ #include "base/memory/scoped_refptr.h" #include "build/build_config.h" #include "printing/mojom/print.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/size.h" namespace base { class DictionaryValue; class Value; -} +} // namespace base // This is the interface for platform-specific code for a print backend namespace printing { @@ -109,6 +110,39 @@ #endif // BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_WIN) + +struct COMPONENT_EXPORT(PRINT_BACKEND) PageOutputQualityAttribute { + PageOutputQualityAttribute(); + PageOutputQualityAttribute(const std::string& display_name, + const std::string& name); + ~PageOutputQualityAttribute(); + + bool operator==(const PageOutputQualityAttribute& other) const; + + // Localized name of the page output quality attribute. + std::string display_name; + + // Internal ID of the page output quality attribute. + std::string name; +}; +using PageOutputQualityAttributes = std::vector<PageOutputQualityAttribute>; + +struct COMPONENT_EXPORT(PRINT_BACKEND) PageOutputQuality { + PageOutputQuality(); + PageOutputQuality(const PageOutputQuality& other); + ~PageOutputQuality(); + + // All options of page output quality. + PageOutputQualityAttributes qualities; + + // Default option of page output quality. + // TODO(crbug.com/1291257): Need populate this option in the next CLs. + absl::optional<std::string> default_quality; +}; + +#endif // BUILDFLAG(IS_WIN) + struct COMPONENT_EXPORT(PRINT_BACKEND) PrinterSemanticCapsAndDefaults { PrinterSemanticCapsAndDefaults(); PrinterSemanticCapsAndDefaults(const PrinterSemanticCapsAndDefaults& other); @@ -149,6 +183,10 @@ bool pin_supported = false; AdvancedCapabilities advanced_capabilities; #endif // BUILDFLAG(IS_CHROMEOS) + +#if BUILDFLAG(IS_WIN) + absl::optional<PageOutputQuality> page_output_quality; +#endif // BUILDFLAG(IS_WIN) }; struct COMPONENT_EXPORT(PRINT_BACKEND) PrinterCapsAndDefaults { @@ -215,6 +253,23 @@ // Returns true if printer_name points to a valid printer. virtual bool IsValidPrinter(const std::string& printer_name) = 0; +#if BUILDFLAG(IS_WIN) + + // This method uses the XPS API to get the printer capabilities. + mojom::ResultCode GetXmlPrinterCapabilitiesForXpsDriver( + const std::string& printer_name, + std::string& capabilities); + + // Since parsing XML data to `PrinterSemanticCapsAndDefaults` can not be done + // in the print_backend level, parse base::Value into + // `PrinterSemanticCapsAndDefaults` data structure instead. Parsing XML data + // to base::Value will be processed by data_decoder service. + mojom::ResultCode ParseValueForXpsPrinterCapabilities( + const base::Value& value, + PrinterSemanticCapsAndDefaults* printer_info); + +#endif // BUILDFLAG(IS_WIN) + // Allocates a print backend. static scoped_refptr<PrintBackend> CreateInstance(const std::string& locale); @@ -225,13 +280,6 @@ protected: friend class base::RefCountedThreadSafe<PrintBackend>; -#if BUILDFLAG(IS_WIN) - FRIEND_TEST_ALL_PREFIXES(PrintBackendTest, - MANUAL_GetXmlPrinterCapabilitiesForXpsDriver); - FRIEND_TEST_ALL_PREFIXES(PrintBackendTest, - ParseValueForXpsPrinterCapabilities); -#endif - PrintBackend(); virtual ~PrintBackend(); @@ -239,18 +287,6 @@ static scoped_refptr<PrintBackend> CreateInstanceImpl( const base::DictionaryValue* print_backend_settings, const std::string& locale); - -#if BUILDFLAG(IS_WIN) - // Gets the semantic capabilities and defaults for a specific printer. - // This method uses the XPS API to get the printer capabilities. - // TODO(crbug.com/1291257): This method is not fully implemented yet. - mojom::ResultCode GetXmlPrinterCapabilitiesForXpsDriver( - const std::string& printer_name, - std::string& capabilities); - mojom::ResultCode ParseValueForXpsPrinterCapabilities( - const base::Value& value, - PrinterSemanticCapsAndDefaults* printer_info); -#endif }; } // namespace printing
diff --git a/printing/backend/print_backend_unittest.cc b/printing/backend/print_backend_unittest.cc index 972e39b2..d6a169ae 100644 --- a/printing/backend/print_backend_unittest.cc +++ b/printing/backend/print_backend_unittest.cc
@@ -58,6 +58,7 @@ } #if BUILDFLAG(IS_WIN) + // This test is for the XPS API that read the XML capabilities of a // specific printer. TEST_F(PrintBackendTest, MANUAL_GetXmlPrinterCapabilitiesForXpsDriver) { @@ -79,7 +80,8 @@ // in this test is based on the XML data returned by // `GetXmlPrinterCapabilitiesForXpsDriver` API and processed by data_decoder // service. - absl::optional<base::Value> capabilities = base::JSONReader::Read(R"({ + // This is the correct format of XPS "PageOutputQuality" capability. + absl::optional<base::Value> correct_capabilities = base::JSONReader::Read(R"({ "type": "element", "tag": "psf:PrintCapabilities", "children": [ @@ -224,12 +226,280 @@ ] } )"); + ASSERT_TRUE(correct_capabilities); PrinterSemanticCapsAndDefaults printer_info; - ASSERT_TRUE(capabilities); + + // Expect that parsing XPS Printer Capabilities is successful. + // After parsing, `printer_info` will have 2 capabilities: "PageOutputQuality" + // and "PageOutputColor". EXPECT_EQ(GetPrintBackend()->ParseValueForXpsPrinterCapabilities( - *capabilities, &printer_info), + *correct_capabilities, &printer_info), mojom::ResultCode::kSuccess); } + +TEST_F(PrintBackendTest, + ParseCorrectPageOutputQualityForXpsPrinterCapabilities) { + // This is the correct format of XPS "PageOutputQuality" capability. + absl::optional<base::Value> correct_capabilities = base::JSONReader::Read(R"({ + "type": "element", + "tag": "psf:PrintCapabilities", + "children": [ + { + "type": "element", + "tag": "psf:Feature", + "attributes": { + "name": "psk:PageOutputQuality" + }, + "children": [ + { + "type": "element", + "tag": "psf:Feature", + "attributes": { + "name": "psk:PageOutputQuality" + } + }, + { + "type": "element", + "tag": "psf:Property", + "attributes": { + "name": "psf:SelectionType" + }, + "children": [ + { + "type": "element", + "tag": "psf:Value", + "attributes": { + "xsi:type": "xsd:QName" + }, + "children": [ + { + "type": "text", + "text": "psk:PickOne" + } + ] + } + ] + }, + { + "type": "element", + "tag": "psf:Property", + "attributes": { + "name": "psf:DisplayName" + }, + "children": [ + { + "type": "element", + "tag": "psf:Value", + "attributes": { + "xsi:type": "xsd:string" + }, + "children": [ + { + "type": "text", + "text": "Quality" + } + ] + } + ] + }, + { + "type": "element", + "tag": "psf:Option", + "attributes": { + "name": "ns0000:Draft", + "constrain": "psk:None" + }, + "children": [ + { + "type": "element", + "tag": "psf:Property", + "attributes": { + "name": "psf:DisplayName" + }, + "children": [ + { + "type": "element", + "tag": "psf:Value", + "attributes": { + "xsi:type": "xsd:string" + }, + "children": [ + { + "type": "text", + "text": "Draft" + } + ] + } + ] + } + ] + }, + { + "type": "element", + "tag": "psf:Option", + "attributes": { + "name": "ns0000:Advanced", + "constrain": "psk:None" + }, + "children": [ + { + "type": "element", + "tag": "psf:Property", + "attributes": { + "name": "psf:DisplayName" + }, + "children": [ + { + "type": "element", + "tag": "psf:Value", + "attributes": { + "xsi:type": "xsd:string" + }, + "children": [ + { + "type": "text", + "text": "Advanced" + } + ] + } + ] + } + ] + }, + { + "type": "element", + "tag": "psf:Option", + "attributes": { + "name": "psk:Normal" + } + } + ] + }, + { + "type": "element", + "tag": "psf:Feature", + "attributes": { + "name": "psk:PageOutputColor" + } + } + ] +} +)"); + ASSERT_TRUE(correct_capabilities); + PrinterSemanticCapsAndDefaults printer_info; + + // Expect that parsing XPS Printer Capabilities is successful. + // After parsing, `printer_info` will have 2 capabilities: "PageOutputQuality" + // and "PageOutputColor". + EXPECT_EQ(GetPrintBackend()->ParseValueForXpsPrinterCapabilities( + *correct_capabilities, &printer_info), + mojom::ResultCode::kSuccess); + + // After parsing, `PageOutputQuality` of `printer_info` is expected to have 3 + // options listed in `kPageOutputQualities`. + const PageOutputQualityAttributes kPageOutputQualities = { + PageOutputQualityAttribute("Draft", "ns0000:Draft"), + PageOutputQualityAttribute("Advanced", "ns0000:Advanced"), + PageOutputQualityAttribute("", "psk:Normal")}; + EXPECT_EQ(printer_info.page_output_quality->qualities, kPageOutputQualities); +} + +TEST_F(PrintBackendTest, + ParseIncorrectPageOutputQualityForXpsPrinterCapabilities) { + // This string below is incorrect format of XPS `PageOutputQuality` capability + // when the property inside option ns0000:Draft does not have any value. + absl::optional<base::Value> incorrect_capabilities = + base::JSONReader::Read(R"({ + "type": "element", + "tag": "psf:PrintCapabilities", + "children": [ + { + "type": "element", + "tag": "psf:Feature", + "attributes": { + "name": "psk:PageOutputQuality" + }, + "children": [ + { + "type": "element", + "tag": "psf:Feature", + "attributes": { + "name": "psk:PageOutputQuality" + } + }, + { + "type": "element", + "tag": "psf:Property", + "attributes": { + "name": "psf:SelectionType" + }, + "children": [ + { + "type": "element", + "tag": "psf:Value", + "attributes": { + "xsi:type": "xsd:QName" + }, + "children": [ + { + "type": "text", + "text": "psk:PickOne" + } + ] + } + ] + }, + { + "type": "element", + "tag": "psf:Property", + "attributes": { + "name": "psf:DisplayName" + }, + "children": [ + { + "type": "element", + "tag": "psf:Value", + "attributes": { + "xsi:type": "xsd:string" + }, + "children": [ + { + "type": "text", + "text": "Quality" + } + ] + } + ] + }, + { + "type": "element", + "tag": "psf:Option", + "attributes": { + "name": "ns0000:Draft", + "constrain": "psk:None" + }, + "children": [ + { + "type": "element", + "tag": "psf:Property", + "attributes": { + "name": "psf:DisplayName" + } + } + ] + } + ] + } + ] +} +)"); + ASSERT_TRUE(incorrect_capabilities); + PrinterSemanticCapsAndDefaults printer_info; + EXPECT_EQ(GetPrintBackend()->ParseValueForXpsPrinterCapabilities( + *incorrect_capabilities, &printer_info), + mojom::ResultCode::kFailed); +} + #endif } // namespace printing
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc index a86d5ac..d4f61ce 100644 --- a/printing/backend/print_backend_win.cc +++ b/printing/backend/print_backend_win.cc
@@ -10,6 +10,7 @@ #include <wrl/client.h> #include <memory> +#include <utility> #include "base/logging.h" #include "base/memory/free_deleter.h" @@ -38,6 +39,9 @@ constexpr char kPrintCapabilities[] = "psf:PrintCapabilities"; constexpr char kFeature[] = "psf:Feature"; constexpr char kPageOutputQuality[] = "psk:PageOutputQuality"; +constexpr char kOption[] = "psf:Option"; +constexpr char kProperty[] = "psf:Property"; +constexpr char kValue[] = "psf:Value"; constexpr char kName[] = "name"; // Wrapper class to close provider automatically. @@ -58,8 +62,53 @@ mojom::ResultCode LoadPageOutputQuality( const base::Value& page_output_quality, PrinterSemanticCapsAndDefaults* printer_info) { - // TODO(crbug.com/1291257): Need to parse `page_output_quality` into - // `printer_info`. More work is expected here. + PageOutputQuality printer_page_output_quality; + std::vector<const base::Value*> options; + data_decoder::GetAllXmlElementChildrenWithTag(page_output_quality, kOption, + &options); + if (options.empty()) { + LOG(WARNING) << "Incorrect XML format"; + return mojom::ResultCode::kFailed; + } + for (const auto* option : options) { + PageOutputQualityAttribute quality; + quality.name = data_decoder::GetXmlElementAttribute(*option, kName); + int property_count = + data_decoder::GetXmlElementChildrenCount(*option, kProperty); + + // TODO(crbug.com/1291257): Each formatted option is expected to have zero + // or one property. Each property inside an option is expected to + // have one value. + // Source: + // https://docs.microsoft.com/en-us/windows/win32/printdocs/pageoutputquality + // If an option has more than one property or a property has more than one + // value, more work is expected here. + + // In the case an option looks like <psf:Option name="psk:Text />, + // property_count is 0. In this case, an option only has `name` + // and does not have `display_name`. + if (property_count > 1) { + LOG(WARNING) << "Incorrect XML format"; + return mojom::ResultCode::kFailed; + } + if (property_count == 1) { + const base::Value* property_element = data_decoder::FindXmlElementPath( + *option, {kOption, kProperty}, /*unique_path=*/nullptr); + int value_count = + data_decoder::GetXmlElementChildrenCount(*property_element, kValue); + if (value_count != 1) { + LOG(WARNING) << "Incorrect XML format"; + return mojom::ResultCode::kFailed; + } + const base::Value* value_element = data_decoder::FindXmlElementPath( + *option, {kOption, kProperty, kValue}, /*unique_path=*/nullptr); + std::string text; + data_decoder::GetXmlElementText(*value_element, &text); + quality.display_name = std::move(text); + } + printer_page_output_quality.qualities.push_back(std::move(quality)); + } + printer_info->page_output_quality = std::move(printer_page_output_quality); return mojom::ResultCode::kSuccess; }
diff --git a/storage/browser/file_system/file_system_context.h b/storage/browser/file_system/file_system_context.h index 2d7ad9f..a607578 100644 --- a/storage/browser/file_system/file_system_context.h +++ b/storage/browser/file_system/file_system_context.h
@@ -350,6 +350,12 @@ bool is_incognito() { return is_incognito_; } + // TODO(com/1231162): Remove this. Used only by test code and to migrate media + // license data to the new backend. + PluginPrivateFileSystemBackend* plugin_private_backend() const { + return plugin_private_backend_.get(); + } + private: // For CreateFileSystemOperation. friend class FileSystemOperationRunner; @@ -428,11 +434,6 @@ return sandbox_backend_.get(); } - // Used only by test code. - PluginPrivateFileSystemBackend* plugin_private_backend() const { - return plugin_private_backend_.get(); - } - // Override the default leveldb Env with `env_override_` if set. std::unique_ptr<leveldb::Env> env_override_;
diff --git a/storage/browser/file_system/plugin_private_file_system_backend.cc b/storage/browser/file_system/plugin_private_file_system_backend.cc index 8e50c87..735ecc19 100644 --- a/storage/browser/file_system/plugin_private_file_system_backend.cc +++ b/storage/browser/file_system/plugin_private_file_system_backend.cc
@@ -9,6 +9,7 @@ #include <map> #include <memory> #include <utility> +#include <vector> #include "base/bind.h" #include "base/containers/contains.h" @@ -99,6 +100,16 @@ } // namespace +PluginPrivateFileSystemBackend::CdmFileInfo::CdmFileInfo( + const std::string& name, + const std::string& legacy_file_system_id) + : name(name), legacy_file_system_id(legacy_file_system_id) {} +PluginPrivateFileSystemBackend::CdmFileInfo::CdmFileInfo(const CdmFileInfo&) = + default; +PluginPrivateFileSystemBackend::CdmFileInfo::CdmFileInfo(CdmFileInfo&&) = + default; +PluginPrivateFileSystemBackend::CdmFileInfo::~CdmFileInfo() = default; + PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend( scoped_refptr<base::SequencedTaskRunner> file_task_runner, const base::FilePath& profile_path, @@ -303,11 +314,12 @@ *last_modified_time = base::Time::UnixEpoch(); std::string fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( - kFileSystemTypePluginPrivate, "pluginprivate", base::FilePath()); + kFileSystemTypePluginPrivate, kPluginPrivateRootName, + base::FilePath()); DCHECK(ValidateIsolatedFileSystemId(fsid)); std::string root = GetIsolatedFileSystemRootURIString(origin.GetURL(), fsid, - "pluginprivate"); + kPluginPrivateRootName); std::unique_ptr<FileSystemOperationContext> operation_context( std::make_unique<FileSystemOperationContext>(context)); @@ -358,6 +370,65 @@ } } +std::vector<PluginPrivateFileSystemBackend::CdmFileInfo> +PluginPrivateFileSystemBackend::GetMediaLicenseFilesForOriginOnFileTaskRunner( + FileSystemContext* context, + const url::Origin& origin) { + DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); + + std::unique_ptr<FileSystemOperationContext> operation_context( + std::make_unique<FileSystemOperationContext>(context)); + + // Determine the available plugin private filesystem directories for this + // origin. Currently the plugin private filesystem is only used by Encrypted + // Media Content Decryption Modules. Each CDM gets a directory based on the + // mimetype (e.g. plugin application/x-ppapi-widevine-cdm uses directory + // application_x-ppapi-widevine-cdm). Enumerate through the set of + // directories so that data from any CDM used by this origin is counted. + base::File::Error error; + base::FilePath path = + obfuscated_file_util()->GetDirectoryForStorageKeyAndType( + blink::StorageKey(origin), "", false, &error); + if (error != base::File::FILE_OK) + return {}; + + std::vector<CdmFileInfo> cdm_files; + base::FileEnumerator directory_enumerator(path, false, + base::FileEnumerator::DIRECTORIES); + base::FilePath plugin_path; + while (!(plugin_path = directory_enumerator.Next()).empty()) { + std::string plugin_name = plugin_path.BaseName().MaybeAsASCII(); + + std::string fsid = + IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( + kFileSystemTypePluginPrivate, kPluginPrivateRootName, + base::FilePath()); + DCHECK(ValidateIsolatedFileSystemId(fsid)); + std::string root = GetIsolatedFileSystemRootURIString( + origin.GetURL(), fsid, kPluginPrivateRootName); + + if (OpenFileSystemOnFileTaskRunner( + obfuscated_file_util(), plugin_map_, origin, fsid, plugin_name, + OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT) != base::File::FILE_OK) { + continue; + } + std::unique_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( + obfuscated_file_util()->CreateFileEnumerator( + operation_context.get(), + context->CrackURL( + GURL(root), blink::StorageKey(url::Origin::Create(GURL(root)))), + true)); + + base::FilePath cdm_file_path; + while (!(cdm_file_path = enumerator->Next()).empty()) { + cdm_files.emplace_back(cdm_file_path.BaseName().AsUTF8Unsafe(), + plugin_path.BaseName().AsUTF8Unsafe()); + } + } + + return cdm_files; +} + scoped_refptr<QuotaReservation> PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner( const blink::StorageKey& storage_key,
diff --git a/storage/browser/file_system/plugin_private_file_system_backend.h b/storage/browser/file_system/plugin_private_file_system_backend.h index d1422e6..9b1aab7 100644 --- a/storage/browser/file_system/plugin_private_file_system_backend.h +++ b/storage/browser/file_system/plugin_private_file_system_backend.h
@@ -54,6 +54,18 @@ class FileSystemIDToPluginMap; using StatusCallback = base::OnceCallback<void(base::File::Error result)>; + // Used to migrate media license data to the new backend. + struct COMPONENT_EXPORT(STORAGE_BROWSER) CdmFileInfo { + CdmFileInfo(const std::string& name, + const std::string& legacy_file_system_id); + CdmFileInfo(const CdmFileInfo&); + CdmFileInfo(CdmFileInfo&&); + ~CdmFileInfo(); + + const std::string name; + const std::string legacy_file_system_id; + }; + PluginPrivateFileSystemBackend( scoped_refptr<base::SequencedTaskRunner> file_task_runner, const base::FilePath& profile_path, @@ -145,13 +157,20 @@ int64_t* total_size, base::Time* last_modified_time); + // Used to migrate media license data to the new backend. + // TODO(crbug.com/1231162): Once all media license data has been migrated, the + // PPFS will have no more consumers and we can remove it entirely. + std::vector<CdmFileInfo> GetMediaLicenseFilesForOriginOnFileTaskRunner( + FileSystemContext* context, + const url::Origin& origin); + ObfuscatedFileUtilMemoryDelegate* obfuscated_file_util_memory_delegate(); + const base::FilePath& base_path() const { return base_path_; } private: friend class PluginPrivateFileSystemBackendTest; ObfuscatedFileUtil* obfuscated_file_util(); - const base::FilePath& base_path() const { return base_path_; } const scoped_refptr<base::SequencedTaskRunner> file_task_runner_; const FileSystemOptions file_system_options_;
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc index 3909485..4c1ee64 100644 --- a/storage/browser/quota/quota_database.cc +++ b/storage/browser/quota/quota_database.cc
@@ -229,16 +229,6 @@ blink::mojom::StorageType storage_type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug/1210252): Update to not execute 2 sql statements on creation. - QuotaErrorOr<BucketInfo> bucket_result = - GetBucket(storage_key, bucket_name, storage_type); - - if (bucket_result.ok()) - return QuotaError::kEntryExistsError; - - if (bucket_result.error() != QuotaError::kNotFound) - return bucket_result.error(); - base::Time now = base::Time::Now(); return CreateBucketInternal(storage_key, storage_type, bucket_name, /*use_count=*/0, now, now); @@ -391,23 +381,17 @@ if (open_error != QuotaError::kNone) return open_error; - // Check if bucket exists first. Running an update statement on a bucket that - // doesn't exist fails DCHECK and crashes. - // TODO(crbug/1210252): Update to not execute 2 sql statements. - QuotaErrorOr<BucketInfo> result = - GetBucket(storage_key, kDefaultBucketName, type); - if (!result.ok()) - return result.error(); - // clang-format off static constexpr char kSql[] = "UPDATE buckets " "SET use_count = use_count + 1, last_accessed = ? " - "WHERE id = ?"; + "WHERE storage_key = ? AND type = ? AND name = ?"; // clang-format on sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindTime(0, last_accessed); - statement.BindInt64(1, result->id.value()); + statement.BindString(1, storage_key.Serialize()); + statement.BindInt(2, static_cast<int>(type)); + statement.BindString(3, kDefaultBucketName); if (!statement.Run()) return QuotaError::kDatabaseError; @@ -424,13 +408,6 @@ if (open_error != QuotaError::kNone) return open_error; - // Check if bucket exists first. Running an update statement on a bucket that - // doesn't exist fails DCHECK and crashes. - // TODO(crbug/1210252): Update to not execute 2 sql statements. - QuotaErrorOr<BucketTableEntry> entry = GetBucketInfo(bucket_id); - if (!entry.ok()) - return entry.error(); - // clang-format off static constexpr char kSql[] = "UPDATE buckets " @@ -456,13 +433,6 @@ if (open_error != QuotaError::kNone) return open_error; - // Check if bucket exists first. Running an update statement on a bucket that - // doesn't exist fails DCHECK and crashes. - // TODO(crbug/1210252): Update to not execute 2 sql statements. - QuotaErrorOr<BucketTableEntry> entry = GetBucketInfo(bucket_id); - if (!entry.ok()) - return entry.error(); - static constexpr char kSql[] = "UPDATE buckets SET last_modified = ? WHERE id = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc index d7965f6..1585d01 100644 --- a/storage/browser/quota/quota_database_unittest.cc +++ b/storage/browser/quota/quota_database_unittest.cc
@@ -565,11 +565,16 @@ base::Time::FromJavaTime(30)), QuotaError::kNone); - // one persistent. + // One persistent. EXPECT_EQ(db.SetBucketLastAccessTime(bucket4.bucket_id, base::Time::FromJavaTime(40)), QuotaError::kNone); + // One non-existent. + EXPECT_EQ( + db.SetBucketLastAccessTime(BucketId(777), base::Time::FromJavaTime(40)), + QuotaError::kNone); + result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); EXPECT_TRUE(result.ok()); EXPECT_EQ(bucket1.bucket_id, result.value().id); @@ -632,9 +637,9 @@ StorageKey::CreateFromStringForTesting("http://example/"); base::Time now = base::Time::Now(); - // Should error if bucket doesn't exist. + // Doesn't error if bucket doesn't exist. EXPECT_EQ(db.SetStorageKeyLastAccessTime(storage_key, kTemp, now), - QuotaError::kNotFound); + QuotaError::kNone); QuotaErrorOr<BucketInfo> bucket = db.CreateBucketForTesting(storage_key, kDefaultBucketName, kTemp); @@ -723,6 +728,11 @@ db.SetBucketLastModifiedTime(bucket4.id, base::Time::FromJavaTime(30)), QuotaError::kNone); + // Non-existent bucket. + EXPECT_EQ( + db.SetBucketLastModifiedTime(BucketId(777), base::Time::FromJavaTime(0)), + QuotaError::kNone); + result = db.GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); EXPECT_TRUE(result.ok()); buckets = result.value();
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index 93b4d494..27da1df9 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -1819,7 +1819,7 @@ { "args": [], "cros_board": "atlas", - "cros_img": "atlas-release/R100-14526.28.0", + "cros_img": "atlas-release/R100-14526.43.0", "name": "lacros_all_tast_tests_ATLAS_RELEASE_BETA", "resultdb": { "enable": true, @@ -1879,7 +1879,7 @@ { "args": [], "cros_board": "eve", - "cros_img": "eve-release/R100-14526.28.0", + "cros_img": "eve-release/R100-14526.43.0", "name": "lacros_all_tast_tests_EVE_RELEASE_BETA", "resultdb": { "enable": true,
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index de5bb39ae..c5a3dc66 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -9971,12 +9971,12 @@ "--test-runner-outdir", ".", "--client-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--client-version=98", + "--client-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android30.textpb" @@ -9986,11 +9986,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_client_from_98" + "weblayer_skew_tests_with_client_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_client_from_98", + "name": "weblayer_skew_tests_with_client_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -10000,8 +10000,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -10477,10 +10477,10 @@ "--client-outdir", ".", "--implementation-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--impl-version=98", + "--impl-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android30.textpb" @@ -10490,11 +10490,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_impl_from_98" + "weblayer_skew_tests_with_impl_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_impl_from_98", + "name": "weblayer_skew_tests_with_impl_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -10504,8 +10504,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index fc5d864..0c485fc8 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -45271,12 +45271,12 @@ "--test-runner-outdir", ".", "--client-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--client-version=98", + "--client-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android29.textpb" @@ -45286,11 +45286,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_client_from_98" + "weblayer_skew_tests_with_client_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_client_from_98", + "name": "weblayer_skew_tests_with_client_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45300,8 +45300,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -45777,10 +45777,10 @@ "--client-outdir", ".", "--implementation-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--impl-version=98", + "--impl-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android29.textpb" @@ -45790,11 +45790,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_impl_from_98" + "weblayer_skew_tests_with_impl_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_impl_from_98", + "name": "weblayer_skew_tests_with_impl_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45804,8 +45804,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -46283,12 +46283,12 @@ "--test-runner-outdir", ".", "--client-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--client-version=98", + "--client-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android23.textpb" @@ -46298,11 +46298,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_chrome_with_client_from_98" + "weblayer_skew_tests_with_chrome_with_client_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_chrome_with_client_from_98", + "name": "weblayer_skew_tests_with_chrome_with_client_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46312,8 +46312,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -46789,10 +46789,10 @@ "--client-outdir", ".", "--implementation-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--impl-version=98", + "--impl-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android23.textpb" @@ -46802,11 +46802,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_chrome_with_impl_from_98" + "weblayer_skew_tests_with_chrome_with_impl_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_chrome_with_impl_from_98", + "name": "weblayer_skew_tests_with_chrome_with_impl_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46816,8 +46816,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47362,12 +47362,12 @@ "--test-runner-outdir", ".", "--client-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--client-version=98", + "--client-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android27.textpb" @@ -47377,11 +47377,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_client_from_98" + "weblayer_skew_tests_with_client_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_client_from_98", + "name": "weblayer_skew_tests_with_client_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -47391,8 +47391,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47868,10 +47868,10 @@ "--client-outdir", ".", "--implementation-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--impl-version=98", + "--impl-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android27.textpb" @@ -47881,11 +47881,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_impl_from_98" + "weblayer_skew_tests_with_impl_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_impl_from_98", + "name": "weblayer_skew_tests_with_impl_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -47895,8 +47895,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48441,12 +48441,12 @@ "--test-runner-outdir", ".", "--client-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--client-version=98", + "--client-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android28.textpb" @@ -48456,11 +48456,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_client_from_98" + "weblayer_skew_tests_with_client_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_client_from_98", + "name": "weblayer_skew_tests_with_client_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -48470,8 +48470,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48947,10 +48947,10 @@ "--client-outdir", ".", "--implementation-outdir", - "../../weblayer_instrumentation_test_M98/out/Release", + "../../weblayer_instrumentation_test_M99/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--impl-version=98", + "--impl-version=99", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android28.textpb" @@ -48960,11 +48960,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_skew_tests_with_impl_from_98" + "weblayer_skew_tests_with_impl_from_99" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_skew_tests_with_impl_from_98", + "name": "weblayer_skew_tests_with_impl_from_99", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -48974,8 +48974,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/weblayer-x86", - "location": "weblayer_instrumentation_test_M98", - "revision": "version:98.0.4758.109" + "location": "weblayer_instrumentation_test_M99", + "revision": "version:99.0.4844.88" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter b/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter index 3934a48..c431cb3d 100644 --- a/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter +++ b/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter
@@ -45,9 +45,6 @@ # crbug.com/1062055 -org.chromium.chrome.browser.metrics.StartupLoadingMetricsTest.testWebApkStartRecorded -# crbug.com/1077316 --org.chromium.chrome.browser.ntp.cards.promo.HomepagePromoTest.testChangeHomepageAndUndo_* - # crbug.com/1090942 -org.chromium.chrome.browser.autofill.settings.AutofillPaymentMethodsFragmentTest.*
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json index 42fb832..3b004d8 100644 --- a/testing/buildbot/internal.chromeos.fyi.json +++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1148,7 +1148,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R100-14526.28.0", + "cros_img": "octopus-release/R100-14526.43.0", "name": "lacros_fyi_tast_tests_OCTOPUS_RELEASE_BETA", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1190,7 +1190,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R100-14526.28.0", + "cros_img": "octopus-release/R100-14526.43.0", "name": "ozone_unittests_OCTOPUS_RELEASE_BETA", "swarming": {}, "test": "ozone_unittests",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 79f722b..d7d35f0e 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -496,18 +496,18 @@ '--client-outdir', '.', '--implementation-outdir', - '../../weblayer_instrumentation_test_M98/out/Release', + '../../weblayer_instrumentation_test_M99/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=98', + '--impl-version=99', ], - 'identifier': 'with_impl_from_98', + 'identifier': 'with_impl_from_99', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/weblayer-x86', - 'location': 'weblayer_instrumentation_test_M98', - 'revision': 'version:98.0.4758.109', + 'location': 'weblayer_instrumentation_test_M99', + 'revision': 'version:99.0.4844.88', } ], }, @@ -640,18 +640,18 @@ '--client-outdir', '.', '--implementation-outdir', - '../../weblayer_instrumentation_test_M98/out/Release', + '../../weblayer_instrumentation_test_M99/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=98', + '--impl-version=99', ], - 'identifier': 'with_impl_from_98', + 'identifier': 'with_impl_from_99', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/weblayer-x86', - 'location': 'weblayer_instrumentation_test_M98', - 'revision': 'version:98.0.4758.109', + 'location': 'weblayer_instrumentation_test_M99', + 'revision': 'version:99.0.4844.88', } ], }, @@ -782,20 +782,20 @@ '--test-runner-outdir', '.', '--client-outdir', - '../../weblayer_instrumentation_test_M98/out/Release', + '../../weblayer_instrumentation_test_M99/out/Release', '--implementation-outdir', '.', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--client-version=98', + '--client-version=99', ], - 'identifier': 'with_client_from_98', + 'identifier': 'with_client_from_99', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/weblayer-x86', - 'location': 'weblayer_instrumentation_test_M98', - 'revision': 'version:98.0.4758.109', + 'location': 'weblayer_instrumentation_test_M99', + 'revision': 'version:99.0.4844.88', } ], }, @@ -893,8 +893,8 @@ 'CROS_ATLAS_RELEASE_BETA': { 'skylab': { 'cros_board': 'atlas', - 'cros_chrome_version': '100.0.4896.44', - 'cros_img': 'atlas-release/R100-14526.28.0', + 'cros_chrome_version': '100.0.4896.54', + 'cros_img': 'atlas-release/R100-14526.43.0', }, 'enabled': True, 'identifier': 'ATLAS_RELEASE_BETA', @@ -929,8 +929,8 @@ 'CROS_EVE_RELEASE_BETA': { 'skylab': { 'cros_board': 'eve', - 'cros_chrome_version': '100.0.4896.44', - 'cros_img': 'eve-release/R100-14526.28.0', + 'cros_chrome_version': '100.0.4896.54', + 'cros_img': 'eve-release/R100-14526.43.0', }, 'enabled': True, 'identifier': 'EVE_RELEASE_BETA', @@ -1001,8 +1001,8 @@ 'CROS_OCTOPUS_RELEASE_BETA': { 'skylab': { 'cros_board': 'octopus', - 'cros_chrome_version': '100.0.4896.44', - 'cros_img': 'octopus-release/R100-14526.28.0', + 'cros_chrome_version': '100.0.4896.54', + 'cros_img': 'octopus-release/R100-14526.43.0', }, 'enabled': True, 'identifier': 'OCTOPUS_RELEASE_BETA',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9c153053..97cb25d1 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -7062,10 +7062,9 @@ ], "experiments": [ { - "name": "ReleaseHiddenTilesAndRequiredTilesOnly_1", + "name": "Enabled_2", "enable_features": [ - "UiCompositorReleaseTileResourcesForHiddenLayers", - "UiCompositorRequiredTilesOnly" + "UiCompositorReleaseTileResourcesForHiddenLayers" ] } ]
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 8abe2c7..21a718ae8 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -10116,19 +10116,27 @@ Timestamp timestamp string value + # Represents logged source line numbers reported in an error. + # NOTE: file and line are from chromium c++ implementation code, not js. + type PlayerErrorSourceLocation extends object + properties + string file + integer line + # Corresponds to kMediaError type PlayerError extends object properties - enum type - # Compatability until we switch to media_error - pipeline_error - media_error - # When this switches to using media::Status instead of PipelineStatus - # we can remove "errorCode" and replace it with the fields from - # a Status instance. This also seems like a duplicate of the error - # level enum - there is a todo bug to have that level removed and - # use this instead. (crbug.com/1068454) - string errorCode + string errorType + # Code is the numeric enum entry for a specific set of error codes, such + # as PipelineStatusCodes in media/base/pipeline_status.h + integer code + # A trace of where this error was caused / where it passed through. + array of PlayerErrorSourceLocation stack + # Errors potentially have a root cause error, ie, a DecoderError might be + # caused by an WindowsError + array of PlayerError cause + # Extra data attached to an error, such as an HRESULT, Video Codec, etc. + object data # This can be called multiple times, and can be used to set / override / # remove player properties. A null propValue indicates removal.
diff --git a/third_party/blink/public/mojom/webauthn/authenticator.mojom b/third_party/blink/public/mojom/webauthn/authenticator.mojom index a6a20981..20ab3074 100644 --- a/third_party/blink/public/mojom/webauthn/authenticator.mojom +++ b/third_party/blink/public/mojom/webauthn/authenticator.mojom
@@ -129,16 +129,6 @@ // See https://www.iana.org/assignments/cose/cose.xhtml#algorithms int32 public_key_algo; - // Only supported by fido2 devices on android, will eventually supported by - // other platform. - // True if getClientExtensionResults() called on the returned - // PublicKeyCredential instance should contain an 'uvm' extension output. - // If so, |user_verification_methods| contains the actual value. - [EnableIf=is_android] - bool echo_user_verification_methods; - [EnableIf=is_android] - array<UvmEntry>? user_verification_methods; - // True if getClientExtensionResults() called on the returned // PublicKeyCredential instance should contain a `credProps` extension // output. |has_cred_props_rk| indicates if the rk member in that extension @@ -494,13 +484,6 @@ // https://w3c.github.io/webauthn/#prf-extension bool prf_enable; - // Only supported by fido2 devices on android, will eventually supported by - // other platform. - // Whether the user verification method extension is requested by - // the RP. See https://w3c.github.io/webauthn/#sctn-uvm-extension - [EnableIf=is_android] - bool user_verification_methods; - // The value of the `credentialProtectionPolicy` extension, or UNSPECIFIED if // none was provided. ProtectionPolicy protection_policy;
diff --git a/third_party/blink/public/web/web_media_inspector.h b/third_party/blink/public/web/web_media_inspector.h index 1af4bbc..2e5e7c0 100644 --- a/third_party/blink/public/web/web_media_inspector.h +++ b/third_party/blink/public/web/web_media_inspector.h
@@ -33,9 +33,20 @@ using InspectorPlayerEvents = WebVector<InspectorPlayerEvent>; struct InspectorPlayerError { - enum class Type { kPipelineError, kMediaStatus }; - Type type; - WebString errorCode; + struct Data { + WebString name; + WebString value; + }; + struct SourceLocation { + WebString filename; + int line_number; + }; + WebString group; + int code; + WebString message; + WebVector<SourceLocation> stack; + WebVector<InspectorPlayerError> caused_by; + WebVector<Data> data; }; using InspectorPlayerErrors = WebVector<InspectorPlayerError>;
diff --git a/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc b/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc index d92c0b2..1d1ec1f 100644 --- a/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc +++ b/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc
@@ -38,7 +38,7 @@ } template <typename Direction> -void SameBlockWordIterator<Direction>::AdvanceNextWord() { +bool SameBlockWordIterator<Direction>::AdvanceNextWord() { do { int pos = Direction::FindNextWordPos(current_node_text_, current_text_offset_); @@ -47,9 +47,10 @@ .StripWhiteSpace(); if (!next_word.IsEmpty()) { current_text_offset_ = pos; - return; + return true; } } while (NextNode()); + return false; } template <typename Direction>
diff --git a/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.h b/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.h index 28e1490b7..8968208c 100644 --- a/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.h +++ b/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.h
@@ -128,8 +128,10 @@ // with until the current position. String TextFromStart() const; - // Moves the current position to the beginning of the next word. - void AdvanceNextWord(); + // Moves the current position to the beginning of the next word. Returns true + // if the text advanced successfully, and false if the iterator reached the + // end of the block. + bool AdvanceNextWord(); void Trace(Visitor* visitor) const;
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc index d1c745f..d6347b3 100644 --- a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc +++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
@@ -205,7 +205,7 @@ error_ = shared_highlighting::LinkGenerationError::kNone; selector_ready_status_.reset(); - // It is possible we have unsurved callback, but if we are starting a new + // It is possible we have unserved callback, but if we are starting a new // generation, then we have a new selection, in which case it is safe to // assume that the client is not waiting for the callback return. response_callback_.Reset();
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc index 8980302..3ff1e7d 100644 --- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc +++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc
@@ -124,6 +124,8 @@ constexpr int kMaxIterationCountToRecord = 10; constexpr int kMinWordCount = 3; +absl::optional<int> g_exactTextMaxCharsOverride; + TextFragmentSelectorGenerator::TextFragmentSelectorGenerator( LocalFrame* main_frame) : frame_(main_frame) {} @@ -426,7 +428,7 @@ } String selected_text = PlainText(ephemeral_range).StripWhiteSpace(); // If too long should use ranges. - if (selected_text.length() > kExactTextMaxChars) { + if (selected_text.length() > GetExactTextMaxChars()) { step_ = kRange; return; } @@ -453,6 +455,10 @@ } int num_words_to_add = 1; + + // Determine length of target string for verifictaion. + unsigned target_length = PlainText(range_->ToEphemeralRange()).length(); + // Initialize range start/end and word min count, if needed. if (!range_start_iterator_ && !range_end_iterator_) { PositionInFlatTree range_start_position = @@ -471,8 +477,42 @@ range_end_position); } - // Use at least 3 words from both sides for more robust link to text. - num_words_to_add = kMinWordCount; + // Use at least 3 words from both sides for more robust link to text unless + // the selected text is shorter than 6 words. + if (TextFragmentFinder::IsInSameUninterruptedBlock(range_start_position, + range_end_position)) { + num_words_to_add = 0; + auto* range_start_counter = + MakeGarbageCollected<ForwardSameBlockWordIterator>( + range_start_position); + // TODO(crbug.com/1302719) ForwardSameBlockWordIterator Should be made to + // return the current posision in a form that is comparable against + // range_end_position directly. + + while (num_words_to_add < kMinWordCount * 2 && + range_start_counter->AdvanceNextWord() && + range_start_counter->TextFromStart().length() <= target_length) { + num_words_to_add++; + } + num_words_to_add = num_words_to_add / 2; + if (num_words_to_add == 0) { + // If there is only one word found in the range selection explicitly set + // exact selector to avoid round tripping. + EphemeralRangeInFlatTree ephemeral_range = range_->ToEphemeralRange(); + String selected_text = PlainText(ephemeral_range).StripWhiteSpace(); + step_ = kExact; + state_ = kTestCandidate; + selector_ = std::make_unique<TextFragmentSelector>( + TextFragmentSelector::SelectorType::kExact, selected_text, "", "", + ""); + return; + } + } else { + // If the the start and end are in different blocks overlaps dont need to + // be prevented as the number of words will limited by the block + // boundaries. + num_words_to_add = kMinWordCount; + } } if (!range_start_iterator_ && !range_end_iterator_) { @@ -495,13 +535,8 @@ range_start_iterator_ ? range_start_iterator_->TextFromStart() : ""; String end = range_end_iterator_ ? range_end_iterator_->TextFromStart() : ""; - if (start.length() + end.length() > - PlainText(range_->ToEphemeralRange()).length()) { + if (start.length() + end.length() > target_length) { if (!selector_) { - // If we overlap for the first attempt we cannot add context as there is - // no selector start or end. - // TODO(crbug.com/1302719): Fallback to using less words or exact - // selector. state_ = kFailure; error_ = LinkGenerationError::kNoRange; return; @@ -647,4 +682,20 @@ std::move(pending_generate_selector_callback_).Run(selector, error_); } +// static +void TextFragmentSelectorGenerator::OverrideExactTextMaxCharsForTesting( + int value) { + if (value < 0) + g_exactTextMaxCharsOverride.reset(); + else + g_exactTextMaxCharsOverride = value; +} + +unsigned TextFragmentSelectorGenerator::GetExactTextMaxChars() { + if (g_exactTextMaxCharsOverride) + return g_exactTextMaxCharsOverride.value(); + else + return kExactTextMaxChars; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h index 4cf3ded..a6e85ba1 100644 --- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h +++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h
@@ -65,6 +65,8 @@ LocalFrame* GetFrame() { return frame_; } private: + friend class TextFragmentSelectorGeneratorTest; + FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest, GetPreviousTextEndPosition_PrevNode); FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest, @@ -90,7 +92,12 @@ FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest, GetNextTextStartPosition_InvisibleAfterSelection); FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest, + RangeSelector_RangeMultipleNonBlockNodes); + FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest, GetNextTextStartPosition_NoNextNode); + FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest, + ExactTextSelector_Long); + FRIEND_TEST_ALL_PREFIXES( TextFragmentSelectorGeneratorTest, GetPreviousTextEndPosition_ShouldSkipNodesWithNoLayoutObject); @@ -159,6 +166,11 @@ // Called to notify clients of the result of |Generate|. void NotifyClientSelectorReady(const TextFragmentSelector& selector); + // Called by tests to change default parameters. A negative value will reset + // the override. + static void OverrideExactTextMaxCharsForTesting(int value); + unsigned GetExactTextMaxChars(); + Member<LocalFrame> frame_; // This is the Range for which we're generating a selector.
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc index 53da0b7..5a8783f1 100644 --- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc +++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc
@@ -122,6 +122,16 @@ base::HistogramTester histogram_tester_; ScopedFakeUkmRecorder scoped_ukm_recorder_; int generate_call_count_ = 0; + + struct ScopedExactTextMaxCharsOverride { + explicit ScopedExactTextMaxCharsOverride(int value) { + TextFragmentSelectorGenerator::OverrideExactTextMaxCharsForTesting(value); + } + + ~ScopedExactTextMaxCharsOverride() { + TextFragmentSelectorGenerator::OverrideExactTextMaxCharsForTesting(-1); + } + }; }; // Basic exact selector case. @@ -161,6 +171,26 @@ "First%20paragraph%20text%20that%20is"); } +// A single long word will return an exact selection, even if it would normally +// exceed the max chars for exact threshold. +TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector_Long) { + ScopedExactTextMaxCharsOverride force_range_generation(10); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete(R"HTML( + <!DOCTYPE html> + <div>Test page</div> + <p id='first'>first_texts_and_last</p> + )HTML"); + Node* first_paragraph = GetDocument().getElementById("first")->firstChild(); + const auto& selected_start = Position(first_paragraph, 0); + const auto& selected_end = Position(first_paragraph, 20); + ASSERT_EQ("first_texts_and_last", + PlainText(EphemeralRange(selected_start, selected_end))); + + VerifySelector(selected_start, selected_end, "first_texts_and_last"); +} + // Exact selector test where selection contains nested <i> node. TEST_F(TextFragmentSelectorGeneratorTest, ExactTextWithNestedTextNodes) { SimRequest request("https://example.com/test.html", "text/html"); @@ -636,6 +666,28 @@ "First-,paragraph,text,-Second%20paragraph"); } +// When selecting multiple short non block nodes, ensure range is produced +// correctly. +TEST_F(TextFragmentSelectorGeneratorTest, + RangeSelector_RangeMultipleNonBlockNodes) { + // This ensures that a range selector is created instead of an exact text + // selector. + ScopedExactTextMaxCharsOverride force_range_generation(4); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete(R"HTML( + <!DOCTYPE html> + <span id='foo'>foo</span> <span id='bar'>bar</span> + )HTML"); + Node* foo = GetDocument().getElementById("foo")->firstChild(); + Node* bar = GetDocument().getElementById("bar")->firstChild(); + const auto& selected_start = Position(foo, 0); + const auto& selected_end = Position(bar, 3); + ASSERT_EQ("foo bar", PlainText(EphemeralRange(selected_start, selected_end))); + + VerifySelector(selected_start, selected_end, "foo,bar"); +} + // When using all the selected text for the range is not enough for unique // match, context should be added, but only prefxi and no suffix is available. TEST_F(TextFragmentSelectorGeneratorTest, @@ -687,36 +739,27 @@ "text_text_text_text_text_text_text_text_and_last_text"); } -// When range start and end overlap for the first candidate it should return -// empty selector. +// The generator tries to include at least 3 words from the start and end of a +// range. This test ensures that the number of words used is reduced if there +// are fewer than 6 words in the selection, preventing the start and end +// overlaping. TEST_F(TextFragmentSelectorGeneratorTest, - RangeSelector_OverlapFailOnFirstAttenpt) { + RangeSelector_OverlapFailOnFirstAttempt) { + ScopedExactTextMaxCharsOverride force_range_generation(10); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( <!DOCTYPE html> <div>Test page</div> - <p id='first'>First paragraph text - with_a_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word - with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word - with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word - with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word - with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word - end of first paragraph</p> + <p id='first'>one two three four five</p> )HTML"); Node* first_paragraph = GetDocument().getElementById("first")->firstChild(); - const auto& selected_start = Position(first_paragraph, 23); - const auto& selected_end = Position(first_paragraph, 364); - ASSERT_EQ( - "with_a_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word \ -with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word \ -with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word \ -with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word \ -with_another_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_word", - PlainText(EphemeralRange(selected_start, selected_end))); + const auto& selected_start = Position(first_paragraph, 0); + const auto& selected_end = Position(first_paragraph, 23); + ASSERT_EQ("one two three four five", + PlainText(EphemeralRange(selected_start, selected_end))); - VerifySelectorFails(selected_start, selected_end, - LinkGenerationError::kNoRange); + VerifySelector(selected_start, selected_end, "one%20two,four%20five"); } // When range start and end overlap on second or later attempt it should stop
diff --git a/third_party/blink/renderer/core/inspector/inspector_media_agent.cc b/third_party/blink/renderer/core/inspector/inspector_media_agent.cc index 69b2b3be..409528e 100644 --- a/third_party/blink/renderer/core/inspector/inspector_media_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_media_agent.cc
@@ -29,15 +29,6 @@ } } -const char* ConvertErrorTypeEnum(InspectorPlayerError::Type level) { - switch (level) { - case InspectorPlayerError::Type::kPipelineError: - return protocol::Media::PlayerError::TypeEnum::Pipeline_error; - case InspectorPlayerError::Type::kMediaStatus: - return protocol::Media::PlayerError::TypeEnum::Media_error; - } -} - std::unique_ptr<protocol::Media::PlayerEvent> ConvertToProtocolType( const InspectorPlayerEvent& event) { return protocol::Media::PlayerEvent::create() @@ -62,11 +53,37 @@ .build(); } +std::unique_ptr<protocol::Media::PlayerErrorSourceLocation> +ConvertToProtocolType(const InspectorPlayerError::SourceLocation& stack) { + return protocol::Media::PlayerErrorSourceLocation::create() + .setFile(stack.filename) + .setLine(stack.line_number) + .build(); +} + std::unique_ptr<protocol::Media::PlayerError> ConvertToProtocolType( const InspectorPlayerError& error) { + auto caused_by = + std::make_unique<protocol::Array<protocol::Media::PlayerError>>(); + auto stack = std::make_unique< + protocol::Array<protocol::Media::PlayerErrorSourceLocation>>(); + auto data = protocol::DictionaryValue::create(); + + for (const InspectorPlayerError& cause : error.caused_by) + caused_by->push_back(ConvertToProtocolType(cause)); + + for (const InspectorPlayerError::Data& pair : error.data) + data->setString(pair.name, pair.value); + + for (const InspectorPlayerError::SourceLocation& pair : error.stack) + stack->push_back(ConvertToProtocolType(pair)); + return protocol::Media::PlayerError::create() - .setType(ConvertErrorTypeEnum(error.type)) - .setErrorCode(error.errorCode) + .setErrorType(error.group) + .setCode(error.code) + .setCause(std::move(caused_by)) + .setData(std::move(data)) + .setStack(std::move(stack)) .build(); }
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc index b2b7f82..a8f122f0 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
@@ -495,11 +495,6 @@ if (extensions->hasHmacCreateSecret()) { mojo_options->hmac_create_secret = extensions->hmacCreateSecret(); } -#if BUILDFLAG(IS_ANDROID) - if (extensions->hasUvm()) { - mojo_options->user_verification_methods = extensions->uvm(); - } -#endif if (extensions->hasCredentialProtectionPolicy()) { const auto& policy = extensions->credentialProtectionPolicy(); if (policy == "userVerificationOptional") {
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc index 5375e37..14de665 100644 --- a/third_party/blink/renderer/modules/mediastream/media_devices.cc +++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -667,11 +667,14 @@ } void MediaDevices::OnDispatcherHostConnectionError() { - for (ScriptPromiseResolver* resolver : requests_) { + // Move the set to a local variable to prevent script execution in Reject() + // from invalidating the iterator used by the loop. + HeapHashSet<Member<ScriptPromiseResolver>> requests; + requests_.swap(requests); + for (ScriptPromiseResolver* resolver : requests) { resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kAbortError, "enumerateDevices() failed.")); } - requests_.clear(); dispatcher_host_.reset(); if (connection_error_test_callback_)
diff --git a/third_party/blink/renderer/modules/webgpu/BUILD.gn b/third_party/blink/renderer/modules/webgpu/BUILD.gn index dcfece5..e7d4345b 100644 --- a/third_party/blink/renderer/modules/webgpu/BUILD.gn +++ b/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -83,6 +83,8 @@ "gpu_uncaptured_error_event.h", "gpu_validation_error.cc", "gpu_validation_error.h", + "texture_utils.cc", + "texture_utils.h", ] deps = [ "//gpu/command_buffer/client:webgpu_interface",
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc index 5fbf92e..1c97f25 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -28,6 +28,7 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_command_buffer.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device.h" #include "third_party/blink/renderer/modules/webgpu/gpu_texture.h" +#include "third_party/blink/renderer/modules/webgpu/texture_utils.h" #include "third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h" #include "third_party/blink/renderer/platform/graphics/graphics_types.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -408,8 +409,26 @@ } } - GetProcs().queueWriteTexture(GetHandle(), &dawn_destination, data, data_size, - &dawn_data_layout, &dawn_write_size); + if (dawn_data_layout.offset > data_size) { + device_->InjectError(WGPUErrorType_Validation, "Data offset is too large"); + return; + } + + WGPUTextureFormat format = destination->texture()->Format(); + size_t required_copy_size = 0; + if (!ComputeAndValidateRequiredBytesInCopy( + data_size, dawn_data_layout, dawn_write_size, format, + dawn_destination.aspect, &required_copy_size, device_)) { + return; + } + + // Only send the data which is really required. + const void* data_ptr = + static_cast<const uint8_t*>(data) + dawn_data_layout.offset; + dawn_data_layout.offset = 0; + GetProcs().queueWriteTexture(GetHandle(), &dawn_destination, data_ptr, + required_copy_size, &dawn_data_layout, + &dawn_write_size); EnsureFlush(); return; }
diff --git a/third_party/blink/renderer/modules/webgpu/texture_utils.cc b/third_party/blink/renderer/modules/webgpu/texture_utils.cc new file mode 100644 index 0000000..87cffc8c --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/texture_utils.cc
@@ -0,0 +1,281 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/webgpu/texture_utils.h" + +#include "third_party/blink/renderer/modules/webgpu/gpu_device.h" + +namespace blink { + +namespace { + +struct TexelBlockInfo { + uint32_t byteSize; + uint32_t width; + uint32_t height; +}; + +bool ValidateFormatAndAspectForCopy(WGPUTextureFormat format, + WGPUTextureAspect aspect) { + switch (format) { + // For depth/stencil formats, see the valid format and aspect combinations + // for copy at https://gpuweb.github.io/gpuweb/#depth-formats + case WGPUTextureFormat_Stencil8: + return aspect != WGPUTextureAspect_DepthOnly; + + case WGPUTextureFormat_Depth16Unorm: + return aspect != WGPUTextureAspect_StencilOnly; + + case WGPUTextureFormat_Depth24Plus: + // Depth32Float is not copyable when it is used as copy dst in WriteTexture + case WGPUTextureFormat_Depth32Float: + return false; + + case WGPUTextureFormat_Depth24PlusStencil8: + case WGPUTextureFormat_Depth24UnormStencil8: + // Depth aspect of Depth32FloatStencil8 is not copyable when it is used as + // copy dst in WriteTexture + case WGPUTextureFormat_Depth32FloatStencil8: + return aspect == WGPUTextureAspect_StencilOnly; + + // These formats are not copyable in WriteTexture + case WGPUTextureFormat_R8BG8Biplanar420Unorm: + case WGPUTextureFormat_Force32: + case WGPUTextureFormat_Undefined: + return false; + + default: + return aspect == WGPUTextureAspect_All; + } +} + +TexelBlockInfo GetTexelBlockInfoForCopy(WGPUTextureFormat format, + WGPUTextureAspect aspect) { + if (!ValidateFormatAndAspectForCopy(format, aspect)) { + return {0u, 0u, 0u}; + } + + switch (format) { + case WGPUTextureFormat_R8Unorm: + case WGPUTextureFormat_R8Snorm: + case WGPUTextureFormat_R8Uint: + case WGPUTextureFormat_R8Sint: + return {1u, 1u, 1u}; + + case WGPUTextureFormat_R16Uint: + case WGPUTextureFormat_R16Sint: + case WGPUTextureFormat_R16Float: + case WGPUTextureFormat_RG8Unorm: + case WGPUTextureFormat_RG8Snorm: + case WGPUTextureFormat_RG8Uint: + case WGPUTextureFormat_RG8Sint: + return {2u, 1u, 1u}; + + case WGPUTextureFormat_R32Float: + case WGPUTextureFormat_R32Uint: + case WGPUTextureFormat_R32Sint: + case WGPUTextureFormat_RG16Uint: + case WGPUTextureFormat_RG16Sint: + case WGPUTextureFormat_RG16Float: + case WGPUTextureFormat_RGBA8Unorm: + case WGPUTextureFormat_RGBA8UnormSrgb: + case WGPUTextureFormat_RGBA8Snorm: + case WGPUTextureFormat_RGBA8Uint: + case WGPUTextureFormat_RGBA8Sint: + case WGPUTextureFormat_BGRA8Unorm: + case WGPUTextureFormat_BGRA8UnormSrgb: + case WGPUTextureFormat_RGB10A2Unorm: + case WGPUTextureFormat_RG11B10Ufloat: + case WGPUTextureFormat_RGB9E5Ufloat: + return {4u, 1u, 1u}; + + case WGPUTextureFormat_RG32Float: + case WGPUTextureFormat_RG32Uint: + case WGPUTextureFormat_RG32Sint: + case WGPUTextureFormat_RGBA16Uint: + case WGPUTextureFormat_RGBA16Sint: + case WGPUTextureFormat_RGBA16Float: + return {8u, 1u, 1u}; + + case WGPUTextureFormat_RGBA32Float: + case WGPUTextureFormat_RGBA32Uint: + case WGPUTextureFormat_RGBA32Sint: + return {16u, 1u, 1u}; + + case WGPUTextureFormat_Stencil8: + return {1u, 1u, 1u}; + + case WGPUTextureFormat_Depth16Unorm: + return {2u, 1u, 1u}; + + // Only stencil aspect is valid for WriteTexture + case WGPUTextureFormat_Depth24UnormStencil8: + case WGPUTextureFormat_Depth24PlusStencil8: + case WGPUTextureFormat_Depth32FloatStencil8: + return {1u, 1u, 1u}; + + case WGPUTextureFormat_BC1RGBAUnorm: + case WGPUTextureFormat_BC1RGBAUnormSrgb: + case WGPUTextureFormat_BC4RUnorm: + case WGPUTextureFormat_BC4RSnorm: + return {8u, 4u, 4u}; + + case WGPUTextureFormat_BC2RGBAUnorm: + case WGPUTextureFormat_BC2RGBAUnormSrgb: + case WGPUTextureFormat_BC3RGBAUnorm: + case WGPUTextureFormat_BC3RGBAUnormSrgb: + case WGPUTextureFormat_BC5RGUnorm: + case WGPUTextureFormat_BC5RGSnorm: + case WGPUTextureFormat_BC6HRGBUfloat: + case WGPUTextureFormat_BC6HRGBFloat: + case WGPUTextureFormat_BC7RGBAUnorm: + case WGPUTextureFormat_BC7RGBAUnormSrgb: + return {16u, 4u, 4u}; + + case WGPUTextureFormat_ETC2RGB8Unorm: + case WGPUTextureFormat_ETC2RGB8UnormSrgb: + case WGPUTextureFormat_ETC2RGB8A1Unorm: + case WGPUTextureFormat_ETC2RGB8A1UnormSrgb: + case WGPUTextureFormat_EACR11Unorm: + case WGPUTextureFormat_EACR11Snorm: + return {8u, 4u, 4u}; + + case WGPUTextureFormat_ETC2RGBA8Unorm: + case WGPUTextureFormat_ETC2RGBA8UnormSrgb: + case WGPUTextureFormat_EACRG11Unorm: + case WGPUTextureFormat_EACRG11Snorm: + return {16u, 4u, 4u}; + + case WGPUTextureFormat_ASTC4x4Unorm: + case WGPUTextureFormat_ASTC4x4UnormSrgb: + return {16u, 4u, 4u}; + case WGPUTextureFormat_ASTC5x4Unorm: + case WGPUTextureFormat_ASTC5x4UnormSrgb: + return {16u, 5u, 4u}; + case WGPUTextureFormat_ASTC5x5Unorm: + case WGPUTextureFormat_ASTC5x5UnormSrgb: + return {16u, 5u, 5u}; + case WGPUTextureFormat_ASTC6x5Unorm: + case WGPUTextureFormat_ASTC6x5UnormSrgb: + return {16u, 6u, 5u}; + case WGPUTextureFormat_ASTC6x6Unorm: + case WGPUTextureFormat_ASTC6x6UnormSrgb: + return {16u, 6u, 6u}; + case WGPUTextureFormat_ASTC8x5Unorm: + case WGPUTextureFormat_ASTC8x5UnormSrgb: + return {16u, 8u, 5u}; + case WGPUTextureFormat_ASTC8x6Unorm: + case WGPUTextureFormat_ASTC8x6UnormSrgb: + return {16u, 8u, 6u}; + case WGPUTextureFormat_ASTC8x8Unorm: + case WGPUTextureFormat_ASTC8x8UnormSrgb: + return {16u, 8u, 8u}; + case WGPUTextureFormat_ASTC10x5Unorm: + case WGPUTextureFormat_ASTC10x5UnormSrgb: + return {16u, 10u, 5u}; + case WGPUTextureFormat_ASTC10x6Unorm: + case WGPUTextureFormat_ASTC10x6UnormSrgb: + return {16u, 10u, 6u}; + case WGPUTextureFormat_ASTC10x8Unorm: + case WGPUTextureFormat_ASTC10x8UnormSrgb: + return {16u, 10u, 8u}; + case WGPUTextureFormat_ASTC10x10Unorm: + case WGPUTextureFormat_ASTC10x10UnormSrgb: + return {16u, 10u, 10u}; + case WGPUTextureFormat_ASTC12x10Unorm: + case WGPUTextureFormat_ASTC12x10UnormSrgb: + return {16u, 12u, 10u}; + case WGPUTextureFormat_ASTC12x12Unorm: + case WGPUTextureFormat_ASTC12x12UnormSrgb: + return {16u, 12u, 12u}; + + default: + NOTREACHED(); + return {0u, 0u, 0u}; + } +} + +} // anonymous namespace + +bool ComputeAndValidateRequiredBytesInCopy(size_t data_size, + WGPUTextureDataLayout layout, + WGPUExtent3D extent, + WGPUTextureFormat format, + WGPUTextureAspect aspect, + size_t* required_copy_size, + GPUDevice* device) { + TexelBlockInfo blockInfo = GetTexelBlockInfoForCopy(format, aspect); + if (!blockInfo.byteSize) { + device->InjectError( + WGPUErrorType_Validation, + "Format, aspect or the combination are not valid for WriteTexture"); + return false; + } + + uint32_t widthInBlocks = extent.width / blockInfo.width; + uint32_t heightInBlocks = extent.height / blockInfo.height; + size_t lastRowBytes = widthInBlocks * blockInfo.byteSize; + + if (layout.bytesPerRow == WGPU_STRIDE_UNDEFINED && + (heightInBlocks > 1 || extent.depthOrArrayLayers > 1)) { + device->InjectError(WGPUErrorType_Validation, + "bytesPerRow must be specified"); + return false; + } + + if (layout.rowsPerImage == WGPU_STRIDE_UNDEFINED && + extent.depthOrArrayLayers > 1) { + device->InjectError(WGPUErrorType_Validation, + "rowsPerImage must be specified"); + return false; + } + + if (layout.bytesPerRow < lastRowBytes) { + device->InjectError(WGPUErrorType_Validation, + "bytesPerRow in image data layout is too small"); + return false; + } + + if (layout.rowsPerImage < heightInBlocks) { + device->InjectError(WGPUErrorType_Validation, + "rowsPerImage in image data layout is too small"); + return false; + } + + if (extent.depthOrArrayLayers == 0) { + *required_copy_size = 0; + return true; + } + + base::CheckedNumeric<size_t> requiredBytesInCopy = 0; + if (extent.depthOrArrayLayers > 1) { + requiredBytesInCopy = layout.bytesPerRow; + requiredBytesInCopy *= layout.rowsPerImage; + requiredBytesInCopy *= (extent.depthOrArrayLayers - 1); + } + if (heightInBlocks != 0) { + size_t lastImageBytes = + layout.bytesPerRow * (heightInBlocks - 1) + lastRowBytes; + requiredBytesInCopy += lastImageBytes; + } + + if (!requiredBytesInCopy.IsValid()) { + device->InjectError(WGPUErrorType_Validation, + "Required copy size overflows"); + return false; + } + + *required_copy_size = requiredBytesInCopy.ValueOrDie(); + DCHECK(data_size >= layout.offset); + if (*required_copy_size > data_size - layout.offset) { + device->InjectError( + WGPUErrorType_Validation, + "Required copy size for texture layout exceed data size with offset"); + return false; + } + + return true; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/texture_utils.h b/third_party/blink/renderer/modules/webgpu/texture_utils.h new file mode 100644 index 0000000..a2a6262 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/texture_utils.h
@@ -0,0 +1,22 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_TEXTURE_UTILS_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_TEXTURE_UTILS_H_ + +#include "third_party/blink/renderer/modules/webgpu/dawn_object.h" + +namespace blink { + +bool ComputeAndValidateRequiredBytesInCopy(size_t data_size, + WGPUTextureDataLayout layout, + WGPUExtent3D extent, + WGPUTextureFormat format, + WGPUTextureAspect aspect, + size_t* required_copy_size, + GPUDevice* device); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_TEXTURE_UTILS_H_
diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc index d06bcad..429117a6 100644 --- a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
@@ -994,7 +994,7 @@ // https://bugs.chromium.org/p/libyuv/issues/detail?id=845 media::PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( frame.get(), rgba_8888, frame->visible_rect().width() * 4, - premultiply_alpha); + premultiply_alpha, media::PaintCanvasVideoRenderer::kFilterBilinear); return true; }
diff --git a/third_party/blink/renderer/platform/weborigin/security_policy.cc b/third_party/blink/renderer/platform/weborigin/security_policy.cc index e0527ec9..458bb1b 100644 --- a/third_party/blink/renderer/platform/weborigin/security_policy.cc +++ b/third_party/blink/renderer/platform/weborigin/security_policy.cc
@@ -88,9 +88,10 @@ const String& referrer) { network::mojom::ReferrerPolicy referrer_policy_no_default = ReferrerUtils::MojoReferrerPolicyResolveDefault(referrer_policy); - if (referrer == Referrer::NoReferrer()) + // Empty (a possible input) and default (the value of `Referrer::NoReferrer`) + // strings are not equivalent. + if (referrer == Referrer::NoReferrer() || referrer.IsEmpty()) return Referrer(Referrer::NoReferrer(), referrer_policy_no_default); - DCHECK(!referrer.IsEmpty()); KURL referrer_url = KURL(NullURL(), referrer).UrlStrippedForUseAsReferrer();
diff --git a/third_party/blink/renderer/platform/weborigin/security_policy_test.cc b/third_party/blink/renderer/platform/weborigin/security_policy_test.cc index bf0c744..99cb76ac 100644 --- a/third_party/blink/renderer/platform/weborigin/security_policy_test.cc +++ b/third_party/blink/renderer/platform/weborigin/security_policy_test.cc
@@ -107,6 +107,7 @@ "blob:http://a.test/b3aae9c8-7f90-440d-8d7c-43aa20d72fde"; const char kFilesystemURL[] = "filesystem:http://a.test/path/t/file.html"; const char kInvalidURL[] = "not-a-valid-url"; + const char kEmptyURL[] = ""; bool reduced_granularity = base::FeatureList::IsEnabled(features::kReducedReferrerGranularity); @@ -249,6 +250,8 @@ kInsecureURLA}, {network::mojom::ReferrerPolicy::kAlways, kInvalidURL, kInsecureURLA, nullptr}, + {network::mojom::ReferrerPolicy::kAlways, kEmptyURL, kInsecureURLA, + nullptr}, }; for (TestCase test : inputs) {
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index bd5a66e..f8e3787 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -1224,7 +1224,6 @@ crbug.com/1035582 fast/hidpi/scrollbar-appearance-increase-device-scale-factor.html [ Failure ] crbug.com/1035582 paint/invalidation/overflow/float-overflow-right.html [ Failure ] crbug.com/1035582 virtual/prefer_compositing_to_lcd_text/scrollbars/listbox-scrollbar-combinations.html [ Failure ] -crbug.com/1035582 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance.html [ Failure Timeout ] crbug.com/1035582 virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Failure Timeout ] crbug.com/1035582 http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js [ Failure Timeout ] crbug.com/1035582 paint/invalidation/forms/checkbox-focus-by-mouse-then-keydown.html [ Failure ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index ab0bb1f..a95b270 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -1771,7 +1771,6 @@ [ Linux ] virtual/scalefactor150/fast/hidpi/static/* [ Pass ] [ Win ] virtual/scalefactor150/fast/hidpi/static/* [ Pass ] virtual/scalefactor200/fast/hidpi/static/* [ Pass ] -virtual/scalefactor200withzoom/fast/hidpi/static/* [ Pass ] # Memory measurement tests are run as virtual tests. external/wpt/measure-memory/* [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index b57813d3..f29cee1 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2105,13 +2105,9 @@ crbug.com/326139 crbug.com/390125 media/video-frame-accurate-seek.html [ Failure Pass ] crbug.com/421283 html/marquee/marquee-scrollamount.html [ Failure Pass ] -# TODO(oshima): Mac is currently not supported. -crbug.com/567837 [ Mac ] virtual/scalefactor200withzoom/fast/hidpi/static/* [ Skip ] - # TODO(oshima): Move the event scaling code to eventSender and remove this. crbug.com/567837 virtual/scalefactor200/fast/hidpi/static/gesture-scroll-amount.html [ Failure Timeout ] crbug.com/567837 virtual/scalefactor200/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure Timeout ] -crbug.com/567837 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure Timeout ] crbug.com/567837 [ Linux ] virtual/scalefactor150/fast/hidpi/static/mousewheel-scroll-amount.html [ Failure Timeout ] crbug.com/567837 [ Win ] virtual/scalefactor150/fast/hidpi/static/mousewheel-scroll-amount.html [ Failure Timeout ] crbug.com/567837 [ Linux ] virtual/scalefactor150/fast/hidpi/static/gesture-scroll-amount.html [ Failure Timeout ] @@ -2804,9 +2800,6 @@ crbug.com/1298321 fast/forms/calendar-picker/date-picker-appearance-zoom150.html [ Failure Pass Timeout ] crbug.com/1298321 fast/forms/select-popup/popup-menu-appearance-zoom.html [ Failure Pass Timeout ] crbug.com/1298321 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom200.html [ Failure Pass Timeout ] -crbug.com/1298321 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass Timeout ] -crbug.com/1298321 virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance.html [ Failure Pass Timeout ] -crbug.com/1298321 virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure Pass Timeout ] crbug.com/1298321 virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ Failure Pass Timeout ] crbug.com/1298321 virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure Pass Timeout ] crbug.com/1298321 virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 313b46c5..943d157 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -224,7 +224,6 @@ "bases": ["external/wpt/css/css-backgrounds/hidpi", "external/wpt/css/css-paint-api/hidpi"], "args": ["--force-device-scale-factor=2", - "--enable-use-zoom-for-dsf=false", "--enable-threaded-compositing"] }, { @@ -256,14 +255,6 @@ "args": ["--force-device-scale-factor=1.5"] }, { - "prefix": "scalefactor200withzoom", - "platforms": ["Linux", "Mac", "Win"], - "bases": ["fast/hidpi/static", - "inspector-protocol/page/get-layout-metrics-css.js"], - "args": ["--force-device-scale-factor=2", - "--enable-use-zoom-for-dsf"] - }, - { "prefix": "schemeful-same-site", "platforms": ["Linux", "Mac", "Win"], "bases": ["external/wpt/cookies"], @@ -370,16 +361,6 @@ "--force-device-scale-factor=2"] }, { - "prefix": "compositor-threaded-percent-based-scrolling-dsf-2-highdpi", - "platforms": ["Linux", "Mac", "Win"], - "bases": ["virtual/percent-based-scrolling"], - "args": ["--enable-features=PercentBasedScrolling", - "--enable-threaded-compositing", - "--enable-prefer-compositing-to-lcd-text", - "--force-device-scale-factor=2", - "--enable-use-zoom-for-dsf=false"] - }, - { "prefix": "smooth_compositor_threaded_scrollbar_scrolling", "platforms": ["Linux", "Mac", "Win"], "bases": ["fast/scrolling/scrollbars/scroll-chaining-for-gesture-based-scrolling.html"],
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index e30a04cd..2be11d31 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: 505182e838025407ddf849bf9d27240351c6b938 +Version: 4e535d84cbd58e22b0c953d894c8a3c56a30f483
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 908c3b0d..9274938b 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -232181,10 +232181,14 @@ "997c5a2b72bafcad3421ccb48e48e323de6ef6f0", [] ], - "idb-partitioned-iframe.tentative.html": [ + "idb-partitioned-basic-iframe.tentative.html": [ "ed6bbf272f0af4609e77afa7679ec5f0d677e100", [] ], + "idb-partitioned-persistence-iframe.tentative.html": [ + "ad6869f945a44a5f9d13a3ba0bee2cba7c3d0cf1", + [] + ], "idbfactory-origin-isolation-iframe.html": [ "d405ea48e15e298241a2c400a6d04adbd054e1e5", [] @@ -288566,7 +288570,7 @@ [] ], "font-test-utils.js": [ - "84dade8d4b7baa0c07be2aca1cd7c1af6b9bac79", + "1a5f3859e7d0b7ab31bc81621840c79478f27abe", [] ] } @@ -294019,6 +294023,10 @@ "8df98474b589d070992677cb0134bd47bd0509c4", [] ], + "require-corp-revalidated-images.https-expected.txt": [ + "4c2cceb4fa6ae2dca4db5db31ef072d4321bd901", + [] + ], "require-corp-sw-from-require-corp.https.html.headers": [ "8df98474b589d070992677cb0134bd47bd0509c4", [] @@ -294049,7 +294057,7 @@ [] ], "corp-image.py": [ - "29689c45d6ad6f6cc5f020790dfb0f5455ffaca7", + "e507846181d980fe045028b0aacd9e31600b3b89", [] ], "cross-origin-isolated-frame.html": [ @@ -294081,7 +294089,7 @@ [] ], "load-corp-images.html": [ - "1251b8c470763d4410349892e09325025627a184", + "288610046e61c6bb09a2eb25e01013081c0e5ea0", [] ], "load-corp-images.html.headers": [ @@ -331147,7 +331155,7 @@ ] ], "url-format.any.js": [ - "33732fa61fc3ddd0f52b23fe83ea824cc6abae06", + "69c51113e6b99b0a1575b9373aa2a2482779638d", [ "FileAPI/url/url-format.any.html", { @@ -331659,7 +331667,14 @@ ] ], "idb-partitioned-basic.tentative.sub.html": [ - "326d1f4d3d5d38057c5a903526dca843eaf8ac9b", + "16bdacf6c6d9713c2765ee25b637deff869ede5f", + [ + null, + {} + ] + ], + "idb-partitioned-persistence.tentative.sub.html": [ + "54f76f517d172ef1f739ff9dc5d78d3a1fc03b21", [ null, {} @@ -387967,7 +387982,7 @@ ] ], "Screen-pixelDepth-Screen-colorDepth001.html": [ - "2a8d5b5b4928a5782a61174834bb547f094f2553", + "f394560ff1332b778258eeeb9c4bdc231dfbae57", [ null, {} @@ -388058,7 +388073,7 @@ ] ], "cssom-view-window-screen-interface.html": [ - "29802ac7129a95c8d20091b279d3a32bbf58943e", + "f4d33130027e2a3b63290ec1f0a678c2e8e4c2da", [ null, {} @@ -423695,7 +423710,7 @@ ] ], "font_access_permission.tentative.https.window.js": [ - "6826f102743f013a0d6a156fe715c52ebf453825", + "db395c242602652b94d6bed250c2ad280ccbf210", [ "font-access/font_access_permission.tentative.https.window.html", { @@ -449619,7 +449634,7 @@ ] ], "require-corp-cached-images.https.html": [ - "f5eaddbdd15a8a4fae4d17195eb6d40fc1b7eacd", + "269698bc1ab208226edaa4276a3e0d6ffbd66dd2", [ null, {} @@ -449632,6 +449647,13 @@ {} ] ], + "require-corp-revalidated-images.https.html": [ + "420190aad359e3127b1cc0f394832842511c99ae", + [ + null, + {} + ] + ], "require-corp-sw-from-none.https.html": [ "a60b8bd457ea0af21c882bf37f0f107c1065026e", [
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html index 2a8d5b5b..f394560 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html
@@ -11,14 +11,16 @@ </head> <body> <p>This case tests the Screen pixelDepth and colorDepth</p> - <p>The test passes if the value is 24</p> + <p>The test passes if the value is either 24 or 30</p> <div id="log"></div> <script> test(function(){ - assert_equals(testColorDepth(), 24, "Expected value for colorDepth is 24"); + let colorDepth = testColorDepth(); + assert_true(colorDepth == 24 || colorDepth == 30, "Expected value for colorDepth is either 24 or 30"); },'testColorDepth'); test(function(){ - assert_equals(testPixelDepth(), 24, "Expected value for pixelDepth is 24"); + let pixelDepth = testPixelDepth(); + assert_true(pixelDepth == 24 || pixelDepth == 30, "Expected value for pixelDepth is either 24 or 30"); },'testPixelDepth'); function testColorDepth(){ var colorDepth = window.screen.colorDepth;
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/cssom-view-window-screen-interface.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/cssom-view-window-screen-interface.html index 29802ac7..f4d33130 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom-view/cssom-view-window-screen-interface.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/cssom-view-window-screen-interface.html
@@ -21,8 +21,8 @@ "window.screen.availWidth >= 0 && window.screen.availWidth <= window.screen.width"); test(function(){assert_true(window.screen.availHeight >= 0 && window.screen.availHeight <= window.screen.height);}, "window.screen.availHeight >= 0 && window.screen.availHeight <= window.screen.height"); - test(function(){assert_in_array(window.screen.colorDepth, [0, 16, 24, 32]);}, - "window.screen.colorDepth == 0 || window.screen.colorDepth == 16 || window.screen.colorDepth == 24 || window.screen.colorDepth == 32"); + test(function(){assert_in_array(window.screen.colorDepth, [0, 16, 24, 30, 32]);}, + "window.screen.colorDepth == 0 || window.screen.colorDepth == 16 || window.screen.colorDepth == 24 || window.screen.colorDepth == 30 || window.screen.colorDepth == 32"); test(function(){assert_equals(window.screen.pixelDepth, window.screen.colorDepth);}, "window.screen.pixelDepth must return the value returned by window.screen.colorDepth"); </script>
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/blink/web_tests/flag-specific/highdpi/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index 7522161..0000000 --- a/third_party/blink/web_tests/flag-specific/highdpi/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/virtual/scalefactor200withzoom/inspector-protocol/page/get-layout-metrics-css-expected.txt b/third_party/blink/web_tests/flag-specific/highdpi/virtual/scalefactor200withzoom/inspector-protocol/page/get-layout-metrics-css-expected.txt deleted file mode 100644 index 33a45a2..0000000 --- a/third_party/blink/web_tests/flag-specific/highdpi/virtual/scalefactor200withzoom/inspector-protocol/page/get-layout-metrics-css-expected.txt +++ /dev/null
@@ -1,94 +0,0 @@ -Tests that Page.getLayoutMetrics returns reasonable values. -# initial metrics -cssLayoutViewport{ - clientHeight : 585 - clientWidth : 785 - pageX : 0 - pageY : 0 -} -cssContentSize{ - height : 10016 - width : 10008 - x : 0 - y : 0 -} -cssVisualViewport{ - clientHeight : 585 - clientWidth : 785 - offsetX : 0 - offsetY : 0 - pageX : 0 - pageY : 0 - scale : 1 - zoom : 1 -} -# scroll (100, 100) -cssLayoutViewport{ - clientHeight : 585 - clientWidth : 785 - pageX : 100 - pageY : 100 -} -cssContentSize{ - height : 10016 - width : 10008 - x : 0 - y : 0 -} -cssVisualViewport{ - clientHeight : 585 - clientWidth : 785 - offsetX : 0 - offsetY : 0 - pageX : 100 - pageY : 100 - scale : 1 - zoom : 1 -} -# internals.setPageScaleFactor(2) -cssLayoutViewport{ - clientHeight : 285 - clientWidth : 385 - pageX : 100 - pageY : 100 -} -cssContentSize{ - height : 10016 - width : 10008 - x : 0 - y : 0 -} -cssVisualViewport{ - clientHeight : 292.5 - clientWidth : 392.5 - offsetX : 0 - offsetY : 0 - pageX : 100 - pageY : 100 - scale : 2 - zoom : 1 -} -# internals.setPageScaleFactor(0.5) -cssLayoutViewport{ - clientHeight : 1185 - clientWidth : 1585 - pageX : 100 - pageY : 100 -} -cssContentSize{ - height : 10016 - width : 10008 - x : 0 - y : 0 -} -cssVisualViewport{ - clientHeight : 1170 - clientWidth : 1570 - offsetX : 0 - offsetY : 0 - pageX : 100 - pageY : 100 - scale : 0.5 - zoom : 1 -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.png deleted file mode 100644 index 62786715..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.png deleted file mode 100644 index 547c2c66..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.txt deleted file mode 100644 index cb9b046..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -CONSOLE ERROR: Uncaught ReferenceError: test_driver is not defined -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index 23ae6c87..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance-expected.png deleted file mode 100644 index 46f6bfa..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png deleted file mode 100644 index ada90607..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/platform/mac/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png deleted file mode 100644 index b8b5e15..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.png deleted file mode 100644 index b160a38..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.txt b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.txt deleted file mode 100644 index cb9b046..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -CONSOLE ERROR: Uncaught ReferenceError: test_driver is not defined -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.txt b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.txt deleted file mode 100644 index 43e5eeed..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/drag-image-expected.png b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/drag-image-expected.png deleted file mode 100644 index b1695d03..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/drag-image-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/drag-image-expected.txt b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/drag-image-expected.txt deleted file mode 100644 index 8b13789..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/drag-image-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index d199b841..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance-expected.png deleted file mode 100644 index d3e562e3..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png deleted file mode 100644 index dd9fc52..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/platform/win7/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png deleted file mode 100644 index c19eea8..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/compositor-threaded-percent-based-scrolling-dsf-2-highdpi/README.md b/third_party/blink/web_tests/virtual/compositor-threaded-percent-based-scrolling-dsf-2-highdpi/README.md deleted file mode 100644 index 0764cec2b..0000000 --- a/third_party/blink/web_tests/virtual/compositor-threaded-percent-based-scrolling-dsf-2-highdpi/README.md +++ /dev/null
@@ -1,3 +0,0 @@ -This directory is dedicated for testing the "Percent based scrolling" feature -on the compositor thread when the device scale factor is 2 and use-zoom-for-dsf -disabled.
diff --git a/third_party/blink/web_tests/virtual/scalefactor200withzoom/fast/hidpi/static/README.txt b/third_party/blink/web_tests/virtual/scalefactor200withzoom/fast/hidpi/static/README.txt deleted file mode 100644 index 4727b98..0000000 --- a/third_party/blink/web_tests/virtual/scalefactor200withzoom/fast/hidpi/static/README.txt +++ /dev/null
@@ -1,4 +0,0 @@ -# This suite runs the tests in fast/hidpi/static with -# --force-device-scale-factor=2, --enable-use-zoom-for-dsf -# TODO(oshima): Remove this virtual test when all platforms are migrated -# to use zoom for dsf.
diff --git a/third_party/blink/web_tests/virtual/scalefactor200withzoom/inspector-protocol/page/README.txt b/third_party/blink/web_tests/virtual/scalefactor200withzoom/inspector-protocol/page/README.txt deleted file mode 100644 index f0bdb3f..0000000 --- a/third_party/blink/web_tests/virtual/scalefactor200withzoom/inspector-protocol/page/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -# This suite runs the test `http/tests/inspector-protocol/page/page-getLayoutMetrics.js` with -# --force-device-scale-factor=2, --enable-use-zoom-for-dsf
diff --git a/third_party/blink/web_tests/virtual/scalefactor200withzoom/resize-observer/hidpi/README.txt b/third_party/blink/web_tests/virtual/scalefactor200withzoom/resize-observer/hidpi/README.txt deleted file mode 100644 index b40118bd..0000000 --- a/third_party/blink/web_tests/virtual/scalefactor200withzoom/resize-observer/hidpi/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -# This suite contains resize observer tests run -# with the flags --force-device-scale-factor=2
diff --git a/third_party/blink/web_tests/virtual/scalefactor200withzoom/resize-observer/hidpi/device-pixel-hidpi.html b/third_party/blink/web_tests/virtual/scalefactor200withzoom/resize-observer/hidpi/device-pixel-hidpi.html deleted file mode 100644 index 9bb467b..0000000 --- a/third_party/blink/web_tests/virtual/scalefactor200withzoom/resize-observer/hidpi/device-pixel-hidpi.html +++ /dev/null
@@ -1,52 +0,0 @@ -<!doctype HTML> -<script src="../../../../resources/testharness.js"></script> -<script src="../../../../resources/testharnessreport.js"></script> -<script src="../../../../resize-observer/resources/resizeTestHelper.js"></script> -<body> - <svg height="430" width="500" > - <rect x="0" y="380" width="10.5" height="10" style="fill:orange; stroke:black; stroke-width:1" /> - </svg> -</body> - -<script> -'use strict'; - -function test() { - let t = document.querySelector('rect'); - let helper = new ResizeTestHelper( - "An observation is fired for an svg rect when device-pixel-content-box is being " + - "observed and device scale factor is 2", - [ - { - setup: observer => { - observer.observe(t, {box: "device-pixel-content-box"}); - }, - notify: entries => { - assert_equals(entries.length, 1, "1 pending notification"); - assert_equals(entries[0].target, t, "target is t"); - assert_equals(entries[0].contentRect.width, 10.5, "target width"); - assert_equals(entries[0].contentRect.height, 10, "target height"); - assert_equals(entries[0].contentBoxSize[0].inlineSize, 10.5, - "target content-box inline size"); - assert_equals(entries[0].contentBoxSize[0].blockSize,10, - "target content-box block size"); - assert_equals(entries[0].borderBoxSize[0].inlineSize, 10.5, - "target border-box inline size"); - assert_equals(entries[0].borderBoxSize[0].blockSize, 10, - "target border-box block size"); - assert_equals(entries[0].devicePixelContentBoxSize[0].inlineSize, 21, - "target device-pixel-content-box inline size"); - assert_equals(entries[0].devicePixelContentBoxSize[0].blockSize, 20, - "target device-pixel-content-box block size"); - } - } - ]); - - return helper.start(() => t.remove()); -} - - -test(); - - -</script>
diff --git a/third_party/blink/web_tests/wpt_internal/shared_storage/run-url-selection-operation.https.html b/third_party/blink/web_tests/wpt_internal/shared_storage/run-url-selection-operation.https.html index 8a105b8..733d28fe 100644 --- a/third_party/blink/web_tests/wpt_internal/shared_storage/run-url-selection-operation.https.html +++ b/third_party/blink/web_tests/wpt_internal/shared_storage/run-url-selection-operation.https.html
@@ -34,16 +34,8 @@ "test-url-selection-operation", [url0, url1], {data: {'mockResult': -1}}); assert_true(uuid2.startsWith('urn:uuid:')); attachFencedFrame(uuid2); - - // There is no API to observe load failure in the FencedFrame. Thus, set up - // a timeout. If the document loads, "loaded" will be sent to the server from - // the FencedFrame. Otherwise "failed-to-load" will be sent after 3 seconds. - step_timeout(() => { - writeValueToServer(ancestor_key, "failed_to_load"); - }, 3000); - const result2 = await nextValueFromServer(ancestor_key); - assert_equals(result2, "failed_to_load"); + assert_equals(result2, "frame0_loaded"); }, 'runURLSelectionOperation'); </script>
diff --git a/tools/licenses.py b/tools/licenses.py index 53125aa5..f893533 100755 --- a/tools/licenses.py +++ b/tools/licenses.py
@@ -327,6 +327,13 @@ "License Android Compatible": "yes", "License File": "/third_party/swiftshader/LICENSE.txt", }, + os.path.join('third_party', 'swiftshader', 'third_party', 'SPIRV-Tools'): { + "Name": "SPIRV-Tools", + "URL": "https://github.com/KhronosGroup/SPIRV-Tools", + "License": "Apache 2.0", + "License File": + "/third_party/swiftshader/third_party/SPIRV-Tools/LICENSE", + }, } # Special value for 'License File' field used to indicate that the license file
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b694573..d959489 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2196,23 +2196,6 @@ <int value="257" label="GATT_FAILURE"/> </enum> -<enum name="AndroidHomepagePromoAction"> - <int value="0" label="Promo created"> - The Android Homepage promo was created on the new tab page. - </int> - <int value="1" label="Promo shown">The Android homepage promo was shown.</int> - <int value="2" label="Promo dismissed"> - User dismissed the homepage promo. - </int> - <int value="3" label="Promo accepted"> - User changed their homepage by accepting the promo. - </int> - <int value="4" label="Promo change undo"> - User changed their homepage by accepting the promo, but then undid the - change through snackbar. - </int> -</enum> - <enum name="AndroidIntentNonSafelistedHeaderNameHashes"> <int value="4229679564" label="user-agent"/> </enum> @@ -80119,6 +80102,7 @@ <int value="395" label="WEBLOC"/> <int value="396" label="XSD"/> <int value="397" label="AVIF"/> + <int value="398" label="INETLOC"/> </enum> <enum name="SBClientDownloadIsSignedBinary"> @@ -81035,6 +81019,9 @@ <int value="9" label="Invalid selection result found in prefs"/> <int value="10" label="Database initialization failed"/> <int value="11" label="At least one segment is not available"/> + <int value="12" label="At least one segment does not have default signals"/> + <int value="13" label="At least one segment default model execution failed"/> + <int value="14" label="At least one segment default model missing metadata"/> </enum> <enum name="SelectedNewTabCreationOption">
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml index 6895b6ad..ce616ad 100644 --- a/tools/metrics/histograms/metadata/arc/histograms.xml +++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -969,9 +969,9 @@ </histogram> <histogram name="Arc.ImageCopyPasteCompatOperationType" - enum="ArcImageCopyPasteCompatOperationType" expires_after="2022-04-01"> - <owner>tetsui@chromium.org</owner> + enum="ArcImageCopyPasteCompatOperationType" expires_after="2022-10-01"> <owner>yhanada@chromium.org</owner> + <owner>arc-framework@google.com</owner> <summary> The operation type (copy-paste or drag-drop) and the source of the image (from browser or Files app), counted when image copy-paste app compat is @@ -986,9 +986,9 @@ </summary> </histogram> -<histogram name="Arc.ImeCount" units="units" expires_after="2022-04-01"> +<histogram name="Arc.ImeCount" units="units" expires_after="2022-10-01"> <owner>yhanada@chromium.org</owner> - <owner>tetsui@chromium.org</owner> + <owner>arc-framework@chromium.org</owner> <summary> The number of IME apps installed. Collected at startup and when an IME app is installed or uninstalled.
diff --git a/tools/metrics/histograms/metadata/nearby/histograms.xml b/tools/metrics/histograms/metadata/nearby/histograms.xml index 24bb35fd..61055a4 100644 --- a/tools/metrics/histograms/metadata/nearby/histograms.xml +++ b/tools/metrics/histograms/metadata/nearby/histograms.xml
@@ -1194,6 +1194,19 @@ </summary> </histogram> +<histogram name="Nearby.Share.WifiNetworkConfiguration.Result" + enum="BooleanSuccess" expires_after="2023-02-01"> + <owner>crisrael@google.com</owner> + <owner>nearby-share-chromeos-eng@google.com</owner> + <summary> + Records the success/failure of the Wi-Fi Network Configuration Handler. When + Wi-Fi credentials are successfully received, the Configuration Handler will + attempt to configure that network automatically. Emitted immediately after + the transfer has completed and the Configuration Handler attempted to + configure the network. + </summary> +</histogram> + </histograms> </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml index 59206dd..61401eb 100644 --- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml +++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -257,6 +257,20 @@ </histogram> <histogram + name="SegmentationPlatform.ModelExecution.DefaultProvider.Status.{SegmentationModel}" + enum="SegmentationPlatformModelExecutionStatus" expires_after="2022-08-01"> + <owner>nyquist@chromium.org</owner> + <owner>shaktisahu@chromium.org</owner> + <owner>chrome-segmentation-platform@google.com</owner> + <summary> + Records the execution status after executing the {SegmentationModel} + segmentation model with default provider. Recorded every time a default + provider for {SegmentationModel} is executed. + </summary> + <token key="SegmentationModel" variants="SegmentationModel"/> +</histogram> + +<histogram name="SegmentationPlatform.ModelExecution.Duration.FeatureProcessing.{SegmentationModel}" units="ms" expires_after="2022-08-01"> <owner>nyquist@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 0d1dc6c1..24e10b80 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "e83825f7eb252fa86e2a07f9f4a2f1b1e980ecee", - "remote_path": "perfetto_binaries/trace_processor_shell/win/0c2a0d0a169256990c11edeaf23c477693472df4/trace_processor_shell.exe" + "hash": "ace34d3ad83d174b06d87c113b864005ad955612", + "remote_path": "perfetto_binaries/trace_processor_shell/win/d89b25832b668dcf2d55bccbfb57f9a24723b869/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "58ad8635ba37cb2bcef7982fa53084a2a9f74214", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/8eb58df9cb83670f3fd54cc99055f367de18a001/trace_processor_shell" + "hash": "815295f9d6329edb5a5a0b64c04637417b2d8dd5", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/8c8fafb6ff4b4a715b868915840fc95040290ef7/trace_processor_shell" }, "mac_arm64": { "hash": "c0397e87456ad6c6a7aa0133e5b81c97adbab4ab", "remote_path": "perfetto_binaries/trace_processor_shell/mac_arm64/cefb3e0ec3a0580c996f801e854fe02963c03d5c/trace_processor_shell" }, "linux": { - "hash": "7e8ec049a560f4aa91c912f2041ebddcfe84c7ae", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/6c4a33cc8d5b0640ce6c86413fa93b99aa7851b4/trace_processor_shell" + "hash": "c2cdd48accd88830e5004082ceacf8bea8b9d7f4", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/d89b25832b668dcf2d55bccbfb57f9a24723b869/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 9331c86..323647f1 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -362,4 +362,6 @@ <item id="printing_oauth2_metadata_request" added_in_milestone="101" type="partial" second_id="printing_oauth2_http_exchange" content_hash_code="041eb66d" os_list="chromeos" semantics_fields="2,4" file_path="chrome/browser/ash/printing/oauth2/authorization_server_data.cc" /> <item id="printing_oauth2_registration_request" added_in_milestone="101" type="partial" second_id="printing_oauth2_http_exchange" content_hash_code="039d2748" os_list="chromeos" semantics_fields="2,4" file_path="chrome/browser/ash/printing/oauth2/authorization_server_data.cc" /> <item id="printing_oauth2_http_exchange" added_in_milestone="101" type="completing" content_hash_code="079d0e2f" os_list="chromeos" semantics_fields="1,3,5,6" policy_fields="-1,3,5" file_path="chrome/browser/ash/printing/oauth2/http_exchange.cc" /> + <item id="printing_oauth2_first_token_request" added_in_milestone="102" type="partial" second_id="printing_oauth2_http_exchange" content_hash_code="00850a77" os_list="chromeos" semantics_fields="2,4" file_path="chrome/browser/ash/printing/oauth2/authorization_server_session.cc" /> + <item id="printing_oauth2_next_token_request" added_in_milestone="102" type="partial" second_id="printing_oauth2_http_exchange" content_hash_code="002fbbfd" os_list="chromeos" semantics_fields="2,4" file_path="chrome/browser/ash/printing/oauth2/authorization_server_session.cc" /> </annotations>
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index 6405066..09a9eb5 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -102,7 +102,9 @@ <traffic_annotation unique_id="download_recovery_component"/> </sender> <sender name="ChromeOS Printers Manager"> + <traffic_annotation unique_id="printing_oauth2_first_token_request"/> <traffic_annotation unique_id="printing_oauth2_metadata_request"/> + <traffic_annotation unique_id="printing_oauth2_next_token_request"/> <traffic_annotation unique_id="printing_oauth2_registration_request"/> </sender> </group>
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 826048d..72a2d6b 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -492,6 +492,7 @@ "junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java", "junit/src/org/chromium/ui/widget/LoadingViewTest.java", "junit/src/org/chromium/ui/widget/ViewLookupCachingFrameLayoutTest.java", + "junit/src/org/chromium/ui/widget/ViewRectProviderTest.java", ] deps = [ ":ui_java",
diff --git a/ui/android/java/src/org/chromium/ui/widget/TextViewWithTightWrapTest.java b/ui/android/java/src/org/chromium/ui/widget/TextViewWithTightWrapTest.java index 861ae845..bb4d3ce 100644 --- a/ui/android/java/src/org/chromium/ui/widget/TextViewWithTightWrapTest.java +++ b/ui/android/java/src/org/chromium/ui/widget/TextViewWithTightWrapTest.java
@@ -40,6 +40,7 @@ RenderTestRule.Builder.withPublicCorpus() .setRevision(RENDER_TEST_REVISION) .setDescription(RENDER_TEST_REVISION_DESCRIPTION) + .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE) .build(); @Before
diff --git a/ui/android/java/src/org/chromium/ui/widget/ViewRectProvider.java b/ui/android/java/src/org/chromium/ui/widget/ViewRectProvider.java index 767a390..bd42ce5 100644 --- a/ui/android/java/src/org/chromium/ui/widget/ViewRectProvider.java +++ b/ui/android/java/src/org/chromium/ui/widget/ViewRectProvider.java
@@ -11,8 +11,9 @@ import androidx.core.view.ViewCompat; /** - * Provides a {@Rect} for the location of a {@View} in its window, see - * {@link View#getLocationOnScreen(int[])}. + * Provides a {@link Rect} for the location of a {@link View} in its window, see + * {@link View#getLocationOnScreen(int[])}. When view bound changes, {@link RectProvider.Observer} + * will be notified. */ public class ViewRectProvider extends RectProvider implements ViewTreeObserver.OnGlobalLayoutListener, View.OnAttachStateChangeListener, @@ -21,6 +22,9 @@ private final Rect mInsetRect = new Rect(); private final View mView; + private int mCachedViewWidth; + private int mCachedViewHeight; + /** If not {@code null}, the {@link ViewTreeObserver} that we are registered to. */ private ViewTreeObserver mViewTreeObserver; @@ -34,6 +38,8 @@ mView = view; mCachedWindowCoordinates[0] = -1; mCachedWindowCoordinates[1] = -1; + mCachedViewWidth = -1; + mCachedViewHeight = -1; } /** @@ -41,8 +47,7 @@ * when creating the {@link Rect}. */ public void setInsetPx(int left, int top, int right, int bottom) { - mInsetRect.set(left, top, right, bottom); - refreshRectBounds(); + setInsetPx(new Rect(left, top, right, bottom)); } /** @@ -50,8 +55,10 @@ * when creating the {@link Rect}. */ public void setInsetPx(Rect insetRect) { + if (insetRect.equals(mInsetRect)) return; + mInsetRect.set(insetRect); - refreshRectBounds(); + refreshRectBounds(/*forceRefresh=*/true); } /** @@ -59,7 +66,10 @@ * @param includePadding Whether padding should be included. Defaults to false. */ public void setIncludePadding(boolean includePadding) { + if (includePadding == mIncludePadding) return; + mIncludePadding = includePadding; + refreshRectBounds(/*forceRefresh=*/true); } @Override @@ -69,7 +79,7 @@ mViewTreeObserver.addOnGlobalLayoutListener(this); mViewTreeObserver.addOnPreDrawListener(this); - refreshRectBounds(); + refreshRectBounds(/*forceRefresh=*/false); super.startObserving(observer); } @@ -99,7 +109,7 @@ if (!mView.isShown()) { notifyRectHidden(); } else { - refreshRectBounds(); + refreshRectBounds(/*forceRefresh=*/false); } return true; @@ -114,17 +124,26 @@ notifyRectHidden(); } - private void refreshRectBounds() { + /** + * @param forceRefresh Whether the rect bounds should be refreshed even when the window + * coordinates and view sizes haven't changed. This is needed when inset or padding changes. + * */ + private void refreshRectBounds(boolean forceRefresh) { int previousPositionX = mCachedWindowCoordinates[0]; int previousPositionY = mCachedWindowCoordinates[1]; + int previousWidth = mCachedViewWidth; + int previousHeight = mCachedViewHeight; mView.getLocationInWindow(mCachedWindowCoordinates); mCachedWindowCoordinates[0] = Math.max(mCachedWindowCoordinates[0], 0); mCachedWindowCoordinates[1] = Math.max(mCachedWindowCoordinates[1], 0); + mCachedViewWidth = mView.getWidth(); + mCachedViewHeight = mView.getHeight(); - // Return if the window coordinates haven't changed. - if (mCachedWindowCoordinates[0] == previousPositionX - && mCachedWindowCoordinates[1] == previousPositionY) { + // Return if the window coordinates and view sizes haven't changed. + if (!forceRefresh && mCachedWindowCoordinates[0] == previousPositionX + && mCachedWindowCoordinates[1] == previousPositionY + && mCachedViewWidth == previousWidth && mCachedViewHeight == previousHeight) { return; }
diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java b/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java index fc0de40c..6d67f61 100644 --- a/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java +++ b/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java
@@ -118,17 +118,68 @@ String ANDROID_VR_RENDER_TESTS = "android-vr-render-tests"; } - @StringDef({Component.NONE}) + @StringDef({Component.NONE, Component.BLINK_CONTACTS, Component.BLINK_FORMS_COLOR, + Component.BLINK_PAYMENTS, Component.PRIVACY, Component.PRIVACY_INCOGNITO, + Component.SERVICES_SIGN_IN, Component.SERVICES_SYNC, Component.UI_BROWSER_AUTOFILL, + Component.UI_BROWSER_BOOKMARKS, Component.UI_BROWSER_BUBBLES_PAGE_INFO, + Component.UI_BROWSER_CONTENT_SUGGESTIONS, Component.UI_BROWSER_CONTENT_SUGGESTIONS_FEED, + Component.UI_BROWSER_CONTENT_SUGGESTIONS_HISTORY, Component.UI_BROWSER_FIRST_RUN, + Component.UI_BROWSER_INCOGNITO, Component.UI_BROWSER_INFOBARS, + Component.UI_BROWSER_MEDIA_PICKER, Component.UI_BROWSER_MOBILE, + Component.UI_BROWSER_MOBILE_APP_MENU, Component.UI_BROWSER_MOBILE_CONTEXT_MENU, + Component.UI_BROWSER_MOBILE_CUSTOM_TABS, Component.UI_BROWSER_MOBILE_MESSAGES, + Component.UI_BROWSER_MOBILE_RECENT_TABS, Component.UI_BROWSER_MOBILE_SETTINGS, + Component.UI_BROWSER_MOBILE_START, Component.UI_BROWSER_MOBILE_TAB_GROUPS, + Component.UI_BROWSER_MOBILE_TAB_SWITCHER, Component.UI_BROWSER_MOBILE_TAB_SWITCHER_GRID, + Component.UI_BROWSER_NEW_TAB_PAGE, Component.UI_BROWSER_NEW_TAB_PAGE_EXPLORE_SITES, + Component.UI_BROWSER_OMNIBOX, Component.UI_BROWSER_SEARCH_VOICE, + Component.UI_BROWSER_SHARING, Component.UI_BROWSER_SHOPPING, + Component.UI_BROWSER_SHOPPING_MERCHANT_TRUST, + Component.UI_BROWSER_SHOPPING_PRICE_TRACKING, Component.UI_BROWSER_TOOLBAR, + Component.UI_BROWSER_WEB_APP_INSTALLS, Component.UI_SETTINGS_PRIVACY}) @Retention(RetentionPolicy.SOURCE) public @interface Component { // Default for now, likely to be removed once all existing uses have a valid component. String NONE = "N/A"; + String BLINK_CONTACTS = "Blink>Contacts"; String BLINK_FORMS_COLOR = "Blink>Forms>Color"; + String BLINK_PAYMENTS = "Blink>Payments"; + String PRIVACY = "Privacy"; + String PRIVACY_INCOGNITO = "Privacy>Incognito"; + String SERVICES_SIGN_IN = "Services>SignIn"; + String SERVICES_SYNC = "Services>Sync"; + String UI_BROWSER_AUTOFILL = "UI>Browser>Autofill"; + String UI_BROWSER_BOOKMARKS = "UI>Browser>Bookmarks"; + String UI_BROWSER_BUBBLES_PAGE_INFO = "UI>Browser>Bubbles>PageInfo"; + String UI_BROWSER_CONTENT_SUGGESTIONS = "UI>Browser>ContentSuggestions"; + String UI_BROWSER_CONTENT_SUGGESTIONS_FEED = "UI>Browser>ContentSuggestions>Feed"; + String UI_BROWSER_CONTENT_SUGGESTIONS_HISTORY = "UI>Browser>ContentSuggestions>History"; String UI_BROWSER_FIRST_RUN = "UI>Browser>FirstRun"; + String UI_BROWSER_INCOGNITO = "UI>Browser>Incognito"; + String UI_BROWSER_INFOBARS = "UI>Browser>Infobars"; + String UI_BROWSER_MEDIA_PICKER = "UI>Browser>MediaPicker"; + String UI_BROWSER_MOBILE = "UI>Browser>Mobile"; String UI_BROWSER_MOBILE_APP_MENU = "UI>Browser>Mobile>AppMenu"; String UI_BROWSER_MOBILE_CONTEXT_MENU = "UI>Browser>Mobile>ContextMenu"; + String UI_BROWSER_MOBILE_CUSTOM_TABS = "UI>Browser>Mobile>CustomTabs"; String UI_BROWSER_MOBILE_MESSAGES = "UI>Browser>Mobile>Messages"; + String UI_BROWSER_MOBILE_RECENT_TABS = "UI>Browser>Mobile>RecentTabs"; + String UI_BROWSER_MOBILE_SETTINGS = "UI>Browser>Mobile>Settings"; String UI_BROWSER_MOBILE_START = "UI>Browser>Mobile>Start"; + String UI_BROWSER_MOBILE_TAB_GROUPS = "UI>Browser>Mobile>TabGroups"; + String UI_BROWSER_MOBILE_TAB_SWITCHER = "UI>Browser>Mobile>TabSwitcher"; + String UI_BROWSER_MOBILE_TAB_SWITCHER_GRID = "UI>Browser>Mobile>TabSwitcher>Grid"; + String UI_BROWSER_NEW_TAB_PAGE = "UI>Browser>NewTabPage"; + String UI_BROWSER_NEW_TAB_PAGE_EXPLORE_SITES = "UI>Browser>NewTabPage>ExploreSites"; + String UI_BROWSER_OMNIBOX = "UI>Browser>Omnibox"; + String UI_BROWSER_SEARCH_VOICE = "UI>Browser>Search>Voice"; + String UI_BROWSER_SHARING = "UI>Browser>Sharing"; + String UI_BROWSER_SHOPPING = "UI>Browser>Shopping"; + String UI_BROWSER_SHOPPING_MERCHANT_TRUST = "UI>Browser>Shopping>MerchantTrust"; + String UI_BROWSER_SHOPPING_PRICE_TRACKING = "UI>Browser>Shopping>PriceTracking"; + String UI_BROWSER_TOOLBAR = "UI>Browser>Toolbar"; + String UI_BROWSER_WEB_APP_INSTALLS = "UI>Browser>WebAppInstalls"; + String UI_SETTINGS_PRIVACY = "UI>Settings>Privacy"; } // Skia Gold-specific constructor used by the builder.
diff --git a/ui/android/junit/src/org/chromium/ui/widget/ViewRectProviderTest.java b/ui/android/junit/src/org/chromium/ui/widget/ViewRectProviderTest.java new file mode 100644 index 0000000..ba02b4f --- /dev/null +++ b/ui/android/junit/src/org/chromium/ui/widget/ViewRectProviderTest.java
@@ -0,0 +1,180 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.widget; + +import android.app.Activity; +import android.graphics.Rect; +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.View.OnAttachStateChangeListener; +import android.widget.FrameLayout; +import android.widget.FrameLayout.LayoutParams; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowView; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.ui.widget.RectProvider.Observer; +import org.chromium.ui.widget.ViewRectProviderTest.MyShadowView; + +import java.util.Optional; + +/** Unit tests for {@link ViewRectProvider} .*/ +@RunWith(BaseRobolectricTestRunner.class) +@Config(shadows = MyShadowView.class) +public class ViewRectProviderTest { + private static final int WIDTH = 600; + private static final int HEIGHT = 800; + + /** Custom ShadowView which includes setter for {@link View#isShown}. **/ + @Implements(View.class) + public static class MyShadowView extends ShadowView { + boolean mIsShown; + + /** Empty ctor required for shadow classes. */ + public MyShadowView() {} + + @Implementation + protected boolean isShown() { + return mIsShown; + } + + @Implementation + protected void getLocationInWindow(int[] outLocation) { + outLocation[0] = this.realView.getLeft(); + outLocation[1] = this.realView.getTop(); + } + + void setIsShown(boolean isShown) { + mIsShown = isShown; + } + } + + private ViewRectProvider mViewRectProvider; + private FrameLayout mRootView; + private View mView; + private MyShadowView mShadowView; + private Activity mActivity; + private RectProvider.Observer mObserver; + + private CallbackHelper mOnRectChangeCallback; + private CallbackHelper mOnRectHideCallback; + + @Before + public void setup() { + mActivity = Robolectric.buildActivity(Activity.class).get(); + mRootView = new FrameLayout(mActivity); + mActivity.setContentView(mRootView); + + mView = new View(mActivity); + + mRootView.addView( + mView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mViewRectProvider = new ViewRectProvider(mView); + + mOnRectChangeCallback = new CallbackHelper(); + mOnRectHideCallback = new CallbackHelper(); + mObserver = new Observer() { + @Override + public void onRectChanged() { + mOnRectChangeCallback.notifyCalled(); + } + + @Override + public void onRectHidden() { + mOnRectHideCallback.notifyCalled(); + } + }; + + View rootView = mRootView.getRootView(); + rootView.measure(MeasureSpec.makeMeasureSpec(WIDTH, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(HEIGHT, MeasureSpec.EXACTLY)); + rootView.layout(0, 0, WIDTH, HEIGHT); + + mShadowView = Shadow.extract(mView); + mShadowView.setIsShown(true); + + mViewRectProvider.startObserving(mObserver); + } + + @Test + public void testProviderViewBound() { + assertRectMatch(0, 0, WIDTH, HEIGHT); + } + + @Test + public void testOnRectHidden() { + mShadowView.setIsShown(false); + + int expectedCounts = 0; + mView.getViewTreeObserver().dispatchOnGlobalLayout(); + Assert.assertEquals("#onGlobalLayout should call #onRectHidden.", ++expectedCounts, + mOnRectHideCallback.getCallCount()); + + mView.getViewTreeObserver().dispatchOnPreDraw(); + Assert.assertEquals("#onPreDraw should call #onRectHidden.", ++expectedCounts, + mOnRectHideCallback.getCallCount()); + + Optional<OnAttachStateChangeListener> listener = + mShadowView.getOnAttachStateChangeListeners().stream().findFirst(); + Assert.assertTrue(listener.isPresent()); + listener.get().onViewDetachedFromWindow(mView); + Assert.assertEquals("#onViewDetachedFromWindow should call #onRectHidden.", + ++expectedCounts, mOnRectHideCallback.getCallCount()); + } + + @Test + public void testOnRectChanged() { + int expectedCounts = 0; + + mView.layout(0, 0, WIDTH, HEIGHT); + mView.getViewTreeObserver().dispatchOnPreDraw(); + Assert.assertEquals("View does not changes its bound. Should not trigger #onRectChanged.", + expectedCounts, mOnRectChangeCallback.getCallCount()); + mView.layout(0, 0, 100, 100); + mView.getViewTreeObserver().dispatchOnPreDraw(); + Assert.assertEquals("View changing its bound should trigger #onRectChanged.", + ++expectedCounts, mOnRectChangeCallback.getCallCount()); + assertRectMatch(0, 0, 100, 100); + + mView.layout(1, 1, 101, 101); + mView.getViewTreeObserver().dispatchOnPreDraw(); + Assert.assertEquals("View changing its position on screen should trigger #onRectChanged.", + ++expectedCounts, mOnRectChangeCallback.getCallCount()); + assertRectMatch(1, 1, 101, 101); + + mViewRectProvider.setInsetPx(new Rect(0, 0, 0, 0)); + Assert.assertEquals("Setting same view inset should not trigger #onRectChanged.", + expectedCounts, mOnRectChangeCallback.getCallCount()); + mViewRectProvider.setInsetPx(new Rect(0, 0, 0, 1)); + Assert.assertEquals( + "Setting different inset on ViewRectProvider should trigger #onRectChanged.", + ++expectedCounts, mOnRectChangeCallback.getCallCount()); + assertRectMatch(1, 1, 101, 100); + + mViewRectProvider.setIncludePadding(false); + Assert.assertEquals( + "Setting same ViewProvider#setIncludePadding should not trigger #onRectChanged.", + expectedCounts, mOnRectChangeCallback.getCallCount()); + mViewRectProvider.setIncludePadding(true); + Assert.assertEquals( + "Setting different ViewProvider#setIncludePadding should trigger #onRectChanged.", + ++expectedCounts, mOnRectChangeCallback.getCallCount()); + } + + private void assertRectMatch(int left, int top, int right, int bottom) { + final Rect expectedRect = new Rect(left, top, right, bottom); + Assert.assertEquals("Rect does not match.", expectedRect, mViewRectProvider.getRect()); + } +}
diff --git a/ui/base/ime/ash/input_method_ash.cc b/ui/base/ime/ash/input_method_ash.cc index 82dd9ed..17cc6694 100644 --- a/ui/base/ime/ash/input_method_ash.cc +++ b/ui/base/ime/ash/input_method_ash.cc
@@ -181,7 +181,7 @@ handling_key_event_ = false; } -void InputMethodAsh::OnTextInputTypeChanged(const TextInputClient* client) { +void InputMethodAsh::OnTextInputTypeChanged(TextInputClient* client) { if (!IsTextInputClientFocused(client)) return;
diff --git a/ui/base/ime/ash/input_method_ash.h b/ui/base/ime/ash/input_method_ash.h index aa7c7ef..7b472f6 100644 --- a/ui/base/ime/ash/input_method_ash.h +++ b/ui/base/ime/ash/input_method_ash.h
@@ -36,7 +36,7 @@ // Overridden from InputMethod: ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; - void OnTextInputTypeChanged(const TextInputClient* client) override; + void OnTextInputTypeChanged(TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; bool IsCandidatePopupOpen() const override;
diff --git a/ui/base/ime/dummy_input_method.cc b/ui/base/ime/dummy_input_method.cc index ad9ea54..d924bfd 100644 --- a/ui/base/ime/dummy_input_method.cc +++ b/ui/base/ime/dummy_input_method.cc
@@ -53,8 +53,7 @@ return ui::EventDispatchDetails(); } -void DummyInputMethod::OnTextInputTypeChanged(const TextInputClient* client) { -} +void DummyInputMethod::OnTextInputTypeChanged(TextInputClient* client) {} void DummyInputMethod::OnCaretBoundsChanged(const TextInputClient* client) { }
diff --git a/ui/base/ime/dummy_input_method.h b/ui/base/ime/dummy_input_method.h index 55afd03b..c307a3f0 100644 --- a/ui/base/ime/dummy_input_method.h +++ b/ui/base/ime/dummy_input_method.h
@@ -38,7 +38,7 @@ void DetachTextInputClient(TextInputClient* client) override; TextInputClient* GetTextInputClient() const override; ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; - void OnTextInputTypeChanged(const TextInputClient* client) override; + void OnTextInputTypeChanged(TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; TextInputType GetTextInputType() const override;
diff --git a/ui/base/ime/fuchsia/input_method_fuchsia.cc b/ui/base/ime/fuchsia/input_method_fuchsia.cc index 6f5e12a..46e7288 100644 --- a/ui/base/ime/fuchsia/input_method_fuchsia.cc +++ b/ui/base/ime/fuchsia/input_method_fuchsia.cc
@@ -64,7 +64,7 @@ } } -void InputMethodFuchsia::OnTextInputTypeChanged(const TextInputClient* client) { +void InputMethodFuchsia::OnTextInputTypeChanged(TextInputClient* client) { DVLOG(1) << __func__; InputMethodBase::OnTextInputTypeChanged(client);
diff --git a/ui/base/ime/fuchsia/input_method_fuchsia.h b/ui/base/ime/fuchsia/input_method_fuchsia.h index 2b90161..0c1e047 100644 --- a/ui/base/ime/fuchsia/input_method_fuchsia.h +++ b/ui/base/ime/fuchsia/input_method_fuchsia.h
@@ -36,7 +36,7 @@ VirtualKeyboardController* GetVirtualKeyboardController() final; ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) final; void CancelComposition(const TextInputClient* client) final; - void OnTextInputTypeChanged(const TextInputClient* client) final; + void OnTextInputTypeChanged(TextInputClient* client) final; void OnCaretBoundsChanged(const TextInputClient* client) final; bool IsCandidatePopupOpen() const final;
diff --git a/ui/base/ime/input_method.h b/ui/base/ime/input_method.h index 4abb93c..1c2f18ce 100644 --- a/ui/base/ime/input_method.h +++ b/ui/base/ime/input_method.h
@@ -116,7 +116,7 @@ // existing composition text and call InputMethod::CancelComposition() when // necessary. Otherwise unexpected behavior may happen. This method has no // effect if the client is not the focused client. - virtual void OnTextInputTypeChanged(const TextInputClient* client) = 0; + virtual void OnTextInputTypeChanged(TextInputClient* client) = 0; // Called by the focused client whenever its caret bounds is changed. // This method has no effect if the client is not the focused client.
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc index 012c0ce..4d0a371 100644 --- a/ui/base/ime/input_method_base.cc +++ b/ui/base/ime/input_method_base.cc
@@ -80,7 +80,7 @@ text_input_client_->EnsureCaretNotInRect(keyboard_bounds_); } -void InputMethodBase::OnTextInputTypeChanged(const TextInputClient* client) { +void InputMethodBase::OnTextInputTypeChanged(TextInputClient* client) { if (!IsTextInputClientFocused(client)) return; NotifyTextInputStateChanged(client);
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h index a96a82d..d67d387 100644 --- a/ui/base/ime/input_method_base.h +++ b/ui/base/ime/input_method_base.h
@@ -59,7 +59,7 @@ // If a derived class overrides this method, it should call parent's // implementation. - void OnTextInputTypeChanged(const TextInputClient* client) override; + void OnTextInputTypeChanged(TextInputClient* client) override; TextInputType GetTextInputType() const override; void SetVirtualKeyboardVisibilityIfEnabled(bool should_show) override;
diff --git a/ui/base/ime/linux/fake_input_method_context.cc b/ui/base/ime/linux/fake_input_method_context.cc index 582ddf3..c2116234 100644 --- a/ui/base/ime/linux/fake_input_method_context.cc +++ b/ui/base/ime/linux/fake_input_method_context.cc
@@ -36,7 +36,8 @@ const gfx::Range& selection_range) {} void FakeInputMethodContext::SetContentType(TextInputType input_type, - int input_flags) {} + int input_flags, + bool should_do_learning) {} VirtualKeyboardController* FakeInputMethodContext::GetVirtualKeyboardController() {
diff --git a/ui/base/ime/linux/fake_input_method_context.h b/ui/base/ime/linux/fake_input_method_context.h index 9d34dd4..f95f0ad8 100644 --- a/ui/base/ime/linux/fake_input_method_context.h +++ b/ui/base/ime/linux/fake_input_method_context.h
@@ -28,7 +28,9 @@ void SetCursorLocation(const gfx::Rect& rect) override; void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override; - void SetContentType(TextInputType input_type, int input_flags) override; + void SetContentType(TextInputType input_type, + int input_flags, + bool should_do_learning) override; VirtualKeyboardController* GetVirtualKeyboardController() override; };
diff --git a/ui/base/ime/linux/input_method_auralinux.cc b/ui/base/ime/linux/input_method_auralinux.cc index 2559495..d5b66b7c 100644 --- a/ui/base/ime/linux/input_method_auralinux.cc +++ b/ui/base/ime/linux/input_method_auralinux.cc
@@ -364,8 +364,7 @@ context_simple_->Blur(); } -void InputMethodAuraLinux::OnTextInputTypeChanged( - const TextInputClient* client) { +void InputMethodAuraLinux::OnTextInputTypeChanged(TextInputClient* client) { UpdateContextFocusState(); InputMethodBase::OnTextInputTypeChanged(client); @@ -375,7 +374,8 @@ ? context_.get() : context_simple_.get(); int flags = client ? client->GetTextInputFlags() : TEXT_INPUT_FLAG_NONE; - context->SetContentType(text_input_type_, flags); + context->SetContentType(text_input_type_, flags, + client && client->ShouldDoLearning()); // TODO(yoichio): Support inputmode HTML attribute. }
diff --git a/ui/base/ime/linux/input_method_auralinux.h b/ui/base/ime/linux/input_method_auralinux.h index 8538640..ca27b0f 100644 --- a/ui/base/ime/linux/input_method_auralinux.h +++ b/ui/base/ime/linux/input_method_auralinux.h
@@ -31,7 +31,7 @@ // Overriden from InputMethod. ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; - void OnTextInputTypeChanged(const TextInputClient* client) override; + void OnTextInputTypeChanged(TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; bool IsCandidatePopupOpen() const override;
diff --git a/ui/base/ime/linux/input_method_auralinux_unittest.cc b/ui/base/ime/linux/input_method_auralinux_unittest.cc index 75263d30..0074ccc 100644 --- a/ui/base/ime/linux/input_method_auralinux_unittest.cc +++ b/ui/base/ime/linux/input_method_auralinux_unittest.cc
@@ -157,7 +157,9 @@ TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16(re.str())); } - void SetContentType(TextInputType input_type, int input_flags) override {} + void SetContentType(TextInputType input_type, + int input_flags, + bool should_do_learning) override {} private: LinuxInputMethodContextDelegate* delegate_;
diff --git a/ui/base/ime/linux/linux_input_method_context.h b/ui/base/ime/linux/linux_input_method_context.h index 7fec4da..708d6c9 100644 --- a/ui/base/ime/linux/linux_input_method_context.h +++ b/ui/base/ime/linux/linux_input_method_context.h
@@ -46,7 +46,9 @@ const gfx::Range& selection_range) = 0; // Tells the system IME the content type of the text input client is changed. - virtual void SetContentType(TextInputType input_type, int input_flags) = 0; + virtual void SetContentType(TextInputType input_type, + int input_flags, + bool should_do_learning) = 0; // Resets the context. A client needs to call OnTextInputTypeChanged() again // before calling DispatchKeyEvent().
diff --git a/ui/base/ime/mock_input_method.cc b/ui/base/ime/mock_input_method.cc index 18b7bd0..b634571 100644 --- a/ui/base/ime/mock_input_method.cc +++ b/ui/base/ime/mock_input_method.cc
@@ -85,7 +85,7 @@ } #endif -void MockInputMethod::OnTextInputTypeChanged(const TextInputClient* client) { +void MockInputMethod::OnTextInputTypeChanged(TextInputClient* client) { for (InputMethodObserver& observer : observer_list_) observer.OnTextInputStateChanged(client); }
diff --git a/ui/base/ime/mock_input_method.h b/ui/base/ime/mock_input_method.h index d619768..d86a85c 100644 --- a/ui/base/ime/mock_input_method.h +++ b/ui/base/ime/mock_input_method.h
@@ -49,7 +49,7 @@ void DetachTextInputClient(TextInputClient* client) override; TextInputClient* GetTextInputClient() const override; ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; - void OnTextInputTypeChanged(const TextInputClient* client) override; + void OnTextInputTypeChanged(TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; TextInputType GetTextInputType() const override;
diff --git a/ui/base/ime/win/input_method_win_imm32.cc b/ui/base/ime/win/input_method_win_imm32.cc index e6c1afe..59a4577 100644 --- a/ui/base/ime/win/input_method_win_imm32.cc +++ b/ui/base/ime/win/input_method_win_imm32.cc
@@ -86,8 +86,7 @@ return !!handled; } -void InputMethodWinImm32::OnTextInputTypeChanged( - const TextInputClient* client) { +void InputMethodWinImm32::OnTextInputTypeChanged(TextInputClient* client) { InputMethodBase::OnTextInputTypeChanged(client); if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) return;
diff --git a/ui/base/ime/win/input_method_win_imm32.h b/ui/base/ime/win/input_method_win_imm32.h index 88385e1f..323ff6f 100644 --- a/ui/base/ime/win/input_method_win_imm32.h +++ b/ui/base/ime/win/input_method_win_imm32.h
@@ -31,7 +31,7 @@ // Overridden from InputMethod: bool OnUntranslatedIMEMessage(const CHROME_MSG event, NativeEventResult* result) override; - void OnTextInputTypeChanged(const TextInputClient* client) override; + void OnTextInputTypeChanged(TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; void OnInputLocaleChanged() override;
diff --git a/ui/base/ime/win/input_method_win_tsf.cc b/ui/base/ime/win/input_method_win_tsf.cc index 0c248df..1a02b6f 100644 --- a/ui/base/ime/win/input_method_win_tsf.cc +++ b/ui/base/ime/win/input_method_win_tsf.cc
@@ -93,7 +93,7 @@ return !!handled; } -void InputMethodWinTSF::OnTextInputTypeChanged(const TextInputClient* client) { +void InputMethodWinTSF::OnTextInputTypeChanged(TextInputClient* client) { InputMethodBase::OnTextInputTypeChanged(client); if (!ui::TSFBridge::GetInstance() || !IsTextInputClientFocused(client) || !IsWindowFocused(client)) {
diff --git a/ui/base/ime/win/input_method_win_tsf.h b/ui/base/ime/win/input_method_win_tsf.h index 37738b4..f35f6a19 100644 --- a/ui/base/ime/win/input_method_win_tsf.h +++ b/ui/base/ime/win/input_method_win_tsf.h
@@ -31,7 +31,7 @@ void OnBlur() override; bool OnUntranslatedIMEMessage(const CHROME_MSG event, NativeEventResult* result) override; - void OnTextInputTypeChanged(const TextInputClient* client) override; + void OnTextInputTypeChanged(TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; void DetachTextInputClient(TextInputClient* client) override;
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index 8a451a2..35c277e 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -2525,12 +2525,12 @@ #file-type-filter-container { display: flex; font-size: 13px; - padding: 12px 0 16px 12px; + padding: 12px 0 12px 12px; } .file-type-filter-button { --border-color: var(--cros-button-stroke-color-secondary); - --cr-button-height: 28px; + --cr-button-height: 32px; --hover-bg-color: var(--cros-ripple-color); --hover-border-color: var(--cros-button-stroke-color-secondary); --ink-color: var(--cros-ripple-color); @@ -2538,6 +2538,7 @@ --text-color: var(--cros-text-color-secondary); border-radius: 20px; margin-inline: 4px; + min-width: auto; outline: none; }
diff --git a/ui/gtk/input_method_context_impl_gtk.cc b/ui/gtk/input_method_context_impl_gtk.cc index 2036c9a..d0f6840 100644 --- a/ui/gtk/input_method_context_impl_gtk.cc +++ b/ui/gtk/input_method_context_impl_gtk.cc
@@ -252,7 +252,8 @@ } void InputMethodContextImplGtk::SetContentType(ui::TextInputType input_type, - int input_flags) { + int input_flags, + bool should_do_learning) { // Do nothing. }
diff --git a/ui/gtk/input_method_context_impl_gtk.h b/ui/gtk/input_method_context_impl_gtk.h index 4a9e15e8..1d485bb 100644 --- a/ui/gtk/input_method_context_impl_gtk.h +++ b/ui/gtk/input_method_context_impl_gtk.h
@@ -39,7 +39,9 @@ void Blur() override; void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override; - void SetContentType(ui::TextInputType input_type, int input_flags) override; + void SetContentType(ui::TextInputType input_type, + int input_flags, + bool should_do_learning) override; ui::VirtualKeyboardController* GetVirtualKeyboardController() override; private:
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn index b4bcd3c..f54e0f6 100644 --- a/ui/ozone/BUILD.gn +++ b/ui/ozone/BUILD.gn
@@ -238,7 +238,10 @@ deps = [ "//base" ] - visibility += [ "//chrome/test:browser_tests_runner" ] + visibility += [ + "//chrome/test:browser_tests_runner", + "//content/public/browser:browser_sources", + ] } component("ozone") {
diff --git a/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/ui/ozone/platform/drm/host/drm_display_host_manager.cc index 6bda9fb..0c0eeaa 100644 --- a/ui/ozone/platform/drm/host/drm_display_host_manager.cc +++ b/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -11,6 +11,7 @@ #include <utility> #include "base/bind.h" +#include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/strings/string_util.h" @@ -27,6 +28,7 @@ #include "ui/ozone/platform/drm/host/drm_display_host.h" #include "ui/ozone/platform/drm/host/drm_native_display_delegate.h" #include "ui/ozone/platform/drm/host/gpu_thread_adapter.h" +#include "ui/ozone/public/ozone_switches.h" namespace ui { @@ -184,6 +186,15 @@ } host_properties->supports_overlays = primary_drm_device_handle_->has_atomic_capabilities(); + // TODO(b/192563524): The legacy video decoder wraps its frames with legacy + // mailboxes instead of SharedImages. The display compositor can composite + // these quads, but does not support promoting them to overlays. Thus, we + // disable overlays on platforms using the legacy video decoder. + auto* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch( + switches::kPlatformDisallowsChromeOSDirectVideoDecoder)) { + host_properties->supports_overlays = false; + } drm_devices_[primary_graphics_card_path_] = primary_graphics_card_path_sysfs; }
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc index 662f27d8..5571950 100644 --- a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc +++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
@@ -388,12 +388,15 @@ } void WaylandInputMethodContext::SetContentType(TextInputType input_type, - int input_flags) { + int input_flags, + bool should_do_learning) { if (!text_input_) return; uint32_t content_purpose = InputTypeToContentPurpose(input_type); uint32_t content_hint = InputFlagsToContentHint(input_flags); + if (should_do_learning) + content_hint |= ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA; text_input_->SetContentType(content_hint, content_purpose); }
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.h b/ui/ozone/platform/wayland/host/wayland_input_method_context.h index d2b7082..0b4f7aa 100644 --- a/ui/ozone/platform/wayland/host/wayland_input_method_context.h +++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.h
@@ -49,7 +49,9 @@ void SetCursorLocation(const gfx::Rect& rect) override; void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override; - void SetContentType(TextInputType input_type, int input_flags) override; + void SetContentType(TextInputType input_type, + int input_flags, + bool should_do_learning) override; void Reset() override; void Focus() override; void Blur() override;
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc index 70b566e..d88ef947 100644 --- a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -388,7 +388,21 @@ ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL)) .Times(1); input_method_context_->SetContentType(TEXT_INPUT_TYPE_URL, - TEXT_INPUT_FLAG_AUTOCOMPLETE_ON); + TEXT_INPUT_FLAG_AUTOCOMPLETE_ON, + /*should_do_learning=*/false); + connection_->ScheduleFlush(); + Sync(); +} + +TEST_P(WaylandInputMethodContextTest, SetContentTypeWithoutLearning) { + EXPECT_CALL(*zwp_text_input_, + SetContentType(ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_COMPLETION | + ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA, + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL)) + .Times(1); + input_method_context_->SetContentType(TEXT_INPUT_TYPE_URL, + TEXT_INPUT_FLAG_AUTOCOMPLETE_ON, + /*should_do_learning=*/true); connection_->ScheduleFlush(); Sync(); }
diff --git a/ui/ozone/public/ozone_switches.cc b/ui/ozone/public/ozone_switches.cc index 60ff1cd4..f7975dc 100644 --- a/ui/ozone/public/ozone_switches.cc +++ b/ui/ozone/public/ozone_switches.cc
@@ -44,4 +44,10 @@ // Specifies ozone screen size. const char kOzoneOverrideScreenSize[] = "ozone-override-screen-size"; +// ChromeOS uses one of two VideoDecoder implementations based on SoC/board +// specific configurations that are signalled via this command line flag. +// TODO(b/159825227): remove when the "old" video decoder is fully launched. +const char kPlatformDisallowsChromeOSDirectVideoDecoder[] = + "platform-disallows-chromeos-direct-video-decoder"; + } // namespace switches
diff --git a/ui/ozone/public/ozone_switches.h b/ui/ozone/public/ozone_switches.h index 3a56b500..0ab7661 100644 --- a/ui/ozone/public/ozone_switches.h +++ b/ui/ozone/public/ozone_switches.h
@@ -36,6 +36,9 @@ COMPONENT_EXPORT(OZONE_SWITCHES) extern const char kOzoneOverrideScreenSize[]; +COMPONENT_EXPORT(OZONE_SWITCHES) +extern const char kPlatformDisallowsChromeOSDirectVideoDecoder[]; + } // namespace switches #endif // UI_OZONE_PUBLIC_OZONE_SWITCHES_H_
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc index f9f48d00..f058d07 100644 --- a/ui/views/controls/textfield/textfield_unittest.cc +++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -158,7 +158,7 @@ // InputMethod: ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* key) override; - void OnTextInputTypeChanged(const ui::TextInputClient* client) override; + void OnTextInputTypeChanged(ui::TextInputClient* client) override; void OnCaretBoundsChanged(const ui::TextInputClient* client) override {} void CancelComposition(const ui::TextInputClient* client) override; bool IsCandidatePopupOpen() const override; @@ -273,8 +273,7 @@ return dispatch_details; } -void MockInputMethod::OnTextInputTypeChanged( - const ui::TextInputClient* client) { +void MockInputMethod::OnTextInputTypeChanged(ui::TextInputClient* client) { if (IsTextInputClientFocused(client)) text_input_type_changed_ = true; InputMethodBase::OnTextInputTypeChanged(client);
diff --git a/weblayer/browser/java/res/values/styles.xml b/weblayer/browser/java/res/values/styles.xml index c583442..a2b7a60 100644 --- a/weblayer/browser/java/res/values/styles.xml +++ b/weblayer/browser/java/res/values/styles.xml
@@ -8,7 +8,7 @@ <style name="Theme.WebLayer.Settings" parent="Theme.WebLayer"> <item name="preferenceTheme">@style/PreferenceTheme</item> - <item name="alertDialogTheme">@style/Theme.Chromium.AlertDialog</item> + <item name="alertDialogTheme">@style/ThemeOverlay.BrowserUI.AlertDialog</item> <!-- Text style attributes used by the preference_material.xml layout. --> <item name="android:textAppearanceListItem">@style/TextAppearance.TextLarge.Primary</item>